Exemplo n.º 1
0
 def testComposerHtmlAccessor(self):
     """Test that we can retrieve the ComposerHtml instance given an item.
     """
     myComposition = QgsComposition(self.iface.mapCanvas().mapSettings())
     mySubstitutionMap = {'replace-me': 'Foo bar'}
     myFile = os.path.join(TEST_DATA_DIR, 'template.qpt')
     with open(myFile, 'rt') as myTemplateFile:
         myTemplateContent = myTemplateFile.read()
     myDocument = QDomDocument()
     myDocument.setContent(myTemplateContent)
     myComposition.loadFromTemplate(myDocument, mySubstitutionMap)
     myItem = myComposition.getComposerItemById('html-test')
     myComposerHtml = myComposition.getComposerHtmlByItem(myItem)
     myMessage = 'Could not retrieve the composer html given an item'
     self.assertIsNotNone(myComposerHtml, myMessage)
Exemplo n.º 2
0
 def testComposerHtmlAccessor(self):
     """Test that we can retrieve the ComposerHtml instance given an item.
     """
     myComposition = QgsComposition(self.iface.mapCanvas().mapRenderer())
     mySubstitutionMap = {'replace-me': 'Foo bar'}
     myFile = os.path.join(TEST_DATA_DIR, 'template.qpt')
     with open(myFile, 'rt') as myTemplateFile:
         myTemplateContent = myTemplateFile.read()
     myDocument = QDomDocument()
     myDocument.setContent(myTemplateContent)
     myComposition.loadFromTemplate(myDocument, mySubstitutionMap)
     myItem = myComposition.getComposerItemById('html-test')
     myComposerHtml = myComposition.getComposerHtmlByItem(myItem)
     myMessage = 'Could not retrieve the composer html given an item'
     self.assertIsNotNone(myComposerHtml, myMessage)
Exemplo n.º 3
0
 def testComposerHtmlAccessor(self):
     """Test that we can retrieve the ComposerHtml instance given an item.
     """
     myComposition = QgsComposition(CANVAS.mapRenderer())
     mySubstitutionMap = {'replace-me': 'Foo bar'}
     myFile = os.path.join(TEST_DATA_DIR, 'template.qpt')
     myTemplateFile = file(myFile, 'rt')
     myTemplateContent = myTemplateFile.read()
     myTemplateFile.close()
     myDocument = QDomDocument()
     myDocument.setContent(myTemplateContent)
     myComposition.loadFromTemplate(myDocument, mySubstitutionMap)
     myItem = myComposition.getComposerItemById('html-test')
     myComposerHtml = myComposition.getComposerHtmlByItem(myItem)
     myMessage = 'Could not retrieve the composer html given an item'
     assert myComposerHtml is not None, myMessage
Exemplo n.º 4
0
 def testComposerHtmlAccessor(self):
     """Test that we can retrieve the ComposerHtml instance given an item.
     """
     myComposition = QgsComposition(CANVAS.mapRenderer())
     mySubstitutionMap = {"replace-me": "Foo bar"}
     myFile = os.path.join(TEST_DATA_DIR, "template.qpt")
     myTemplateFile = file(myFile, "rt")
     myTemplateContent = myTemplateFile.read()
     myTemplateFile.close()
     myDocument = QDomDocument()
     myDocument.setContent(myTemplateContent)
     myComposition.loadFromTemplate(myDocument, mySubstitutionMap)
     myItem = myComposition.getComposerItemById("html-test")
     myComposerHtml = myComposition.getComposerHtmlByItem(myItem)
     myMessage = "Could not retrieve the composer html given an item"
     assert myComposerHtml is not None, myMessage
Exemplo n.º 5
0
def qgis_composer_renderer(impact_report, component):
    """Default Map Report Renderer using QGIS Composer.

    Render using qgis composer for a given impact_report data and component
    context.

    :param impact_report: ImpactReport contains data about the report that is
        going to be generated.
    :type impact_report: safe.report.impact_report.ImpactReport

    :param component: Contains the component metadata and context for
        rendering the output.
    :type component:
        safe.report.report_metadata.QgisComposerComponentsMetadata

    :return: Whatever type of output the component should be.

    .. versionadded:: 4.0
    """
    context = component.context
    """:type: safe.report.extractors.composer.QGISComposerContext"""
    qgis_composition_context = impact_report.qgis_composition_context

    # load composition object
    composition = QgsComposition(qgis_composition_context.map_settings)

    # load template
    main_template_folder = impact_report.metadata.template_folder

    # we do this condition in case custom template was found
    if component.template.startswith('../qgis-composer-templates/'):
        template_path = os.path.join(main_template_folder, component.template)
    else:
        template_path = component.template

    with open(template_path) as template_file:
        template_content = template_file.read()

    document = QtXml.QDomDocument()
    document.setContent(template_content)

    load_status = composition.loadFromTemplate(
        document, context.substitution_map)

    if not load_status:
        raise TemplateLoadingError(
            tr('Error loading template: %s') % template_path)

    # replace image path
    for img in context.image_elements:
        item_id = img.get('id')
        path = img.get('path')
        image = composition_item(composition, item_id, QgsComposerPicture)
        """:type: qgis.core.QgsComposerPicture"""
        if image and path:
            image.setPicturePath(path)

    # replace html frame
    for html_el in context.html_frame_elements:
        item_id = html_el.get('id')
        mode = html_el.get('mode')
        composer_item = composition.getComposerItemById(item_id)
        try:
            html_element = composition.getComposerHtmlByItem(composer_item)
        except:
            pass
        """:type: qgis.core.QgsComposerHtml"""
        if html_element:
            if mode == 'text':
                text = html_el.get('text')
                text = text if text else ''
                html_element.setContentMode(QgsComposerHtml.ManualHtml)
                html_element.setHtml(text)
                html_element.loadHtml()
            elif mode == 'url':
                url = html_el.get('url')
                html_element.setContentMode(QgsComposerHtml.Url)
                qurl = QUrl.fromLocalFile(url)
                html_element.setUrl(qurl)

    original_crs = impact_report.impact_function.crs
    destination_crs = qgis_composition_context.map_settings.destinationCrs()
    coord_transform = QgsCoordinateTransform(original_crs, destination_crs)

    # resize map extent
    for map_el in context.map_elements:
        item_id = map_el.get('id')
        split_count = map_el.get('grid_split_count')
        layers = [
            layer for layer in map_el.get('layers') if isinstance(
                layer, QgsMapLayer)
        ]
        map_extent_option = map_el.get('extent')
        composer_map = composition_item(composition, item_id, QgsComposerMap)

        for index, layer in enumerate(layers):
            # we need to check whether the layer is registered or not
            registered_layer = (
                QgsMapLayerRegistry.instance().mapLayer(layer.id()))
            if registered_layer:
                if not registered_layer == layer:
                    layers[index] = registered_layer
            else:
                QgsMapLayerRegistry.instance().addMapLayer(layer)

        """:type: qgis.core.QgsComposerMap"""
        if composer_map:

            # Search for specified map extent in the template.
            min_x = composer_map.extent().xMinimum() if (
                impact_report.use_template_extent) else None
            min_y = composer_map.extent().yMinimum() if (
                impact_report.use_template_extent) else None
            max_x = composer_map.extent().xMaximum() if (
                impact_report.use_template_extent) else None
            max_y = composer_map.extent().yMaximum() if (
                impact_report.use_template_extent) else None

            composer_map.setKeepLayerSet(True)
            layer_set = [l.id() for l in layers if isinstance(l, QgsMapLayer)]
            composer_map.setLayerSet(layer_set)
            map_overview_extent = None
            if map_extent_option and isinstance(
                    map_extent_option, QgsRectangle):
                # use provided map extent
                extent = coord_transform.transform(map_extent_option)
                for l in [layer for layer in layers if
                          isinstance(layer, QgsMapLayer)]:
                    layer_extent = coord_transform.transform(l.extent())
                    if l.name() == map_overview['id']:
                        map_overview_extent = layer_extent
            else:
                # if map extent not provided, try to calculate extent
                # from list of given layers. Combine it so all layers were
                # shown properly
                extent = QgsRectangle()
                extent.setMinimal()
                for l in [layer for layer in layers if
                          isinstance(layer, QgsMapLayer)]:
                    # combine extent if different layer is provided.
                    layer_extent = coord_transform.transform(l.extent())
                    extent.combineExtentWith(layer_extent)
                    if l.name() == map_overview['id']:
                        map_overview_extent = layer_extent

            width = extent.width()
            height = extent.height()
            longest_width = width if width > height else height
            half_length = longest_width / 2
            margin = half_length / 5
            center = extent.center()
            min_x = min_x or (center.x() - half_length - margin)
            max_x = max_x or (center.x() + half_length + margin)
            min_y = min_y or (center.y() - half_length - margin)
            max_y = max_y or (center.y() + half_length + margin)

            # noinspection PyCallingNonCallable
            square_extent = QgsRectangle(min_x, min_y, max_x, max_y)

            if component.key == 'population-infographic' and (
                    map_overview_extent):
                square_extent = map_overview_extent

            composer_map.zoomToExtent(square_extent)
            composer_map.renderModeUpdateCachedImage()

            actual_extent = composer_map.extent()

            # calculate intervals for grid
            x_interval = actual_extent.width() / split_count
            composer_map.grid().setIntervalX(x_interval)
            y_interval = actual_extent.height() / split_count
            composer_map.grid().setIntervalY(y_interval)

    # calculate legend element
    for leg_el in context.map_legends:
        item_id = leg_el.get('id')
        title = leg_el.get('title')
        layers = [
            layer for layer in leg_el.get('layers') if isinstance(
                layer, QgsMapLayer)
        ]
        symbol_count = leg_el.get('symbol_count')
        column_count = leg_el.get('column_count')

        legend = composition_item(composition, item_id, QgsComposerLegend)
        """:type: qgis.core.QgsComposerLegend"""
        if legend:
            # set column count
            if column_count:
                legend.setColumnCount(column_count)
            elif symbol_count <= 7:
                legend.setColumnCount(1)
            else:
                legend.setColumnCount(symbol_count / 7 + 1)

            # set legend title
            if title is not None and not impact_report.legend_layers:
                legend.setTitle(title)

            # set legend
            root_group = legend.modelV2().rootGroup()
            for layer in layers:
                # we need to check whether the layer is registered or not
                registered_layer = (
                    QgsMapLayerRegistry.instance().mapLayer(layer.id()))
                if registered_layer:
                    if not registered_layer == layer:
                        layer = registered_layer
                else:
                    QgsMapLayerRegistry.instance().addMapLayer(layer)
                # used for customizations
                tree_layer = root_group.addLayer(layer)
                if impact_report.legend_layers or (
                        not impact_report.multi_exposure_impact_function):
                    QgsLegendRenderer.setNodeLegendStyle(
                        tree_layer, QgsComposerLegendStyle.Hidden)
            legend.synchronizeWithModel()

    # process to output

    # in case output folder not specified
    if impact_report.output_folder is None:
        impact_report.output_folder = mkdtemp(dir=temp_dir())

    output_format = component.output_format
    component_output_path = impact_report.component_absolute_output_path(
        component.key)
    component_output = None

    doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT
    template_format = QgisComposerComponentsMetadata.OutputFormat.QPT
    if isinstance(output_format, list):
        component_output = []
        for i in range(len(output_format)):
            each_format = output_format[i]
            each_path = component_output_path[i]

            if each_format in doc_format:
                result_path = create_qgis_pdf_output(
                    impact_report,
                    each_path,
                    composition,
                    each_format,
                    component)
                component_output.append(result_path)
            elif each_format == template_format:
                result_path = create_qgis_template_output(
                    each_path, composition)
                component_output.append(result_path)
    elif isinstance(output_format, dict):
        component_output = {}
        for key, each_format in output_format.iteritems():
            each_path = component_output_path[key]

            if each_format in doc_format:
                result_path = create_qgis_pdf_output(
                    impact_report,
                    each_path,
                    composition,
                    each_format,
                    component)
                component_output[key] = result_path
            elif each_format == template_format:
                result_path = create_qgis_template_output(
                    each_path, composition)
                component_output[key] = result_path
    elif (output_format in
            QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT):
        component_output = None

        if output_format in doc_format:
            result_path = create_qgis_pdf_output(
                impact_report,
                component_output_path,
                composition,
                output_format,
                component)
            component_output = result_path
        elif output_format == template_format:
            result_path = create_qgis_template_output(
                component_output_path, composition)
            component_output = result_path

    component.output = component_output

    return component.output
Exemplo n.º 6
0
    def generate_report(self):
        # Generate pdf report from impact/hazard
        LOGGER.info("Generating report")
        if not self.impact_exists:
            # Cannot generate report when no impact layer present
            LOGGER.info("Cannot Generate report when no impact present.")
            return

        project_instance = QgsProject.instance()
        project_instance.setFileName(self.project_path)
        project_instance.read()

        # get layer registry
        layer_registry = QgsMapLayerRegistry.instance()
        layer_registry.removeAllMapLayers()

        # Set up the map renderer that will be assigned to the composition
        map_renderer = CANVAS.mapRenderer()

        # Enable on the fly CRS transformations
        map_renderer.setProjectionsEnabled(True)

        default_crs = map_renderer.destinationCrs()
        crs = QgsCoordinateReferenceSystem("EPSG:4326")
        map_renderer.setDestinationCrs(crs)

        # add place name layer
        layer_registry.addMapLayer(self.cities_layer, False)

        # add airport layer
        layer_registry.addMapLayer(self.airport_layer, False)

        # add volcano layer
        layer_registry.addMapLayer(self.volcano_layer, False)

        # add impact layer
        hazard_layer = read_qgis_layer(self.hazard_path, self.tr("People Affected"))
        layer_registry.addMapLayer(hazard_layer, False)

        # add basemap layer
        layer_registry.addMapLayer(self.highlight_base_layer, False)

        # add basemap layer
        layer_registry.addMapLayer(self.overview_layer, False)

        CANVAS.setExtent(hazard_layer.extent())
        CANVAS.refresh()

        template_path = self.ash_fixtures_dir("realtime-ash.qpt")

        with open(template_path) as f:
            template_content = f.read()

        document = QDomDocument()
        document.setContent(template_content)

        # Now set up the composition
        # map_settings = QgsMapSettings()
        # composition = QgsComposition(map_settings)
        composition = QgsComposition(map_renderer)

        subtitution_map = self.event_dict()
        LOGGER.debug(subtitution_map)

        # load composition object from template
        result = composition.loadFromTemplate(document, subtitution_map)
        if not result:
            LOGGER.exception("Error loading template %s with keywords\n %s", template_path, subtitution_map)
            raise MapComposerError

        # get main map canvas on the composition and set extent
        map_impact = composition.getComposerItemById("map-impact")
        if map_impact:
            map_impact.zoomToExtent(hazard_layer.extent())
            map_impact.renderModeUpdateCachedImage()
        else:
            LOGGER.exception("Map canvas could not be found in template %s", template_path)
            raise MapComposerError

        # get overview map canvas on the composition and set extent
        map_overall = composition.getComposerItemById("map-overall")
        if map_overall:
            map_overall.setLayerSet([self.overview_layer.id()])
            # this is indonesia extent
            indonesia_extent = QgsRectangle(
                94.0927980005593554, -15.6629591962689343, 142.0261493318861312, 10.7379406374101816
            )
            map_overall.zoomToExtent(indonesia_extent)
            map_overall.renderModeUpdateCachedImage()
        else:
            LOGGER.exception("Map canvas could not be found in template %s", template_path)
            raise MapComposerError

        # setup impact table
        self.render_population_table()
        self.render_nearby_table()
        self.render_landcover_table()

        impact_table = composition.getComposerItemById("table-impact")
        if impact_table is None:
            message = "table-impact composer item could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        impacts_html = composition.getComposerHtmlByItem(impact_table)
        if impacts_html is None:
            message = "Impacts QgsComposerHtml could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        impacts_html.setUrl(QUrl(self.population_html_path))

        # setup nearby table
        nearby_table = composition.getComposerItemById("table-nearby")
        if nearby_table is None:
            message = "table-nearby composer item could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        nearby_html = composition.getComposerHtmlByItem(nearby_table)
        if nearby_html is None:
            message = "Nearby QgsComposerHtml could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        nearby_html.setUrl(QUrl(self.nearby_html_path))

        # setup landcover table
        landcover_table = composition.getComposerItemById("table-landcover")
        if landcover_table is None:
            message = "table-landcover composer item could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        landcover_html = composition.getComposerHtmlByItem(landcover_table)
        if landcover_html is None:
            message = "Landcover QgsComposerHtml could not be found"
            LOGGER.exception(message)
            raise MapComposerError(message)
        landcover_html.setUrl(QUrl(self.landcover_html_path))

        # setup logos
        logos_id = ["logo-bnpb", "logo-geologi"]
        for logo_id in logos_id:
            logo_picture = composition.getComposerItemById(logo_id)
            if logo_picture is None:
                message = "%s composer item could not be found" % logo_id
                LOGGER.exception(message)
                raise MapComposerError(message)
            pic_path = os.path.basename(logo_picture.picturePath())
            pic_path = os.path.join("logo", pic_path)
            logo_picture.setPicturePath(self.ash_fixtures_dir(pic_path))

        # save a pdf
        composition.exportAsPDF(self.map_report_path)

        project_instance.write(QFileInfo(self.project_path))

        layer_registry.removeAllMapLayers()
        map_renderer.setDestinationCrs(default_crs)
        map_renderer.setProjectionsEnabled(False)
        LOGGER.info("Report generation completed.")
Exemplo n.º 7
0
    def generate_report(self):
        # Generate pdf report from impact/hazard
        LOGGER.info('Generating report')
        if not self.impact_exists:
            # Cannot generate report when no impact layer present
            LOGGER.info('Cannot Generate report when no impact present.')
            return

        project_instance = QgsProject.instance()
        project_instance.setFileName(self.project_path)
        project_instance.read()

        # get layer registry
        layer_registry = QgsMapLayerRegistry.instance()
        layer_registry.removeAllMapLayers()

        # Set up the map renderer that will be assigned to the composition
        map_renderer = CANVAS.mapRenderer()

        # Enable on the fly CRS transformations
        map_renderer.setProjectionsEnabled(True)

        default_crs = map_renderer.destinationCrs()
        crs = QgsCoordinateReferenceSystem('EPSG:4326')
        map_renderer.setDestinationCrs(crs)

        # add place name layer
        layer_registry.addMapLayer(self.cities_layer, False)

        # add airport layer
        layer_registry.addMapLayer(self.airport_layer, False)

        # add volcano layer
        layer_registry.addMapLayer(self.volcano_layer, False)

        # add impact layer
        hazard_layer = read_qgis_layer(self.hazard_path,
                                       self.tr('People Affected'))
        layer_registry.addMapLayer(hazard_layer, False)

        # add basemap layer
        layer_registry.addMapLayer(self.highlight_base_layer, False)

        # add basemap layer
        layer_registry.addMapLayer(self.overview_layer, False)

        CANVAS.setExtent(hazard_layer.extent())
        CANVAS.refresh()

        template_path = self.ash_fixtures_dir('realtime-ash.qpt')

        with open(template_path) as f:
            template_content = f.read()

        document = QDomDocument()
        document.setContent(template_content)

        # Now set up the composition
        # map_settings = QgsMapSettings()
        # composition = QgsComposition(map_settings)
        composition = QgsComposition(map_renderer)

        subtitution_map = self.event_dict()
        LOGGER.debug(subtitution_map)

        # load composition object from template
        result = composition.loadFromTemplate(document, subtitution_map)
        if not result:
            LOGGER.exception('Error loading template %s with keywords\n %s',
                             template_path, subtitution_map)
            raise MapComposerError

        # get main map canvas on the composition and set extent
        map_impact = composition.getComposerItemById('map-impact')
        if map_impact:
            map_impact.zoomToExtent(hazard_layer.extent())
            map_impact.renderModeUpdateCachedImage()
        else:
            LOGGER.exception('Map canvas could not be found in template %s',
                             template_path)
            raise MapComposerError

        # get overview map canvas on the composition and set extent
        map_overall = composition.getComposerItemById('map-overall')
        if map_overall:
            map_overall.setLayerSet([self.overview_layer.id()])
            # this is indonesia extent
            indonesia_extent = QgsRectangle(94.0927980005593554,
                                            -15.6629591962689343,
                                            142.0261493318861312,
                                            10.7379406374101816)
            map_overall.zoomToExtent(indonesia_extent)
            map_overall.renderModeUpdateCachedImage()
        else:
            LOGGER.exception('Map canvas could not be found in template %s',
                             template_path)
            raise MapComposerError

        # setup impact table
        self.render_population_table()
        self.render_nearby_table()
        self.render_landcover_table()

        impact_table = composition.getComposerItemById('table-impact')
        if impact_table is None:
            message = 'table-impact composer item could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        impacts_html = composition.getComposerHtmlByItem(impact_table)
        if impacts_html is None:
            message = 'Impacts QgsComposerHtml could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        impacts_html.setUrl(QUrl(self.population_html_path))

        # setup nearby table
        nearby_table = composition.getComposerItemById('table-nearby')
        if nearby_table is None:
            message = 'table-nearby composer item could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        nearby_html = composition.getComposerHtmlByItem(nearby_table)
        if nearby_html is None:
            message = 'Nearby QgsComposerHtml could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        nearby_html.setUrl(QUrl(self.nearby_html_path))

        # setup landcover table
        landcover_table = composition.getComposerItemById('table-landcover')
        if landcover_table is None:
            message = 'table-landcover composer item could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        landcover_html = composition.getComposerHtmlByItem(landcover_table)
        if landcover_html is None:
            message = 'Landcover QgsComposerHtml could not be found'
            LOGGER.exception(message)
            raise MapComposerError(message)
        landcover_html.setUrl(QUrl(self.landcover_html_path))

        # setup logos
        logos_id = ['logo-bnpb', 'logo-geologi']
        for logo_id in logos_id:
            logo_picture = composition.getComposerItemById(logo_id)
            if logo_picture is None:
                message = '%s composer item could not be found' % logo_id
                LOGGER.exception(message)
                raise MapComposerError(message)
            pic_path = os.path.basename(logo_picture.picturePath())
            pic_path = os.path.join('logo', pic_path)
            logo_picture.setPicturePath(self.ash_fixtures_dir(pic_path))

        # save a pdf
        composition.exportAsPDF(self.map_report_path)

        project_instance.write(QFileInfo(self.project_path))

        layer_registry.removeAllMapLayers()
        map_renderer.setDestinationCrs(default_crs)
        map_renderer.setProjectionsEnabled(False)
        LOGGER.info('Report generation completed.')
Exemplo n.º 8
0
def qgis_composer_renderer(impact_report, component):
    """Default Map Report Renderer using QGIS Composer.

    Render using qgis composer for a given impact_report data and component
    context.

    :param impact_report: ImpactReport contains data about the report that is
        going to be generated.
    :type impact_report: safe.report.impact_report.ImpactReport

    :param component: Contains the component metadata and context for
        rendering the output.
    :type component:
        safe.report.report_metadata.QgisComposerComponentsMetadata

    :return: Whatever type of output the component should be.

    .. versionadded:: 4.0
    """
    context = component.context
    """:type: safe.report.extractors.composer.QGISComposerContext"""
    qgis_composition_context = impact_report.qgis_composition_context
    inasafe_context = impact_report.inasafe_context

    # load composition object
    composition = QgsComposition(qgis_composition_context.map_settings)

    # load template
    main_template_folder = impact_report.metadata.template_folder

    # we do this condition in case custom template was found
    if component.template.startswith('../qgis-composer-templates/'):
        template_path = os.path.join(main_template_folder, component.template)
    else:
        template_path = component.template

    with open(template_path) as template_file:
        template_content = template_file.read()

    document = QtXml.QDomDocument()
    document.setContent(template_content)

    load_status = composition.loadFromTemplate(
        document, context.substitution_map)

    if not load_status:
        raise TemplateLoadingError(
            tr('Error loading template: %s') % template_path)

    # replace image path
    for img in context.image_elements:
        item_id = img.get('id')
        path = img.get('path')
        image = composition_item(composition, item_id, QgsComposerPicture)
        """:type: qgis.core.QgsComposerPicture"""
        if image and path:
            image.setPicturePath(path)

    # replace html frame
    for html_el in context.html_frame_elements:
        item_id = html_el.get('id')
        mode = html_el.get('mode')
        composer_item = composition.getComposerItemById(item_id)
        try:
            html_element = composition.getComposerHtmlByItem(composer_item)
        except:
            pass
        """:type: qgis.core.QgsComposerHtml"""
        if html_element:
            if mode == 'text':
                text = html_el.get('text')
                text = text if text else ''
                html_element.setContentMode(QgsComposerHtml.ManualHtml)
                html_element.setHtml(text)
                html_element.loadHtml()
            elif mode == 'url':
                url = html_el.get('url')
                html_element.setContentMode(QgsComposerHtml.Url)
                qurl = QUrl.fromLocalFile(url)
                html_element.setUrl(qurl)

    original_crs = impact_report.impact_function.impact.crs()
    destination_crs = qgis_composition_context.map_settings.destinationCrs()
    coord_transform = QgsCoordinateTransform(original_crs, destination_crs)

    # resize map extent
    for map_el in context.map_elements:
        item_id = map_el.get('id')
        split_count = map_el.get('grid_split_count')
        layers = map_el.get('layers')
        map_extent_option = map_el.get('extent')
        composer_map = composition_item(composition, item_id, QgsComposerMap)
        """:type: qgis.core.QgsComposerMap"""
        if composer_map:
            composer_map.setKeepLayerSet(True)
            layer_set = [l.id() for l in layers if isinstance(l, QgsMapLayer)]
            composer_map.setLayerSet(layer_set)
            if map_extent_option and isinstance(
                    map_extent_option, QgsRectangle):
                # use provided map extent
                extent = coord_transform.transform(map_extent_option)
                for l in [layer for layer in layers if
                          isinstance(layer, QgsMapLayer)]:
                    layer_extent = coord_transform.transform(l.extent())
                    if l.name() == map_overview['id']:
                        map_overview_extent = layer_extent
            else:
                # if map extent not provided, try to calculate extent
                # from list of given layers. Combine it so all layers were
                # shown properly
                map_overview_extent = None
                extent = QgsRectangle()
                extent.setMinimal()
                for l in [layer for layer in layers if
                          isinstance(layer, QgsMapLayer)]:
                    # combine extent if different layer is provided.
                    layer_extent = coord_transform.transform(l.extent())
                    extent.combineExtentWith(layer_extent)
                    if l.name() == map_overview['id']:
                        map_overview_extent = layer_extent

            width = extent.width()
            height = extent.height()
            longest_width = width if width > height else height
            half_length = longest_width / 2
            margin = half_length / 5
            center = extent.center()
            min_x = center.x() - half_length - margin
            max_x = center.x() + half_length + margin
            min_y = center.y() - half_length - margin
            max_y = center.y() + half_length + margin

            # noinspection PyCallingNonCallable
            square_extent = QgsRectangle(min_x, min_y, max_x, max_y)

            if component.key == 'population-infographic' and (
                    map_overview_extent):
                square_extent = map_overview_extent

            composer_map.zoomToExtent(square_extent)
            composer_map.renderModeUpdateCachedImage()

            actual_extent = composer_map.extent()

            # calculate intervals for grid
            x_interval = actual_extent.width() / split_count
            composer_map.grid().setIntervalX(x_interval)
            y_interval = actual_extent.height() / split_count
            composer_map.grid().setIntervalY(y_interval)

    # calculate legend element
    for leg_el in context.map_legends:
        item_id = leg_el.get('id')
        title = leg_el.get('title')
        layers = leg_el.get('layers')
        symbol_count = leg_el.get('symbol_count')
        column_count = leg_el.get('column_count')

        legend = composition_item(composition, item_id, QgsComposerLegend)
        """:type: qgis.core.QgsComposerLegend"""
        if legend:
            # set column count
            if column_count:
                legend.setColumnCount(column_count)
            elif symbol_count <= 7:
                legend.setColumnCount(1)
            else:
                legend.setColumnCount(symbol_count / 7 + 1)

            # set legend title
            if title is not None:
                legend.setTitle(title)

            # set legend
            root_group = legend.modelV2().rootGroup()
            for l in layers:
                # used for customizations
                tree_layer = root_group.addLayer(l)
                QgsLegendRenderer.setNodeLegendStyle(
                    tree_layer, QgsComposerLegendStyle.Hidden)
            legend.synchronizeWithModel()

    # process to output

    # in case output folder not specified
    if impact_report.output_folder is None:
        impact_report.output_folder = mkdtemp(dir=temp_dir())

    output_format = component.output_format
    component_output_path = impact_report.component_absolute_output_path(
        component.key)
    component_output = None

    doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT
    template_format = QgisComposerComponentsMetadata.OutputFormat.QPT
    if isinstance(output_format, list):
        component_output = []
        for i in range(len(output_format)):
            each_format = output_format[i]
            each_path = component_output_path[i]

            if each_format in doc_format:
                result_path = create_qgis_pdf_output(
                    impact_report,
                    each_path,
                    composition,
                    each_format,
                    component)
                component_output.append(result_path)
            elif each_format == template_format:
                result_path = create_qgis_template_output(
                    each_path, composition)
                component_output.append(result_path)
    elif isinstance(output_format, dict):
        component_output = {}
        for key, each_format in output_format.iteritems():
            each_path = component_output_path[key]

            if each_format in doc_format:
                result_path = create_qgis_pdf_output(
                    impact_report,
                    each_path,
                    composition,
                    each_format,
                    component)
                component_output[key] = result_path
            elif each_format == template_format:
                result_path = create_qgis_template_output(
                    each_path, composition)
                component_output[key] = result_path
    elif (output_format in
            QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT):
        component_output = None

        if output_format in doc_format:
            result_path = create_qgis_pdf_output(
                impact_report,
                component_output_path,
                composition,
                output_format,
                component)
            component_output = result_path
        elif output_format == template_format:
            result_path = create_qgis_template_output(
                component_output_path, composition)
            component_output = result_path

    component.output = component_output

    return component.output