[GIS] PyQGIS toggle group visibility (and recursively subsub…group visibility)

group-layerpyqgisqgisqt4

I would like to set visibility of a layer group and all of its children (and grand-children and so on…) using PyQGIS (QGIS 2.14.1).

Assume the groups name is g0 with subgroups g0[1…n] and subsub…groups g0[1…n][1…n][…].

QgsProject.instance().layerTreeRoot().findGroup('g0').setVisible(False)

sets the group and ALL what comes beneath invisible, so far so good:

enter image description here

But vice versa

QgsProject.instance().layerTreeRoot().findGroup('g0').setVisible(True)

sets the group visible and leaves all its children untouched, wich results in nothing visible at all:

enter image description here

QgsProject.instance().layerTreeRoot().findGroup('g0').updateChildVisibility()

only touches the direct children and not recursively all the descendants:

enter image description here

I wonder why manually setting the root groups (g0) visibility does result in recursively setting the visibility of all beneath it at all.

Question: Do I have to implement some recursive function to set the visibility of a group and its whole big family, or is there a more convenient way to accomplish this? Or is here something buggy?

Best Answer

It's not a bug. It's a feature. :D

Check boxes in the layer tree have three states (see Qt docs):

Qt::Unchecked            0  
Qt::PartiallyChecked     1 (some children are checked and some are not) 
Qt::Checked              2

Therefore, the setVisible() function expects a Qt.checkState value, not a boolean value. By chance, it seems that False is resolved to 0 and True to 1. The value 2 is what you're actually looking for:

QgsProject.instance().layerTreeRoot().findGroup('g0').setVisible(2)

Or, if you prefer:

from PyQt4.QtCore import Qt
QgsProject.instance().layerTreeRoot().findGroup('g0').setVisible(Qt.Checked)

This call will check the g0 group and all its children (grandchildren, great grandchildren, and so on).

Related Question