Skip to content

Commit

Permalink
Fix deselecting null category when categorising using expression
Browse files Browse the repository at this point in the history
hides all features (fix #14273)
  • Loading branch information
nyalldawson committed Feb 16, 2016
1 parent 4094bae commit 13c5848
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 21 deletions.
6 changes: 4 additions & 2 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Expand Up @@ -585,6 +585,8 @@ QString QgsCategorizedSymbolRendererV2::filter( const QgsFields& fields )
}
}

QString attr = isExpression ? mAttrName : QString( "\"%1\"" ).arg( mAttrName );

if ( allActive && hasDefault )
{
return QString();
Expand All @@ -595,11 +597,11 @@ QString QgsCategorizedSymbolRendererV2::filter( const QgsFields& fields )
}
else if ( defaultActive )
{
return QString( "(\"%1\") NOT IN (%2) OR (\"%1\") IS NULL" ).arg( mAttrName, inactiveValues );
return QString( "(%1) NOT IN (%2) OR (%1) IS NULL" ).arg( attr, inactiveValues );
}
else
{
return QString( "(\"%1\") IN (%2)" ).arg( mAttrName, activeValues );
return QString( "(%1) IN (%2)" ).arg( attr, activeValues );
}
}

Expand Down
110 changes: 91 additions & 19 deletions tests/src/python/test_qgscategorizedsymbolrendererv2.py
Expand Up @@ -27,7 +27,9 @@
QgsPoint,
QgsSymbolV2,
QgsSymbolLayerV2Utils,
QgsRenderContext
QgsRenderContext,
QgsField,
QgsFields
)
from PyQt4.QtCore import Qt, QVariant
from PyQt4.QtXml import QDomDocument
Expand Down Expand Up @@ -58,58 +60,128 @@ def testFilter(self):
# add default category
renderer.addCategory(QgsRendererCategoryV2('', createMarkerSymbol(), 'default'))

self.assertEqual(renderer.filter(), '')
fields = QgsFields()
fields.append(QgsField('field', QVariant.String))
fields.append(QgsField('num', QVariant.Double))

self.assertEqual(renderer.filter(fields), '')
# remove categories, leaving default
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(), "(\"field\") NOT IN ('a') OR (\"field\") IS NULL")
self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a') OR (\"field\") IS NULL")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL")
self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL")
self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL")
# remove default category
assert renderer.updateCategoryRenderState(3, False)
self.assertEqual(renderer.filter(), "FALSE")
self.assertEqual(renderer.filter(fields), "FALSE")
# add back other categories, leaving default disabled
assert renderer.updateCategoryRenderState(0, True)
self.assertEqual(renderer.filter(), "(\"field\") IN ('a')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a')")
assert renderer.updateCategoryRenderState(1, True)
self.assertEqual(renderer.filter(), "(\"field\") IN ('a','b')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b')")
assert renderer.updateCategoryRenderState(2, True)
self.assertEqual(renderer.filter(), "(\"field\") IN ('a','b','c')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')")

renderer.deleteAllCategories()
# just default category
renderer.addCategory(QgsRendererCategoryV2('', createMarkerSymbol(), 'default'))
self.assertEqual(renderer.filter(), '')
self.assertEqual(renderer.filter(fields), '')
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(), 'FALSE')
self.assertEqual(renderer.filter(fields), 'FALSE')

renderer.deleteAllCategories()
# no default category
renderer.addCategory(QgsRendererCategoryV2('a', createMarkerSymbol(), 'a'))
renderer.addCategory(QgsRendererCategoryV2('b', createMarkerSymbol(), 'b'))
renderer.addCategory(QgsRendererCategoryV2('c', createMarkerSymbol(), 'c'))
self.assertEqual(renderer.filter(), "(\"field\") IN ('a','b','c')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')")
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(), "(\"field\") IN ('b','c')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b','c')")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(), "(\"field\") IN ('b')")
self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b')")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(), "FALSE")
self.assertEqual(renderer.filter(fields), "FALSE")

renderer.deleteAllCategories()
renderer.setClassAttribute('num')
# numeric categories
renderer.addCategory(QgsRendererCategoryV2(1, createMarkerSymbol(), 'a'))
renderer.addCategory(QgsRendererCategoryV2(2, createMarkerSymbol(), 'b'))
renderer.addCategory(QgsRendererCategoryV2(3, createMarkerSymbol(), 'c'))
self.assertEqual(renderer.filter(), '(\"field\") IN (1,2,3)')
self.assertEqual(renderer.filter(fields), '(\"num\") IN (1,2,3)')
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(), "(\"field\") IN (2,3)")
self.assertEqual(renderer.filter(fields), "(\"num\") IN (2,3)")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(), "(\"field\") IN (2)")
self.assertEqual(renderer.filter(fields), "(\"num\") IN (2)")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(fields), "FALSE")

def testFilterExpression(self):
"""Test filter creation with expression"""
renderer = QgsCategorizedSymbolRendererV2()
renderer.setClassAttribute('field + field2')

renderer.addCategory(QgsRendererCategoryV2('a', createMarkerSymbol(), 'a'))
renderer.addCategory(QgsRendererCategoryV2('b', createMarkerSymbol(), 'b'))
renderer.addCategory(QgsRendererCategoryV2('c', createMarkerSymbol(), 'c'))
# add default category
renderer.addCategory(QgsRendererCategoryV2('', createMarkerSymbol(), 'default'))

fields = QgsFields()
fields.append(QgsField('field', QVariant.String))

self.assertEqual(renderer.filter(fields), '')
# remove categories, leaving default
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(fields), "(field + field2) NOT IN ('a') OR (field + field2) IS NULL")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(), "FALSE")
self.assertEqual(renderer.filter(fields), "(field + field2) NOT IN ('a','b') OR (field + field2) IS NULL")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(fields), "(field + field2) NOT IN ('a','b','c') OR (field + field2) IS NULL")
# remove default category
assert renderer.updateCategoryRenderState(3, False)
self.assertEqual(renderer.filter(fields), "FALSE")
# add back other categories, leaving default disabled
assert renderer.updateCategoryRenderState(0, True)
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('a')")
assert renderer.updateCategoryRenderState(1, True)
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('a','b')")
assert renderer.updateCategoryRenderState(2, True)
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('a','b','c')")

renderer.deleteAllCategories()
# just default category
renderer.addCategory(QgsRendererCategoryV2('', createMarkerSymbol(), 'default'))
self.assertEqual(renderer.filter(fields), '')
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(fields), 'FALSE')

renderer.deleteAllCategories()
# no default category
renderer.addCategory(QgsRendererCategoryV2('a', createMarkerSymbol(), 'a'))
renderer.addCategory(QgsRendererCategoryV2('b', createMarkerSymbol(), 'b'))
renderer.addCategory(QgsRendererCategoryV2('c', createMarkerSymbol(), 'c'))
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('a','b','c')")
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('b','c')")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(fields), "(field + field2) IN ('b')")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(fields), "FALSE")

renderer.deleteAllCategories()
# numeric categories
renderer.addCategory(QgsRendererCategoryV2(1, createMarkerSymbol(), 'a'))
renderer.addCategory(QgsRendererCategoryV2(2, createMarkerSymbol(), 'b'))
renderer.addCategory(QgsRendererCategoryV2(3, createMarkerSymbol(), 'c'))
self.assertEqual(renderer.filter(fields), '(field + field2) IN (1,2,3)')
assert renderer.updateCategoryRenderState(0, False)
self.assertEqual(renderer.filter(fields), "(field + field2) IN (2,3)")
assert renderer.updateCategoryRenderState(2, False)
self.assertEqual(renderer.filter(fields), "(field + field2) IN (2)")
assert renderer.updateCategoryRenderState(1, False)
self.assertEqual(renderer.filter(fields), "FALSE")

if __name__ == "__main__":
unittest.main()

0 comments on commit 13c5848

Please sign in to comment.