From f54cba7226c448990cc637f57769be3157959cb2 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 28 Jul 2023 10:17:11 +1000 Subject: [PATCH] Add API to set specific symbol to render for selected features in a vector layer If set, then that symbol will be used for selected features. Allows eg selected lines to be rendered in a thicker line style vs non-selected lines for improved visibility. --- .../qgsvectorlayerselectionproperties.sip.in | 21 +++++ src/core/vector/qgsvectorlayerrenderer.cpp | 81 +++++++++++++++--- src/core/vector/qgsvectorlayerrenderer.h | 2 + .../qgsvectorlayerselectionproperties.cpp | 26 ++++++ .../qgsvectorlayerselectionproperties.h | 24 +++++- tests/src/python/test_qgsvectorlayer.py | 22 ++++- .../src/python/test_qgsvectorlayerrenderer.py | 41 +++++++++ .../expected_selection_symbol.png | Bin 0 -> 471523 bytes 8 files changed, 202 insertions(+), 15 deletions(-) create mode 100644 tests/testdata/control_images/vectorlayerrenderer/expected_selection_symbol/expected_selection_symbol.png diff --git a/python/core/auto_generated/vector/qgsvectorlayerselectionproperties.sip.in b/python/core/auto_generated/vector/qgsvectorlayerselectionproperties.sip.in index 5e5eca93d5d7..d42d818e2042 100644 --- a/python/core/auto_generated/vector/qgsvectorlayerselectionproperties.sip.in +++ b/python/core/auto_generated/vector/qgsvectorlayerselectionproperties.sip.in @@ -11,6 +11,7 @@ + class QgsVectorLayerSelectionProperties : QgsMapLayerSelectionProperties { %Docstring(signature="appended") @@ -28,6 +29,7 @@ Implementation of layer selection properties for vector layers. %Docstring Constructor for QgsVectorLayerSelectionProperties, with the specified ``parent`` object. %End + ~QgsVectorLayerSelectionProperties(); virtual QDomElement writeXml( QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context ); @@ -54,6 +56,25 @@ An invalid ``color`` indicates that the default (i.e. project level) selection color should be used instead. .. seealso:: :py:func:`selectionColor` +%End + + QgsSymbol *selectionSymbol() const; +%Docstring +Returns the symbol used to render selected features in the layer. + +May be ``None`` if the default symbol should be used instead. + +.. seealso:: :py:func:`setSelectionSymbol` +%End + + void setSelectionSymbol( QgsSymbol *symbol /Transfer/ ); +%Docstring +Sets the ``symbol`` used to render selected features in the layer. + +Ownership of ``symbol`` is transferred to the plot. If ``symbol`` is ``None`` then +the default symbol will be used instead. + +.. seealso:: :py:func:`selectionSymbol` %End }; diff --git a/src/core/vector/qgsvectorlayerrenderer.cpp b/src/core/vector/qgsvectorlayerrenderer.cpp index 2f8c69442685..77e2141040f1 100644 --- a/src/core/vector/qgsvectorlayerrenderer.cpp +++ b/src/core/vector/qgsvectorlayerrenderer.cpp @@ -59,6 +59,9 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer *layer, QgsRender if ( layerSelectionColor.isValid() ) context.setSelectionColor( layerSelectionColor ); + if ( QgsSymbol *selectionSymbol = qobject_cast< QgsVectorLayerSelectionProperties * >( layer->selectionProperties() )->selectionSymbol() ) + mSelectionSymbol.reset( selectionSymbol->clone() ); + if ( !mainRenderer ) return; @@ -450,6 +453,9 @@ void QgsVectorLayerRenderer::drawRenderer( QgsFeatureRenderer *renderer, QgsFeat clipEngine->prepareGeometry(); } + if ( mSelectionSymbol && isMainRenderer ) + mSelectionSymbol->startRender( context, mFields ); + QgsFeature fet; while ( fit.nextFeature( fet ) ) { @@ -473,14 +479,24 @@ void QgsVectorLayerRenderer::drawRenderer( QgsFeatureRenderer *renderer, QgsFeat if ( ! mNoSetLayerExpressionContext ) context.expressionContext().setFeature( fet ); - bool sel = isMainRenderer && context.showSelection() && mSelectedFeatureIds.contains( fet.id() ); - bool drawMarker = isMainRenderer && ( mDrawVertexMarkers && context.drawEditingInformation() && ( !mVertexMarkerOnlyForSelection || sel ) ); + const bool featureIsSelected = isMainRenderer && context.showSelection() && mSelectedFeatureIds.contains( fet.id() ); + bool drawMarker = isMainRenderer && ( mDrawVertexMarkers && context.drawEditingInformation() && ( !mVertexMarkerOnlyForSelection || featureIsSelected ) ); // render feature bool rendered = false; if ( !context.testFlag( Qgis::RenderContextFlag::SkipSymbolRendering ) ) { - rendered = renderer->renderFeature( fet, context, -1, sel, drawMarker ); + if ( featureIsSelected && mSelectionSymbol ) + { + // note: here we pass "false" for the selected argument, as we don't want to change + // the user's defined selection symbol colors or settings in any way + mSelectionSymbol->renderFeature( fet, context, -1, false, drawMarker ); + rendered = renderer->willRenderFeature( fet, context ); + } + else + { + rendered = renderer->renderFeature( fet, context, -1, featureIsSelected, drawMarker ); + } } else { @@ -542,6 +558,9 @@ void QgsVectorLayerRenderer::drawRenderer( QgsFeatureRenderer *renderer, QgsFeat delete context.expressionContext().popScope(); + if ( mSelectionSymbol && isMainRenderer ) + mSelectionSymbol->stopRender( context ); + stopRenderer( renderer, nullptr ); } @@ -625,7 +644,7 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q if ( renderer->orderByEnabled() ) { QVector currentValues; - for ( auto const idx : orderByAttributeIdx ) + for ( const int idx : std::as_const( orderByAttributeIdx ) ) { currentValues.push_back( fet.attribute( idx ) ); } @@ -644,11 +663,13 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q if ( !context.testFlag( Qgis::RenderContextFlag::SkipSymbolRendering ) ) { - if ( !features.back().contains( sym ) ) + QHash > &featuresBack = features.back(); + auto featuresBackIt = featuresBack.find( sym ); + if ( featuresBackIt == featuresBack.end() ) { - features.back().insert( sym, QList() ); + featuresBackIt = featuresBack.insert( sym, QList() ); } - features.back()[sym].append( fet ); + featuresBackIt->append( fet ); } // new labeling engine @@ -713,7 +734,7 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q context.setFeatureClipGeometry( mClipFeatureGeom ); // 2. draw features in correct order - for ( auto &featureLists : features ) + for ( const QHash< QgsSymbol *, QList > &featureLists : features ) { for ( int l = 0; l < levels.count(); l++ ) { @@ -728,7 +749,7 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q } const int layer = item.layer(); const QList &lst = featureLists[item.symbol()]; - for ( auto fit = lst.begin(); fit != lst.end(); ++fit ) + for ( const QgsFeature &feature : lst ) { if ( context.renderingStopped() ) { @@ -736,16 +757,19 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q return; } - const bool sel = isMainRenderer && context.showSelection() && mSelectedFeatureIds.contains( fit->id() ); + const bool featureIsSelected = isMainRenderer && context.showSelection() && mSelectedFeatureIds.contains( feature.id() ); + if ( featureIsSelected && mSelectionSymbol ) + continue; // defer rendering of selected symbols + // maybe vertex markers should be drawn only during the last pass... - const bool drawMarker = isMainRenderer && ( mDrawVertexMarkers && context.drawEditingInformation() && ( !mVertexMarkerOnlyForSelection || sel ) ); + const bool drawMarker = isMainRenderer && ( mDrawVertexMarkers && context.drawEditingInformation() && ( !mVertexMarkerOnlyForSelection || featureIsSelected ) ); if ( ! mNoSetLayerExpressionContext ) - context.expressionContext().setFeature( *fit ); + context.expressionContext().setFeature( feature ); try { - renderer->renderFeature( *fit, context, layer, sel, drawMarker ); + renderer->renderFeature( feature, context, layer, featureIsSelected, drawMarker ); // as soon as first feature is rendered, we can start showing layer updates. // but if we are blocking render updates (so that a previously cached image is being shown), we wait @@ -766,6 +790,37 @@ void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureRenderer *renderer, Q } } + if ( mSelectionSymbol && !mSelectedFeatureIds.empty() && isMainRenderer && context.showSelection() ) + { + mSelectionSymbol->startRender( context, mFields ); + + for ( const QHash< QgsSymbol *, QList > &featureLists : features ) + { + for ( auto it = featureLists.constBegin(); it != featureLists.constEnd(); ++it ) + { + const QList &lst = it.value(); + for ( const QgsFeature &feature : lst ) + { + if ( context.renderingStopped() ) + { + break; + } + + const bool featureIsSelected = mSelectedFeatureIds.contains( feature.id() ); + if ( !featureIsSelected ) + continue; + + const bool drawMarker = mDrawVertexMarkers && context.drawEditingInformation(); + // note: here we pass "false" for the selected argument, as we don't want to change + // the user's defined selection symbol colors or settings in any way + mSelectionSymbol->renderFeature( feature, context, -1, false, drawMarker ); + } + } + } + + mSelectionSymbol->stopRender( context ); + } + stopRenderer( renderer, selRenderer ); } diff --git a/src/core/vector/qgsvectorlayerrenderer.h b/src/core/vector/qgsvectorlayerrenderer.h index 12c444b8da36..7d6cc51a6b76 100644 --- a/src/core/vector/qgsvectorlayerrenderer.h +++ b/src/core/vector/qgsvectorlayerrenderer.h @@ -159,6 +159,8 @@ class QgsVectorLayerRenderer : public QgsMapLayerRenderer bool mNoSetLayerExpressionContext = false; + std::unique_ptr< QgsSymbol > mSelectionSymbol; + }; diff --git a/src/core/vector/qgsvectorlayerselectionproperties.cpp b/src/core/vector/qgsvectorlayerselectionproperties.cpp index e88a4e40bdb8..e77df8ca7525 100644 --- a/src/core/vector/qgsvectorlayerselectionproperties.cpp +++ b/src/core/vector/qgsvectorlayerselectionproperties.cpp @@ -17,12 +17,15 @@ #include "qgsvectorlayerselectionproperties.h" #include "qgscolorutils.h" +#include "qgssymbollayerutils.h" QgsVectorLayerSelectionProperties::QgsVectorLayerSelectionProperties( QObject *parent ) : QgsMapLayerSelectionProperties( parent ) { } +QgsVectorLayerSelectionProperties::~QgsVectorLayerSelectionProperties() = default; + QDomElement QgsVectorLayerSelectionProperties::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) { @@ -30,6 +33,13 @@ QDomElement QgsVectorLayerSelectionProperties::writeXml( QDomElement &parentElem QgsColorUtils::writeXml( mSelectionColor, QStringLiteral( "selectionColor" ), document, element, context ); + if ( mSelectionSymbol ) + { + QDomElement selectionSymbolElement = document.createElement( QStringLiteral( "selectionSymbol" ) ); + selectionSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mSelectionSymbol.get(), document, context ) ); + element.appendChild( selectionSymbolElement ); + } + parentElement.appendChild( element ); return element; } @@ -41,6 +51,11 @@ bool QgsVectorLayerSelectionProperties::readXml( const QDomElement &element, con return false; mSelectionColor = QgsColorUtils::readXml( selectionElement, QStringLiteral( "selectionColor" ), context ); + + { + const QDomElement selectionSymbolElement = selectionElement.firstChildElement( QStringLiteral( "selectionSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) ); + mSelectionSymbol.reset( QgsSymbolLayerUtils::loadSymbol( selectionSymbolElement, context ) ); + } return true; } @@ -48,6 +63,7 @@ QgsVectorLayerSelectionProperties *QgsVectorLayerSelectionProperties::clone() co { std::unique_ptr< QgsVectorLayerSelectionProperties > res = std::make_unique< QgsVectorLayerSelectionProperties >( nullptr ); res->mSelectionColor = mSelectionColor; + res->mSelectionSymbol.reset( mSelectionSymbol ? mSelectionSymbol->clone() : nullptr ); return res.release(); } @@ -60,3 +76,13 @@ void QgsVectorLayerSelectionProperties::setSelectionColor( const QColor &color ) { mSelectionColor = color; } + +QgsSymbol *QgsVectorLayerSelectionProperties::selectionSymbol() const +{ + return mSelectionSymbol.get(); +} + +void QgsVectorLayerSelectionProperties::setSelectionSymbol( QgsSymbol *symbol ) +{ + mSelectionSymbol.reset( symbol ); +} diff --git a/src/core/vector/qgsvectorlayerselectionproperties.h b/src/core/vector/qgsvectorlayerselectionproperties.h index 1d0356076c02..f7b12ffb8e9e 100644 --- a/src/core/vector/qgsvectorlayerselectionproperties.h +++ b/src/core/vector/qgsvectorlayerselectionproperties.h @@ -26,6 +26,8 @@ #include +class QgsSymbol; + /** * \class QgsVectorLayerSelectionProperties * \ingroup core @@ -43,6 +45,7 @@ class CORE_EXPORT QgsVectorLayerSelectionProperties : public QgsMapLayerSelectio * Constructor for QgsVectorLayerSelectionProperties, with the specified \a parent object. */ QgsVectorLayerSelectionProperties( QObject *parent SIP_TRANSFERTHIS = nullptr ); + ~QgsVectorLayerSelectionProperties() override; QDomElement writeXml( QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context ) override; bool readXml( const QDomElement &element, const QgsReadWriteContext &context ) override; @@ -68,10 +71,29 @@ class CORE_EXPORT QgsVectorLayerSelectionProperties : public QgsMapLayerSelectio */ void setSelectionColor( const QColor &color ); + /** + * Returns the symbol used to render selected features in the layer. + * + * May be NULLPTR if the default symbol should be used instead. + * + * \see setSelectionSymbol() + */ + QgsSymbol *selectionSymbol() const; + + /** + * Sets the \a symbol used to render selected features in the layer. + * + * Ownership of \a symbol is transferred to the plot. If \a symbol is NULLPTR then + * the default symbol will be used instead. + * + * \see selectionSymbol() + */ + void setSelectionSymbol( QgsSymbol *symbol SIP_TRANSFER ); + private: QColor mSelectionColor; - + std::unique_ptr< QgsSymbol > mSelectionSymbol; }; #endif // QGSVECTORLAYERSELECTIONPROPERTIES_H diff --git a/tests/src/python/test_qgsvectorlayer.py b/tests/src/python/test_qgsvectorlayer.py index 6c379c50c6c1..2e6bbc44c670 100644 --- a/tests/src/python/test_qgsvectorlayer.py +++ b/tests/src/python/test_qgsvectorlayer.py @@ -4537,6 +4537,7 @@ def test_selection_properties(self): self.assertTrue(vl.isValid()) self.assertFalse(vl.selectionProperties().selectionColor().isValid()) + self.assertFalse(vl.selectionProperties().selectionSymbol()) vl.selectionProperties().setSelectionColor( QColor(255, 0, 0) ) @@ -4546,7 +4547,7 @@ def test_selection_properties(self): p = QgsProject() p.addMapLayer(vl) - # test saving and restoring split policies + # test saving and restoring with tempfile.TemporaryDirectory() as temp: self.assertTrue(p.write(temp + '/test.qgs')) @@ -4559,6 +4560,25 @@ def test_selection_properties(self): self.assertEqual(vl2.selectionProperties().selectionColor(), QColor(255, 0, 0)) + selected_symbol = QgsMarkerSymbol() + selected_symbol.setColor(QColor(25, 26, 27)) + vl.selectionProperties().setSelectionSymbol( + selected_symbol + ) + + with tempfile.TemporaryDirectory() as temp: + self.assertTrue(p.write(temp + '/test.qgs')) + + p2 = QgsProject() + self.assertTrue(p2.read(temp + '/test.qgs')) + + vl2 = list(p2.mapLayers().values())[0] + self.assertEqual(vl2.name(), vl.name()) + + self.assertEqual(vl2.selectionProperties().selectionSymbol().color(), + QColor(25, 26, 27)) + + # TODO: # - fetch rect: feat with changed geometry: 1. in rect, 2. out of rect # - more join tests diff --git a/tests/src/python/test_qgsvectorlayerrenderer.py b/tests/src/python/test_qgsvectorlayerrenderer.py index 9eae96da4ba1..5093168dff4c 100644 --- a/tests/src/python/test_qgsvectorlayerrenderer.py +++ b/tests/src/python/test_qgsvectorlayerrenderer.py @@ -742,6 +742,47 @@ def testRenderWithSelectedFeatureColor(self): ) ) + def testRenderWithSelectedFeatureSymbol(self): + poly_layer = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys.shp')) + self.assertTrue(poly_layer.isValid()) + + sym1 = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_color': '#000000', 'outline_width': '1'}) + renderer = QgsSingleSymbolRenderer(sym1) + poly_layer.setRenderer(renderer) + + poly_layer.selectAll() + + poly_layer.selectionProperties().setSelectionSymbol( + QgsFillSymbol.createSimple({'style': 'no', 'outline_color': '#6666ff', 'outline_width': '3'}) + ) + + mapsettings = QgsMapSettings() + mapsettings.setOutputSize(QSize(400, 400)) + mapsettings.setOutputDpi(96) + mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) + mapsettings.setExtent(QgsRectangle(-13875783.2, 2266009.4, -8690110.7, 6673344.5)) + mapsettings.setLayers([poly_layer]) + + self.assertTrue( + self.render_map_settings_check( + 'selection_symbol', + 'selection_symbol', + mapsettings + ) + ) + + # also try with symbol levels + renderer.setUsingSymbolLevels(True) + poly_layer.setRenderer(renderer) + + self.assertTrue( + self.render_map_settings_check( + 'selection_symbol', + 'selection_symbol', + mapsettings + ) + ) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/vectorlayerrenderer/expected_selection_symbol/expected_selection_symbol.png b/tests/testdata/control_images/vectorlayerrenderer/expected_selection_symbol/expected_selection_symbol.png new file mode 100644 index 0000000000000000000000000000000000000000..39b49170319c2f4a3c97c18f359b6638b8f76dab GIT binary patch literal 471523 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 literal 0 HcmV?d00001