def test_datadefined_margin(self): polygonLayer = QgsVectorLayer('Polygon?field=margin:int', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([0]) poly.setGeometry( QgsGeometry.fromWkt( 'Polygon((30 30, 40 30, 40 40, 30 40, 30 30))')) polygonLayer.dataProvider().addFeatures([poly]) poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([10]) poly.setGeometry( QgsGeometry.fromWkt( 'Polygon((10 10, 20 10, 20 20, 10 20, 10 10))')) polygonLayer.dataProvider().addFeatures([poly]) poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([20]) poly.setGeometry( QgsGeometry.fromWkt( 'Polygon((50 50, 60 50, 60 60, 50 60, 50 50))')) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) layout = QgsPrintLayout(QgsProject.instance()) map = QgsLayoutItemMap(layout) map.setCrs(polygonLayer.crs()) map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) map.setFrameEnabled(True) map.setLayers([polygonLayer]) map.setExtent(QgsRectangle(0, 0, 100, 50)) layout.addLayoutItem(map) atlas = layout.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) map.setAtlasDriven(True) map.setAtlasScalingMode(QgsLayoutItemMap.Auto) map.setAtlasMargin(77.0) map.dataDefinedProperties().setProperty( QgsLayoutObject.MapAtlasMargin, QgsProperty.fromExpression('margin/2')) atlas.beginRender() atlas.first() self.assertEqual(map.extent(), QgsRectangle(25, 30, 45, 40)) self.assertTrue(atlas.next()) self.assertEqual(map.extent(), QgsRectangle(4.5, 9.75, 25.5, 20.25)) self.assertTrue(atlas.next()) self.assertEqual(map.extent(), QgsRectangle(44, 49.5, 66, 60.5)) QgsProject.instance().removeMapLayer(polygonLayer)
def testCrsChanged(self): """ Test that the CRS changed signal is emitted in the right circumstances """ p = QgsProject() layout = QgsLayout(p) p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) map = QgsLayoutItemMap(layout) grid = map.grid() spy = QSignalSpy(grid.crsChanged) # map grid and map have no explicit crs set, so follows project crs => signal should be emitted # when project crs is changed p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(len(spy), 1) p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(len(spy), 2) # set explicit crs on map item map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356')) self.assertEqual(len(spy), 3) map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356')) self.assertEqual(len(spy), 3) map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355')) self.assertEqual(len(spy), 4) # should not care about project crs changes anymore.. p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(len(spy), 4) # set back to project crs map.setCrs(QgsCoordinateReferenceSystem()) self.assertEqual(len(spy), 5) map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355')) self.assertEqual(len(spy), 6) # data defined crs map.dataDefinedProperties().setProperty( QgsLayoutObject.MapCrs, QgsProperty.fromValue('EPSG:4283')) self.assertEqual(len(spy), 6) map.refresh() self.assertEqual(len(spy), 7) # explicit crs for map grid grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3857')) self.assertEqual(len(spy), 8) grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3857')) self.assertEqual(len(spy), 8) map.dataDefinedProperties().setProperty( QgsLayoutObject.MapCrs, QgsProperty.fromValue('EPSG:3111')) map.refresh() self.assertEqual(len(spy), 8) grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(len(spy), 9)
def testDataDefinedBackgroundColor(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemMap(layout) item.setBackgroundColor(QColor(255, 0, 0)) self.assertEqual(item.backgroundColor(), QColor(255, 0, 0)) self.assertEqual(item.brush().color().name(), QColor(255, 0, 0).name()) item.dataDefinedProperties().setProperty(QgsLayoutObject.BackgroundColor, QgsProperty.fromExpression("'blue'")) item.refreshDataDefinedProperty() self.assertEqual(item.backgroundColor(), QColor(255, 0, 0)) # should not change self.assertEqual(item.brush().color().name(), QColor(0, 0, 255).name())
def testDataDefinedBackgroundColor(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemMap(layout) item.setBackgroundColor(QColor(255, 0, 0)) self.assertEqual(item.backgroundColor(), QColor(255, 0, 0)) self.assertEqual(item.brush().color().name(), QColor(255, 0, 0).name()) item.dataDefinedProperties().setProperty(QgsLayoutObject.BackgroundColor, QgsProperty.fromExpression("'blue'")) item.refreshDataDefinedProperty() self.assertEqual(item.backgroundColor(), QColor(255, 0, 0)) # should not change self.assertEqual(item.brush().color().name(), QColor(0, 0, 255).name())
def testDataDefinedFrameColor(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemMap(layout) item.setFrameEnabled(True) item.setFrameStrokeColor(QColor(255, 0, 0)) self.assertEqual(item.frameStrokeColor(), QColor(255, 0, 0)) self.assertEqual(item.pen().color().name(), QColor(255, 0, 0).name()) item.dataDefinedProperties().setProperty(QgsLayoutObject.FrameColor, QgsProperty.fromExpression("'blue'")) item.refreshDataDefinedProperty() self.assertEqual(item.frameStrokeColor(), QColor(255, 0, 0)) # should not change self.assertEqual(item.pen().color().name(), QColor(0, 0, 255).name())
def testDataDefinedFrameColor(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemMap(layout) item.setFrameEnabled(True) item.setFrameStrokeColor(QColor(255, 0, 0)) self.assertEqual(item.frameStrokeColor(), QColor(255, 0, 0)) self.assertEqual(item.pen().color().name(), QColor(255, 0, 0).name()) item.dataDefinedProperties().setProperty(QgsLayoutObject.FrameColor, QgsProperty.fromExpression("'blue'")) item.refreshDataDefinedProperty() self.assertEqual(item.frameStrokeColor(), QColor(255, 0, 0)) # should not change self.assertEqual(item.pen().color().name(), QColor(0, 0, 255).name())
def test_datadefined_margin(self): polygonLayer = QgsVectorLayer('Polygon?field=margin:int', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([0]) poly.setGeometry(QgsGeometry.fromWkt('Polygon((30 30, 40 30, 40 40, 30 40, 30 30))')) polygonLayer.dataProvider().addFeatures([poly]) poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([10]) poly.setGeometry(QgsGeometry.fromWkt('Polygon((10 10, 20 10, 20 20, 10 20, 10 10))')) polygonLayer.dataProvider().addFeatures([poly]) poly = QgsFeature(polygonLayer.fields()) poly.setAttributes([20]) poly.setGeometry(QgsGeometry.fromWkt('Polygon((50 50, 60 50, 60 60, 50 60, 50 50))')) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) layout = QgsPrintLayout(QgsProject.instance()) map = QgsLayoutItemMap(layout) map.setCrs(polygonLayer.crs()) map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) map.setFrameEnabled(True) map.setLayers([polygonLayer]) map.setExtent(QgsRectangle(0, 0, 100, 50)) layout.addLayoutItem(map) atlas = layout.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) map.setAtlasDriven(True) map.setAtlasScalingMode(QgsLayoutItemMap.Auto) map.setAtlasMargin(77.0) map.dataDefinedProperties().setProperty(QgsLayoutObject.MapAtlasMargin, QgsProperty.fromExpression('margin/2')) atlas.beginRender() atlas.first() self.assertEqual(map.extent(), QgsRectangle(25, 30, 45, 40)) self.assertTrue(atlas.next()) self.assertEqual(map.extent(), QgsRectangle(4.5, 9.75, 25.5, 20.25)) self.assertTrue(atlas.next()) self.assertEqual(map.extent(), QgsRectangle(44, 49.5, 66, 60.5)) QgsProject.instance().removeMapLayer(polygonLayer)
def testContainsAdvancedEffectsAndRasterization(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemLabel(layout) self.assertFalse(item.containsAdvancedEffects()) # item opacity requires that the individual item be flattened to a raster item item.setItemOpacity(0.5) self.assertTrue(item.containsAdvancedEffects()) # but not the WHOLE layout self.assertFalse(item.requiresRasterization()) item.dataDefinedProperties().setProperty( QgsLayoutObject.Opacity, QgsProperty.fromExpression('100')) item.refresh() self.assertFalse(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) item.dataDefinedProperties().setProperty(QgsLayoutObject.Opacity, QgsProperty()) item.refresh() self.assertTrue(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) item.setItemOpacity(1.0) self.assertFalse(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) # item blend mode is NOT an advanced effect -- rather it requires that the WHOLE layout be rasterized to achieve item.setBlendMode(QPainter.CompositionMode_DestinationAtop) self.assertFalse(item.containsAdvancedEffects()) self.assertTrue(item.requiresRasterization()) map = QgsLayoutItemMap(layout) # map items are different -- because they override paint, they don't get the auto-flattening and rasterization map.setItemOpacity(0.5) self.assertFalse(map.containsAdvancedEffects()) # rather, a map with opacity requires the WHOLE layout to be rasterized self.assertTrue(map.requiresRasterization()) map.dataDefinedProperties().setProperty( QgsLayoutObject.Opacity, QgsProperty.fromExpression('100')) map.refresh() self.assertFalse(map.containsAdvancedEffects()) self.assertTrue(map.requiresRasterization())
def testContainsAdvancedEffectsAndRasterization(self): layout = QgsLayout(QgsProject.instance()) item = QgsLayoutItemLabel(layout) self.assertFalse(item.containsAdvancedEffects()) # item opacity requires that the individual item be flattened to a raster item item.setItemOpacity(0.5) self.assertTrue(item.containsAdvancedEffects()) # but not the WHOLE layout self.assertFalse(item.requiresRasterization()) item.dataDefinedProperties().setProperty(QgsLayoutObject.Opacity, QgsProperty.fromExpression('100')) item.refresh() self.assertFalse(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) item.dataDefinedProperties().setProperty(QgsLayoutObject.Opacity, QgsProperty()) item.refresh() self.assertTrue(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) item.setItemOpacity(1.0) self.assertFalse(item.containsAdvancedEffects()) self.assertFalse(item.requiresRasterization()) # item blend mode is NOT an advanced effect -- rather it requires that the WHOLE layout be rasterized to achieve item.setBlendMode(QPainter.CompositionMode_DestinationAtop) self.assertFalse(item.containsAdvancedEffects()) self.assertTrue(item.requiresRasterization()) map = QgsLayoutItemMap(layout) # map items are different -- because they override paint, they don't get the auto-flattening and rasterization map.setItemOpacity(0.5) self.assertFalse(map.containsAdvancedEffects()) # rather, a map with opacity requires the WHOLE layout to be rasterized self.assertTrue(map.requiresRasterization()) map.dataDefinedProperties().setProperty(QgsLayoutObject.Opacity, QgsProperty.fromExpression('100')) map.refresh() self.assertFalse(map.containsAdvancedEffects()) self.assertTrue(map.requiresRasterization())
def testLabelMargin(self): """ Test rendering map item with a label margin set """ format = QgsTextFormat() format.setFont(QgsFontUtils.getStandardTestFont("Bold")) format.setSize(20) format.setNamedStyle("Bold") format.setColor(QColor(0, 0, 0)) settings = QgsPalLayerSettings() settings.setFormat(format) settings.fieldName = "'X'" settings.isExpression = True settings.placement = QgsPalLayerSettings.OverPoint vl = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer", "vl", "memory") vl.setRenderer(QgsNullSymbolRenderer()) f = QgsFeature(vl.fields(), 1) for x in range(15): for y in range(15): f.setGeometry(QgsPoint(x, y)) vl.dataProvider().addFeature(f) vl.setLabeling(QgsVectorLayerSimpleLabeling(settings)) vl.setLabelsEnabled(True) p = QgsProject() engine_settings = QgsLabelingEngineSettings() engine_settings.setFlag(QgsLabelingEngineSettings.UsePartialCandidates, False) engine_settings.setFlag(QgsLabelingEngineSettings.DrawLabelRectOnly, True) p.setLabelingEngineSettings(engine_settings) p.addMapLayer(vl) layout = QgsLayout(p) layout.initializeDefaults() p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(10, 10, 180, 180)) map.setFrameEnabled(True) map.zoomToExtent(vl.extent()) map.setLayers([vl]) layout.addLayoutItem(map) checker = QgsLayoutChecker('composermap_label_nomargin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setLabelMargin( QgsLayoutMeasurement(15, QgsUnitTypes.LayoutMillimeters)) checker = QgsLayoutChecker('composermap_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setLabelMargin( QgsLayoutMeasurement(3, QgsUnitTypes.LayoutCentimeters)) checker = QgsLayoutChecker('composermap_label_cm_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setMapRotation(45) map.zoomToExtent(vl.extent()) map.setScale(map.scale() * 1.2) checker = QgsLayoutChecker('composermap_rotated_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) # data defined map.setMapRotation(0) map.zoomToExtent(vl.extent()) map.dataDefinedProperties().setProperty( QgsLayoutObject.MapLabelMargin, QgsProperty.fromExpression('1+3')) map.refresh() checker = QgsLayoutChecker('composermap_dd_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message)
def testLabelMargin(self): """ Test rendering map item with a label margin set """ format = QgsTextFormat() format.setFont(QgsFontUtils.getStandardTestFont("Bold")) format.setSize(20) format.setNamedStyle("Bold") format.setColor(QColor(0, 0, 0)) settings = QgsPalLayerSettings() settings.setFormat(format) settings.fieldName = "'X'" settings.isExpression = True settings.placement = QgsPalLayerSettings.OverPoint vl = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer", "vl", "memory") vl.setRenderer(QgsNullSymbolRenderer()) f = QgsFeature(vl.fields(), 1) for x in range(15): for y in range(15): f.setGeometry(QgsPoint(x, y)) vl.dataProvider().addFeature(f) vl.setLabeling(QgsVectorLayerSimpleLabeling(settings)) vl.setLabelsEnabled(True) p = QgsProject() engine_settings = QgsLabelingEngineSettings() engine_settings.setFlag(QgsLabelingEngineSettings.UsePartialCandidates, False) engine_settings.setFlag(QgsLabelingEngineSettings.DrawLabelRectOnly, True) p.setLabelingEngineSettings(engine_settings) p.addMapLayer(vl) layout = QgsLayout(p) layout.initializeDefaults() p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(10, 10, 180, 180)) map.setFrameEnabled(True) map.zoomToExtent(vl.extent()) map.setLayers([vl]) layout.addLayoutItem(map) checker = QgsLayoutChecker('composermap_label_nomargin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setLabelMargin(QgsLayoutMeasurement(15, QgsUnitTypes.LayoutMillimeters)) checker = QgsLayoutChecker('composermap_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setLabelMargin(QgsLayoutMeasurement(3, QgsUnitTypes.LayoutCentimeters)) checker = QgsLayoutChecker('composermap_label_cm_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) map.setMapRotation(45) map.zoomToExtent(vl.extent()) map.setScale(map.scale() * 1.2) checker = QgsLayoutChecker('composermap_rotated_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message) # data defined map.setMapRotation(0) map.zoomToExtent(vl.extent()) map.dataDefinedProperties().setProperty(QgsLayoutObject.MapLabelMargin, QgsProperty.fromExpression('1+3')) map.refresh() checker = QgsLayoutChecker('composermap_dd_label_margin', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() self.report += checker.report() self.assertTrue(result, message)