Skip to content

Commit f77c4c8

Browse files
committedMar 14, 2023
Fix incorrect legend key entries are returned for rule based
renderers with else rules Fixes map based legend filtering with some rule based renderers
1 parent c2b60ac commit f77c4c8

File tree

2 files changed

+99
-28
lines changed

2 files changed

+99
-28
lines changed
 

‎src/core/symbology/qgsrulebasedrenderer.cpp

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,14 @@
2222
#include "qgslogger.h"
2323
#include "qgsogcutils.h"
2424
#include "qgssinglesymbolrenderer.h"
25-
#include "qgspointdisplacementrenderer.h"
2625
#include "qgsinvertedpolygonrenderer.h"
27-
#include "qgspainteffect.h"
28-
#include "qgspainteffectregistry.h"
2926
#include "qgsproperty.h"
3027
#include "qgsstyleentityvisitor.h"
3128
#include "qgsembeddedsymbolrenderer.h"
3229
#include "qgslinesymbol.h"
3330
#include "qgsfillsymbol.h"
3431
#include "qgsmarkersymbol.h"
32+
#include "qgspointdistancerenderer.h"
3533

3634
#include <QSet>
3735

@@ -679,43 +677,52 @@ QgsSymbolList QgsRuleBasedRenderer::Rule::symbolsForFeature( const QgsFeature &f
679677

680678
QSet<QString> QgsRuleBasedRenderer::Rule::legendKeysForFeature( const QgsFeature &feature, QgsRenderContext *context )
681679
{
682-
QSet< QString> lst;
680+
QSet< QString> res;
683681
if ( !isFilterOK( feature, context ) )
684-
return lst;
685-
lst.insert( mRuleKey );
682+
return res;
686683

687-
const auto constMActiveChildren = mActiveChildren;
688-
for ( Rule *rule : constMActiveChildren )
684+
res.insert( mRuleKey );
685+
686+
// first determine if any non else rules match at this level
687+
bool matchedNonElseRule = false;
688+
for ( Rule *rule : std::as_const( mActiveChildren ) )
689689
{
690-
bool validKey = false;
691690
if ( rule->isElse() )
692691
{
693-
if ( rule->children().isEmpty() )
694-
{
695-
RuleList lst = rulesForFeature( feature, context, false );
696-
lst.removeOne( rule );
697-
698-
if ( lst.empty() )
699-
{
700-
validKey = true;
701-
}
702-
}
703-
else
704-
{
705-
validKey = true;
706-
}
692+
continue;
707693
}
708-
else if ( rule->willRenderFeature( feature, context ) )
694+
if ( rule->willRenderFeature( feature, context ) )
709695
{
710-
validKey = true;
696+
res.unite( rule->legendKeysForFeature( feature, context ) );
697+
matchedNonElseRule = true;
711698
}
699+
}
712700

713-
if ( validKey )
701+
// second chance -- allow else rules to take effect if valid
702+
if ( !matchedNonElseRule )
703+
{
704+
for ( Rule *rule : std::as_const( mActiveChildren ) )
714705
{
715-
lst.unite( rule->legendKeysForFeature( feature, context ) );
706+
if ( rule->isElse() )
707+
{
708+
if ( rule->children().isEmpty() )
709+
{
710+
RuleList lst = rulesForFeature( feature, context, false );
711+
lst.removeOne( rule );
712+
713+
if ( lst.empty() )
714+
{
715+
res.unite( rule->legendKeysForFeature( feature, context ) );
716+
}
717+
}
718+
else
719+
{
720+
res.unite( rule->legendKeysForFeature( feature, context ) );
721+
}
722+
}
716723
}
717724
}
718-
return lst;
725+
return res;
719726
}
720727

721728
QgsRuleBasedRenderer::RuleList QgsRuleBasedRenderer::Rule::rulesForFeature( const QgsFeature &feature, QgsRenderContext *context, bool onlyActive )

‎tests/src/core/testqgsrulebasedrenderer.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,70 @@ class TestQgsRuleBasedRenderer: public QgsTest
11791179
QCOMPARE( renderer->legendKeys(), expected );
11801180
}
11811181

1182+
void testLegendKeysForFeature()
1183+
{
1184+
QgsRuleBasedRenderer::Rule *rootRule = new QgsRuleBasedRenderer::Rule( nullptr );
1185+
std::unique_ptr< QgsRuleBasedRenderer > renderer = std::make_unique< QgsRuleBasedRenderer >( rootRule );
1186+
std::unique_ptr< QgsMarkerSymbol > symbol( QgsMarkerSymbol::createSimple( {} ) );
1187+
1188+
QgsRuleBasedRenderer::Rule *lessThanTwoRule = new QgsRuleBasedRenderer::Rule( symbol->clone(), 0, 0, "\"Importance\" <= 2" );
1189+
rootRule->appendChild( lessThanTwoRule );
1190+
1191+
QgsRuleBasedRenderer::Rule *elseRule = new QgsRuleBasedRenderer::Rule( nullptr, 0, 0, QString(), QString(), QString(), true );
1192+
rootRule->appendChild( elseRule );
1193+
1194+
QgsRuleBasedRenderer::Rule *oneRule = new QgsRuleBasedRenderer::Rule( symbol->clone(), 0, 0, "\"Pilots\" = 1" );
1195+
elseRule->appendChild( oneRule );
1196+
1197+
QgsRuleBasedRenderer::Rule *twoRule = new QgsRuleBasedRenderer::Rule( symbol->clone(), 0, 0, "\"Pilots\" = 2" );
1198+
elseRule->appendChild( twoRule );
1199+
1200+
QgsRuleBasedRenderer::Rule *threeRule = new QgsRuleBasedRenderer::Rule( symbol->clone(), 0, 0, "\"Pilots\" = 3" );
1201+
elseRule->appendChild( threeRule );
1202+
1203+
QgsFields fields;
1204+
fields.append( QgsField( QStringLiteral( "Importance" ), QVariant::Int ) );
1205+
fields.append( QgsField( QStringLiteral( "Pilots" ), QVariant::Int ) );
1206+
1207+
QgsFeature feature( fields );
1208+
QgsExpressionContext expContext;
1209+
expContext.setFields( fields );
1210+
QgsRenderContext rc;
1211+
rc.setExpressionContext( expContext );
1212+
1213+
renderer->startRender( rc, fields );
1214+
1215+
QSet< QString > expected{rootRule->ruleKey(), elseRule->ruleKey() };
1216+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1217+
1218+
feature.setAttributes( QgsAttributes() << 1 << 2 );
1219+
expected = {rootRule->ruleKey(), lessThanTwoRule->ruleKey() };
1220+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1221+
1222+
feature.setAttributes( QgsAttributes() << 2 << 2 );
1223+
expected = {rootRule->ruleKey(), lessThanTwoRule->ruleKey() };
1224+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1225+
1226+
feature.setAttributes( QgsAttributes() << 3 << 1 );
1227+
expected = {rootRule->ruleKey(), elseRule->ruleKey(), oneRule->ruleKey() };
1228+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1229+
1230+
feature.setAttributes( QgsAttributes() << 3 << 2 );
1231+
expected = {rootRule->ruleKey(), elseRule->ruleKey(), twoRule->ruleKey() };
1232+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1233+
1234+
feature.setAttributes( QgsAttributes() << 3 << 3 );
1235+
expected = {rootRule->ruleKey(), elseRule->ruleKey(), threeRule->ruleKey() };
1236+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1237+
1238+
feature.setAttributes( QgsAttributes() << 3 << 4 );
1239+
expected = {rootRule->ruleKey(), elseRule->ruleKey() };
1240+
QCOMPARE( renderer->legendKeysForFeature( feature, rc ), expected );
1241+
1242+
renderer->stopRender( rc );
1243+
}
1244+
1245+
11821246
void testLegendKeyToExpression()
11831247
{
11841248
QgsRuleBasedRenderer::Rule *rootRule = new QgsRuleBasedRenderer::Rule( nullptr );

0 commit comments

Comments
 (0)
Please sign in to comment.