mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
Fix legend count is 0 if graduated/categorized expression uses geometry
Likely fixes many other bugs too with graduated/categorized renderers Fixes #15544
This commit is contained in:
parent
17567ee5aa
commit
b5867bff58
@ -93,6 +93,8 @@ class QgsCategorizedSymbolRenderer : QgsFeatureRenderer
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool filterNeedsGeometry() const;
|
||||
|
||||
virtual QString dump() const;
|
||||
|
||||
virtual QgsCategorizedSymbolRenderer *clone() const /Factory/;
|
||||
|
@ -130,6 +130,8 @@ class QgsGraduatedSymbolRenderer : QgsFeatureRenderer
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool filterNeedsGeometry() const;
|
||||
|
||||
virtual QString dump() const;
|
||||
|
||||
virtual QgsGraduatedSymbolRenderer *clone() const /Factory/;
|
||||
|
@ -452,6 +452,19 @@ QSet<QString> QgsCategorizedSymbolRenderer::usedAttributes( const QgsRenderConte
|
||||
return attributes;
|
||||
}
|
||||
|
||||
bool QgsCategorizedSymbolRenderer::filterNeedsGeometry() const
|
||||
{
|
||||
QgsExpression testExpr( mAttrName );
|
||||
if ( !testExpr.hasParserError() )
|
||||
{
|
||||
QgsExpressionContext context;
|
||||
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); // unfortunately no layer access available!
|
||||
testExpr.prepare( &context );
|
||||
return testExpr.needsGeometry();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString QgsCategorizedSymbolRenderer::dump() const
|
||||
{
|
||||
QString s = QStringLiteral( "CATEGORIZED: idx %1\n" ).arg( mAttrName );
|
||||
|
@ -102,6 +102,7 @@ class CORE_EXPORT QgsCategorizedSymbolRenderer : public QgsFeatureRenderer
|
||||
void startRender( QgsRenderContext &context, const QgsFields &fields ) override;
|
||||
void stopRender( QgsRenderContext &context ) override;
|
||||
QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
|
||||
bool filterNeedsGeometry() const override;
|
||||
QString dump() const override;
|
||||
QgsCategorizedSymbolRenderer *clone() const override SIP_FACTORY;
|
||||
void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const override;
|
||||
|
@ -425,6 +425,19 @@ QSet<QString> QgsGraduatedSymbolRenderer::usedAttributes( const QgsRenderContext
|
||||
return attributes;
|
||||
}
|
||||
|
||||
bool QgsGraduatedSymbolRenderer::filterNeedsGeometry() const
|
||||
{
|
||||
QgsExpression testExpr( mAttrName );
|
||||
if ( !testExpr.hasParserError() )
|
||||
{
|
||||
QgsExpressionContext context;
|
||||
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); // unfortunately no layer access available!
|
||||
testExpr.prepare( &context );
|
||||
return testExpr.needsGeometry();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsGraduatedSymbolRenderer::updateRangeSymbol( int rangeIndex, QgsSymbol *symbol )
|
||||
{
|
||||
if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
|
||||
|
@ -152,6 +152,7 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer : public QgsFeatureRenderer
|
||||
void startRender( QgsRenderContext &context, const QgsFields &fields ) override;
|
||||
void stopRender( QgsRenderContext &context ) override;
|
||||
QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
|
||||
bool filterNeedsGeometry() const override;
|
||||
QString dump() const override;
|
||||
QgsGraduatedSymbolRenderer *clone() const override SIP_FACTORY;
|
||||
void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const override;
|
||||
|
@ -458,6 +458,31 @@ class TestQgsCategorizedSymbolRenderer(unittest.TestCase):
|
||||
self.assertEqual(symbol.color().name(), '#0aff0a')
|
||||
renderer.stopRender(context)
|
||||
|
||||
def testUsedAttributes(self):
|
||||
renderer = QgsCategorizedSymbolRenderer()
|
||||
ctx = QgsRenderContext()
|
||||
|
||||
# attribute can contain either attribute name or an expression.
|
||||
# Sometimes it is not possible to distinguish between those two,
|
||||
# e.g. "a - b" can be both a valid attribute name or expression.
|
||||
# Since we do not have access to fields here, the method should return both options.
|
||||
renderer.setClassAttribute("value")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"value"})
|
||||
renderer.setClassAttribute("value - 1")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"value", "value - 1"})
|
||||
renderer.setClassAttribute("valuea - valueb")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"valuea", "valuea - valueb", "valueb"})
|
||||
|
||||
def testFilterNeedsGeometry(self):
|
||||
renderer = QgsCategorizedSymbolRenderer()
|
||||
|
||||
renderer.setClassAttribute("value")
|
||||
self.assertFalse(renderer.filterNeedsGeometry())
|
||||
renderer.setClassAttribute("$area")
|
||||
self.assertTrue(renderer.filterNeedsGeometry())
|
||||
renderer.setClassAttribute("value - $area")
|
||||
self.assertTrue(renderer.filterNeedsGeometry())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@ -450,11 +450,30 @@ class TestQgsGraduatedSymbolRenderer(unittest.TestCase):
|
||||
'(0.5000-1.0000,1.0000-1.1000,1.1000-1.2000,1.2000-5.0000,)',
|
||||
'Quantile classification not correct')
|
||||
|
||||
# Tests still needed
|
||||
def testUsedAttributes(self):
|
||||
renderer = QgsGraduatedSymbolRenderer()
|
||||
ctx = QgsRenderContext()
|
||||
|
||||
# Other calculation method tests
|
||||
# createRenderer function
|
||||
# symbolForFeature correctly selects range
|
||||
# attribute can contain either attribute name or an expression.
|
||||
# Sometimes it is not possible to distinguish between those two,
|
||||
# e.g. "a - b" can be both a valid attribute name or expression.
|
||||
# Since we do not have access to fields here, the method should return both options.
|
||||
renderer.setClassAttribute("value")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"value"})
|
||||
renderer.setClassAttribute("value - 1")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"value", "value - 1"})
|
||||
renderer.setClassAttribute("valuea - valueb")
|
||||
self.assertEqual(renderer.usedAttributes(ctx), {"valuea", "valuea - valueb", "valueb"})
|
||||
|
||||
def testFilterNeedsGeometry(self):
|
||||
renderer = QgsGraduatedSymbolRenderer()
|
||||
|
||||
renderer.setClassAttribute("value")
|
||||
self.assertFalse(renderer.filterNeedsGeometry())
|
||||
renderer.setClassAttribute("$area")
|
||||
self.assertTrue(renderer.filterNeedsGeometry())
|
||||
renderer.setClassAttribute("value - $area")
|
||||
self.assertTrue(renderer.filterNeedsGeometry())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user