diff --git a/python/PyQt6/core/auto_generated/annotations/qgsannotationitem.sip.in b/python/PyQt6/core/auto_generated/annotations/qgsannotationitem.sip.in index 0e5bfb6cee3e..40471f69201e 100644 --- a/python/PyQt6/core/auto_generated/annotations/qgsannotationitem.sip.in +++ b/python/PyQt6/core/auto_generated/annotations/qgsannotationitem.sip.in @@ -146,6 +146,24 @@ Sets the item's z ``index``, which controls the order in which annotation items are rendered in the layer. .. seealso:: :py:func:`zIndex` +%End + + bool enabled() const; +%Docstring +Returns ``True`` if the item is enabled and will be rendered in the layer. + +.. seealso:: :py:func:`setEnabled` + +.. versionadded:: 3.36 +%End + + void setEnabled( bool enabled ); +%Docstring +Sets if the item will be rendered or not in the layer. + +.. seealso:: :py:func:`enabled` + +.. versionadded:: 3.36 %End virtual QList< QgsAnnotationItemNode > nodes() const; diff --git a/python/core/auto_generated/annotations/qgsannotationitem.sip.in b/python/core/auto_generated/annotations/qgsannotationitem.sip.in index 0e5bfb6cee3e..40471f69201e 100644 --- a/python/core/auto_generated/annotations/qgsannotationitem.sip.in +++ b/python/core/auto_generated/annotations/qgsannotationitem.sip.in @@ -146,6 +146,24 @@ Sets the item's z ``index``, which controls the order in which annotation items are rendered in the layer. .. seealso:: :py:func:`zIndex` +%End + + bool enabled() const; +%Docstring +Returns ``True`` if the item is enabled and will be rendered in the layer. + +.. seealso:: :py:func:`setEnabled` + +.. versionadded:: 3.36 +%End + + void setEnabled( bool enabled ); +%Docstring +Sets if the item will be rendered or not in the layer. + +.. seealso:: :py:func:`enabled` + +.. versionadded:: 3.36 %End virtual QList< QgsAnnotationItemNode > nodes() const; diff --git a/src/core/annotations/qgsannotationitem.cpp b/src/core/annotations/qgsannotationitem.cpp index a19bc3d912a6..945226319277 100644 --- a/src/core/annotations/qgsannotationitem.cpp +++ b/src/core/annotations/qgsannotationitem.cpp @@ -40,6 +40,7 @@ QList QgsAnnotationItem::nodes() const void QgsAnnotationItem::copyCommonProperties( const QgsAnnotationItem *other ) { + setEnabled( other->enabled() ); setZIndex( other->zIndex() ); setUseSymbologyReferenceScale( other->useSymbologyReferenceScale() ); setSymbologyReferenceScale( other->symbologyReferenceScale() ); @@ -47,6 +48,7 @@ void QgsAnnotationItem::copyCommonProperties( const QgsAnnotationItem *other ) bool QgsAnnotationItem::writeCommonProperties( QDomElement &element, QDomDocument &, const QgsReadWriteContext & ) const { + element.setAttribute( QStringLiteral( "enabled" ), static_cast( enabled() ) ); element.setAttribute( QStringLiteral( "zIndex" ), zIndex() ); element.setAttribute( QStringLiteral( "useReferenceScale" ), useSymbologyReferenceScale() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ); element.setAttribute( QStringLiteral( "referenceScale" ), qgsDoubleToString( symbologyReferenceScale() ) ); @@ -55,6 +57,7 @@ bool QgsAnnotationItem::writeCommonProperties( QDomElement &element, QDomDocumen bool QgsAnnotationItem::readCommonProperties( const QDomElement &element, const QgsReadWriteContext & ) { + setEnabled( element.attribute( QStringLiteral( "enabled" ) ).toInt() ); setZIndex( element.attribute( QStringLiteral( "zIndex" ) ).toInt() ); setUseSymbologyReferenceScale( element.attribute( QStringLiteral( "useReferenceScale" ), QStringLiteral( "0" ) ).toInt() ); setSymbologyReferenceScale( element.attribute( QStringLiteral( "referenceScale" ) ).toDouble() ); diff --git a/src/core/annotations/qgsannotationitem.h b/src/core/annotations/qgsannotationitem.h index ad1125a8912a..170214f877fe 100644 --- a/src/core/annotations/qgsannotationitem.h +++ b/src/core/annotations/qgsannotationitem.h @@ -174,6 +174,22 @@ class CORE_EXPORT QgsAnnotationItem */ void setZIndex( int index ) { mZIndex = index; } + /** + * Returns TRUE if the item is enabled and will be rendered in the layer. + * + * \see setEnabled() + * \since QGIS 3.36 + */ + bool enabled() const { return mEnabled; } + + /** + * Sets if the item will be rendered or not in the layer. + * + * \see enabled() + * \since QGIS 3.36 + */ + void setEnabled( bool enabled ) { mEnabled = enabled; } + /** * Returns the nodes for the item, used for editing the item. * @@ -259,7 +275,7 @@ class CORE_EXPORT QgsAnnotationItem private: int mZIndex = 0; - + bool mEnabled = true; bool mUseReferenceScale = false; double mReferenceScale = 0; diff --git a/src/core/annotations/qgsannotationlayerrenderer.cpp b/src/core/annotations/qgsannotationlayerrenderer.cpp index 3b4e8bbdad89..ec7ef3af42f4 100644 --- a/src/core/annotations/qgsannotationlayerrenderer.cpp +++ b/src/core/annotations/qgsannotationlayerrenderer.cpp @@ -85,6 +85,9 @@ bool QgsAnnotationLayerRenderer::render() break; } + if ( !item.second->enabled() ) + continue; + std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride; if ( item.second->useSymbologyReferenceScale() ) { diff --git a/tests/src/python/test_qgsannotationlayer.py b/tests/src/python/test_qgsannotationlayer.py index f51ecd1fc235..0c07f8bc8e14 100644 --- a/tests/src/python/test_qgsannotationlayer.py +++ b/tests/src/python/test_qgsannotationlayer.py @@ -597,6 +597,55 @@ def test_render_via_job_with_transform(self): self.assertTrue(compareWkt(result, expected, tol=1000), "mismatch Expected:\n{}\nGot:\n{}\n".format(expected, result)) + def testRenderWithDisabledItems(self): + layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext())) + self.assertTrue(layer.isValid()) + + item = QgsAnnotationPolygonItem( + QgsPolygon(QgsLineString([QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13)]))) + item.setSymbol( + QgsFillSymbol.createSimple({'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2'})) + item.setZIndex(1) + i1_id = layer.addItem(item) + + item = QgsAnnotationLineItem(QgsLineString([QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) + item.setSymbol(QgsLineSymbol.createSimple({'color': '#ffff00', 'line_width': '3'})) + item.setZIndex(2) + item.setEnabled(False) + i2_id = layer.addItem(item) + + layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) + + settings = QgsMapSettings() + settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) + settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518)) + settings.setOutputSize(QSize(300, 300)) + + settings.setFlag(QgsMapSettings.Antialiasing, False) + + rc = QgsRenderContext.fromMapSettings(settings) + rc.setCoordinateTransform(QgsCoordinateTransform(layer.crs(), settings.destinationCrs(), QgsProject.instance())) + rc.setExtent( + rc.coordinateTransform().transformBoundingBox(settings.extent(), QgsCoordinateTransform.ReverseTransform)) + image = QImage(200, 200, QImage.Format_ARGB32) + image.setDotsPerMeterX(int(96 / 25.4 * 1000)) + image.setDotsPerMeterY(int(96 / 25.4 * 1000)) + image.fill(QColor(255, 255, 255)) + painter = QPainter(image) + rc.setPainter(painter) + + try: + renderer = layer.createMapRenderer(rc) + renderer.render() + finally: + painter.end() + + self.assertTrue(self.image_check('layer_render_disabled', 'layer_render_disabled', image)) + # also check details of rendered items + item_details = renderer.takeRenderedItemDetails() + self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 1) + self.assertCountEqual([i.itemId() for i in item_details], [i1_id]) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/annotation_layer/expected_layer_render_disabled/expected_layer_render_disabled.png b/tests/testdata/control_images/annotation_layer/expected_layer_render_disabled/expected_layer_render_disabled.png new file mode 100644 index 000000000000..0fff4975b9fc Binary files /dev/null and b/tests/testdata/control_images/annotation_layer/expected_layer_render_disabled/expected_layer_render_disabled.png differ