Add child with multiple columns to qtreeview in pyside

3.8k Views Asked by At

How do I add children nodes as seen in the image below. I know how to add a single row and a child. However I get stuck when trying to add a child node that has a checkbox in the second column.

enter image description here

import sys
import os
from PySide import QtGui, QtCore

class Soccer(object):
    def __init__(self,  name='', team=''):
        self.name = name
        self.team = team
        self.op_forward = True
        self.op_goalie = False

class Football(object):
    def __init__(self, name='', team=''):
        self.name = name
        self.team = team
        self.op_quarterback = False
        self.op_center = False
        self.op_coach = False

class Example(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Example, self).__init__(parent)
        self.resize(500, 300)
        self.setWindowTitle('Test')

        # variables
        self.assets = [
            Soccer(name='Doug', team='Nailers'),
            Soccer(name='Leslie', team='Sonics'),
            Football(name='Kevin', team='Patriots'),
            Football(name='Matt', team='Cowboys'),
        ]

        # create widgets
        lb_simulators = QtGui.QLabel('Simulators')
        lb_simulators.setProperty('class', 'section')

        self.items_model = QtGui.QStandardItemModel()
        self.ui_items = QtGui.QTreeView()
        self.ui_items.setAlternatingRowColors(True)
        self.ui_items.setSortingEnabled(True)
        self.ui_items.setAllColumnsShowFocus(True)
        self.ui_items.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.ui_items.header().setResizeMode(QtGui.QHeaderView.Interactive)
        self.ui_items.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.ui_items.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.ui_items.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui_items.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.ui_items.setModel(self.items_model)
        self.ui_items.setRootIsDecorated(False)
        self.ui_items.setFont(QtGui.QFont("Arial", 8, QtGui.QFont.Normal))

        # layout
        grid = QtGui.QVBoxLayout()
        grid.setContentsMargins(10,10,10,10)
        grid.addWidget(lb_simulators)
        grid.addWidget(self.ui_items)

        # main layout
        main_widget = QtGui.QWidget()
        main_widget.setLayout(grid)
        self.setCentralWidget(main_widget)

        self.create_model()

    def create_model(self):
        model = self.ui_items.model()
        model.clear()
        headers = ['Name', ''] # 'Sim', 'Continue', 'Wavelet/Resim', 'Post']
        model.setHorizontalHeaderLabels(headers)
        self.ui_items.sortByColumn(0, QtCore.Qt.AscendingOrder)

        for x in self.assets:
            model.insertRow(0)

            # Append object
            model.setData(model.index(0, 0), x, role=QtCore.Qt.UserRole)
            model.setData(model.index(0, 0), x.name)
            model.setData(model.index(0, 1), x.team)

            # if isinstance(x, Football):
            #     item = model.itemFromIndex(model.index(0,0))


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

if __name__ == '__main__':
    main()
1

There are 1 best solutions below

0
ekhumoro On BEST ANSWER

The setData method sets the value for the specified data role. The role to make items checkable is Qt.CheckStateRole, and the values are given by the check-state enum.

So the second column in your example can be made checkable like this:

model.setData(model.index(0, 1), x.team)
model.setData(model.index(0, 1), QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole)

However, if you're using a QStandardItemModel, it provides a more readable syntax, so your loop to populate the treeview could be re-written like this:

for x in self.assets:
    column1 = QtGui.QStandardItem(x.name)
    column1.setData(x, QtCore.Qt.UserRole)
    column2 = QtGui.QStandardItem(x.team)
    column2.setCheckable(True)
    model.appendRow([column1, column2])