[GIS] How to change visibility of a particular layer category in PyQGIS

categorized-rendererpyqgissymbologytable of contents

I've got one layer with its symbol MARKER, categorized by an expression in 4 colors. The colors depends on a value of a column. So from the TOC, I'm able to click and enable/disable, as they were different layers, and show one category a time.

From python script, I want to do the same, with a loop: show/hide in the map the different existing categories one each time (for printing separated the 4 jpg),

I tried to show the active layers, and categories aren't not showing as a proper layer. So, I thought that the proper layer was a group tree, but when I ask for QgsLayerTreeGroup always show no group.

How can I obtain categories for changing their visibility in the map?

root = QgsProject.instance().layerTreeRoot()
for child in root.children():
    if isinstance(child, QgsLayerTreeGroup):
       print "- group: " + child.name()
        if child.name() == "rara": #to check subgroups within test group
            print "rara"
            for subChild in child.children():
                print "child"
                if isinstance(subChild, QgsLayerTreeGroup):
                    subChild.name()
    else:
        print "no group: " + root.name()

Best Answer

Assuming layer is your QgsVectorLayer, you can access layer legend nodes in this way:

from PyQt4.QtCore import Qt
ltl = QgsProject.instance().layerTreeRoot().findLayer( layer.id() )
ltm = iface.layerTreeView().model()
legendNodes = ltm.layerLegendNodes( ltl )

Now you can make a particular category invisible (e.g., 'cat_A'):

legendNode = [ln for ln in legendNodes if ln.data( Qt.DisplayRole ) == 'cat_A']
if legendNode:
    legendNode[0].setData( Qt.Unchecked, Qt.CheckStateRole )

Alternatively, you could do the following to achieve the same result:

ltm = iface.layerTreeView().model()
lsi = layer.rendererV2().legendSymbolItemsV2()
ruleKey = [l.ruleKey() for l in lsi if l.label() == "cat_A"]
if ruleKey:
    ltm.findLegendNode( layer.id(), ruleKey[0] ).setData( Qt.Unchecked, Qt.CheckStateRole )
Related Question