def testExpressionInText(self): """Test expressions embedded in legend node text""" point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') layout = QgsPrintLayout(QgsProject.instance()) layout.setName('LAYOUT') layout.initializeDefaults() map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(20, 20, 80, 80)) map.setFrameEnabled(True) map.setLayers([point_layer]) layout.addLayoutItem(map) map.setExtent(point_layer.extent()) legend = QgsLayoutItemLegend(layout) legend.setTitle("Legend") legend.attemptSetSceneRect(QRectF(120, 20, 100, 100)) legend.setFrameEnabled(True) legend.setFrameStrokeWidth(QgsLayoutMeasurement(2)) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') legend.setLegendFilterByMapEnabled(False) legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setAutoUpdateModel(False) QgsProject.instance().addMapLayers([point_layer]) s = QgsMapSettings() s.setLayers([point_layer]) group = legend.model().rootGroup().addGroup("Group [% 1 + 5 %] [% @layout_name %]") layer_tree_layer = group.addLayer(point_layer) layer_tree_layer.setCustomProperty("legend/title-label", 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]') QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0, 'xxxx') legend.model().refreshLayerLegend(layer_tree_layer) legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel('bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]') layout.addLayoutItem(legend) legend.setLinkedMap(map) map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30)) checker = QgsLayoutChecker( 'composer_legend_expressions', layout) checker.setControlPathPrefix("composer_legend") result, message = checker.testLayout() self.assertTrue(result, message) QgsProject.instance().removeMapLayers([point_layer.id()])
def testCase(self): TEST_DATA_DIR = unitTestDataPath() vectorFileInfo = QFileInfo(TEST_DATA_DIR + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) layout = QgsPrintLayout(QgsProject.instance()) layout.initializeDefaults() label = QgsLayoutItemLabel(layout) layout.addLayoutItem(label) self.evaluation_test(layout, label) self.feature_evaluation_test(layout, label, mVectorLayer) self.page_evaluation_test(layout, label, mVectorLayer)
def rotation_test(self): # We will create a polygon layer with a rotated rectangle. # Then we will make it the object layer for the atlas, # rotate the map and test that the bounding rectangle # is smaller than the bounds without rotation. polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) points = [(10, 15), (15, 10), (45, 40), (40, 45)] poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]])) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) # Recreating the layout locally composition = QgsPrintLayout(QgsProject.instance()) composition.initializeDefaults() # the atlas map atlasMap = QgsLayoutItemMap(composition) atlasMap.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlasMap.setFrameEnabled(True) atlasMap.setLayers([polygonLayer]) atlasMap.setExtent(QgsRectangle(0, 0, 100, 50)) composition.addLayoutItem(atlasMap) # the atlas atlas = composition.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlasMap.setAtlasMargin(0.0) # Testing atlasMap.setMapRotation(0.0) atlas.beginRender() atlas.first() nonRotatedExtent = QgsRectangle(atlasMap.extent()) atlasMap.setMapRotation(45.0) atlas.first() rotatedExtent = QgsRectangle(atlasMap.extent()) self.assertLess(rotatedExtent.width(), nonRotatedExtent.width() * 0.9) self.assertLess(rotatedExtent.height(), nonRotatedExtent.height() * 0.9) QgsProject.instance().removeMapLayer(polygonLayer)
def prepareIteratorLayout(self): layer_path = os.path.join(TEST_DATA_DIR, 'france_parts.shp') layer = QgsVectorLayer(layer_path, 'test', "ogr") project = QgsProject() project.addMapLayers([layer]) # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) project.setCrs(crs) layout = QgsPrintLayout(project) layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", "outline_width": "4", "outline_color": '255,255,255'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) layer.setRenderer(renderer) # the atlas map atlas_map = QgsLayoutItemMap(layout) atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlas_map.setFrameEnabled(True) atlas_map.setLayers([layer]) layout.addLayoutItem(atlas_map) # the atlas atlas = layout.atlas() atlas.setCoverageLayer(layer) atlas.setEnabled(True) atlas_map.setExtent( QgsRectangle(332719.06221504929, 6765214.5887386119, 560957.85090677091, 6993453.3774303338)) atlas_map.setAtlasDriven(True) atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlas_map.setAtlasMargin(0.10) return project, layout
def testDuplicateLayout(self): """ Test duplicating layouts """ project = QgsProject() manager = QgsLayoutManager(project) doc = QDomDocument("testdoc") self.assertFalse(manager.duplicateLayout(None, 'dest')) layout = QgsPrintLayout(project) layout.setName('test layout') layout.initializeDefaults() manager.addLayout(layout) # duplicate name self.assertFalse(manager.duplicateLayout(layout, 'test layout')) result = manager.duplicateLayout(layout, 'dupe layout') self.assertTrue(result) # make sure result in stored in manager self.assertEqual(result, manager.layoutByName('dupe layout')) self.assertEqual(result.name(), 'dupe layout') self.assertEqual(result.pageCollection().pageCount(), 1)
def testDuplicateLayout(self): """ Test duplicating layouts """ project = QgsProject() manager = QgsLayoutManager(project) doc = QDomDocument("testdoc") self.assertFalse(manager.duplicateLayout(None, 'dest')) layout = QgsPrintLayout(project) layout.setName('test layout') layout.initializeDefaults() manager.addLayout(layout) # duplicate name self.assertFalse(manager.duplicateLayout(layout, 'test layout')) result = manager.duplicateLayout(layout, 'dupe layout') self.assertTrue(result) # make sure result in stored in manager self.assertEqual(result, manager.layoutByName('dupe layout')) self.assertEqual(result.name(), 'dupe layout') self.assertEqual(result.pageCollection().pageCount(), 1)
def createComposition(self): ''' Create a print Layout ''' c = QgsPrintLayout(QgsProject.instance()) c.initializeDefaults() c.setUnits(QgsUnitTypes.LayoutMillimeters) g=QgsLayoutGridSettings(c) g.setOffset( QgsLayoutPoint(3.5, 0, QgsUnitTypes.LayoutMillimeters) ) g.setResolution( QgsLayoutMeasurement(2.5) ) # Set page number self.getPageNumberNeeded() # Set main properties for i in range(1, self.numPages): p=QgsLayoutItemPage(c) #page.setPageSize('A6') p.setPageSize( QgsLayoutSize(self.pageWidth, self.pageHeight, QgsUnitTypes.LayoutMillimeters) ) c.pageCollection().addPage(p) # Set the global currentComposition self.currentComposition = c
def createComposition(self): ''' Create a print Layout ''' c = QgsPrintLayout(self.mProject) c.initializeDefaults() c.setUnits(QgsUnitTypes.LayoutMillimeters) g=QgsLayoutGridSettings(c) g.setOffset( QgsLayoutPoint(3.5, 0, QgsUnitTypes.LayoutMillimeters) ) g.setResolution( QgsLayoutMeasurement(2.5) ) # Set page number self.getPageNumberNeeded() # Set main properties for i in range(1, self.numPages): p=QgsLayoutItemPage(c) #page.setPageSize('A6') p.setPageSize( QgsLayoutSize(self.pageWidth, self.pageHeight, QgsUnitTypes.LayoutMillimeters) ) c.pageCollection().addPage(p) # Set the global currentComposition self.currentComposition = c
def testExpressionInText(self): """Test expressions embedded in legend node text""" point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') layout = QgsPrintLayout(QgsProject.instance()) layout.setName('LAYOUT') layout.initializeDefaults() map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(20, 20, 80, 80)) map.setFrameEnabled(True) map.setLayers([point_layer]) layout.addLayoutItem(map) map.setExtent(point_layer.extent()) legend = QgsLayoutItemLegend(layout) legend.setTitle("Legend") legend.attemptSetSceneRect(QRectF(120, 20, 100, 100)) legend.setFrameEnabled(True) legend.setFrameStrokeWidth(QgsLayoutMeasurement(2)) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') legend.setLegendFilterByMapEnabled(False) legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setAutoUpdateModel(False) QgsProject.instance().addMapLayers([point_layer]) s = QgsMapSettings() s.setLayers([point_layer]) group = legend.model().rootGroup().addGroup( "Group [% 1 + 5 %] [% @layout_name %]") layer_tree_layer = group.addLayer(point_layer) layer_tree_layer.setCustomProperty( "legend/title-label", 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]') QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0, 'xxxx') legend.model().refreshLayerLegend(layer_tree_layer) legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel( 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]') layout.addLayoutItem(legend) legend.setLinkedMap(map) map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30)) checker = QgsLayoutChecker('composer_legend_expressions', layout) checker.setControlPathPrefix("composer_legend") result, message = checker.testLayout() self.assertTrue(result, message) QgsProject.instance().removeMapLayers([point_layer.id()])
class TestQgsLayoutAtlas(unittest.TestCase): def setUp(self): self.report = "<h1>Python QgsLayoutAtlas Tests</h1>\n" def tearDown(self): report_file_path = "%s/qgistest.html" % QDir.tempPath() with open(report_file_path, 'a') as report_file: report_file.write(self.report) def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob(os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create layout with layout map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.layout = QgsPrintLayout(QgsProject.instance()) self.layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", 'outline_color': 'black'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.atlas_map = QgsLayoutItemMap(self.layout) self.atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) self.atlas_map.setFrameEnabled(True) self.atlas_map.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.atlas_map) # the atlas self.atlas = self.layout.atlas() self.atlas.setCoverageLayer(mVectorLayer) self.atlas.setEnabled(True) # an overview self.overview = QgsLayoutItemMap(self.layout) self.overview.attemptSetSceneRect(QRectF(180, 20, 50, 50)) self.overview.setFrameEnabled(True) self.overview.overview().setLinkedMap(self.atlas_map) self.overview.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.overview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.overview.setExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127", 'outline_color': 'black'} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.overview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.attemptSetSceneRect(QRectF(150, 5, 60, 15)) self.mLabel1.setMarginX(1) self.mLabel1.setMarginY(1) # feature number label self.mLabel2 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel2) self.mLabel2.setText("# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.attemptSetSceneRect(QRectF(150, 200, 60, 15)) self.mLabel2.setMarginX(1) self.mLabel2.setMarginY(1) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() self.rotation_test() shutil.rmtree(tmppath, True) def testReadWriteXml(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setHideCoverage(True) atlas.setFilenameExpression('filename exp') atlas.setCoverageLayer(vector_layer) atlas.setPageNameExpression('page name') atlas.setSortFeatures(True) atlas.setSortAscending(False) atlas.setSortExpression('sort exp') atlas.setFilterFeatures(True) atlas.setFilterExpression('filter exp') doc = QDomDocument("testdoc") elem = l.writeXml(doc, QgsReadWriteContext()) l2 = QgsPrintLayout(p) self.assertTrue(l2.readXml(elem, doc, QgsReadWriteContext())) atlas2 = l2.atlas() self.assertTrue(atlas2.enabled()) self.assertTrue(atlas2.hideCoverage()) self.assertEqual(atlas2.filenameExpression(), 'filename exp') self.assertEqual(atlas2.coverageLayer(), vector_layer) self.assertEqual(atlas2.pageNameExpression(), 'page name') self.assertTrue(atlas2.sortFeatures()) self.assertFalse(atlas2.sortAscending()) self.assertEqual(atlas2.sortExpression(), 'sort exp') self.assertTrue(atlas2.filterFeatures()) self.assertEqual(atlas2.filterExpression(), 'filter exp') def testIteration(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas_feature_changed_spy = QSignalSpy(atlas.featureChanged) context_changed_spy = QSignalSpy(l.reportContext().changed) self.assertTrue(atlas.beginRender()) self.assertTrue(atlas.first()) self.assertEqual(len(atlas_feature_changed_spy), 1) self.assertEqual(len(context_changed_spy), 1) self.assertEqual(atlas.currentFeatureNumber(), 0) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertEqual(l.reportContext().layer(), vector_layer) f1 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 2) self.assertEqual(len(context_changed_spy), 2) self.assertEqual(atlas.currentFeatureNumber(), 1) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') f2 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 3) self.assertEqual(len(context_changed_spy), 3) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') f3 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 4) self.assertEqual(len(context_changed_spy), 4) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') f4 = l.reportContext().feature() self.assertFalse(atlas.next()) self.assertTrue(atlas.seekTo(2)) self.assertEqual(len(atlas_feature_changed_spy), 5) self.assertEqual(len(context_changed_spy), 5) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.last()) self.assertEqual(len(atlas_feature_changed_spy), 6) self.assertEqual(len(context_changed_spy), 6) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 7) self.assertEqual(len(context_changed_spy), 7) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.previous()) self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertFalse(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertTrue(atlas.endRender()) self.assertEqual(len(atlas_feature_changed_spy), 10) self.assertTrue(atlas.seekTo(f1)) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertTrue(atlas.seekTo(f4)) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.seekTo(f3)) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.seekTo(f2)) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') self.assertFalse(atlas.seekTo(QgsFeature(5))) def testUpdateFeature(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) self.assertTrue(atlas.beginRender()) self.assertTrue(atlas.first()) self.assertEqual(atlas.currentFeatureNumber(), 0) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertEqual(l.reportContext().layer(), vector_layer) vector_layer.startEditing() self.assertTrue(vector_layer.changeAttributeValue(l.reportContext().feature().id(), 4, 'Nah, Canberra mate!')) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') l.atlas().refreshCurrentFeature() self.assertEqual(l.reportContext().feature()[4], 'Nah, Canberra mate!') vector_layer.rollBack() def testFileName(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas.setFilenameExpression("'output_' || \"NAME_1\"") self.assertTrue(atlas.beginRender()) self.assertEqual(atlas.count(), 4) atlas.first() self.assertEqual(atlas.currentFilename(), 'output_Basse-Normandie') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Basse-Normandie.png') self.assertEqual(atlas.filePath('/tmp/output/', '.png'), '/tmp/output/output_Basse-Normandie.png') self.assertEqual(atlas.filePath('/tmp/output/', 'svg'), '/tmp/output/output_Basse-Normandie.svg') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Bretagne') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Bretagne.png') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Pays de la Loire') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Pays de la Loire.png') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Centre') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Centre.png') # try changing expression, filename should be updated instantly atlas.setFilenameExpression("'export_' || \"NAME_1\"") self.assertEqual(atlas.currentFilename(), 'export_Centre') atlas.endRender() def testNameForPage(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas.setPageNameExpression("\"NAME_1\"") self.assertTrue(atlas.beginRender()) self.assertEqual(atlas.nameForPage(0), 'Basse-Normandie') self.assertEqual(atlas.nameForPage(1), 'Bretagne') self.assertEqual(atlas.nameForPage(2), 'Pays de la Loire') self.assertEqual(atlas.nameForPage(3), 'Centre') def filename_test(self): self.atlas.setFilenameExpression("'output_' || @atlas_featurenumber") self.atlas.beginRender() for i in range(0, self.atlas.count()): self.atlas.seekTo(i) expected = "output_%d" % (i + 1) self.assertEqual(self.atlas.currentFilename(), expected) self.atlas.endRender() def autoscale_render_test(self): self.atlas_map.setExtent( QgsRectangle(332719.06221504929, 6765214.5887386119, 560957.85090677091, 6993453.3774303338)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_autoscale%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() self.atlas_map.setAtlasDriven(False) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas_map.setAtlasMargin(0) def fixedscale_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_fixedscale%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def predefinedscales_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Predefined) scales = [1800000, 5000000] self.layout.reportContext().setPredefinedScales(scales) for i, s in enumerate(self.layout.reportContext().predefinedScales()): self.assertEqual(s, scales[i]) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_predefinedscales%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def hidden_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(True) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_hiding%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() self.atlas.setHideCoverage(False) def sorting_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(False) self.atlas.setSortFeatures(True) self.atlas.setSortKeyAttributeIndex(4) # departement name self.atlas.setSortAscending(False) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_sorting%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def filtering_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(False) self.atlas.setSortFeatures(False) self.atlas.setFilterFeatures(True) self.atlas.setFeatureFilter("substr(NAME_1,1,1)='P'") # select only 'Pays de la loire' self.atlas.beginRender() for i in range(0, 1): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_filtering%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def legend_test(self): self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) # add a point layer ptLayer = QgsVectorLayer("Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory") pr = ptLayer.dataProvider() f1 = QgsFeature(1) f1.initAttributes(2) f1.setAttribute(0, 1) f1.setAttribute(1, "Test label 1") f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRenderer("attr", [QgsRendererCategory(1, QgsMarkerSymbol.createSimple({"color": "255,0,0", 'outline_color': 'black'}), "red"), QgsRendererCategory(2, QgsMarkerSymbol.createSimple({"color": "0,0,255", 'outline_color': 'black'}), "blue")]) ptLayer.setRenderer(r) QgsProject.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.layers layers = [ptLayer] + layers self.atlas_map.setLayers(layers) self.overview.setLayers(layers) # add a legend legend = QgsLayoutItemLegend(self.layout) legend.attemptMove(QgsLayoutPoint(200, 100)) # sets the legend filter parameter legend.setLinkedMap(self.atlas_map) legend.setLegendFilterOutAtlas(True) self.layout.addLayoutItem(legend) self.atlas.beginRender() self.atlas.seekTo(0) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_legend', self.layout) myTestResult, myMessage = checker.testLayout() self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() # restore state self.atlas_map.setLayers([layers[1]]) self.layout.removeLayoutItem(legend) QgsProject.instance().removeMapLayer(ptLayer.id()) def rotation_test(self): # We will create a polygon layer with a rotated rectangle. # Then we will make it the object layer for the atlas, # rotate the map and test that the bounding rectangle # is smaller than the bounds without rotation. polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) points = [(10, 15), (15, 10), (45, 40), (40, 45)] poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]])) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) # Recreating the layout locally composition = QgsPrintLayout(QgsProject.instance()) composition.initializeDefaults() # the atlas map atlasMap = QgsLayoutItemMap(composition) atlasMap.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlasMap.setFrameEnabled(True) atlasMap.setLayers([polygonLayer]) atlasMap.setExtent(QgsRectangle(0, 0, 100, 50)) composition.addLayoutItem(atlasMap) # the atlas atlas = composition.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlasMap.setAtlasMargin(0.0) # Testing atlasMap.setMapRotation(0.0) atlas.beginRender() atlas.first() nonRotatedExtent = QgsRectangle(atlasMap.extent()) atlasMap.setMapRotation(45.0) atlas.first() rotatedExtent = QgsRectangle(atlasMap.extent()) self.assertLess(rotatedExtent.width(), nonRotatedExtent.width() * 0.9) self.assertLess(rotatedExtent.height(), nonRotatedExtent.height() * 0.9) QgsProject.instance().removeMapLayer(polygonLayer)
class layerOut(QDialog,Ui_decorationDialog): def __init__(self, proj,qssStyle): super(layerOut, self).__init__() self.setupUi(self) self.project = proj print(self.project) self.initLayerOut() self.slot_connect() self.font = QFont('Arial', 24) self.color = QColor('black') # styleFile = './QSS-master/ElegantDark.qss' # qssStyle = CommonHelper.readQSS(styleFile) QDialog.setStyleSheet(self, qssStyle) def initLayerOut(self): self.layout = QgsPrintLayout(self.project) self.layout.initializeDefaults() self.QgsLayerView = QgsLayoutView() self.QgsLayerView.setPreviewModeEnabled(True) self.QgsLayerView.setContentsMargins(0,0,0,0) # self.QgsLayerView.resize(800,600) self.QgsLayerView.setCurrentLayout(self.layout) self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewDeuteranope) # self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewMode) self.QgsLayerView.unlockAllItems() self.layout.refresh() self.QgsLayerView.cursorPosChanged.connect(self.show_lonlat) self.selectTool = QgsLayoutViewToolSelect(self.QgsLayerView) self.selectTool.setLayout(self.layout) Layout = QVBoxLayout(self.widget) Layout.setContentsMargins(0, 0, 0, 0) Layout.addWidget(self.QgsLayerView) for layer in self.project.mapLayers().values(): self.comboBox.addItem(layer.name()) self.effect.addItem('PreviewGrayscale') self.effect.addItem('PreviewMono') self.effect.addItem('PreviewProtanope') self.effect.addItem('PreviewDeuteranope') def slot_connect(self): self.addMap.clicked.connect(self.createMap) self.addTitle.clicked.connect(self.createTittle) self.addLegend.clicked.connect(self.createLegend) self.addScale.clicked.connect(self.createScaleBar) self.exportPDF.clicked.connect(self.saveAsPDF) self.exportIMG.clicked.connect(self.saveAsIMG) self.getFont.clicked.connect(self.setFont) self.getColor.clicked.connect(self.setColor) self.deleteItem.clicked.connect(self.deleteSelectItem) self.changeEffect.clicked.connect(self.setEffect) def createMap(self): try: self.map = QgsLayoutItemMap(self.layout) self.map.setLocked(False) self.map.attemptSetSceneRect(QRectF(8.5, 20, 200, 160)) self.map.setFrameEnabled(True) layer = self.project.mapLayersByName(self.comboBox.currentText())[0] # layer.renderer().setRedBand(3) # layer.renderer().setGreenBand(2) # layer.renderer().setBlueBand(1) self.map.setLayers([layer]) self.map.setBackgroundColor(QColor(255, 255, 255)) self.map.zoomToExtent(layer.extent()) self.layout.addItem(self.map) except: pass # polygon = QPolygonF() # polygon.append(QPointF(0.0, 0.0)) # polygon.append(QPointF(100.0, 0.0)) # polygon.append(QPointF(200.0, 100.0)) # polygon.append(QPointF(100.0, 200.0)) # # polygonItem = QgsLayoutItemPolygon(polygon, self.layout) # self.layout.addItem(polygonItem) # # props = {} # props["color"] = "green" # props["style"] = "solid" # props["style_border"] = "solid" # props["color_border"] = "black" # props["width_border"] = "10.0" # props["joinstyle"] = "miter" # # symbol = QgsFillSymbol.createSimple(props) # polygonItem.setSymbol(symbol) def createTittle(self): title = QgsLayoutItemLabel(self.layout) # title.setLocked(False) title.setText(self.title.text()) title.setFont(self.font) title.setFontColor(self.color) title.adjustSizeToText() self.layout.addLayoutItem(title) title.attemptMove(QgsLayoutPoint(130, 5, QgsUnitTypes.LayoutMillimeters)) def createLegend(self): try: legend = QgsLayoutItemLegend(self.layout) legend.setTitle("Legend") legend.setLinkedMap(self.map) # map is an instance of QgsLayoutItemMap self.layout.addItem(legend) legend.attemptMove(QgsLayoutPoint(230, 15, QgsUnitTypes.LayoutMillimeters)) except: pass def createScaleBar(self): try: scalebar = QgsLayoutItemScaleBar(self.layout) scalebar.setStyle('Line Ticks Up') scalebar.setUnits(QgsUnitTypes.DistanceKilometers) scalebar.setNumberOfSegments(6) scalebar.setNumberOfSegmentsLeft(0) scalebar.setUnitsPerSegment(2) scalebar.setLinkedMap(self.map) scalebar.setUnitLabel('km') scalebar.setFont(QFont('Arial', 14)) scalebar.update() self.layout.addLayoutItem(scalebar) scalebar.attemptMove(QgsLayoutPoint(180, 190, QgsUnitTypes.LayoutMillimeters)) except: pass def saveAsPDF(self): fullpath, format = QFileDialog.getSaveFileName(self, '存储为pdf', '', '*.pdf') print(fullpath) exporter = QgsLayoutExporter(self.layout) exporter.exportToPdf(fullpath, QgsLayoutExporter.PdfExportSettings()) def saveAsIMG(self): fullpath, format = QFileDialog.getSaveFileName(self, '存储为img', '', '*.jpg;;*.png') print(fullpath) exporter = QgsLayoutExporter(self.layout) exporter.exportToImage(fullpath, QgsLayoutExporter.ImageExportSettings()) def setFont(self): font, ok = QFontDialog.getFont() if ok: self.font = font def setColor(self): self.color = QColorDialog.getColor() print(self.color) def show_lonlat(self, point): # print(point) self.mousePos = point def deleteSelectItem(self): print('delete...') # print(self.QgsLayerView.itemFocused()) try: self.QgsLayerView.deleteSelectedItems() except: pass def setEffect(self): # self.effect.addItem('PreviewGrayscale') # self.effect.addItem('PreviewMono') # self.effect.addItem('PreviewProtanope') # self.effect.addItem('PreviewDeuteranope') if self.effect.currentText() == 'PreviewGrayscale': self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewGrayscale) elif self.effect.currentText() == 'PreviewMono': self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewMono) elif self.effect.currentText() == 'PreviewProtanope': self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewProtanope) elif self.effect.currentText() == 'PreviewDeuteranope': self.QgsLayerView.setPreviewMode(QgsPreviewEffect.PreviewDeuteranope)
def testSymbolExpressionRender(self): """Test expressions embedded in legend node text""" point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') layout = QgsPrintLayout(QgsProject.instance()) layout.setName('LAYOUT') layout.initializeDefaults() map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(20, 20, 80, 80)) map.setFrameEnabled(True) map.setLayers([point_layer]) layout.addLayoutItem(map) map.setExtent(point_layer.extent()) legend = QgsLayoutItemLegend(layout) legend.setTitle("Legend") legend.attemptSetSceneRect(QRectF(120, 20, 100, 100)) legend.setFrameEnabled(True) legend.setFrameStrokeWidth(QgsLayoutMeasurement(2)) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') legend.setLegendFilterByMapEnabled(False) legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setStyleFont(QgsLegendStyle.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16)) legend.setAutoUpdateModel(False) QgsProject.instance().addMapLayers([point_layer]) s = QgsMapSettings() s.setLayers([point_layer]) group = legend.model().rootGroup().addGroup( "Group [% 1 + 5 %] [% @layout_name %]") layer_tree_layer = group.addLayer(point_layer) counterTask = point_layer.countSymbolFeatures() counterTask.waitForFinished() # does this even work? layer_tree_layer.setCustomProperty( "legend/title-label", 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]') QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0, 'xxxx') legend.model().refreshLayerLegend(layer_tree_layer) layer_tree_layer.setLabelExpression( 'Concat(@symbol_id, @symbol_label, count("Class"))') legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel( ' sym 1') legend.model().layerLegendNodes(layer_tree_layer)[1].setUserLabel( '[%@symbol_count %]') legend.model().layerLegendNodes(layer_tree_layer)[2].setUserLabel( '[% count("Class") %]') layout.addLayoutItem(legend) legend.setLinkedMap(map) legend.updateLegend() print(layer_tree_layer.labelExpression()) TM = QgsApplication.taskManager() actask = TM.activeTasks() print(TM.tasks(), actask) count = actask[0] count.waitForFinished() map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30)) checker = QgsLayoutChecker('composer_legend_symbol_expression', layout) checker.setControlPathPrefix("composer_legend") sleep(4) result, message = checker.testLayout() self.assertTrue(result, message) QgsProject.instance().removeMapLayers([point_layer.id()])
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
def test_duplicate_chart_in_layout(self): # pylint: disable=too-many-statements """ Test duplicate charts in layout plot up and down """ print('duplicate charts in layout plot up and down') # create project and layout project = QgsProject.instance() layout = QgsPrintLayout(project) layout_name = "PrintLayoutDuplicatePlot" layout.initializeDefaults() layout.setName(layout_name) manager = project.layoutManager() self.assertEqual(True, manager.addLayout(layout)) layout = manager.layoutByName(layout_name) layout_plot = PlotLayoutItem(layout) self.assertEqual(len(layout_plot.plot_settings), 1) # self.assertEqual(len(layout.items()), 0) layout.addLayoutItem(layout_plot) # self.assertEqual(len(layout.items()), 1) plot_dialog = PlotLayoutItemWidget(None, layout_plot) self.assertEqual(len(layout_plot.plot_settings), 1) # edit first plot plot_dialog.setDockMode(True) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('violin') self.assertEqual(plot_property_panel.ptype, 'violin') plot_property_panel.x_combo.setExpression('mid') plot_property_panel.data_defined_properties.setProperty( PlotSettings.PROPERTY_FILTER, QgsProperty.fromExpression('"mid">20')) plot_property_panel.acceptPanel() plot_property_panel.destroy() # duplicate plot plot_dialog.duplicate_plot() self.assertEqual(len(layout_plot.plot_settings), 2) self.assertEqual(layout_plot.plot_settings[0].plot_type, 'violin') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'violin') self.assertEqual((layout_plot.plot_settings[0]).properties['x_name'], 'mid') self.assertEqual((layout_plot.plot_settings[1]).properties['x_name'], 'mid') self.assertEqual( layout_plot.plot_settings[0].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"mid">20')) self.assertEqual( layout_plot.plot_settings[1].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"mid">20')) # edit second plot plot_dialog.plot_list.setCurrentRow(1) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('bar') self.assertEqual(plot_property_panel.ptype, 'bar') plot_property_panel.x_combo.setExpression('qid') plot_property_panel.data_defined_properties.setProperty( PlotSettings.PROPERTY_FILTER, QgsProperty.fromExpression('"qid">20')) plot_property_panel.acceptPanel() plot_property_panel.destroy() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'violin') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'bar') self.assertEqual((layout_plot.plot_settings[0]).properties['x_name'], 'mid') self.assertEqual((layout_plot.plot_settings[1]).properties['x_name'], 'qid') self.assertEqual( layout_plot.plot_settings[0].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"mid">20')) self.assertEqual( layout_plot.plot_settings[1].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"qid">20')) # edit first plot plot_dialog.plot_list.setCurrentRow(0) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('scatter') self.assertEqual(plot_property_panel.ptype, 'scatter') plot_property_panel.x_combo.setExpression('uid') plot_property_panel.data_defined_properties.setProperty( PlotSettings.PROPERTY_FILTER, QgsProperty.fromExpression('"uid">20')) plot_property_panel.acceptPanel() plot_property_panel.destroy() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'scatter') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'bar') self.assertEqual((layout_plot.plot_settings[0]).properties['x_name'], 'uid') self.assertEqual((layout_plot.plot_settings[1]).properties['x_name'], 'qid') self.assertEqual( layout_plot.plot_settings[0].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"uid">20')) self.assertEqual( layout_plot.plot_settings[1].data_defined_properties.property( PlotSettings.PROPERTY_FILTER), QgsProperty.fromExpression('"qid">20')) self.assertEqual(True, manager.removeLayout(layout))
def test_move_chart_in_layout(self): """ Test moving charts in layout plot up and down """ # print('moving charts in layout plot up and down') # create project and layout project = QgsProject.instance() layout = QgsPrintLayout(project) layout_name = "PrintLayoutMovingUpDown" layout.initializeDefaults() layout.setName(layout_name) manager = project.layoutManager() self.assertEqual(True, manager.addLayout(layout)) layout = manager.layoutByName(layout_name) layout_plot = PlotLayoutItem(layout) self.assertEqual(len(layout_plot.plot_settings), 1) # self.assertEqual(len(layout.items()), 0) layout.addLayoutItem(layout_plot) # self.assertEqual(len(layout.items()), 1) plot_dialog = PlotLayoutItemWidget(None, layout_plot) # add second plot plot_dialog.add_plot() self.assertEqual(len(layout_plot.plot_settings), 2) # edit first plot plot_dialog.setDockMode(True) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('violin') self.assertEqual(plot_property_panel.ptype, 'violin') plot_property_panel.acceptPanel() plot_property_panel.destroy() # edit second plot plot_dialog.plot_list.setCurrentRow(1) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('bar') self.assertEqual(plot_property_panel.ptype, 'bar') plot_property_panel.acceptPanel() plot_property_panel.destroy() # move up and down # cannot move up first item plot_dialog.plot_list.setCurrentRow(0) plot_dialog.move_up_plot() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'violin') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'bar') # move up second item plot_dialog.plot_list.setCurrentRow(1) plot_dialog.move_up_plot() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'bar') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'violin') # cannot move down second item plot_dialog.plot_list.setCurrentRow(1) plot_dialog.move_down_plot() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'bar') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'violin') # move down first item plot_dialog.plot_list.setCurrentRow(0) plot_dialog.move_down_plot() self.assertEqual(layout_plot.plot_settings[0].plot_type, 'violin') self.assertEqual(layout_plot.plot_settings[1].plot_type, 'bar') self.assertEqual(True, manager.removeLayout(layout))
def test_read_write_project_with_layout(self): """ Test saving/restoring dialog state of layout plot in project """ # print('read write project with layout test') # create project and layout project = QgsProject.instance() layout = QgsPrintLayout(project) layout_name = "PrintLayoutReadWrite" layout.initializeDefaults() layout.setName(layout_name) layout_plot = PlotLayoutItem(layout) layout_plot.setId('plot_item') plot_item_id = layout_plot.id() self.assertEqual(len(layout_plot.plot_settings), 1) # self.assertEqual(len(layout.items()), 0) layout.addLayoutItem(layout_plot) # self.assertEqual(len(layout.items()), 1) plot_dialog = PlotLayoutItemWidget(None, layout_plot) # add second plot plot_dialog.add_plot() self.assertEqual(len(layout_plot.plot_settings), 2) # edit first plot plot_dialog.setDockMode(True) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('violin') self.assertEqual(plot_property_panel.ptype, 'violin') plot_property_panel.acceptPanel() plot_property_panel.destroy() # edit second plot plot_dialog.plot_list.setCurrentRow(1) plot_dialog.show_properties() plot_property_panel = plot_dialog.panel plot_property_panel.set_plot_type('bar') self.assertEqual(plot_property_panel.ptype, 'bar') plot_property_panel.acceptPanel() plot_property_panel.destroy() # write xml xml_doc = QDomDocument('layout') element = layout.writeXml(xml_doc, QgsReadWriteContext()) layout_plot.remove_plot(0) self.assertEqual(len(layout_plot.plot_settings), 1) self.assertEqual(layout_plot.plot_settings[0].plot_type, 'bar') layout_plot.remove_plot(0) self.assertEqual(len(layout_plot.plot_settings), 0) # read xml layout2 = QgsPrintLayout(project) self.assertTrue( layout2.readXml(element, xml_doc, QgsReadWriteContext())) layout_plot2 = layout2.itemById(plot_item_id) self.assertTrue(layout_plot2) self.assertEqual(len(layout_plot2.plot_settings), 2) self.assertEqual(layout_plot2.plot_settings[0].plot_type, 'violin') self.assertEqual(layout_plot2.plot_settings[1].plot_type, 'bar')
class TestQgsLayoutAtlas(unittest.TestCase): def setUp(self): self.report = "<h1>Python QgsLayoutAtlas Tests</h1>\n" def tearDown(self): report_file_path = "%s/qgistest.html" % QDir.tempPath() with open(report_file_path, 'a') as report_file: report_file.write(self.report) def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob(os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create layout with layout map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.layout = QgsPrintLayout(QgsProject.instance()) self.layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", 'outline_color': 'black'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.atlas_map = QgsLayoutItemMap(self.layout) self.atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) self.atlas_map.setFrameEnabled(True) self.atlas_map.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.atlas_map) # the atlas self.atlas = self.layout.atlas() self.atlas.setCoverageLayer(mVectorLayer) self.atlas.setEnabled(True) # an overview self.overview = QgsLayoutItemMap(self.layout) self.overview.attemptSetSceneRect(QRectF(180, 20, 50, 50)) self.overview.setFrameEnabled(True) self.overview.overview().setLinkedMap(self.atlas_map) self.overview.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.overview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.overview.setExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127", 'outline_color': 'black'} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.overview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.attemptSetSceneRect(QRectF(150, 5, 60, 15)) self.mLabel1.setMarginX(1) self.mLabel1.setMarginY(1) # feature number label self.mLabel2 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel2) self.mLabel2.setText("# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.attemptSetSceneRect(QRectF(150, 200, 60, 15)) self.mLabel2.setMarginX(1) self.mLabel2.setMarginY(1) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() self.rotation_test() shutil.rmtree(tmppath, True) def testReadWriteXml(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setHideCoverage(True) atlas.setFilenameExpression('filename exp') atlas.setCoverageLayer(vector_layer) atlas.setPageNameExpression('page name') atlas.setSortFeatures(True) atlas.setSortAscending(False) atlas.setSortExpression('sort exp') atlas.setFilterFeatures(True) atlas.setFilterExpression('filter exp') doc = QDomDocument("testdoc") elem = l.writeXml(doc, QgsReadWriteContext()) l2 = QgsPrintLayout(p) self.assertTrue(l2.readXml(elem, doc, QgsReadWriteContext())) atlas2 = l2.atlas() self.assertTrue(atlas2.enabled()) self.assertTrue(atlas2.hideCoverage()) self.assertEqual(atlas2.filenameExpression(), 'filename exp') self.assertEqual(atlas2.coverageLayer(), vector_layer) self.assertEqual(atlas2.pageNameExpression(), 'page name') self.assertTrue(atlas2.sortFeatures()) self.assertFalse(atlas2.sortAscending()) self.assertEqual(atlas2.sortExpression(), 'sort exp') self.assertTrue(atlas2.filterFeatures()) self.assertEqual(atlas2.filterExpression(), 'filter exp') def testIteration(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas_feature_changed_spy = QSignalSpy(atlas.featureChanged) context_changed_spy = QSignalSpy(l.reportContext().changed) self.assertTrue(atlas.beginRender()) self.assertTrue(atlas.first()) self.assertEqual(len(atlas_feature_changed_spy), 1) self.assertEqual(len(context_changed_spy), 1) self.assertEqual(atlas.currentFeatureNumber(), 0) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertEqual(l.reportContext().layer(), vector_layer) f1 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 2) self.assertEqual(len(context_changed_spy), 2) self.assertEqual(atlas.currentFeatureNumber(), 1) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') f2 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 3) self.assertEqual(len(context_changed_spy), 3) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') f3 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 4) self.assertEqual(len(context_changed_spy), 4) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') f4 = l.reportContext().feature() self.assertFalse(atlas.next()) self.assertTrue(atlas.seekTo(2)) self.assertEqual(len(atlas_feature_changed_spy), 5) self.assertEqual(len(context_changed_spy), 5) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.last()) self.assertEqual(len(atlas_feature_changed_spy), 6) self.assertEqual(len(context_changed_spy), 6) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 7) self.assertEqual(len(context_changed_spy), 7) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.previous()) self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertFalse(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertTrue(atlas.endRender()) self.assertEqual(len(atlas_feature_changed_spy), 10) self.assertTrue(atlas.seekTo(f1)) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertTrue(atlas.seekTo(f4)) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.seekTo(f3)) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.seekTo(f2)) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') self.assertFalse(atlas.seekTo(QgsFeature(5))) def testUpdateFeature(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) self.assertTrue(atlas.beginRender()) self.assertTrue(atlas.first()) self.assertEqual(atlas.currentFeatureNumber(), 0) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertEqual(l.reportContext().layer(), vector_layer) vector_layer.startEditing() self.assertTrue(vector_layer.changeAttributeValue(l.reportContext().feature().id(), 4, 'Nah, Canberra mate!')) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') l.atlas().refreshCurrentFeature() self.assertEqual(l.reportContext().feature()[4], 'Nah, Canberra mate!') vector_layer.rollBack() def testFileName(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas.setFilenameExpression("'output_' || \"NAME_1\"") self.assertTrue(atlas.beginRender()) self.assertEqual(atlas.count(), 4) atlas.first() self.assertEqual(atlas.currentFilename(), 'output_Basse-Normandie') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Basse-Normandie.png') self.assertEqual(atlas.filePath('/tmp/output/', '.png'), '/tmp/output/output_Basse-Normandie.png') self.assertEqual(atlas.filePath('/tmp/output/', 'svg'), '/tmp/output/output_Basse-Normandie.svg') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Bretagne') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Bretagne.png') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Pays de la Loire') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Pays de la Loire.png') atlas.next() self.assertEqual(atlas.currentFilename(), 'output_Centre') self.assertEqual(atlas.filePath('/tmp/output/', 'png'), '/tmp/output/output_Centre.png') # try changing expression, filename should be updated instantly atlas.setFilenameExpression("'export_' || \"NAME_1\"") self.assertEqual(atlas.currentFilename(), 'export_Centre') atlas.endRender() def testNameForPage(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas.setPageNameExpression("\"NAME_1\"") self.assertTrue(atlas.beginRender()) self.assertEqual(atlas.nameForPage(0), 'Basse-Normandie') self.assertEqual(atlas.nameForPage(1), 'Bretagne') self.assertEqual(atlas.nameForPage(2), 'Pays de la Loire') self.assertEqual(atlas.nameForPage(3), 'Centre') def filename_test(self): self.atlas.setFilenameExpression("'output_' || @atlas_featurenumber") self.atlas.beginRender() for i in range(0, self.atlas.count()): self.atlas.seekTo(i) expected = "output_%d" % (i + 1) self.assertEqual(self.atlas.currentFilename(), expected) self.atlas.endRender() # using feature attribute (refs https://issues.qgis.org/issues/19552) self.atlas.setFilenameExpression("'output_' || attribute(@atlas_feature,'NAME_1')") expected = ['output_Basse-Normandie', 'output_Bretagne', 'output_Pays de la Loire', 'output_Centre'] self.atlas.beginRender() for i in range(0, self.atlas.count()): self.atlas.seekTo(i) self.assertEqual(self.atlas.currentFilename(), expected[i]) self.atlas.endRender() def autoscale_render_test(self): self.atlas_map.setExtent( QgsRectangle(332719.06221504929, 6765214.5887386119, 560957.85090677091, 6993453.3774303338)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_autoscale%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() self.atlas_map.setAtlasDriven(False) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas_map.setAtlasMargin(0) def fixedscale_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_fixedscale%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def predefinedscales_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Predefined) scales = [1800000, 5000000] self.layout.reportContext().setPredefinedScales(scales) for i, s in enumerate(self.layout.reportContext().predefinedScales()): self.assertEqual(s, scales[i]) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_predefinedscales%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def hidden_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(True) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_hiding%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() self.atlas.setHideCoverage(False) def sorting_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(False) self.atlas.setSortFeatures(True) self.atlas.setSortKeyAttributeIndex(4) # departement name self.atlas.setSortAscending(False) self.atlas.beginRender() for i in range(0, 2): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_sorting%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def filtering_render_test(self): self.atlas_map.setExtent(QgsRectangle(209838.166, 6528781.020, 610491.166, 6920530.620)) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Fixed) self.atlas.setHideCoverage(False) self.atlas.setSortFeatures(False) self.atlas.setFilterFeatures(True) self.atlas.setFeatureFilter("substr(NAME_1,1,1)='P'") # select only 'Pays de la loire' self.atlas.beginRender() for i in range(0, 1): self.atlas.seekTo(i) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_filtering%d' % (i + 1), self.layout) checker.setControlPathPrefix("atlas") myTestResult, myMessage = checker.testLayout(0, 200) self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() def legend_test(self): self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) # add a point layer ptLayer = QgsVectorLayer("Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory") pr = ptLayer.dataProvider() f1 = QgsFeature(1) f1.initAttributes(2) f1.setAttribute(0, 1) f1.setAttribute(1, "Test label 1") f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRenderer("attr", [QgsRendererCategory(1, QgsMarkerSymbol.createSimple({"color": "255,0,0", 'outline_color': 'black'}), "red"), QgsRendererCategory(2, QgsMarkerSymbol.createSimple({"color": "0,0,255", 'outline_color': 'black'}), "blue")]) ptLayer.setRenderer(r) QgsProject.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.layers layers = [ptLayer] + layers self.atlas_map.setLayers(layers) self.overview.setLayers(layers) # add a legend legend = QgsLayoutItemLegend(self.layout) legend.attemptMove(QgsLayoutPoint(200, 100)) # sets the legend filter parameter legend.setLinkedMap(self.atlas_map) legend.setLegendFilterOutAtlas(True) self.layout.addLayoutItem(legend) self.atlas.beginRender() self.atlas.seekTo(0) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_legend', self.layout) myTestResult, myMessage = checker.testLayout() self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() # restore state self.atlas_map.setLayers([layers[1]]) self.layout.removeLayoutItem(legend) QgsProject.instance().removeMapLayer(ptLayer.id()) def rotation_test(self): # We will create a polygon layer with a rotated rectangle. # Then we will make it the object layer for the atlas, # rotate the map and test that the bounding rectangle # is smaller than the bounds without rotation. polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) points = [(10, 15), (15, 10), (45, 40), (40, 45)] poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]])) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) # Recreating the layout locally composition = QgsPrintLayout(QgsProject.instance()) composition.initializeDefaults() # the atlas map atlasMap = QgsLayoutItemMap(composition) atlasMap.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlasMap.setFrameEnabled(True) atlasMap.setLayers([polygonLayer]) atlasMap.setExtent(QgsRectangle(0, 0, 100, 50)) composition.addLayoutItem(atlasMap) # the atlas atlas = composition.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlasMap.setAtlasMargin(0.0) # Testing atlasMap.setMapRotation(0.0) atlas.beginRender() atlas.first() nonRotatedExtent = QgsRectangle(atlasMap.extent()) atlasMap.setMapRotation(45.0) atlas.first() rotatedExtent = QgsRectangle(atlasMap.extent()) self.assertLess(rotatedExtent.width(), nonRotatedExtent.width() * 0.9) self.assertLess(rotatedExtent.height(), nonRotatedExtent.height() * 0.9) QgsProject.instance().removeMapLayer(polygonLayer)
def _load_print_layout(self, layer_name, prod_id, dt=None): window_title = "Print" # will be checked with a found composer title """ Avoid creating a new PrintComposer again and again here. Otherwise more and more composers will be added to the list - even with the same name. """ project = QgsProject.instance() # From it, you can get the current layoutManager instance and deduce the layouts layout_manager = project.layoutManager() layout = layout_manager.layoutByName(window_title) if not layout: self.out("no composer found; creating one...") # Load the template into the composer # QGIS 2: #active_composer = self.iface.createNewComposer(window_title) #createNewComposer() #active_composer = QgsComposition(QgsProject.instance()) #layout = QgsLayout(project) layout = QgsPrintLayout(project) layout.initializeDefaults() # initializes default settings for blank print layout canvas q_xmldoc = self._create_qdocument_from_print_template_content() # load layout from template and add to Layout Manager #layout.composition().loadFromTemplate(q_xmldoc) # QGIS 2 layout.loadFromTemplate(q_xmldoc, QgsReadWriteContext()) layout.setName(window_title) layout_manager.addLayout(layout) # Update Logo: #logo_item = layout.getComposerItemById('logo') # QGIS 2 logo_item = layout.itemById('logo') #self.out(">>> logo_item: '{}'".format(logo_item)) # gibt nur die Objekt-ID aus logo_image = self._model.logo_path self.out("Logo: {}".format(logo_image)) if logo_image.exists(): logo_item.setPicturePath(str(logo_image)) else: self.out(" ERROR: logo '{}' not found!".format(logo_image), False) # if """ Hier versuche ich ein für die Überschrift mit einer ID ('headline') versehenes QgsLabel aus dem Template ausfindig zu machen. Ich mache das hier sehr kompliziert, es gibt bestimmt einen einfacheren Weg. Folgendes hat NICHT funktioniert: map_item = active_composer.getComposerItemById('headline') print(active_composer.items()) liefert: [<PyQt4.QtGui.QGraphicsRectItem object at 0x124c60e8>, <qgis._core.QgsComposerLabel object at 0x124c65a8>, ... ] """ ''' other possibility: for item in list(layout.items()): #if type(item) != QgsComposerLabel: ''' # QgsComposerLabel: composer_label = layout.itemById('headline') # a QgsComposerLabel was provided with the ID 'headline' in the template # -> None if not found if composer_label: title = self._model.title(prod_id, dt) subtitle = "" if prod_id != 'RW': subtitle = "\n{}-Produkt (Basis: RW)".format(prod_id) composer_label.setText(title + subtitle) else: # A note that the template needs to be revised: self.out("no element with id 'headline' found!", False) legend = layout.itemById('legend') if not legend: self.out("legend couldn't created!", False) return # # Layer für die Legende ausfindig machen # # You would just need to make sure your layer has a name you can distinguish from others. Instead of: # Vorherige Version: #active_raster_layer = self.iface.activeLayer() # do: l_layer = project.mapLayersByName(layer_name) if not l_layer: self.out("legend: no layer found with name '{}'!".format(layer_name), False) return active_raster_layer = l_layer[0] #print("Legend active_raster_layer id:", active_raster_layer.id()) # ok #print("Legend active_raster_layer name:", active_raster_layer.name()) # ok #legend.model().setLayerSet([layer.id() for layer in layers]) #legend.model().setLayerSet([active_raster_layer.id()]) # bringt nichts # DAS ist es! Dies fügt zumindest erstmal das interessierende Rasterlayer hinzu: #legend.modelV2().rootGroup().addLayer(active_raster_layer) #legend.updateLegend() #for layout in layout_manager.printLayouts(): # iterate layouts ''' would be ok, if we want to create a new legend -> then legend appears at the upper left corner legend = QgsLayoutItemLegend(layout) #legend.setTitle('Legend') legend.setAutoUpdateModel(False) group = legend.model().rootGroup() group.clear() group.addLayer(active_raster_layer) layout.addItem(legend) legend.adjustBoxSize() #legend.refresh() # avoids adding all other layers ''' # uses existing legend object (see above), so we preserve it's layout position: legend.setAutoUpdateModel(False) group = legend.model().rootGroup() group.clear() group.addLayer(active_raster_layer) legend.adjustBoxSize() """ By default the newly created composer items have zero position (top left corner of the page) and zero size. The position and size are always measured in millimeters. # set label 1cm from the top and 2cm from the left of the page composerLabel.setItemPosition(20, 10) # set both label’s position and size (width 10cm, height 3cm) composerLabel.setItemPosition(20, 10, 100, 30) A frame is drawn around each item by default. How to remove the frame: composerLabel.setFrame(False) """ #print(active_composer.rect().width(), active_composer.rect().height()) # 1054 911 #print(self.iface.mapCanvas().size().width(), self.iface.mapCanvas().size().height()) # 1517 535 # "Leinwandgröße": habe keine vernünftigen Werte oben ermittelt (vielleicht Pixel; ich brauche mm). # selbst, mittels Mauszeiger ermittelt: width = 210 height = 297 # Rand neben der Legende (mm): dw = 10 dh = 14 """