Search code examples
pythonqtsearchpysideqtreeview

Recursively collect all checked QTreeview items in python


Could someone help me create a recursive function which loops through the treeview QStandardItemModel and collects all items which are 'checked true'

I'm not entirely clear on how to go about doing this myself.

enter image description here

from PySide import QtGui, QtCore
from PySide import QtSvg, QtXml
import sys

class Person:
    def __init__(self, name="", children=None):
        self.name = name
        self.children = children if children else []

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.resize(300, 400)
        self.init_ui()

    def init_ui(self):
        # Setup Tabs Widget
        # self.treeview = QtGui.QTreeView()
        self.treeview = QtGui.QTreeView()
        self.treeview.setHeaderHidden(True)
        self.treeview.setUniformRowHeights(True)
        self.treeview.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

        self.model = QtGui.QStandardItemModel()
        self.treeview.setModel(self.model)

        self.action = QtGui.QAction('Print', self)
        self.action.setShortcut('F5')
        self.action.triggered.connect(self.get_checked)

        fileMenu = QtGui.QMenu("&File", self)
        fileMenu.addAction(self.action)
        self.menuBar().addMenu(fileMenu)

        # Setup central widget
        self.setCentralWidget(self.treeview)

        # populate data
        self.populate_people()
        self.treeview.expandAll()

    def populate_people(self):
        parent = Person("Kevin", [
                Person("Tom", [Person("Sally"), Person("Susan")]),
                Person("Snappy", [Person("John"), Person("Kimmy"),
                                  Person("Joe")]),
                Person("Chester", [Person("Danny"), Person("Colleen")])
            ]
        )
        self.create_nodes(parent, self.model)

    def create_nodes(self, node, parent):
        tnode = QtGui.QStandardItem()
        tnode.setCheckable(True)
        tnode.setData(QtCore.Qt.Unchecked, role=QtCore.Qt.CheckStateRole)
        tnode.setData(node.name , role=QtCore.Qt.DisplayRole)
        tnode.setData(node, role=QtCore.Qt.UserRole) # store object on item

        parent.appendRow(tnode)

        for x in node.children:
            self.create_nodes(x, tnode)

    def get_checked(self):
        print "collecting..."


def main():
    app = QtGui.QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Solution

  • It can be done with the model's match method:

    def get_checked(self):
        model = self.treeview.model()
        checked = model.match(
            model.index(0, 0), QtCore.Qt.CheckStateRole,
            QtCore.Qt.Checked, -1,
            QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
        for index in checked:
            item = model.itemFromIndex(index)
            print(item.text())