示例#1
0
    def testIteratorToPdfs(self):
        project, layout = self.prepareIteratorLayout()
        atlas = layout.atlas()
        atlas.setFilenameExpression("'test_exportiteratortopdf_' || \"NAME_1\"")

        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        settings.dpi = 80
        settings.rasterizeWholeImage = False
        settings.forceVectorOutput = False

        result, error = QgsLayoutExporter.exportToPdfs(atlas, self.basetestpath + '/', settings)
        self.assertEqual(result, QgsLayoutExporter.Success, error)

        page1_path = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Basse-Normandie.pdf')
        rendered_page_1 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Basse-Normandie.png')
        pdfToPng(page1_path, rendered_page_1, dpi=80, page=1)
        self.assertTrue(self.checkImage('iteratortopdf1', 'iteratortoimage1', rendered_page_1, size_tolerance=2))
        page2_path = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Bretagne.pdf')
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Bretagne.png')
        pdfToPng(page2_path, rendered_page_2, dpi=80, page=1)
        self.assertTrue(self.checkImage('iteratortopdf2', 'iteratortoimage2', rendered_page_2, size_tolerance=2))
        page3_path = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Centre.pdf')
        self.assertTrue(os.path.exists(page3_path))
        page4_path = os.path.join(self.basetestpath, 'test_exportiteratortopdf_Pays de la Loire.pdf')
        self.assertTrue(os.path.exists(page4_path))
示例#2
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # get the parameter values
        base_project = self.parameterAsFile(parameters, self.BASE_PROJECT, context)
        layout_name = self.parameterAsString(parameters, self.LAYOUT_NAME, context)
        output = self.parameterAsFile(parameters, self.OUTPUT, context)

        # instantiation of the project
        project_instance = QgsProject()
        project_instance.read(base_project)

        # actual export of the PDF
        if layout_name:
            layout = project_instance.layoutManager().layoutByName(layout_name)
        else:
            layout = project_instance.layoutManager().layouts()[0]
        assert(layout is not None, "No layout found")
        export = QgsLayoutExporter(layout)
        export.exportToPdf(output, QgsLayoutExporter.PdfExportSettings())

        # debug
        # project_instance.write(output_file+"debug.qgs")

        # done !!
        return {}
示例#3
0
    def __export(self):
        settings = QSettings()
        format = self.dialogui.comboBox_fileformat.itemData(self.dialogui.comboBox_fileformat.currentIndex())
        filepath = QFileDialog.getSaveFileName(
            self.iface.mainWindow(),
            self.tr("Export Layout"),
            settings.value("/instantprint/lastfile", ""),
            format
        )
        if not all(filepath):
            return

        # Ensure output filename has correct extension
        filename = os.path.splitext(filepath[0])[0] + "." + self.dialogui.comboBox_fileformat.currentText().lower()
        settings.setValue("/instantprint/lastfile", filepath[0])

        if self.populateCompositionFz:
            self.populateCompositionFz(self.layoutView.composition())

        success = False
        layout_name = self.dialogui.comboBox_layouts.currentText()
        layout_item = self.projectLayoutManager.layoutByName(layout_name)
        exporter = QgsLayoutExporter(layout_item)
        if filename[-3:].lower() == u"pdf":
            success = exporter.exportToPdf(filepath[0], QgsLayoutExporter.PdfExportSettings())
        else:
            success = exporter.exportToImage(filepath[0], QgsLayoutExporter.ImageExportSettings())
        if success != 0:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Export Failed"), self.tr("Failed to export the layout."))
示例#4
0
    def testIteratorToPdf(self):
        project, layout = self.prepareIteratorLayout()
        atlas = layout.atlas()

        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        settings.dpi = 80
        settings.rasterizeWholeImage = False
        settings.forceVectorOutput = False

        pdf_path = os.path.join(self.basetestpath, 'test_exportiteratortopdf_single.pdf')
        result, error = QgsLayoutExporter.exportToPdf(atlas, pdf_path, settings)
        self.assertEqual(result, QgsLayoutExporter.Success, error)

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_single1.png')
        pdfToPng(pdf_path, rendered_page_1, dpi=80, page=1)
        self.assertTrue(self.checkImage('iteratortopdfsingle1', 'iteratortoimage1', rendered_page_1, size_tolerance=2))

        rendered_page_2 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_single2.png')
        pdfToPng(pdf_path, rendered_page_2, dpi=80, page=2)
        self.assertTrue(self.checkImage('iteratortopdfsingle2', 'iteratortoimage2', rendered_page_2, size_tolerance=2))

        rendered_page_3 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_single3.png')
        pdfToPng(pdf_path, rendered_page_3, dpi=80, page=3)
        self.assertTrue(os.path.exists(rendered_page_3))
        rendered_page_4 = os.path.join(self.basetestpath, 'test_exportiteratortopdf_single4.png')
        pdfToPng(pdf_path, rendered_page_4, dpi=80, page=4)
        self.assertTrue(os.path.exists(rendered_page_4))
示例#5
0
 def exportPdf(self, outputPath, feedback=None):
     exporter = QgsLayoutExporter(self.layout)
     result, error = exporter.exportToPdfs(
         self.layout.atlas(),
         outputPath,
         settings=QgsLayoutExporter.PdfExportSettings(),
         feedback=feedback)
     return result, error
示例#6
0
    def imprimirPlanol(self, x, y, escala, rotacion, projectePlanol,
                       templateFile, fitxerSortida, tipusSortida):
        self.project.read(projectePlanol)
        template = QFile(templateFile)

        # Creem un document amb la plantilla
        doc = QDomDocument()
        doc.setContent(template, False)

        # Aquest layout no té res a veure amb els layaouts de PyQt.
        # Es una plantilla per el projecte. You must believe it.
        layout = QgsLayout(self.project)
        context = QgsReadWriteContext()
        [items, ok] = layout.loadFromTemplate(doc, context)

        if ok:
            refMap = layout.referenceMap()

            rect = refMap.extent()
            vector = QgsVector(x - rect.center().x(), y - rect.center().y())
            rect += vector
            refMap.setExtent(rect)
            refMap.setScale(escala)
            refMap.setMapRotation(rotacion)

            #Depenent del tipus de sortida...

            exporter = QgsLayoutExporter(layout)
            image_settings = exporter.ImageExportSettings()
            image_settings.dpi = 60

            # result = exporter.exportToImage('d:/dropbox/qpic/preview.png',  image_settings)
            # imatge = QPixmap('d:/dropbox/qpic/preview.png')
            t = time.localtime()

            timestamp = time.strftime('%b-%d-%Y_%H%M%S', t)

            if tipusSortida == 'PDF':
                settings = QgsLayoutExporter.PdfExportSettings()
                settings.dpi = 60
                settings.exportMetadata = False

                fitxerSortida = 'd:/dropbox/qpic/sortida_' + timestamp + '.PDF'
                result = exporter.exportToPdf(fitxerSortida, settings)

                print(fitxerSortida)

            if tipusSortida == 'PNG':
                settings = QgsLayoutExporter.ImageExportSettings()
                settings.dpi = 60

                # fitxerSortida='sortida_'+timestamp+'.PNG'
                fitxerSortida = projectePlanol[0:-4] + '.png'
                result = exporter.exportToImage(fitxerSortida, settings)
示例#7
0
    def exportItemAsPdf(self, comptecommunal, suffix=None):
        """
        Export one PDF file using the template composer
        filled with appropriate data
        for one "compte communal"
        """
        temppath = None
        # print("export pour le cc %s" % comptecommunal)
        # Set configuration
        self.setComposerTemplates(comptecommunal)

        # Create the composition
        self.createComposition()

        if self.currentComposition:
            # Populate composition for all pages
            # print("numpage %s" % self.numPages)
            for i in range(self.numPages):
                j = i + 1
                self.addPageContent(j)

            # Add map in first page if export parcelle
            if self.etype == 'parcelle' and self.print_parcelle_page:
                self.addParcelleMap()

            # Create the pdf output path
            from time import time
            temp = "releve_%s_%s_%s.pdf" % (
                self.etype,
                comptecommunal.replace('+', 'plus').replace(
                    '*', 'fois'),  # .replace('¤', 'plus'),
                int(time() * 100))
            # Create regexp to remove all non ascii chars
            import re
            r = re.compile(r"[^ -~]")
            temp = r.sub('', temp)
            # print temp
            temppath = os.path.join(self.targetDir, temp)
            temppath = os.path.normpath(temppath)
            # print("export temppath %s" % temppath)

            # Export as pdf
            exportersettings = QgsLayoutExporter.PdfExportSettings()
            exportersettings.dpi = 300
            exportersettings.forceVectorOutput = True
            exportersettings.rasterizeWholeImage = False
            exporter = QgsLayoutExporter(self.currentComposition)
            exporter.exportToPdf(temppath, exportersettings)

            # Remove redline layer
            if self.redlineLayer:
                self.mProject.removeMapLayer(self.redlineLayer.id())

        return temppath
示例#8
0
    def export_view(self):
        """
        Export current view to PDF
        """
        # Load template from file
        s = QSettings()
        f = s.value("cadastre/composerTemplateFile", '', type=str)
        if not os.path.exists(f):
            f = os.path.join(str(Path(__file__).resolve().parent), 'composers',
                             'paysage_a4.qpt')
            s.setValue("cadastre/composerTemplateFile", f)

        QApplication.setOverrideCursor(Qt.WaitCursor)
        template_content = None
        with open(f, 'rt', encoding="utf-8") as ff:
            template_content = ff.read()
        if not template_content:
            return
        d = QDomDocument()
        d.setContent(template_content)

        c = QgsPrintLayout(QgsProject.instance())
        c.loadFromTemplate(d, QgsReadWriteContext())

        # Set scale and extent
        cm = c.referenceMap()
        canvas = self.iface.mapCanvas()
        extent = canvas.extent()
        scale = canvas.scale()
        if extent:
            cm.zoomToExtent(extent)
        if scale:
            cm.setScale(scale)

        # Export
        tempDir = s.value("cadastre/tempDir",
                          '%s' % tempfile.gettempdir(),
                          type=str)
        self.targetDir = tempfile.mkdtemp('', 'cad_export_', tempDir)
        temp = int(time() * 100)
        temppath = os.path.join(tempDir, 'export_cadastre_%s.pdf' % temp)

        exporter = QgsLayoutExporter(c)
        exportersettings = QgsLayoutExporter.PdfExportSettings()
        exportersettings.dpi = 300
        exportersettings.forceVectorOutput = True
        exportersettings.rasterizeWholeImage = False  # rasterizeWholeImage = false
        exporter.exportToPdf(temppath, exportersettings)

        QApplication.restoreOverrideCursor()

        if os.path.exists(temppath):
            CadastreCommon.openFile(temppath)
示例#9
0
    def testExportToPdf(self):
        l = QgsLayout(QgsProject.instance())
        l.initializeDefaults()

        # add a second page
        page2 = QgsLayoutItemPage(l)
        page2.setPageSize('A5')
        l.pageCollection().addPage(page2)

        # add some items
        item1 = QgsLayoutItemShape(l)
        item1.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.green)
        fill.setStrokeStyle(Qt.NoPen)
        item1.setSymbol(fill_symbol)
        l.addItem(item1)

        item2 = QgsLayoutItemShape(l)
        item2.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        item2.attemptMove(QgsLayoutPoint(10, 20), page=1)
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.cyan)
        fill.setStrokeStyle(Qt.NoPen)
        item2.setSymbol(fill_symbol)
        l.addItem(item2)

        exporter = QgsLayoutExporter(l)
        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        settings.dpi = 80
        settings.rasterizeWholeImage = False
        settings.forceVectorOutput = False

        pdf_file_path = os.path.join(self.basetestpath, 'test_exporttopdfdpi.pdf')
        self.assertEqual(exporter.exportToPdf(pdf_file_path, settings), QgsLayoutExporter.Success)
        self.assertTrue(os.path.exists(pdf_file_path))

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exporttopdfdpi.png')
        dpi = 80
        pdfToPng(pdf_file_path, rendered_page_1, dpi=dpi, page=1)
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exporttopdfdpi2.png')
        pdfToPng(pdf_file_path, rendered_page_2, dpi=dpi, page=2)

        self.assertTrue(self.checkImage('exporttopdfdpi_page1', 'exporttopdfdpi_page1', rendered_page_1, size_tolerance=1))
        self.assertTrue(self.checkImage('exporttopdfdpi_page2', 'exporttopdfdpi_page2', rendered_page_2, size_tolerance=1))
示例#10
0
    def test_print_layout(self):
        export_file = os.path.join(self.outdir, 'export.pdf')

        project = QgsProject.instance()
        project.read(
            os.path.join(os.path.dirname(os.path.realpath(__file__)),
                         'test_data/simple_polygons.qgz'))

        layout_manager = project.layoutManager()
        layout = layout_manager.layouts()[0]
        exporter = QgsLayoutExporter(layout)

        exporter.exportToPdf(export_file, exporter.PdfExportSettings())

        self.assertTrue(os.path.isfile(export_file))
        self.assertTrue(os.path.getsize(export_file) > 0)
示例#11
0
    def export_pdf(self, count_id, file_name):

        current_dir = os.path.dirname(os.path.abspath(__file__))
        qpt_file_path = os.path.join(current_dir, os.pardir, 'qml', 'plan.qpt')
        self.layout = PlanCreator.create_layout_from_template(qpt_file_path)

        self.set_fields(count_id)

        # self.layers.select_and_zoom_on_section_of_count(count_id)
        canvas = iface.mapCanvas()

        map_item = self.layout.itemById('map')
        map_item.setExtent(canvas.extent())

        exporter = QgsLayoutExporter(self.layout)

        exporter.exportToPdf(file_name, exporter.PdfExportSettings())
示例#12
0
def export_map(project_path, layout_name, pdf_path, thumbnail_path=None):
    # Open project
    project_instance = QgsProject.instance()
    project_instance.setFileName(project_path)
    project_instance.read()

    # Open layout
    manager = QgsProject.instance().layoutManager()
    layout = manager.layoutByName(layout_name)

    # Export PDF
    exporter = QgsLayoutExporter(layout)
    exporter.exportToPdf(pdf_path, QgsLayoutExporter.PdfExportSettings())

    if thumbnail_path:
        # Generate a thumbnail image
        image = exporter.renderPageToImage(0, dpi=50)
        image.save(thumbnail_path)
    def export_pdf(composer_name, composer):
        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        export_path = os.path.join(
                tempfile.gettempdir(),
                '%s_%s.pdf' % (composer_name, uuid4())
              )
        result, error = QgsLayoutExporter.exportToPdf(
            composer,
            export_path,
            settings)

        if (result != QgsLayoutExporter.Success
                or not os.path.isfile(export_path)):
            QgsMessageLog.logMessage("atlasprint: export not generated {} "
                                     "Error: {}".format(export_path, error),
                                     'atlasprint', Qgis.Critical)
            return None

        QgsMessageLog.logMessage("atlasprint: path generated %s" % export_path, 'atlasprint', Qgis.Success)
        return export_path
示例#14
0
 def exportMap(self, composition, debugMode):
     basename = self.mi + '_' + self.inom if self.mi else self.inom
     exporter = QgsLayoutExporter(composition)
     exportStatus = 0
     if not debugMode:
         pdfFilePath = os.path.join(self.exportFolder, f'{basename}.pdf')
         pdfExporterSettings = QgsLayoutExporter.PdfExportSettings()
         pdfExporterSettings.rasterizeWholeImage = True
         pdfExporterSettings.simplifyGeometries = False
         pdfExporterSettings.appendGeoreference = True
         pdfExporterSettings.exportMetadata = False
         pdfExporterSettings.dpi = 400
         exportStatus += exporter.exportToPdf(pdfFilePath, pdfExporterSettings)
     if self.dlgCfg.exportTiff:
         tiffFilePath = os.path.join(self.exportFolder, f'{basename}.tif')
         tiffExporterSettings = QgsLayoutExporter.ImageExportSettings()
         tiffExporterSettings.dpi = 400
         statusTiff = exporter.exportToImage(tiffFilePath, tiffExporterSettings)
         exportStatus += statusTiff
     del exporter
     return not bool(exportStatus)
示例#15
0
    def overrideExportSettings(self, layout, extension):
        """Because GUI settings are not exposed in Python, we need to find and catch user selection
           See discussion at http://osgeo-org.1560.x6.nabble.com/Programmatically-export-layout-with-georeferenced-file-td5365462.html"""

        if extension == '.pdf':
            exportSettings = QgsLayoutExporter.PdfExportSettings()
            if layout.customProperty(
                    'dpi') and layout.customProperty('dpi') != -1:
                exportSettings.dpi = layout.customProperty('dpi')
            if layout.customProperty('forceVector') == True:
                exportSettings.forceVectorOutput = True
            if layout.customProperty('rasterize') == True:
                exportSettings.rasterizeWholeImage = True
        elif extension == '.svg':
            exportSettings = QgsLayoutExporter.SvgExportSettings()
            if layout.customProperty(
                    'dpi') and layout.customProperty('dpi') != -1:
                exportSettings.dpi = layout.customProperty('dpi')
            if layout.customProperty('forceVector') == True:
                exportSettings.forceVectorOutput = True
            if layout.customProperty('svgIncludeMetadata') == True:
                exportSettings.exportMetadata = True
            if layout.customProperty('svgGroupLayers') == True:
                exportSettings.exportAsLayers = True
        else:
            exportSettings = QgsLayoutExporter.ImageExportSettings()
            if layout.customProperty('exportWorldFile') == True:
                exportSettings.generateWorldFile = True
            if layout.customProperty('') == True:
                exportSettings.exportMetadata = True
            if layout.customProperty(
                    'dpi') and layout.customProperty('dpi') != -1:
                exportSettings.dpi = layout.customProperty('dpi')
            # if layout.customProperty('atlasRasterFormat') == True : exportSettings.xxxx = True
            # if layout.customProperty('imageAntialias') == True : exportSettings.xxxx = True

        return exportSettings
示例#16
0
def print_layout(project,
                 layout_name,
                 feature_filter: str = None,
                 scales=None,
                 scale=None,
                 **kwargs):
    """Generate a PDF for an atlas or a report.

    :param project: The QGIS project.
    :type project: QgsProject

    :param layout_name: Name of the layout of the atlas or report.
    :type layout_name: basestring

    :param feature_filter: QGIS Expression to use to select the feature.
    It can return many features, a multiple pages PDF will be returned.
    This is required to print atlas, not report
    :type feature_filter: basestring

    :param scale: A scale to force in the atlas context. Default to None.
    :type scale: int

    :param scales: A list of predefined list of scales to force in the atlas context.
    Default to None.
    :type scales: list

    :return: Path to the PDF.
    :rtype: basestring
    """
    canvas = QgsMapCanvas()
    bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas)
    bridge.setCanvasLayers()
    manager = project.layoutManager()
    master_layout = manager.layoutByName(layout_name)
    settings = QgsLayoutExporter.PdfExportSettings()

    atlas = None
    atlas_layout = None
    report_layout = None

    logger = Logger()

    if not master_layout:
        raise AtlasPrintException('Layout `{}` not found'.format(layout_name))

    if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout:
        for _print_layout in manager.printLayouts():
            if _print_layout.name() == layout_name:
                atlas_layout = _print_layout
                break

        atlas = atlas_layout.atlas()
        if not atlas.enabled():
            raise AtlasPrintException('The layout is not enabled for an atlas')

        layer = atlas.coverageLayer()

        if feature_filter is None:
            raise AtlasPrintException(
                'EXP_FILTER is mandatory to print an atlas layout')

        feature_filter = optimize_expression(layer, feature_filter)

        expression = QgsExpression(feature_filter)
        if expression.hasParserError():
            raise AtlasPrintException(
                'Expression is invalid, parser error: {}'.format(
                    expression.parserErrorString()))

        context = QgsExpressionContext()
        context.appendScope(QgsExpressionContextUtils.globalScope())
        context.appendScope(QgsExpressionContextUtils.projectScope(project))
        context.appendScope(
            QgsExpressionContextUtils.layoutScope(atlas_layout))
        context.appendScope(QgsExpressionContextUtils.atlasScope(atlas))
        context.appendScope(QgsExpressionContextUtils.layerScope(layer))
        expression.prepare(context)
        if expression.hasEvalError():
            raise AtlasPrintException(
                'Expression is invalid, eval error: {}'.format(
                    expression.evalErrorString()))

        atlas.setFilterFeatures(True)
        atlas.setFilterExpression(feature_filter)

        if scale:
            atlas_layout.referenceMap().setAtlasScalingMode(
                QgsLayoutItemMap.Fixed)
            atlas_layout.referenceMap().setScale(scale)

        if scales:
            atlas_layout.referenceMap().setAtlasScalingMode(
                QgsLayoutItemMap.Predefined)
            if Qgis.QGIS_VERSION_INT >= 30900:
                settings.predefinedMapScales = scales
            else:
                atlas_layout.reportContext().setPredefinedScales(scales)

        if not scales and atlas_layout.referenceMap().atlasScalingMode(
        ) == QgsLayoutItemMap.Predefined:
            if Qgis.QGIS_VERSION_INT >= 30900:
                use_project = project.useProjectScales()
                map_scales = project.mapScales()
            else:
                map_scales = project_scales(project)
                use_project = len(map_scales) == 0

            if not use_project or len(map_scales) == 0:
                logger.info(
                    'Map scales not found in project, fetching predefined map scales in global config'
                )
                map_scales = global_scales()

            if Qgis.QGIS_VERSION_INT >= 30900:
                settings.predefinedMapScales = map_scales
            else:
                atlas_layout.reportContext().setPredefinedScales(map_scales)

    elif master_layout.layoutType() == QgsMasterLayoutInterface.Report:
        report_layout = master_layout

    else:
        raise AtlasPrintException('The layout is not supported by the plugin')

    for key, value in kwargs.items():
        found = False
        if atlas_layout:
            item = atlas_layout.itemById(key.lower())
            if isinstance(item, QgsLayoutItemLabel):
                item.setText(value)
                found = True
        logger.info(
            'Additional parameters: {} found in layout {}, value {}'.format(
                key, found, value))

    export_path = os.path.join(tempfile.gettempdir(),
                               '{}_{}.pdf'.format(layout_name, uuid4()))
    result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout,
                                                  export_path, settings)

    if result != QgsLayoutExporter.Success and not os.path.isfile(export_path):
        raise Exception('export not generated {} ({})'.format(
            export_path, error))

    return export_path
示例#17
0
def create_qgis_pdf_output(
        impact_report,
        output_path,
        layout,
        file_format,
        metadata):
    """Produce PDF output using QgsLayout.

    :param output_path: The output path.
    :type output_path: str

    :param layout: QGIS Layout object.
    :type layout: qgis.core.QgsPrintLayout

    :param qgis_composition_context: QGIS Composition context used by renderer.
    :type qgis_composition_context: safe.report.impact_report.
        QgsLayoutContext

    :param file_format: file format of map output, PDF or PNG.
    :type file_format: 'pdf', 'png'

    :param metadata: The component metadata.
    :type metadata: QgisComposerComponentsMetadata

    :return: Generated output path.
    :rtype: str
    """
    # make sure directory is created
    dirname = os.path.dirname(output_path)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    qgis_composition_context = impact_report.qgis_composition_context
    aggregation_summary_layer = (
        impact_report.impact_function.aggregation_summary)

    # process atlas generation
    print_atlas = setting('print_atlas_report', False, bool)
    if layout.atlas().enabled() and (
            print_atlas and aggregation_summary_layer):
        output_path = atlas_renderer(
            layout, aggregation_summary_layer, output_path, file_format)
    # for QGIS layout only pdf and png output are available
    elif file_format == QgisComposerComponentsMetadata.OutputFormat.PDF:
        try:
            exporter = QgsLayoutExporter(layout)
            settings = QgsLayoutExporter.PdfExportSettings()
            settings.dpi = metadata.page_dpi
            settings.rasterizeWholeImage = \
                qgis_composition_context.save_as_raster
            # settings.forceVectorOutput = False
            # settings.exportMetadata = True

            # TODO: ABP: check that page size is set on the pages
            res = exporter.exportToPdf(output_path, settings)
            if res != QgsLayoutExporter.Success:
                LOGGER.error('Error exporting to {}'.format(
                    exporter.errorFile()))
                return None
        except Exception as exc:
            LOGGER.error(exc)
            return None
    elif file_format == QgisComposerComponentsMetadata.OutputFormat.PNG:
        # TODO: implement PNG generation
        raise Exception('Not yet supported')
    return output_path
示例#18
0
 def saveAsPDF(self):
     fullpath, format = QFileDialog.getSaveFileName(self, '存储为pdf', '', '*.pdf')
     print(fullpath)
     exporter = QgsLayoutExporter(self.layout)
     exporter.exportToPdf(fullpath, QgsLayoutExporter.PdfExportSettings())
示例#19
0
def print_atlas(project, layout_name, feature_filter, scales=None, scale=None):
    """Generate an atlas.

    :param project: The project to render as atlas.
    :type project: QgsProject

    :param layout_name: Name of the layout.
    :type layout_name: basestring

    :param feature_filter: QGIS Expression to use to select the feature.
    It can return many features, a multiple pages PDF will be returned.
    :type feature_filter: basestring

    :param scale: A scale to force in the atlas context. Default to None.
    :type scale: int

    :param scales: A list of predefined list of scales to force in the atlas context.
    Default to None.
    :type scales: list

    :return: Path to the PDF.
    :rtype: basestring
    """
    canvas = QgsMapCanvas()
    bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas)
    bridge.setCanvasLayers()
    manager = project.layoutManager()
    master_layout = manager.layoutByName(layout_name)

    if not master_layout:
        raise AtlasPrintException('Layout not found')

    if master_layout.layoutType() != QgsMasterLayoutInterface.PrintLayout:
        raise AtlasPrintException('The layout is not a print layout')

    for l in manager.printLayouts():
        if l.name() == layout_name:
            layout = l
            break
    else:
        raise AtlasPrintException('The layout is not found')

    atlas = layout.atlas()

    if not atlas.enabled():
        raise AtlasPrintException('The layout is not enabled for an atlas')

    settings = QgsLayoutExporter.PdfExportSettings()

    if scale:
        layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Fixed)
        layout.referenceMap().setScale(scale)

    if scales:
        layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Predefined)
        if Qgis.QGIS_VERSION_INT >= 30900:
            settings.predefinedMapScales = scales
        else:
            layout.reportContext().setPredefinedScales(scales)

    layer = atlas.coverageLayer()
    feature_filter = optimize_expression(layer, feature_filter)

    expression = QgsExpression(feature_filter)
    if expression.hasParserError():
        raise AtlasPrintException(
            'Expression is invalid, parser error: {}'.format(
                expression.parserErrorString()))

    context = QgsExpressionContext()
    context.appendScope(QgsExpressionContextUtils.globalScope())
    context.appendScope(QgsExpressionContextUtils.projectScope(project))
    context.appendScope(QgsExpressionContextUtils.layoutScope(layout))
    context.appendScope(QgsExpressionContextUtils.atlasScope(atlas))
    context.appendScope(QgsExpressionContextUtils.layerScope(layer))

    expression.prepare(context)
    if expression.hasEvalError():
        raise AtlasPrintException(
            'Expression is invalid, eval error: {}'.format(
                expression.evalErrorString()))

    atlas.setFilterFeatures(True)
    atlas.setFilterExpression(feature_filter)

    if not scales and layout.referenceMap().atlasScalingMode(
    ) == QgsLayoutItemMap.Predefined:
        if Qgis.QGIS_VERSION_INT >= 30900:
            use_project = project.useProjectScales()
            map_scales = project.mapScales()
        else:
            map_scales = project_scales(project)
            use_project = len(map_scales) == 0

        if not use_project or len(map_scales) == 0:
            QgsMessageLog.logMessage(
                'Map scales not found in project, fetching predefined map scales in global config',
                'atlasprint', Qgis.Info)
            map_scales = global_scales()

        if Qgis.QGIS_VERSION_INT >= 30900:
            settings.predefinedMapScales = map_scales
        else:
            layout.reportContext().setPredefinedScales(map_scales)

    export_path = os.path.join(tempfile.gettempdir(),
                               '{}_{}.pdf'.format(layout_name, uuid4()))
    exporter = QgsLayoutExporter(layout)
    result = exporter.exportToPdf(atlas, export_path, settings)

    if result[0] != QgsLayoutExporter.Success and not os.path.isfile(
            export_path):
        raise Exception('export not generated {}'.format(export_path))

    return export_path
示例#20
0
    def print_atlas(project_path, composer_name, predefined_scales, feature_filter, page_name_expression=None):
        if not feature_filter:
            QgsMessageLog.logMessage("atlasprint: NO feature_filter provided !", 'atlasprint', Qgis.Critical)
            return None

        # Get composer from project
        # in QGIS 2, we can't get composers without iface
        # so we reading project xml and extract composer
        # TODO Since QGIS 3.0, we should be able to use project layoutManager()
        # noinspection PyPep8Naming
        from xml.etree import ElementTree as ET
        composer_xml = None
        with open(project_path, 'r') as f:
            tree = ET.parse(f)
            for elem in tree.findall('.//Composer[@title="%s"]' % composer_name):
                composer_xml = ET.tostring(
                    elem,
                    encoding='utf8',
                    method='xml'
                )
            if not composer_xml:
                for elem in tree.findall('.//Layout[@name="%s"]' % composer_name):
                    composer_xml = ET.tostring(
                        elem,
                        encoding='utf8',
                        method='xml'
                    )

        if not composer_xml:
            QgsMessageLog.logMessage("atlasprint: Composer XML not parsed !", 'atlasprint', Qgis.Critical)
            return None

        document = QDomDocument()
        document.setContent(composer_xml)

        # Get canvas, map setting & instantiate composition
        canvas = QgsMapCanvas()
        project = QgsProject()
        project.read(project_path)
        bridge = QgsLayerTreeMapCanvasBridge(
            project.layerTreeRoot(),
            canvas
        )
        bridge.setCanvasLayers()

        layout = QgsPrintLayout(project)

        # Load content from XML
        layout.loadFromTemplate(
            document,
            QgsReadWriteContext(),
        )

        atlas = layout.atlas()
        atlas.setEnabled(True)

        atlas_map = layout.referenceMap()
        atlas_map.setAtlasDriven(True)
        atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Predefined)

        layout.reportContext().setPredefinedScales(predefined_scales)

        if page_name_expression:
            atlas.setPageNameExpression(page_name_expression)

        # Filter feature here to avoid QGIS looping through every feature when doing : composition.setAtlasMode(QgsComposition.ExportAtlas)
        coverage_layer = atlas.coverageLayer()

        # Filter by FID as QGIS cannot compile expressions with $id or other $ vars
        # which leads to bad performance for big dataset
        use_fid = None
        if '$id' in feature_filter:
            import re
            ids = list(map(int, re.findall(r'\d+', feature_filter)))
            if len(ids) > 0:
                use_fid = ids[0]
        if use_fid:
            qReq = QgsFeatureRequest().setFilterFid(use_fid)
        else:
            qReq = QgsFeatureRequest().setFilterExpression(feature_filter)

        # Change feature_filter in order to improve performance
        pks = coverage_layer.dataProvider().pkAttributeIndexes()
        if use_fid and len(pks) == 1:
            pk = coverage_layer.dataProvider().fields()[pks[0]].name()
            feature_filter = '"%s" IN (%s)' % (pk, use_fid)
            QgsMessageLog.logMessage("atlasprint: feature_filter changed into: %s" % feature_filter, 'atlasprint', Qgis.Info)
            qReq = QgsFeatureRequest().setFilterExpression(feature_filter)
        atlas.setFilterFeatures(True)
        atlas.setFilterExpression(feature_filter)
        uid = uuid4()
        i = 0  # We use a single page for now.

        atlas.beginRender()
        atlas.seekTo(i)

        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        export_path = os.path.join(
                tempfile.gettempdir(),
                '%s_%s.pdf' % (atlas.nameForPage(i), uid)
        )
        exporter = QgsLayoutExporter(layout)
        result = exporter.exportToPdf(export_path, settings)

        atlas.endRender()
        if result != QgsLayoutExporter.Success:
            QgsMessageLog.logMessage("atlasprint: export not generated %s" % export_path, 'atlasprint', Qgis.Critical)
            return None

        if not os.path.isfile(export_path):
            QgsMessageLog.logMessage("atlasprint: export not generated %s" % export_path, 'atlasprint', Qgis.Critical)
            return None

        QgsMessageLog.logMessage("atlasprint: path generated %s" % export_path, 'atlasprint', Qgis.Success)
        return export_path
示例#21
0
    def exportLayout(self, cView, folder, title):
        """Function that sets how to export files."""
        currProject = QgsProject.instance()
        printer = QPrinter()
        painter = QPainter()
        exporter = QgsLayoutExporter(cView)
        # Set page progressbar maximum value
        self.dlg.pageBar.setValue(0)
        self.dlg.pageBar.setMaximum(11)
        # Do the export process
        if not os.path.exists(os.path.join(folder, title)):
            os.makedirs(os.path.join(folder, title))
        exporter.exportToPdf(os.path.join(folder, title, title + '.pdf'),
                             QgsLayoutExporter.PdfExportSettings())
        exporter.exportToImage(os.path.join(folder, title, title + '.jpg'),
                               QgsLayoutExporter.ImageExportSettings())

        # read CSV file & load into list
        with open(os.path.join(self.plugin_dir, "input/metadata_items.csv"),
                  'r') as metadata_file:
            reader = csv.reader(metadata_file, delimiter=',')
            metadata_list = list(reader)

        settings = ET.Element("mapdoc")
        mapdata = ET.SubElement(settings, "mapdata")

        # output fixed QGIS variables to XML
        """ACTION?"""

        # output project variables listed in CSV to XML
        for x in metadata_list:
            ma_variable = str(x[0])
            elem_name = str(x[1])
            elem_name = elem_name.strip()
            ma_level = str(x[2])
            ma_level = ma_level.strip()
            if (ma_level == 'project') and (elem_name != 'no_xml'):
                elem_value = str(
                    QgsExpressionContextUtils.projectScope(
                        currProject).variable(ma_variable))
                ET.SubElement(mapdata, elem_name).text = elem_value
                if elem_value.strip():
                    QgsMessageLog.logMessage(
                        ma_variable + ' exported as ' + elem_value,
                        'MapExport', Qgis.Info)
                else:
                    msgBar.pushMessage(
                        'Warning: missing value for ' + ma_variable, 5)
                    QgsMessageLog.logMessage(
                        'Warning: missing value for ' + ma_variable,
                        'MapExport')

        themes = ET.SubElement(mapdata, "themes")
        for theme in self.dlg.themeBox.findChildren(QCheckBox):
            if theme.isChecked():
                ET.SubElement(themes, 'theme').text = theme.text()

        for layout in QgsProject.instance().layoutManager().printLayouts():
            # Set values of internal variables

            if layout.name() == self.dlg.layoutSelect.currentText():
                date_now = datetime.date.today().strftime("%B %d, %Y")
                ET.SubElement(mapdata, 'lastUpdated').text = date_now
                title = layout.name()
                ET.SubElement(mapdata,
                              'jpgfilename').text = layout.name() + '.jpg'
                ET.SubElement(mapdata,
                              'pdffilename').text = layout.name() + '.pdf'
                # Action: Which map is selected by this?
                item = layout.referenceMap()
                #                item = layout.itemById('main')

                # Get the attr by name and call
                map_scale = getattr(item, 'scale')()

                ET.SubElement(mapdata, 'scale').text = str(round(map_scale))
                map_extent = item.extent()
                map_xmin = map_extent.xMinimum()
                map_xmax = map_extent.xMaximum()
                map_ymin = map_extent.yMinimum()
                map_ymax = map_extent.yMaximum()
                QgsMessageLog.logMessage('Scale ' + str(map_xmin), 'MapExport',
                                         Qgis.Info)

                ET.SubElement(mapdata, 'xmin').text = str(round(map_xmin))
                ET.SubElement(mapdata, 'xmax').text = str(round(map_xmax))
                ET.SubElement(mapdata, 'ymin').text = str(round(map_ymin))
                ET.SubElement(mapdata, 'ymax').text = str(round(map_ymax))

                for x in metadata_list:
                    ma_variable = str(x[0])
                    elem_name = str(x[1])
                    elem_name = elem_name.strip()
                    ma_level = str(x[2])
                    ma_level = ma_level.strip()
                    if ma_level == 'layout':
                        elem_value = str(
                            QgsExpressionContextUtils.layoutScope(
                                layout).variable(ma_variable))
                        ET.SubElement(mapdata, elem_name).text = elem_value
                        if elem_value.strip():
                            QgsMessageLog.logMessage(
                                ma_variable + ' exported as ' + elem_value,
                                'MapExport', Qgis.Info)
                        else:
                            msgBar.pushMessage(
                                'Warning: missing value for ' + ma_variable, 5)
                            QgsMessageLog.logMessage(
                                'Warning: missing value for ' + ma_variable,
                                'MapExport')
                tree = ET.ElementTree(settings)
                tree.write(os.path.join(folder, title, title + '.xml'))

        # Set the location and the file name of the zip
        zippath = os.path.join(folder, title)
        zf = zipfile.ZipFile(
            os.path.abspath(folder) + os.sep + title + ".zip", "w")
        for dirnames, folders, files in os.walk(os.path.join(folder, title)):
            #  for root, dirs, files in os.walk(folder):
            for file in files:
                zf.write(os.path.join(os.path.join(folder, title), file), file)
        zf.close()
        self.pageProcessed()
示例#22
0
def atlas_renderer(layout, coverage_layer, output_path, file_format):
    """Extract composition using atlas generation.

    :param layout: QGIS Print Layout object used for producing the report.
    :type layout: qgis.core.QgsPrintLayout

    :param coverage_layer: Coverage Layer used for atlas map.
    :type coverage_layer: QgsMapLayer

    :param output_path: The output path of the product.
    :type output_path: str

    :param file_format: File format of map output, 'pdf' or 'png'.
    :type file_format: str

    :return: Generated output path(s).
    :rtype: str, list
    """
    # set the composer map to be atlas driven
    composer_map = layout_item(
        layout, 'impact-map', QgsLayoutItemMap)
    composer_map.setAtlasDriven(True)
    composer_map.setAtlasScalingMode(QgsLayoutItemMap.Auto)

    # setup the atlas composition and composition atlas mode
    atlas_composition = layout.atlas()
    atlas_composition.setCoverageLayer(coverage_layer)
    atlas_on_single_file = layout.customProperty('singleFile', True)

    if file_format == QgisComposerComponentsMetadata.OutputFormat.PDF:
        if not atlas_composition.filenameExpression():
            atlas_composition.setFilenameExpression(
                "'output_'||@atlas_featurenumber")
        output_directory = os.path.dirname(output_path)

        # we need to set the predefined scales for atlas
        project_scales = []
        scales = QgsProject.instance().readListEntry(
            "Scales", "/ScalesList")[0]
        has_project_scales = QgsProject.instance().readBoolEntry(
            "Scales", "/useProjectScales")[0]
        if not has_project_scales or not scales:
            scales_string = str(general_setting("Map/scales", PROJECT_SCALES))
            scales = scales_string.split(',')
        for scale in scales:
            parts = scale.split(':')
            if len(parts) == 2:
                project_scales.append(float(parts[1]))
        layout.reportContext().setPredefinedScales(project_scales)

        settings = QgsLayoutExporter.PdfExportSettings()

        LOGGER.info('Exporting Atlas')
        atlas_output = []
        if atlas_on_single_file:
            res, error = QgsLayoutExporter.exportToPdf(
                atlas_composition, output_path, settings)
            atlas_output.append(output_path)
        else:
            res, error = QgsLayoutExporter.exportToPdfs(
                atlas_composition, output_directory, settings)

        if res != QgsLayoutExporter.Success:
            LOGGER.error(error)

        return atlas_output
示例#23
0
    def overrideExportSettings(self, layout, extension):
        """Because GUI settings are not exposed in Python,
           we need to find and catch user selection and override
           export settings values with what is actually active in the GUI.
           See discussion at http://osgeo-org.1560.x6.nabble.com/Programmatically-export-layout-with-georeferenced-file-td5365462.html
        """

        if extension == '.pdf':
            # See QgsLayoutDesignerDialog::getPdfExportSettings
            # let's follow non-default values if set
            exportSettings = QgsLayoutExporter.PdfExportSettings()
            exportSettings.flags = layout.renderContext().flags()
            exportSettings.dpi = layoutDpi
            if layout.customProperty('rasterize') in ['true', True]:
                exportSettings.rasterizeWholeImage = True

            if layout.customProperty('forceVector') == 1:
                exportSettings.forceVectorOutput = True

            if layout.customProperty('pdfTextFormat') == 1:
                exportSettings.textRenderFormat = 1

            if layout.customProperty('pdfOgcBestPracticeFormat') == 1:
                exportSettings.useIso32000ExtensionFormatGeoreferencing = False
                exportSettings.useOgcBestPracticeFormatGeoreferencing = True

            if layout.customProperty('pdfExportThemes'):
                exportSettings.exportThemes = layout.customProperty(
                    'pdfExportThemes')

            if layout.customProperty('pdfIncludeMetadata') == 0:
                exportSettings.exportMetadata = False

            if layout.customProperty('pdfSimplify') == 0:
                exportSettings.simplifyGeometries = False

            if layout.customProperty('pdfCreateGeoPdf') == 1:
                exportSettings.writeGeoPdf = True

            if layout.customProperty('pdfAppendGeoreference') == 0:
                exportSettings.appendGeoreference = False

            if layout.customProperty('pdfExportGeoPdfFeatures') == 0:
                exportSettings.includeGeoPdfFeatures = False

        elif extension == '.svg':
            # See QgsLayoutDesignerDialog::getSvgExportSettings
            exportSettings = QgsLayoutExporter.SvgExportSettings()
            exportSettings.flags = layout.renderContext().flags()
            exportSettings.dpi = layoutDpi
            if layout.customProperty('forceVector') == 1:
                exportSettings.forceVectorOutput = True

            if layout.customProperty('svgIncludeMetadata') == 0:
                exportSettings.exportMetadata = False

            if layout.customProperty('svgSimplify') == 0:
                exportSettings.simplifyGeometries = False

            if layout.customProperty('svgGroupLayers') in ['true', True]:
                exportSettings.exportAsLayers = True

            if layout.customProperty('svgTextFormat') == 1:
                exportSettings.textRenderFormat = 1

            if layout.customProperty('svgCropToContents') in ['true', True]:
                exportSettings.cropToContents = True
            # Todo: add margin values when cropping to content
            #exportSettings.cropMargins = ???QgsMargins???
            #if layout.customProperty('svgDisableRasterTiles')  in ['true', True] : ??? # to fine tune with flags FlagDisableTiledRasterLayerRenders

        else:
            # see QgsLayoutDesignerDialog::getRasterExportSettings for settings
            exportSettings = QgsLayoutExporter.ImageExportSettings()
            exportSettings.flags = layout.renderContext().flags()
            exportSettings.dpi = layoutDpi
            if layout.customProperty('exportWorldFile') in ['true', True]:
                exportSettings.generateWorldFile = True

            if layout.customProperty('imageCropToContents') in ['true', True]:
                exportSettings.cropToContents = True
            # Todo: add margin values when cropping to content
            #exportSettings.cropMargins = ???QgsMargins???
            # exportSettings.exportMetadata = False # what's the corresponding layout's property?
            # layout.customProperty('atlasRasterFormat') # overridden by extension
            # # if layout.customProperty('imageAntialias') in ['true', True] : ??? # to fine tune with flags FlagAntialiasing

        return exportSettings
示例#24
0
文件: core.py 项目: yverdon/geocity
def print_layout(
    project: QgsProject,
    layout_name: str,
    output_format: OutputFormat,
    feature_filter: str = None,
    scales: list = None,
    scale: int = None,
    **kwargs,
):
    """Generate a PDF for an atlas or a report.

    :param project: The QGIS project.
    :type project: QgsProject

    :param layout_name: Name of the layout of the atlas or report.
    :type layout_name: basestring

    :param feature_filter: QGIS Expression to use to select the feature.
    It can return many features, a multiple pages PDF will be returned.
    This is required to print atlas, not report
    :type feature_filter: basestring

    :param scale: A scale to force in the atlas context. Default to None.
    :type scale: int

    :param scales: A list of predefined list of scales to force in the atlas context.
    Default to None.
    :type scales: list

    :param output_format: The output format, default to PDF if not provided.

    :return: Path to the PDF.
    :rtype: basestring
    """
    canvas = QgsMapCanvas()
    bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas)
    bridge.setCanvasLayers()
    manager = project.layoutManager()
    master_layout = manager.layoutByName(layout_name)

    if output_format == OutputFormat.Svg:
        settings = QgsLayoutExporter.SvgExportSettings()
    elif output_format in (OutputFormat.Png, OutputFormat.Jpeg):
        settings = QgsLayoutExporter.ImageExportSettings()
    else:
        # PDF by default
        settings = QgsLayoutExporter.PdfExportSettings()

    atlas = None
    atlas_layout = None
    report_layout = None

    logger = Logger()

    if not master_layout:
        raise AtlasPrintException("Layout `{}` not found".format(layout_name))

    if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout:
        for _print_layout in manager.printLayouts():
            if _print_layout.name() == layout_name:
                atlas_layout = _print_layout
                break

        atlas = atlas_layout.atlas()
        if not atlas.enabled():
            raise AtlasPrintException("The layout is not enabled for an atlas")

        layer = atlas.coverageLayer()

        if feature_filter is None:
            raise AtlasPrintException(
                "EXP_FILTER is mandatory to print an atlas layout")

        feature_filter = optimize_expression(layer, feature_filter)

        expression = QgsExpression(feature_filter)
        if expression.hasParserError():
            raise AtlasPrintException(
                "Expression is invalid, parser error: {}".format(
                    expression.parserErrorString()))

        context = QgsExpressionContext()
        context.appendScope(QgsExpressionContextUtils.globalScope())
        context.appendScope(QgsExpressionContextUtils.projectScope(project))
        context.appendScope(
            QgsExpressionContextUtils.layoutScope(atlas_layout))
        context.appendScope(QgsExpressionContextUtils.atlasScope(atlas))
        context.appendScope(QgsExpressionContextUtils.layerScope(layer))
        expression.prepare(context)
        if expression.hasEvalError():
            raise AtlasPrintException(
                "Expression is invalid, eval error: {}".format(
                    expression.evalErrorString()))

        atlas.setFilterFeatures(True)
        atlas.setFilterExpression(feature_filter)
        atlas.updateFeatures()

        if scale:
            atlas_layout.referenceMap().setAtlasScalingMode(
                QgsLayoutItemMap.Fixed)
            atlas_layout.referenceMap().setScale(scale)

        if scales:
            atlas_layout.referenceMap().setAtlasScalingMode(
                QgsLayoutItemMap.Predefined)
            settings.predefinedMapScales = scales

        if (not scales and atlas_layout.referenceMap().atlasScalingMode()
                == QgsLayoutItemMap.Predefined):
            use_project = project.useProjectScales()
            map_scales = project.mapScales()
            if not use_project or len(map_scales) == 0:
                logger.info(
                    "Map scales not found in project, fetching predefined map scales in global config"
                )
                map_scales = global_scales()
            settings.predefinedMapScales = map_scales

    elif master_layout.layoutType() == QgsMasterLayoutInterface.Report:
        report_layout = master_layout

    else:
        raise AtlasPrintException("The layout is not supported by the plugin")

    for key, value in kwargs.items():
        found = False
        if atlas_layout:
            item = atlas_layout.itemById(key.lower())
            if isinstance(item, QgsLayoutItemLabel):
                item.setText(value)
                found = True
        logger.info(
            'Additional parameters "{key}" {found} in layout, value "{value}"'.
            format(key=key,
                   found="found" if found else "not found",
                   value=value))

    file_name = "{}_{}.{}".format(clean_string(layout_name), uuid4(),
                                  output_format.name.lower())
    export_path = Path(tempfile.gettempdir()).joinpath(file_name)

    Logger().info("Exporting the request in {} using {}".format(
        export_path, output_format.value))

    if output_format in (OutputFormat.Png, OutputFormat.Jpeg):
        exporter = QgsLayoutExporter(atlas_layout or report_layout)
        result = exporter.exportToImage(str(export_path), settings)
        error = result_message(result)
    elif output_format in (OutputFormat.Svg, ):
        exporter = QgsLayoutExporter(atlas_layout or report_layout)
        result = exporter.exportToSvg(str(export_path), settings)
        error = result_message(result)
    else:
        # Default to PDF
        result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout,
                                                      str(export_path),
                                                      settings)
        # Let's override error message
        _ = error
        error = result_message(result)

    if result != QgsLayoutExporter.Success:
        raise Exception("Export not generated in QGIS exporter {} : {}".format(
            export_path, error))

    if not export_path.is_file():
        logger.warning(
            "No error from QGIS Exporter, but the file does not exist.\n"
            "Message from QGIS exporter : {}\n"
            "File path : {}\n".format(error, export_path))
        raise Exception(
            "Export OK from QGIS, but file not found on the file system : {}".
            format(export_path))

    return export_path
示例#25
0
    def TOMsExportAtlas(self, printProposalObject):

        # TH (180608): Export function to deal with atlases

        settings = QSettings()
        format = self.dialogui.comboBox_fileformat.itemData(self.dialogui.comboBox_fileformat.currentIndex())

        # TH (180608): Check to see whether or not the Composer is an Atlas
        currPrintLayout = self.layoutView
        currLayoutAtlas = currPrintLayout.atlas()

        success = False

        # https://gis.stackexchange.com/questions/77848/programmatically-load-composer-from-template-and-generate-atlas-using-pyqgis?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

        self.TOMsSetAtlasValues(currPrintLayout)

        currRevisionDate = self.proposalsManager.date()

        # get the map tiles that are affected by the Proposal
        # self.getProposalTileList(currProposalID, currRevisionDate)

        proposalTileDictionaryForDate = printProposalObject.getProposalTileDictionaryForDate(currRevisionDate)
        """self.tileSet = set(
            proposalTileDictionaryForDate)"""  # TODO: Change around use of tileSet - also might be good to have a current proposal as an object in proposalManager...

        # Now check which tiles to use
        self.tilesToPrint = self.TOMsChooseTiles(proposalTileDictionaryForDate)

        if len(self.tilesToPrint) == 0:
            return

        # get the output location
        dirName = QFileDialog.getExistingDirectory(
            self.iface.mainWindow(),
            self.tr("Export Composition"),
            settings.value("/instantprint/lastdir", ""),
            QFileDialog.ShowDirsOnly
        )
        if not dirName:
            return

        settings.setValue("/instantprint/lastdir", dirName)

        tileIDList = ""
        firstTile = True
        for tile in self.tilesToPrint:
            if firstTile:
                tileIDList = str(tile.attribute("id"))
                firstTile = False
            else:
                tileIDList = tileIDList + ',' + str(tile.attribute("id"))

        currLayoutAtlas.setFilterFeatures(True)
        currLayoutAtlas.setFilterExpression(' "id" in ({tileList})'.format(tileList=tileIDList))

        composerRevisionNr = currPrintLayout.itemById('revisionNr')
        composerEffectiveDate = currPrintLayout.itemById('effectiveDate')
        composerProposalStatus = currPrintLayout.itemById('proposalStatus')

        if composerProposalStatus is not None:
            composerProposalStatus.setText(self.proposalForPrintingStatusText)
        else:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Missing label in Layout"),
                                self.tr("Missing label 'proposalStatus'"))

        composerPrintTypeDetails = currPrintLayout.itemById('printTypeDetails')
        if composerPrintTypeDetails is not None:
            composerPrintTypeDetails.setText(self.proposalPrintTypeDetails)
        else:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Missing label in Layout"),
                                self.tr("Missing label 'printTypeDetails'"))

            # currProposalTitle, currProposalOpenDate = self.getProposalTitle(currProposalID)
            #printProposal = printProposalObject
        currProposalTitle = printProposalObject.getProposalTitle()
        currProposalOpenDate = printProposalObject.getProposalOpenDate()

        if printProposalObject.thisProposalNr == 0:
            currProposalTitle = "CurrentRestrictions_({date})".format(
                date=self.proposalsManager.date().toString('yyyyMMMdd'))

        TOMsMessageLog.logMessage("In TOMsExportAtlas. Now printing " + str(currLayoutAtlas.count()) + " items ....",
                                 level=Qgis.Info)

        currLayoutAtlas.setEnabled(True)
        currLayoutAtlas.updateFeatures()
        currLayoutAtlas.beginRender()

        altasFeatureFound = currLayoutAtlas.first()

        while altasFeatureFound:

            currTileNr = int(currLayoutAtlas.nameForPage(currLayoutAtlas.currentFeatureNumber()))

            currLayoutAtlas.refreshCurrentFeature()

            #tileWithDetails = self.tileFromTileSet(currTileNr)
            tileWithDetails = proposalTileDictionaryForDate[currTileNr]

            if tileWithDetails == None:
                TOMsMessageLog.logMessage("In TOMsExportAtlas. Tile with details not found ....", level=Qgis.Info)
                QMessageBox.warning(self.iface.mainWindow(), self.tr("Print Failed"),
                                    self.tr("Could not find details for " + str(currTileNr)))
                break

            TOMsMessageLog.logMessage("In TOMsExportAtlas. tile nr: " + str(currTileNr) + " RevisionNr: " + str(
                tileWithDetails["RevisionNr"]) + " RevisionDate: " + str(tileWithDetails["LastRevisionDate"]),
                                     level=Qgis.Info)

            if self.proposalForPrintingStatusText == "CONFIRMED":
                composerRevisionNr.setText(str(tileWithDetails["RevisionNr"]))
                composerEffectiveDate.setText(
                    '{date}'.format(date=tileWithDetails["LastRevisionDate"].toString('dd-MMM-yyyy')))
            else:
                composerRevisionNr.setText(str(tileWithDetails["RevisionNr"] + 1))
                # For the Proposal, use the current view date
                composerEffectiveDate.setText(
                    '{date}'.format(date=self.openDateForPrintProposal.toString('dd-MMM-yyyy')))

            filename = currProposalTitle + "_" + str(
                currTileNr) + "." + self.dialogui.comboBox_fileformat.currentText().lower()
            outputFile = os.path.join(dirName, filename)

            exporter = QgsLayoutExporter(currLayoutAtlas.layout())

            if self.dialogui.comboBox_fileformat.currentText().lower() == u"pdf":
                result = exporter.exportToPdf(outputFile, QgsLayoutExporter.PdfExportSettings())
                # success = currLayoutAtlas.composition().exportAsPDF(outputFile)
            else:
                result = exporter.exportToImage(outputFile, 'png', QgsLayoutExporter.ImageExportSettings())
                """image = currLayoutAtlas.composition().printPageAsRaster(0)
                if not image.isNull():
                    success = image.save(outputFile)"""

            if result != QgsLayoutExporter.Success:
                QMessageBox.warning(self.iface.mainWindow(), self.tr("Print Failed"),
                                    self.tr("Failed to print " + exporter.errorFile()))
                break

            altasFeatureFound = currLayoutAtlas.next()

        currLayoutAtlas.endRender()

        QMessageBox.information(self.iface.mainWindow(), "Information",
                                ("Printing completed"))
示例#26
0
    def check_layout_export(self,
                            control_name,
                            expected_nb_raster,
                            layers=None,
                            dpiTarget=None):
        """
        Generate a PDF layout export and control the output matches expected_filename
        """

        # generate vector file
        layout = QgsLayout(QgsProject.instance())
        page = QgsLayoutItemPage(layout)
        page.setPageSize(QgsLayoutSize(50, 33))
        layout.pageCollection().addPage(page)

        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(1, 1, 48, 32))
        map.setFrameEnabled(True)
        layout.addLayoutItem(map)
        map.setExtent(self.lines_layer.extent())
        map.setLayers(layers if layers is not None else
                      [self.points_layer, self.lines_layer, self.polys_layer])

        settings = QgsLayoutExporter.PdfExportSettings()

        if dpiTarget is not None:
            settings.dpi = dpiTarget

        exporter = QgsLayoutExporter(layout)
        result_filename = getTempfilePath('pdf')
        exporter.exportToPdf(result_filename, settings)
        self.assertTrue(os.path.exists(result_filename))

        # Generate a readable PDF file so we count raster in it
        result_txt = getTempfilePath("txt")
        subprocess.run([
            "qpdf", "--qdf", "--object-streams=disable", result_filename,
            result_txt
        ])
        self.assertTrue(os.path.exists(result_txt))

        # expected_file = os.path.join(TEST_DATA_DIR, "control_images/selective_masking/pdf_exports/{}".format(expected_filename))
        # self.assertTrue(os.path.exists(expected_file))

        result = open(result_txt, 'rb')
        result_lines = [l.decode('iso-8859-1') for l in result.readlines()]
        result.close()
        nb_raster = len([l for l in result_lines if "/Subtype /Image" in l])
        self.assertEqual(nb_raster, expected_nb_raster)

        # Generate an image from pdf to compare with expected control image
        # keep PDF DPI resolution (300)
        image_result_filename = getTempfilePath("png")
        subprocess.run([
            "pdftoppm", result_filename,
            os.path.splitext(image_result_filename)[0], "-png", "-r", "300",
            "-singlefile"
        ])

        self.checker.setControlName(control_name)
        self.checker.setRenderedImage(image_result_filename)
        res = self.checker.compareImages(control_name)
        self.report += self.checker.report()
        self.assertTrue(res)
示例#27
0
    def testExportToPdf(self):
        md = QgsProject.instance().metadata()
        md.setTitle('proj title')
        md.setAuthor('proj author')
        md.setCreationDateTime(QDateTime(QDate(2011, 5, 3), QTime(9, 4, 5), QTimeZone(36000)))
        md.setIdentifier('proj identifier')
        md.setAbstract('proj abstract')
        md.setKeywords({'kw': ['kw1', 'kw2'], 'KWx': ['kw3', 'kw4']})
        QgsProject.instance().setMetadata(md)

        l = QgsLayout(QgsProject.instance())
        l.initializeDefaults()

        # add a second page
        page2 = QgsLayoutItemPage(l)
        page2.setPageSize('A5')
        l.pageCollection().addPage(page2)

        # add some items
        item1 = QgsLayoutItemShape(l)
        item1.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.green)
        fill.setStrokeStyle(Qt.NoPen)
        item1.setSymbol(fill_symbol)
        l.addItem(item1)

        item2 = QgsLayoutItemShape(l)
        item2.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        item2.attemptMove(QgsLayoutPoint(10, 20), page=1)
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.cyan)
        fill.setStrokeStyle(Qt.NoPen)
        item2.setSymbol(fill_symbol)
        l.addItem(item2)

        exporter = QgsLayoutExporter(l)
        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        settings.dpi = 80
        settings.rasterizeWholeImage = False
        settings.forceVectorOutput = False
        settings.exportMetadata = True

        pdf_file_path = os.path.join(self.basetestpath, 'test_exporttopdfdpi.pdf')
        self.assertEqual(exporter.exportToPdf(pdf_file_path, settings), QgsLayoutExporter.Success)
        self.assertTrue(os.path.exists(pdf_file_path))

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exporttopdfdpi.png')
        dpi = 80
        pdfToPng(pdf_file_path, rendered_page_1, dpi=dpi, page=1)
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exporttopdfdpi2.png')
        pdfToPng(pdf_file_path, rendered_page_2, dpi=dpi, page=2)

        self.assertTrue(self.checkImage('exporttopdfdpi_page1', 'exporttopdfdpi_page1', rendered_page_1, size_tolerance=1))
        self.assertTrue(self.checkImage('exporttopdfdpi_page2', 'exporttopdfdpi_page2', rendered_page_2, size_tolerance=1))

        d = gdal.Open(pdf_file_path)
        metadata = d.GetMetadata()
        self.assertEqual(metadata['AUTHOR'], 'proj author')
        self.assertEqual(metadata['CREATION_DATE'], "D:20110503090405+10'0'")
        self.assertEqual(metadata['KEYWORDS'], 'KWx: kw3,kw4;kw: kw1,kw2')
        self.assertEqual(metadata['SUBJECT'], 'proj abstract')
        self.assertEqual(metadata['TITLE'], 'proj title')
    def processAlgorithm(self, parameters, context, feedback):
        """This actually creates the print layout and exporting as .pdf document"""

        log = feedback.setProgressText

        input_title = self.parameterAsString(parameters, self.INPUT_TITLE,
                                             context)
        input_subtitle = self.parameterAsString(parameters,
                                                self.INPUT_SUBTITLE, context)
        input_credit_text = self.parameterAsString(parameters,
                                                   self.INPUT_CREDIT_TEXT,
                                                   context)
        output_pdf_path = self.parameterAsString(parameters,
                                                 self.OUTPUT_PDF_PATH, context)

        log(f"Title: {input_title}")
        log(f"Subtitle: {input_subtitle}")
        log(f"Credit Text: {input_credit_text}")
        log(f"Output pdf path: {output_pdf_path}")

        #This creates a new print layout
        project = context.project()
        manager = project.layoutManager()
        layout = QgsPrintLayout(project)
        layoutName = 'EcoValuator Layout'  #layoutName is going to be name of Title. Change this later

        layouts_list = manager.printLayouts()
        for layout in layouts_list:
            if layout.name() == layoutName:
                manager.removeLayout(layout)

        layout = QgsPrintLayout(project)
        layout.initializeDefaults()  #create default map canvas
        layout.setName(layoutName)
        manager.addLayout(layout)

        #This adds a map item to the Print Layout
        map = QgsLayoutItemMap(layout)
        map.setRect(20, 20, 20, 20)

        #Set Extent
        canvas = iface.mapCanvas()
        map.setExtent(canvas.extent())  #sets map extent to current map canvas
        layout.addLayoutItem(map)

        #Move & Resize
        map.attemptMove(QgsLayoutPoint(5, 27, QgsUnitTypes.LayoutMillimeters))
        map.attemptResize(
            QgsLayoutSize(218, 178, QgsUnitTypes.LayoutMillimeters))

        #Gather visible layers in project layer tree and create a list of the map layer objects
        #Those which are not active (layers_to_remove) will subsequently remove from the legend model
        tree_layers = project.layerTreeRoot().children()
        active_layers = [
            layer.name() for layer in tree_layers if layer.isVisible()
        ]
        layers_to_remove = [
            layer for layer in project.mapLayers().values()
            if layer.name() not in active_layers
        ]

        #This adds a legend item to the Print Layout
        legend = QgsLayoutItemLegend(layout)
        layout.addLayoutItem(legend)
        legend.attemptMove(
            QgsLayoutPoint(219, 5, QgsUnitTypes.LayoutMillimeters))
        #Get reference to existing legend model and root group then remove the unchecked layers
        legend.setAutoUpdateModel(False)  #not sure if this line is required
        model = legend.model()
        group = model.rootGroup()
        for layer in layers_to_remove:
            group.removeLayer(layer)
        legend.adjustBoxSize()

        #This adds labels to the map
        title = QgsLayoutItemLabel(layout)
        title.setText(input_title)
        title.setFont(QFont("Arial", 28))
        title.adjustSizeToText()
        layout.addLayoutItem(title)
        title.attemptMove(QgsLayoutPoint(10, 4,
                                         QgsUnitTypes.LayoutMillimeters))

        subtitle = QgsLayoutItemLabel(layout)
        subtitle.setText(input_subtitle)
        subtitle.setFont(QFont("Arial", 17))
        subtitle.adjustSizeToText()
        layout.addLayoutItem(subtitle)
        subtitle.attemptMove(
            QgsLayoutPoint(11, 20, QgsUnitTypes.LayoutMillimeters))

        credit_text = QgsLayoutItemLabel(layout)
        credit_text.setText(input_credit_text)
        credit_text.setFont(QFont("Arial", 10))
        credit_text.adjustSizeToText()
        layout.addLayoutItem(credit_text)
        credit_text.attemptMove(
            QgsLayoutPoint(219, 190, QgsUnitTypes.LayoutMillimeters))

        #this creates credit text (line1) in bottom right corner of map layout giving credit to Key-Log Economics
        keylog_credits1 = QgsLayoutItemLabel(layout)
        keylog_credits1.setText("Created using EcoValuator Plugin")
        keylog_credits1.setFont(QFont("Arial", 10))
        keylog_credits1.adjustSizeToText()
        layout.addLayoutItem(keylog_credits1)
        keylog_credits1.attemptMove(
            QgsLayoutPoint(219, 195, QgsUnitTypes.LayoutMillimeters))

        #this creates credit text (line2) in bottom right corner of map layout giving credit to Key-Log Economics
        keylog_credits2 = QgsLayoutItemLabel(layout)
        keylog_credits2.setText("by Key-Log Economics")
        keylog_credits2.setFont(QFont("Arial", 10))
        keylog_credits2.adjustSizeToText()
        layout.addLayoutItem(keylog_credits2)
        keylog_credits2.attemptMove(
            QgsLayoutPoint(219, 200, QgsUnitTypes.LayoutMillimeters))

        #This exports a Print Layout as an image
        manager = QgsProject.instance().layoutManager(
        )  #this is a reference to the layout Manager, which contains a list of print layouts

        layout = manager.layoutByName(
            layoutName
        )  #this accesses a specific layout, by name (which is a string)

        exporter = QgsLayoutExporter(
            layout)  #this creates a QgsLayoutExporter object
        exporter.exportToPdf(output_pdf_path,
                             QgsLayoutExporter.PdfExportSettings())

        log("Done!")

        result = {
        }  #The processAlgorithm wants to return a dictionary. We don't actually need to do this so instead we return an empty one
        return result
示例#29
0
    def imprimirPlanol(self, x, y, escala, rotacion, midaPagina, templateFile,
                       fitxerSortida, tipusSortida):
        tInicial = time.time()

        template = QFile(templateFile)
        doc = QDomDocument()
        doc.setContent(template, False)

        layout = QgsLayout(self.project)
        # page=QgsLayoutItemPage(layout)
        # page.setPageSize(midaPagina)
        # layout.pageCollection().addPage(page)

        # layout.initializeDefaults()
        # p=layout.pageCollection().pages()[0]
        # p.setPageSize(midaPagina)

        context = QgsReadWriteContext()
        [items, ok] = layout.loadFromTemplate(doc, context)
        # p=layout.pageCollection().pages()[0]
        # p.setPageSize(midaPagina)

        if ok:
            refMap = layout.referenceMap()

            titol = layout.itemById('idNomMapa')
            dataMapa = layout.itemById('idData')
            if self.leTitol.text() != '':
                titol.setText(self.leTitol.text())  #comentat pk peta
            else:
                titol.setText('')
            try:
                t = time.localtime()
                dataMapa.setText(strftime('%b-%d-%Y %H:%M', t))
            except:
                pass

            rect = refMap.extent()
            vector = QgsVector(x - rect.center().x(), y - rect.center().y())
            rect += vector
            refMap.setExtent(rect)
            refMap.setScale(escala)
            refMap.setMapRotation(rotacion)
            #Depenent del tipus de sortida...

            exporter = QgsLayoutExporter(layout)
            # image_settings = exporter.ImageExportSettings()
            # image_settings.dpi = 30

            # result = exporter.exportToImage('d:/dropbox/qpic/preview.png',  image_settings)
            # imatge = QPixmap('d:/dropbox/qpic/preview.png')
            # self.ui.lblImatgeResultat.setPixmap(imatge)

            if tipusSortida == 'PDF':
                settings = QgsLayoutExporter.PdfExportSettings()
                settings.dpi = 300
                settings.exportMetadata = False

                # fitxerSortida='d:/sortida_'+timestamp+'.PDF'
                fitxerSortida += '.PDF'
                result = exporter.exportToPdf(
                    fitxerSortida, settings)  #Cal desar el resultat (???)

                print(fitxerSortida)

            if tipusSortida == 'PNG':
                settings = QgsLayoutExporter.ImageExportSettings()
                settings.dpi = 300

                # fitxerSortida='d:/sortida_'+timestamp+'.PNG'
                fitxerSortida += '.PNG'
                result = exporter.exportToImage(
                    fitxerSortida, settings)  #Cal desar el resultat (???)

            #Obra el document si està marcat checkObrirResultat
            QDesktopServices().openUrl(QUrl(fitxerSortida))

            segonsEmprats = round(time.time() - tInicial, 1)  #???
            layersTemporals = self.project.mapLayersByName(
                "Capa temporal d'impressió")

            estatDirtybit = self.parent.canvisPendents
            for layer in layersTemporals:
                self.project.removeMapLayer(layer.id())
            self.parent.setDirtyBit(estatDirtybit)
示例#30
0
    def exportPDF(self, model, chart_path, gyf, exportDialog, area_id, groups,
                  feature_gids, total):

        # Text from export dialog
        map_title = exportDialog.projectName.text()
        area_name = exportDialog.areaName.text()
        output_path = exportDialog.pdfPath.text()
        output_name = exportDialog.pdfName.text()
        author = exportDialog.author.text()
        gyf_version = model['Version']  #AP 2.0
        date = datetime.datetime.today().strftime('%Y-%m-%d')

        # Get template
        path = os.path.dirname(os.path.realpath(__file__))
        a = path.rfind('\\')
        template_file = open(path[:a] + "/template/qgyf_template1.qpt",
                             encoding="utf-8")
        template_content = template_file.read()
        template_file.close()

        document = QDomDocument()
        proj = QgsProject.instance()
        document.setContent(template_content)
        composition = QgsLayout(proj)
        composition.loadFromTemplate(document, QgsReadWriteContext())

        # Title
        title = sip.cast(composition.itemById("title"), QgsLayoutItemLabel)
        title.setText(map_title)
        title = sip.cast(composition.itemById("title1"), QgsLayoutItemLabel)
        title.setText(map_title)
        title = sip.cast(composition.itemById("title2"), QgsLayoutItemLabel)
        title.setText(map_title)

        # GYF value
        value = sip.cast(composition.itemById("gyf_value"), QgsLayoutItemLabel)
        value.setText('GYF  ' + gyf)
        value = sip.cast(composition.itemById("gyf_value1"),
                         QgsLayoutItemLabel)
        value.setText('GYF  ' + gyf)
        value = sip.cast(composition.itemById("gyf_value2"),
                         QgsLayoutItemLabel)
        value.setText('GYF  ' + gyf)

        # GYF groups
        groups = sorted(list(set(groups)))
        groupList = sip.cast(composition.itemById("groups"),
                             QgsLayoutItemLabel)
        text = '''<font face="tahoma" color="#238973"><h3>GYF Kategorier:</h3></font>
        <p style="font-family:tahoma; font-size:13.5; font-color:#4d4949; line-height:21px">'''
        for g in groups:
            text += g + '<br>'
        text = text + '</p>'
        groupList.setText(text)

        # Research Area
        area_id = area_id.id()
        research_area_lyr = proj.mapLayersByName('Beräkningsområde')[0]
        query = "id = " + str(area_id)
        research_area_lyr.setSubsetString(query)
        for feature in research_area_lyr.getFeatures():
            s = feature['yta']
        area_info = sip.cast(composition.itemById("area_info"),
                             QgsLayoutItemLabel)
        items = [['Beräkningsyta: ', str(int(float(s)))],
                 ['Ekoeffektiv yta: ',
                  str(int(float(total)))]]
        text2 = ""
        for i in items:
            text2 += '<font face="tahoma" color="#238973"><b>'+ i[0] + \
            '</b></font><p style="display:inline;font-family:tahoma; font-size:13.5; font-color:#4d4949; line-height:19px">''' + \
            i[1] + ' m<sup>2</sup></p><br>'
        area_info.setText(text2)
        extent = research_area_lyr.extent()

        # Map
        main_map = sip.cast(composition.itemById("map"), QgsLayoutItemMap)
        main_map.zoomToExtent(extent)
        composition.itemById("map").refresh()
        main_map.setKeepLayerSet(True)
        main_map.setKeepLayerStyles(True)

        # Legend
        legend = sip.cast(composition.itemById("legend"), QgsLayoutItemLegend)
        legend.setLegendFilterByMapEnabled(True)
        # Remove background map from legend - have to be checked out
        #root = QgsLayerTree()
        #for lyr in iface.mapCanvas().layers():
        #    if lyr.type() == QgsMapLayer.VectorLayer:
        #        root.addLayer(lyr)
        #    legend.model().setRootGroup(root)
        legend.setAutoUpdateModel(False)

        # Table Grundytor & Kvaliteter
        root = proj.layerTreeRoot()
        content = [l.name() for l in root.children()]

        db_path = '{}\{}'.format(
            proj.readEntry("QGYF", "dataPath")[0],
            proj.readEntry("QGYF", 'activeDataBase')[0])
        uri = QgsDataSourceUri()
        uri.setDatabase(db_path)
        #Table 2 - ground areas
        uri.setDataSource('', 'ground_areas', None)
        table2 = QgsVectorLayer(uri.uri(), 'ground_areas', 'spatialite')
        if 'ground_areas' not in content:
            proj.addMapLayer(table2, False)
        tableLayout2 = sip.cast(composition.itemById("table2"), QgsLayoutFrame)
        tableLayout2.refreshItemPosition()
        tableLayout2 = tableLayout2.multiFrame()
        tableLayout2.setVectorLayer(table2)
        tableLayout2.setDisplayedFields(
            ['ytgrupp', 'ytklass', 'faktor', 'yta', 'poang'])
        # label
        table_areas = sip.cast(composition.itemById("table_areas"),
                               QgsLayoutItemLabel)
        table2_name = '<font face="tahoma" color="#238973"><b>' + model[
            'Klass_items'][0].title() + 'er</b></font>'
        table_areas.setText(table2_name)
        #h = tableLayout2.totalHeight()

        #Table 1 - qualities
        uri.setDataSource('', 'classification', None)
        table1 = QgsVectorLayer(uri.uri(), 'classification', 'spatialite')
        if 'classification' not in content:
            proj.addMapLayer(table1, False)

        tableLayout = sip.cast(composition.itemById("table"), QgsLayoutFrame)
        #position = tableLayout.positionAtReferencePoint(tableLayout.ReferencePoint())
        #position.setX(position.x() + h)
        #tableLayout.setReferencePoint(position)
        tableLayout.refreshItemPosition()
        tableLayout = tableLayout.multiFrame()
        tableLayout.setVectorLayer(table1)
        tableLayout.setDisplayedFields([
            'id', 'geometri_typ', 'fil_namn', 'grupp', 'kvalitet', 'faktor',
            'yta', 'poang'
        ])
        # Filter
        feature_gids = "', '".join(i for i in feature_gids)
        query = "gid in ('" + feature_gids + "')"
        tableLayout.setFilterFeatures(True)
        tableLayout.setFeatureFilter(query)
        tableLayout.update()
        # label
        table_class = sip.cast(composition.itemById("table_class"),
                               QgsLayoutItemLabel)
        table1_name = '<font face="tahoma" color="#238973"><b>' + model[
            'Klass_items'][1].title() + 'er</b></font>'
        table_class.setText(table1_name)

        # Diagram
        chart = sip.cast(composition.itemById("chart"), QgsLayoutItemPicture)
        chart.setPicturePath(chart_path)
        chart.refreshPicture()

        # Diagram
        chart2 = sip.cast(composition.itemById("chart2"), QgsLayoutItemPicture)
        if float(gyf) > 0.0:
            chart2.setPicturePath(
                proj.readEntry("QGYF", "dataPath")[0] + '\PieChart2.png')
            chart2.refreshPicture()

        # Metadata
        text = '<p style="font-family:tahoma; font-size:13.5; font-color:#4d4949; line-height:21px">Område: ' + \
        area_name + '<br>Utförd av: ' + author + '<br>GYF version: ' + gyf_version + '<br>Datum: ' + date + '</p>'
        info = sip.cast(composition.itemById("info"), QgsLayoutItemLabel)
        info.setText(text)
        info = sip.cast(composition.itemById("info1"), QgsLayoutItemLabel)
        info.setText(text)

        # EXPORT!
        QgsLayoutExporter(composition).exportToPdf(
            output_path + '/' + output_name,
            QgsLayoutExporter.PdfExportSettings())
        QMessageBox.information(ExportDialog(), 'Rapport',
                                'Din rapport har skapats! :)')

        # Reset map view
        research_area_lyr.setSubsetString('')
        proj.removeMapLayer(table1)
        proj.removeMapLayer(table2)