pythonselectionpysideqtreeview

Return top items from QTreeview selection Pyside


I have a QTreeview and based on the users selection I would like to get a unique array containing all the names of the parents of the selected items.

So if any children are selected it would return the parent and if a parent is selected it would still return the parent.

Want returned:

>> [Kevin, Michelle, Nikki, Tim]

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.treeview.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        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):
        parents = [
            Person("Kevin", [Person("Tom"), Person("Sarah"), Person("Chester")]),
            Person("Michelle", [Person("James"), Person("Corey"),Person("Leslie")]),
            Person("Doug", [Person("Fred"), Person("Harold"),Person("Stephen")]),
            Person("Nikki", [Person("Brody"), Person("Tyson"),Person("Bella")]),
            Person("Tim", [Person("Marie"), Person("Val"),Person("Ted")])
        ]

        for p in parents:
            self.create_nodes(p, 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 parents..."


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

if __name__ == '__main__':
    main()

Solution

  • Here is a simple implementation:

    def selectedParents(self):
        parents = set()
        for index in self.treeview.selectedIndexes():
            while index.parent().isValid():
                index = index.parent()
            parents.add(index.sibling(index.row(), 0))
        return [index.data() for index in sorted(parents)]
    

    Note that selectedIndexes() returns the indexes in the order they were selected, and, if there are multiple columns, will include the index of every column in the selected row.

    So the above method makes sure only the text from the first column is included, and also makes sure that the items are returned in the correct order.