Skip to content

Commit df8a5c2

Browse files
committed
Merge pull request #9181 from elpaso/bugfix-21287-rule-based-double-else2
Rule based renderer: check for scale in rulesForFeature Cherry-picked from master commit 2c25c3d
1 parent 3a452ed commit df8a5c2

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

src/core/symbology/qgsrulebasedrenderer.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ QgsLegendSymbolList QgsRuleBasedRenderer::Rule::legendSymbolItems( int currentLe
246246

247247
bool QgsRuleBasedRenderer::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext *context ) const
248248
{
249-
if ( ! mFilter || mElseRule )
249+
if ( ! mFilter || mElseRule || ! context )
250250
return true;
251251

252252
context->expressionContext().setFeature( f );
@@ -647,7 +647,7 @@ QSet<QString> QgsRuleBasedRenderer::Rule::legendKeysForFeature( const QgsFeature
647647
QgsRuleBasedRenderer::RuleList QgsRuleBasedRenderer::Rule::rulesForFeature( const QgsFeature &feature, QgsRenderContext *context, bool onlyActive )
648648
{
649649
RuleList lst;
650-
if ( !isFilterOK( feature, context ) )
650+
if ( ! isFilterOK( feature, context ) || ( context && ! isScaleOK( context->rendererScale() ) ) )
651651
return lst;
652652

653653
if ( mSymbol )

tests/src/python/test_qgsrulebasedrenderer.py

+41-2
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,12 @@ def testWillRenderFeatureNestedElse(self):
150150
vl.setRenderer(QgsRuleBasedRenderer(rootrule))
151151
renderer = vl.renderer()
152152

153-
# Reunder with else rule and all activated
153+
# Render with else rule and all activated
154154
renderer.startRender(ctx, vl.fields())
155155
self.assertTrue(renderer.willRenderFeature(ft, ctx))
156156
renderer.stopRender(ctx)
157157

158-
# Reunder with else rule where else is deactivated
158+
# Render with else rule where else is deactivated
159159
renderer.rootRule().children()[1].setActive(False)
160160
renderer.startRender(ctx, vl.fields())
161161
self.assertFalse(renderer.willRenderFeature(ft, ctx))
@@ -324,6 +324,45 @@ def testConvertFromGraduatedRenderer(self):
324324
self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" >= 0.000000 AND "id" <= 1.000000')
325325
self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" > 1.000000 AND "id" <= 2.000000')
326326

327+
def testWillRenderFeatureTwoElse(self):
328+
"""Regression #21287, also test rulesForFeature since there were no tests any where and I've found a couple of issues"""
329+
330+
vl = self.mapsettings.layers()[0]
331+
ft = vl.getFeature(0) # 'id' = 1
332+
333+
ctx = QgsRenderContext.fromMapSettings(self.mapsettings)
334+
ctx.expressionContext().setFeature(ft)
335+
336+
# Create rulebased style
337+
sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'})
338+
sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'})
339+
sym4 = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_color': 'black'})
340+
341+
self.rx2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 200')
342+
self.rx3 = QgsRuleBasedRenderer.Rule(sym3, 1000, 100000000, 'ELSE') # <<< - match this!
343+
self.rx4 = QgsRuleBasedRenderer.Rule(sym4, 0.1, 999, 'ELSE')
344+
345+
rootrule = QgsRuleBasedRenderer.Rule(None)
346+
rootrule.appendChild(self.rx2)
347+
rootrule.appendChild(self.rx3)
348+
rootrule.appendChild(self.rx4) # <- failed in regression #21287
349+
350+
vl.setRenderer(QgsRuleBasedRenderer(rootrule))
351+
renderer = vl.renderer()
352+
353+
# Render with else rule and all activated
354+
renderer.startRender(ctx, vl.fields())
355+
self.assertTrue(renderer.willRenderFeature(ft, ctx))
356+
357+
# No context? All rules
358+
self.assertEqual(len(rootrule.rulesForFeature(ft)), 2)
359+
self.assertTrue(set(rootrule.rulesForFeature(ft)), set([self.rx3, self.rx4]))
360+
361+
# With context: only the matching one
362+
self.assertEqual(len(rootrule.rulesForFeature(ft, ctx)), 1)
363+
self.assertEqual(rootrule.rulesForFeature(ft, ctx)[0], self.rx3)
364+
renderer.stopRender(ctx)
365+
327366

328367
if __name__ == '__main__':
329368
unittest.main()

0 commit comments

Comments
 (0)