Search code examples
pythoniteratorpyqtpyqt5qtreewidgetitem

How to filter out results that are non-checkable in a QTreeWidgetItemIterator?


Is it possible to filter a QTreeWidgetItemIterator so that items that are not checkable are omitted from the results?

TreeList = ({
    'Header1': (('Item11', 'Item12', )),
    'Header2': (('Item21', 'Item22', )),
})

# LOCATED IN `initLayout` METHOD
for key, value in TreeList.items():
    parent = QTreeWidgetItem(self.ListTreeView, [key])
    for val in value:
        child = QTreeWidgetItem([val])
        child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
        child.setCheckState(0, Qt.Unchecked)
        parent.addChild(child)

# LOCATED IN `initialize` METHOD
iterator = QTreeWidgetItemIterator(self.ListTreeView)
while iterator.value():
    val = iterator.value()

    try:  # Results in object has not attribute
        if val.isCheckable():
            print('checkable')
    except AttributeError as e:
        print(e)

    iterator += 1

In this example, neither Header1 or Header2 are checkable, but the items located under them are. When I iterate through the QTreeWidget, it returns the entire list.

Looking at the documentation for the IteratorFlags, I can see there are flags that can be set, but I don't understand how to set them in Python, and I'm not sure that any of them would fit my needs.

Right now, val.isCheckable() results in an AttributeError; which is expected, as isCheckable() does not appear to be an attribute of QTreeWidgetItem - or is it?

Preferably I would like to filter out non-checkable items, but if this is not possible, how can I check if the value isCheckable()?


Solution

  • The QTreeWidgetItem class is checkable by default, and there are no accessor methods for the checkable state. So you need to use the item-flags instead:

    iterator = QTreeWidgetItemIterator(self.ListTreeView)
    while iterator.value():
        val = iterator.value()
        if val.flags() & Qt.ItemIsUserCheckable:
            print('checkable')
        iterator += 1
    

    Given this, you will also need to explicitly unset the flag for items that you don't want to be checkable:

    for key, value in TreeList.items():
        parent = QTreeWidgetItem(self.ListTreeView, [key])
        # remove checkable flag for header items
        parent.setFlags(parent.flags() & ~Qt.ItemIsUserCheckable)