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 testProxyModel(self): project = QgsProject() manager = QgsLayoutManager(project) model = QgsLayoutManagerModel(manager) proxy = QgsLayoutManagerProxyModel() proxy.setSourceModel(model) self.assertEqual(proxy.rowCount(QModelIndex()), 0) self.assertEqual( proxy.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) layout = QgsPrintLayout(project) layout.setName('ccc') self.assertTrue(manager.addLayout(layout)) self.assertEqual(proxy.rowCount(QModelIndex()), 1) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), 'ccc') self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) layout2 = QgsPrintLayout(project) layout2.setName('bbb') self.assertTrue(manager.addLayout(layout2)) self.assertEqual(proxy.rowCount(QModelIndex()), 2) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), 'bbb') self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'ccc') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) layout.setName('aaa') self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), 'aaa') self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'bbb') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) model.setAllowEmptyLayout(True) self.assertEqual(proxy.rowCount(QModelIndex()), 3) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'aaa') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), Qt.DisplayRole), 'bbb') self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) r = QgsReport(project) r.setName('ddd') manager.addLayout(r) self.assertEqual(proxy.rowCount(QModelIndex()), 4) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'aaa') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), Qt.DisplayRole), 'bbb') self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) self.assertEqual( proxy.data(proxy.index(3, 0, QModelIndex()), Qt.DisplayRole), 'ddd') self.assertEqual( proxy.data(proxy.index(3, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), r) proxy.setFilters(QgsLayoutManagerProxyModel.FilterPrintLayouts) self.assertEqual(proxy.filters(), QgsLayoutManagerProxyModel.FilterPrintLayouts) self.assertEqual(proxy.rowCount(QModelIndex()), 3) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'aaa') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), Qt.DisplayRole), 'bbb') self.assertEqual( proxy.data(proxy.index(2, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) proxy.setFilters(QgsLayoutManagerProxyModel.FilterReports) self.assertEqual(proxy.filters(), QgsLayoutManagerProxyModel.FilterReports) self.assertEqual(proxy.rowCount(QModelIndex()), 2) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( proxy.data(proxy.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), Qt.DisplayRole), 'ddd') self.assertEqual( proxy.data(proxy.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), r) proxy.setFilters(QgsLayoutManagerProxyModel.FilterPrintLayouts | QgsLayoutManagerProxyModel.FilterReports) self.assertEqual( proxy.filters(), QgsLayoutManagerProxyModel.FilterPrintLayouts | QgsLayoutManagerProxyModel.FilterReports) self.assertEqual(proxy.rowCount(QModelIndex()), 4)
def testModel(self): project = QgsProject() manager = QgsLayoutManager(project) model = QgsLayoutManagerModel(manager) self.assertEqual(model.rowCount(QModelIndex()), 0) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None) self.assertEqual(model.indexFromLayout(None), QModelIndex()) layout = QgsPrintLayout(project) layout.setName('test layout') self.assertEqual(model.indexFromLayout(layout), QModelIndex()) self.assertTrue(manager.addLayout(layout)) self.assertEqual(model.rowCount(QModelIndex()), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'test layout') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), layout) self.assertEqual(model.indexFromLayout(layout), model.index(0, 0, QModelIndex())) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(1, 0, QModelIndex())), None) layout.setName('test Layout') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'test Layout') layout2 = QgsPrintLayout(project) layout2.setName('test layout2') self.assertTrue(manager.addLayout(layout2)) self.assertEqual(model.rowCount(QModelIndex()), 2) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'test Layout') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), layout) self.assertEqual(model.indexFromLayout(layout), model.index(0, 0, QModelIndex())) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'test layout2') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) self.assertEqual( model.layoutFromIndex(model.index(1, 0, QModelIndex())), layout2) self.assertEqual(model.indexFromLayout(layout2), model.index(1, 0, QModelIndex())) manager.removeLayout(layout) self.assertEqual(model.rowCount(QModelIndex()), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'test layout2') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), layout2) self.assertEqual( model.layoutFromIndex(model.index(1, 0, QModelIndex())), None) self.assertEqual(model.indexFromLayout(layout2), model.index(0, 0, QModelIndex())) manager.clear() self.assertEqual(model.rowCount(QModelIndex()), 0) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None) # with empty row model.setAllowEmptyLayout(True) self.assertEqual(model.rowCount(QModelIndex()), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None) layout = QgsPrintLayout(project) layout.setName('test layout') self.assertTrue(manager.addLayout(layout)) self.assertEqual(model.rowCount(QModelIndex()), 2) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'test layout') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( model.data(model.index(2, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(2, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None) self.assertEqual( model.layoutFromIndex(model.index(1, 0, QModelIndex())), layout) self.assertEqual(model.indexFromLayout(layout), model.index(1, 0, QModelIndex())) layout2 = QgsPrintLayout(project) layout2.setName('test layout2') self.assertTrue(manager.addLayout(layout2)) self.assertEqual(model.rowCount(QModelIndex()), 3) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'test layout') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout) self.assertEqual( model.data(model.index(2, 0, QModelIndex()), Qt.DisplayRole), 'test layout2') self.assertEqual( model.data(model.index(2, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), layout2) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None) self.assertEqual( model.layoutFromIndex(model.index(1, 0, QModelIndex())), layout) self.assertEqual( model.layoutFromIndex(model.index(2, 0, QModelIndex())), layout2) self.assertEqual(model.indexFromLayout(layout), model.index(1, 0, QModelIndex())) self.assertEqual(model.indexFromLayout(layout2), model.index(2, 0, QModelIndex())) manager.clear() self.assertEqual(model.rowCount(QModelIndex()), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), None) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsLayoutManagerModel.LayoutRole), None) self.assertEqual( model.layoutFromIndex(model.index(0, 0, QModelIndex())), None)
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): 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 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')
def testReadWriteXml(self): p = QgsProject() l = QgsPrintLayout(p) l.setName('my layout') l.setUnits(QgsUnitTypes.LayoutInches) collection = l.pageCollection() # add a page page = QgsLayoutItemPage(l) page.setPageSize('A6') collection.addPage(page) grid = l.gridSettings() grid.setResolution(QgsLayoutMeasurement(5, QgsUnitTypes.LayoutPoints)) g1 = QgsLayoutGuide( Qt.Horizontal, QgsLayoutMeasurement(5, QgsUnitTypes.LayoutCentimeters), l.pageCollection().page(0)) l.guides().addGuide(g1) snapper = l.snapper() snapper.setSnapTolerance(7) # add some items item1 = QgsLayoutItemMap(l) item1.setId('xxyyxx') l.addItem(item1) item2 = QgsLayoutItemMap(l) item2.setId('zzyyzz') l.addItem(item2) l.setReferenceMap(item2) doc = QDomDocument("testdoc") elem = l.writeXml(doc, QgsReadWriteContext()) l2 = QgsPrintLayout(p) self.assertTrue(l2.readXml(elem, doc, QgsReadWriteContext())) self.assertEqual(l2.name(), 'my layout') self.assertEqual(l2.units(), QgsUnitTypes.LayoutInches) collection2 = l2.pageCollection() self.assertEqual(collection2.pageCount(), 1) self.assertAlmostEqual(collection2.page(0).pageSize().width(), 105, 4) self.assertEqual(collection2.page(0).pageSize().height(), 148) self.assertEqual(l2.gridSettings().resolution().length(), 5.0) self.assertEqual(l2.gridSettings().resolution().units(), QgsUnitTypes.LayoutPoints) self.assertEqual(l2.guides().guidesOnPage(0)[0].orientation(), Qt.Horizontal) self.assertEqual(l2.guides().guidesOnPage(0)[0].position().length(), 5.0) self.assertEqual(l2.guides().guidesOnPage(0)[0].position().units(), QgsUnitTypes.LayoutCentimeters) self.assertEqual(l2.snapper().snapTolerance(), 7) # check restored items new_item1 = l2.itemByUuid(item1.uuid()) self.assertTrue(new_item1) self.assertEqual(new_item1.id(), 'xxyyxx') new_item2 = l2.itemByUuid(item2.uuid()) self.assertTrue(new_item2) self.assertEqual(new_item2.id(), 'zzyyzz') self.assertEqual(l2.referenceMap().id(), 'zzyyzz')
def qgis_composer_renderer(impact_report, component): """Default Map Report Renderer using QGIS Composer. Render using qgis composer for a given impact_report data and component context. :param impact_report: ImpactReport contains data about the report that is going to be generated. :type impact_report: safe.report.impact_report.ImpactReport :param component: Contains the component metadata and context for rendering the output. :type component: safe.report.report_metadata.QgisComposerComponentsMetadata :return: Whatever type of output the component should be. .. versionadded:: 4.0 """ context = component.context qgis_composition_context = impact_report.qgis_composition_context # load composition object layout = QgsPrintLayout(QgsProject.instance()) # load template main_template_folder = impact_report.metadata.template_folder # we do this condition in case custom template was found if component.template.startswith('../qgis-composer-templates/'): template_path = os.path.join(main_template_folder, component.template) else: template_path = component.template with open(template_path) as template_file: template_content = template_file.read() document = QtXml.QDomDocument() # Replace for k, v in context.substitution_map.items(): template_content = template_content.replace('[{}]'.format(k), v) document.setContent(template_content) rwcontext = QgsReadWriteContext() load_status = layout.loadFromTemplate(document, rwcontext) if not load_status: raise TemplateLoadingError( tr('Error loading template: %s') % template_path) # replace image path for img in context.image_elements: item_id = img.get('id') path = img.get('path') image = layout_item(layout, item_id, QgsLayoutItemPicture) if image and path: image.setPicturePath(path) # replace html frame for html_el in context.html_frame_elements: item_id = html_el.get('id') mode = html_el.get('mode') html_element = layout_item(layout, item_id, QgsLayoutItemHtml) if html_element: if mode == 'text': text = html_el.get('text') text = text if text else '' html_element.setContentMode(QgsLayoutItemHtml.ManualHtml) html_element.setHtml(text) html_element.loadHtml() elif mode == 'url': url = html_el.get('url') html_element.setContentMode(QgsLayoutItemHtml.Url) qurl = QUrl.fromLocalFile(url) html_element.setUrl(qurl) original_crs = impact_report.impact_function.crs destination_crs = qgis_composition_context.map_settings.destinationCrs() coord_transform = QgsCoordinateTransform(original_crs, destination_crs, QgsProject.instance()) # resize map extent for map_el in context.map_elements: item_id = map_el.get('id') split_count = map_el.get('grid_split_count') layers = [ _layer for _layer in map_el.get('layers') if isinstance(_layer, QgsMapLayer) ] map_extent_option = map_el.get('extent') composer_map = layout_item(layout, item_id, QgsLayoutItemMap) for index, _layer in enumerate(layers): # we need to check whether the layer is registered or not registered_layer = (QgsProject.instance().mapLayer(_layer.id())) if registered_layer: if not registered_layer == _layer: layers[index] = registered_layer else: QgsProject.instance().addMapLayer(_layer) """:type: qgis.core.QgsLayoutItemMap""" if composer_map: # Search for specified map extent in the template. min_x = composer_map.extent().xMinimum() if ( impact_report.use_template_extent) else None min_y = composer_map.extent().yMinimum() if ( impact_report.use_template_extent) else None max_x = composer_map.extent().xMaximum() if ( impact_report.use_template_extent) else None max_y = composer_map.extent().yMaximum() if ( impact_report.use_template_extent) else None composer_map.setKeepLayerSet(True) layer_set = [ _layer for _layer in layers if isinstance(_layer, QgsMapLayer) ] composer_map.setLayers(layer_set) map_overview_extent = None if map_extent_option and isinstance(map_extent_option, QgsRectangle): # use provided map extent extent = coord_transform.transform(map_extent_option) for layer in layer_set: layer_extent = coord_transform.transform(layer.extent()) if layer.name() == map_overview['id']: map_overview_extent = layer_extent else: # if map extent not provided, try to calculate extent # from list of given layers. Combine it so all layers were # shown properly extent = QgsRectangle() extent.setMinimal() for layer in layer_set: # combine extent if different layer is provided. layer_extent = coord_transform.transform(layer.extent()) extent.combineExtentWith(layer_extent) if layer.name() == map_overview['id']: map_overview_extent = layer_extent width = extent.width() height = extent.height() longest_width = width if width > height else height half_length = longest_width / 2 margin = half_length / 5 center = extent.center() min_x = min_x or (center.x() - half_length - margin) max_x = max_x or (center.x() + half_length + margin) min_y = min_y or (center.y() - half_length - margin) max_y = max_y or (center.y() + half_length + margin) # noinspection PyCallingNonCallable square_extent = QgsRectangle(min_x, min_y, max_x, max_y) if component.key == 'population-infographic' and ( map_overview_extent): square_extent = map_overview_extent composer_map.zoomToExtent(square_extent) composer_map.invalidateCache() actual_extent = composer_map.extent() # calculate intervals for grid x_interval = actual_extent.width() / split_count composer_map.grid().setIntervalX(x_interval) y_interval = actual_extent.height() / split_count composer_map.grid().setIntervalY(y_interval) # calculate legend element for leg_el in context.map_legends: item_id = leg_el.get('id') title = leg_el.get('title') layers = [ _layer for _layer in leg_el.get('layers') if isinstance(_layer, QgsMapLayer) ] symbol_count = leg_el.get('symbol_count') column_count = leg_el.get('column_count') legend = layout_item(layout, item_id, QgsLayoutItemLegend) """:type: qgis.core.QgsLayoutItemLegend""" if legend: # set column count if column_count: legend.setColumnCount(column_count) elif symbol_count <= 7: legend.setColumnCount(1) else: legend.setColumnCount(symbol_count / 7 + 1) # set legend title if title is not None and not impact_report.legend_layers: legend.setTitle(title) # set legend root_group = legend.model().rootGroup() for _layer in layers: # we need to check whether the layer is registered or not registered_layer = (QgsProject.instance().mapLayer( _layer.id())) if registered_layer: if not registered_layer == _layer: _layer = registered_layer else: QgsProject.instance().addMapLayer(_layer) # used for customizations tree_layer = root_group.addLayer(_layer) if impact_report.legend_layers or ( not impact_report.multi_exposure_impact_function): QgsLegendRenderer.setNodeLegendStyle( tree_layer, QgsLegendStyle.Hidden) legend.adjustBoxSize() legend.updateFilterByMap(False) # process to output # in case output folder not specified if impact_report.output_folder is None: impact_report.output_folder = mkdtemp(dir=temp_dir()) output_format = component.output_format component_output_path = impact_report.component_absolute_output_path( component.key) component_output = None doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT template_format = QgisComposerComponentsMetadata.OutputFormat.QPT if isinstance(output_format, list): component_output = [] for i in range(len(output_format)): each_format = output_format[i] each_path = component_output_path[i] if each_format in doc_format: result_path = create_qgis_pdf_output(impact_report, each_path, layout, each_format, component) component_output.append(result_path) elif each_format == template_format: result_path = create_qgis_template_output(each_path, layout) component_output.append(result_path) elif isinstance(output_format, dict): component_output = {} for key, each_format in list(output_format.items()): each_path = component_output_path[key] if each_format in doc_format: result_path = create_qgis_pdf_output(impact_report, each_path, layout, each_format, component) component_output[key] = result_path elif each_format == template_format: result_path = create_qgis_template_output(each_path, layout) component_output[key] = result_path elif (output_format in QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT): component_output = None if output_format in doc_format: result_path = create_qgis_pdf_output(impact_report, component_output_path, layout, output_format, component) component_output = result_path elif output_format == template_format: result_path = create_qgis_template_output(component_output_path, layout) component_output = result_path component.output = component_output return component.output
def qgis_composer_html_renderer(impact_report, component): """HTML to PDF renderer using QGIS Composer. Render using qgis composer for a given impact_report data and component context for html input. :param impact_report: ImpactReport contains data about the report that is going to be generated. :type impact_report: safe.report.impact_report.ImpactReport :param component: Contains the component metadata and context for rendering the output. :type component: safe.report.report_metadata.QgisComposerComponentsMetadata :return: Whatever type of output the component should be. .. versionadded:: 4.0 """ context = component.context # QGIS3: not used # qgis_composition_context = impact_report.qgis_composition_context # create new layout with A4 portrait page layout = QgsPrintLayout(QgsProject.instance()) page = QgsLayoutItemPage(layout) page.setPageSize('A4', orientation=QgsLayoutItemPage.Portrait) layout.pageCollection().addPage(page) if not context.html_frame_elements: # if no html frame elements at all, do not generate empty report. component.output = '' return component.output # Add HTML Frame for html_el in context.html_frame_elements: mode = html_el.get('mode') html_element = QgsLayoutItemHtml(layout) margin_left = html_el.get('margin_left', 10) margin_top = html_el.get('margin_top', 10) width = html_el.get('width', component.page_width - 2 * margin_left) height = html_el.get('height', component.page_height - 2 * margin_top) html_frame = QgsLayoutFrame(layout, html_element) html_frame.attemptSetSceneRect( QRectF(margin_left, margin_top, width, height)) html_element.addFrame(html_frame) if html_element: if mode == 'text': text = html_el.get('text') text = text if text else '' html_element.setContentMode(QgsLayoutItemHtml.ManualHtml) html_element.setResizeMode( QgsLayoutItemHtml.RepeatUntilFinished) html_element.setHtml(text) html_element.loadHtml() elif mode == 'url': url = html_el.get('url') html_element.setContentMode(QgsLayoutItemHtml.Url) html_element.setResizeMode( QgsLayoutItemHtml.RepeatUntilFinished) qurl = QUrl.fromLocalFile(url) html_element.setUrl(qurl) # Attempt on removing blank page. Notes: We assume that the blank page # will always appears in the last x page(s), not in the middle. pc = layout.pageCollection() index = pc.pageCount() while pc.pageIsEmpty(index): pc.deletePage(index) index -= 1 # process to output # in case output folder not specified if impact_report.output_folder is None: impact_report.output_folder = mkdtemp(dir=temp_dir()) component_output_path = impact_report.component_absolute_output_path( component.key) component_output = None output_format = component.output_format doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT template_format = QgisComposerComponentsMetadata.OutputFormat.QPT if isinstance(output_format, list): component_output = [] for i in range(len(output_format)): each_format = output_format[i] each_path = component_output_path[i] if each_format in doc_format: result_path = create_qgis_pdf_output(impact_report, each_path, layout, each_format, component) component_output.append(result_path) elif each_format == template_format: result_path = create_qgis_template_output(each_path, layout) component_output.append(result_path) elif isinstance(output_format, dict): component_output = {} for key, each_format in list(output_format.items()): each_path = component_output_path[key] if each_format in doc_format: result_path = create_qgis_pdf_output(impact_report, each_path, layout, each_format, component) component_output[key] = result_path elif each_format == template_format: result_path = create_qgis_template_output(each_path, layout) component_output[key] = result_path elif (output_format in QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT): component_output = None if output_format in doc_format: result_path = create_qgis_pdf_output(impact_report, component_output_path, layout, output_format, component) component_output = result_path elif output_format == template_format: result_path = create_qgis_template_output(component_output_path, layout) component_output = result_path component.output = component_output return component.output