Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d52b461

Browse files
nyalldawsongithub-actions[bot]
authored andcommittedMar 8, 2023
Add QgsFeatureRenderer::legendKeys method to retrieve all legend
keys for the renderer
1 parent 74c11ee commit d52b461

10 files changed

+138
-0
lines changed
 

‎python/core/auto_generated/symbology/qgsrenderer.sip.in

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,15 @@ the UserStyle element of a SLD style document
302302
virtual void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props = QVariantMap() ) const;
303303
%Docstring
304304
used from subclasses to create SLD Rule elements following SLD v1.1 specs
305+
%End
306+
307+
QSet< QString > legendKeys() const;
308+
%Docstring
309+
Returns the set of all legend keys used by the renderer.
310+
311+
.. seealso:: :py:func:`legendSymbolItems`
312+
313+
.. versionadded:: 3.32
305314
%End
306315

307316
virtual bool legendSymbolItemsCheckable() const;
@@ -317,6 +326,8 @@ Returns ``True`` if the legend symbology item with the specified ``key`` is chec
317326

318327
.. seealso:: :py:func:`checkLegendSymbolItem`
319328

329+
.. seealso:: :py:func:`legendKeys`
330+
320331
.. versionadded:: 2.5
321332
%End
322333

@@ -326,6 +337,8 @@ Sets whether the legend symbology item with the specified ``ley`` should be chec
326337

327338
.. seealso:: :py:func:`legendSymbolItemChecked`
328339

340+
.. seealso:: :py:func:`legendKeys`
341+
329342
.. versionadded:: 2.5
330343
%End
331344

@@ -336,6 +349,8 @@ Sets the symbol to be used for a legend symbol item.
336349
:param key: rule key for legend symbol
337350
:param symbol: new symbol for legend item. Ownership is transferred to renderer.
338351

352+
.. seealso:: :py:func:`legendKeys`
353+
339354
.. versionadded:: 2.14
340355
%End
341356

@@ -351,13 +366,18 @@ the features displayed using that key.
351366
- ok: will be set to ``True`` if legend key was successfully converted to a filter expression
352367

353368

369+
.. seealso:: :py:func:`legendKeys`
370+
371+
354372
.. versionadded:: 3.26
355373
%End
356374

357375
virtual QgsLegendSymbolList legendSymbolItems() const;
358376
%Docstring
359377
Returns a list of symbology items for the legend
360378

379+
.. seealso:: :py:func:`legendKeys`
380+
361381
.. versionadded:: 2.6
362382
%End
363383

‎src/core/symbology/qgsrenderer.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,19 @@ QgsFeatureRenderer *QgsFeatureRenderer::loadSld( const QDomNode &node, Qgis::Geo
330330
return r;
331331
}
332332

333+
QSet<QString> QgsFeatureRenderer::legendKeys() const
334+
{
335+
// build up a list of unique legend keys
336+
const QgsLegendSymbolList allLegendSymbols = legendSymbolItems();
337+
QSet< QString > keys;
338+
keys.reserve( allLegendSymbols.size() );
339+
for ( const QgsLegendSymbolItem &symbol : allLegendSymbols )
340+
{
341+
keys.insert( symbol.ruleKey() );
342+
}
343+
return keys;
344+
}
345+
333346
QDomElement QgsFeatureRenderer::writeSld( QDomDocument &doc, const QString &styleName, const QVariantMap &props ) const
334347
{
335348
QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );

‎src/core/symbology/qgsrenderer.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,15 @@ class CORE_EXPORT QgsFeatureRenderer
339339
( void ) props; // warning avoidance
340340
}
341341

342+
/**
343+
* Returns the set of all legend keys used by the renderer.
344+
*
345+
* \see legendSymbolItems()
346+
*
347+
* \since QGIS 3.32
348+
*/
349+
QSet< QString > legendKeys() const;
350+
342351
/**
343352
* Returns TRUE if symbology items in legend are checkable.
344353
*
@@ -350,6 +359,7 @@ class CORE_EXPORT QgsFeatureRenderer
350359
* Returns TRUE if the legend symbology item with the specified \a key is checked.
351360
*
352361
* \see checkLegendSymbolItem()
362+
* \see legendKeys()
353363
*
354364
* \since QGIS 2.5
355365
*/
@@ -359,6 +369,7 @@ class CORE_EXPORT QgsFeatureRenderer
359369
* Sets whether the legend symbology item with the specified \a ley should be checked.
360370
*
361371
* \see legendSymbolItemChecked()
372+
* \see legendKeys()
362373
*
363374
* \since QGIS 2.5
364375
*/
@@ -368,6 +379,9 @@ class CORE_EXPORT QgsFeatureRenderer
368379
* Sets the symbol to be used for a legend symbol item.
369380
* \param key rule key for legend symbol
370381
* \param symbol new symbol for legend item. Ownership is transferred to renderer.
382+
*
383+
* \see legendKeys()
384+
*
371385
* \since QGIS 2.14
372386
*/
373387
virtual void setLegendSymbolItem( const QString &key, QgsSymbol *symbol SIP_TRANSFER );
@@ -382,12 +396,17 @@ class CORE_EXPORT QgsFeatureRenderer
382396
*
383397
* \returns QGIS expression string for matching features with the specified key
384398
*
399+
* \see legendKeys()
400+
*
385401
* \since QGIS 3.26
386402
*/
387403
virtual QString legendKeyToExpression( const QString &key, QgsVectorLayer *layer, bool &ok SIP_OUT ) const;
388404

389405
/**
390406
* Returns a list of symbology items for the legend
407+
*
408+
* \see legendKeys()
409+
*
391410
* \since QGIS 2.6
392411
*/
393412
virtual QgsLegendSymbolList legendSymbolItems() const;

‎tests/src/core/testqgsrulebasedrenderer.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,33 @@ class TestQgsRuleBasedRenderer: public QgsTest
11521152
QCOMPARE( counter->featureCount( "2" ), 1LL );
11531153
}
11541154

1155+
void testLegendKeys()
1156+
{
1157+
QgsRuleBasedRenderer::Rule *rootRule = new QgsRuleBasedRenderer::Rule( nullptr );
1158+
std::unique_ptr< QgsRuleBasedRenderer > renderer = std::make_unique< QgsRuleBasedRenderer >( rootRule );
1159+
1160+
QVERIFY( renderer->legendKeys().empty() );
1161+
1162+
QgsRuleBasedRenderer::Rule *rule2 = new QgsRuleBasedRenderer::Rule( nullptr, 0, 0, "\"field_name\" = 5" );
1163+
QgsRuleBasedRenderer::Rule *rule3 = new QgsRuleBasedRenderer::Rule( nullptr, 2000, 0, "\"field_name\" = 6" );
1164+
QgsRuleBasedRenderer::Rule *rule4 = new QgsRuleBasedRenderer::Rule( nullptr, 0, 1000, "\"field_name\" = 7" );
1165+
QgsRuleBasedRenderer::Rule *rule5 = new QgsRuleBasedRenderer::Rule( nullptr, 1000, 3000 );
1166+
1167+
rootRule->appendChild( rule2 );
1168+
rootRule->appendChild( rule3 );
1169+
rootRule->appendChild( rule4 );
1170+
rootRule->appendChild( rule5 );
1171+
1172+
QSet< QString > expected = QSet< QString >
1173+
{
1174+
rule2->ruleKey(),
1175+
rule3->ruleKey(),
1176+
rule4->ruleKey(),
1177+
rule5->ruleKey()
1178+
};
1179+
QCOMPARE( renderer->legendKeys(), expected );
1180+
}
1181+
11551182
void testLegendKeyToExpression()
11561183
{
11571184
QgsRuleBasedRenderer::Rule *rootRule = new QgsRuleBasedRenderer::Rule( nullptr );

‎tests/src/python/test_qgscategorizedsymbolrenderer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ def testLegendKeysWhileCounting(self):
412412
default_symbol.setColor(QColor(255, 255, 255))
413413
renderer.addCategory(QgsRendererCategory('', default_symbol, 'default'))
414414

415+
self.assertEqual(renderer.legendKeys(), {'0', '1', '2', '3', '4'})
416+
415417
context = QgsRenderContext()
416418
context.setRendererScale(0) # simulate counting
417419
renderer.startRender(context, fields)

‎tests/src/python/test_qgsgraduatedsymbolrenderer.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,21 @@ def testFilterNeedsGeometry(self):
482482
renderer.setClassAttribute("value - $area")
483483
self.assertTrue(renderer.filterNeedsGeometry())
484484

485+
def test_legend_keys(self):
486+
renderer = QgsGraduatedSymbolRenderer()
487+
renderer.setClassAttribute('field_name')
488+
489+
self.assertFalse(renderer.legendKeys())
490+
491+
symbol_a = createMarkerSymbol()
492+
renderer.addClassRange(QgsRendererRange(1, 2, symbol_a, 'a'))
493+
symbol_b = createMarkerSymbol()
494+
renderer.addClassRange(QgsRendererRange(5, 6, symbol_b, 'b'))
495+
symbol_c = createMarkerSymbol()
496+
renderer.addClassRange(QgsRendererRange(15.5, 16.5, symbol_c, 'c', False))
497+
498+
self.assertEqual(renderer.legendKeys(), {'0', '1', '2'})
499+
485500
def test_legend_key_to_expression(self):
486501
renderer = QgsGraduatedSymbolRenderer()
487502
renderer.setClassAttribute('field_name')

‎tests/src/python/test_qgsmergedfeaturerenderer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ def tearDown(self):
4747
with open(report_file_path, 'a') as report_file:
4848
report_file.write(self.report)
4949

50+
def test_legend_keys(self):
51+
symbol1 = QgsFillSymbol()
52+
symbol2 = QgsFillSymbol()
53+
sub_renderer = QgsCategorizedSymbolRenderer('cat', [QgsRendererCategory('cat1', symbol1, 'cat1'),
54+
QgsRendererCategory('cat2', symbol2, 'cat2')
55+
])
56+
57+
renderer = QgsMergedFeatureRenderer(sub_renderer)
58+
self.assertEqual(renderer.legendKeys(), {'0', '1'})
59+
5060
def testSinglePolys(self):
5161
source = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys_overlapping.shp'))
5262
self.assertTrue(source.isValid())

‎tests/src/python/test_qgspointclusterrenderer.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
QgsSymbolLayer,
4646
QgsUnitTypes,
4747
QgsVectorLayer,
48+
QgsCategorizedSymbolRenderer,
49+
QgsRendererCategory
4850
)
4951
from qgis.testing import start_app, unittest
5052

@@ -122,6 +124,18 @@ def testSaveCreate(self):
122124
c = QgsPointClusterRenderer.create(elem, QgsReadWriteContext())
123125
self._checkProperties(c)
124126

127+
def test_legend_keys(self):
128+
symbol1 = QgsMarkerSymbol()
129+
symbol2 = QgsMarkerSymbol()
130+
sub_renderer = QgsCategorizedSymbolRenderer('cat', [QgsRendererCategory('cat1', symbol1, 'cat1'),
131+
QgsRendererCategory('cat2', symbol2, 'cat2')
132+
])
133+
134+
renderer = QgsPointClusterRenderer()
135+
renderer.setEmbeddedRenderer(sub_renderer)
136+
137+
self.assertEqual(renderer.legendKeys(), {'0', '1'})
138+
125139
def testConvert(self):
126140
""" test renderer conversion """
127141

‎tests/src/python/test_qgspointdisplacementrenderer.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,18 @@ def testClusterConcentricLabelsDifferentSizesFarther(self):
485485
self.assertTrue(res)
486486
self._tearDown(layer)
487487

488+
def test_legend_keys(self):
489+
symbol1 = QgsMarkerSymbol()
490+
symbol2 = QgsMarkerSymbol()
491+
sub_renderer = QgsCategorizedSymbolRenderer('cat', [QgsRendererCategory('cat1', symbol1, 'cat1'),
492+
QgsRendererCategory('cat2', symbol2, 'cat2')
493+
])
494+
495+
renderer = QgsPointDisplacementRenderer()
496+
renderer.setEmbeddedRenderer(sub_renderer)
497+
498+
self.assertEqual(renderer.legendKeys(), {'0', '1'})
499+
488500
def test_legend_key_to_expression(self):
489501
sym1 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'})
490502
sub_renderer = QgsSingleSymbolRenderer(sym1)

‎tests/src/python/test_qgssinglesymbolrenderer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ def testUsedAttributes(self):
8484

8585
self.assertCountEqual(self.renderer.usedAttributes(ctx), {})
8686

87+
def test_legend_keys(self):
88+
sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'})
89+
renderer = QgsSingleSymbolRenderer(sym1)
90+
91+
self.assertEqual(renderer.legendKeys(), {'0'})
92+
8793
def test_legend_key_to_expression(self):
8894
sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'})
8995
renderer = QgsSingleSymbolRenderer(sym1)

0 commit comments

Comments
 (0)
Please sign in to comment.