def testCasting(self): """ Test that sip correctly casts stuff """ p = QgsProject() p.read(os.path.join(TEST_DATA_DIR, 'layouts', 'layout_casting.qgs')) layout = p.layoutManager().layouts()[0] # check a method which often fails casting map = layout.itemById('map') self.assertIsInstance(map, QgsLayoutItemMap) label = layout.itemById('label') self.assertIsInstance(label, QgsLayoutItemLabel) # another method -- sometimes this fails casting for different(?) reasons # make sure we start from a new project so sip hasn't remembered item instances p2 = QgsProject() p2.read(os.path.join(TEST_DATA_DIR, 'layouts', 'layout_casting.qgs')) layout = p2.layoutManager().layouts()[0] items = layout.items() map2 = [ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'map' ][0] self.assertIsInstance(map2, QgsLayoutItemMap) label2 = [ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'label' ][0] self.assertIsInstance(label2, QgsLayoutItemLabel)
def testCasting(self): """ Test that sip correctly casts stuff """ p = QgsProject() p.read(os.path.join(TEST_DATA_DIR, 'layouts', 'layout_casting.qgs')) layout = p.layoutManager().layouts()[0] # check a method which often fails casting map = layout.itemById('map') self.assertIsInstance(map, QgsLayoutItemMap) label = layout.itemById('label') self.assertIsInstance(label, QgsLayoutItemLabel) # another method -- sometimes this fails casting for different(?) reasons # make sure we start from a new project so sip hasn't remembered item instances p2 = QgsProject() p2.read(os.path.join(TEST_DATA_DIR, 'layouts', 'layout_casting.qgs')) layout = p2.layoutManager().layouts()[0] items = layout.items() map2 = [i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'map'][0] self.assertIsInstance(map2, QgsLayoutItemMap) label2 = [i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'label'][0] self.assertIsInstance(label2, QgsLayoutItemLabel)
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 {}
def testSaveRestore(self): p = QgsProject() l = QgsPrintLayout(p) p.layoutManager().addLayout(l) map = QgsLayoutItemMap(l) shape = QgsLayoutItemShape(l) l.addLayoutItem(map) l.addLayoutItem(shape) settings = map.itemClippingSettings() settings.setEnabled(True) settings.setFeatureClippingType( QgsMapClippingRegion.FeatureClippingType.NoClipping) settings.setForceLabelsInsideClipPath(True) settings.setSourceItem(shape) # save map to xml doc = QDomDocument("testdoc") elem = doc.createElement("test") self.assertTrue(map.writeXml(elem, doc, QgsReadWriteContext())) elem_shape = doc.createElement("shape") self.assertTrue(shape.writeXml(elem_shape, doc, QgsReadWriteContext())) layout2 = QgsPrintLayout(p) layout2.setName('test2') p.layoutManager().addLayout(layout2) map2 = QgsLayoutItemMap(layout2) layout2.addLayoutItem(map2) shape2 = QgsLayoutItemShape(layout2) layout2.addLayoutItem(shape2) self.assertFalse(map2.itemClippingSettings().enabled()) # restore from xml self.assertTrue( map2.readXml(elem.firstChildElement(), doc, QgsReadWriteContext())) self.assertTrue( shape2.readXml(elem_shape.firstChildElement(), doc, QgsReadWriteContext())) self.assertTrue(map2.itemClippingSettings().enabled()) self.assertEqual(map2.itemClippingSettings().featureClippingType(), QgsMapClippingRegion.FeatureClippingType.NoClipping) self.assertTrue( map2.itemClippingSettings().forceLabelsInsideClipPath()) self.assertIsNone(map2.itemClippingSettings().sourceItem()) map2.finalizeRestoreFromXml() self.assertEqual(map2.itemClippingSettings().sourceItem(), shape2)
def testToMapClippingRegion(self): p = QgsProject() l = QgsPrintLayout(p) p.layoutManager().addLayout(l) map = QgsLayoutItemMap(l) shape = QgsLayoutItemShape(l) l.addLayoutItem(map) map.attemptSetSceneRect(QRectF(10, 20, 100, 80)) map.zoomToExtent(QgsRectangle(100, 200, 50, 40)) l.addLayoutItem(shape) shape.setShapeType(QgsLayoutItemShape.Triangle) shape.attemptSetSceneRect(QRectF(20, 30, 70, 50)) settings = map.itemClippingSettings() settings.setEnabled(True) settings.setFeatureClippingType( QgsMapClippingRegion.FeatureClippingType.NoClipping) settings.setSourceItem(shape) region = settings.toMapClippingRegion() self.assertEqual(region.geometry().asWkt(), 'Polygon ((-5 80, 135 80, 65 180, -5 80))') self.assertEqual(region.featureClip(), QgsMapClippingRegion.FeatureClippingType.NoClipping)
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