0

I found this model to visualize qtableview with checkboxes. It works, but now I want also to change the state of checkboxes programmatically (for example a button that check/uncheck all checkboxes). I have no idea how I can do it...

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class TableModel(QAbstractTableModel):
    def __init__(self, parent=None):
        super(TableModel, self).__init__(parent)
        self.tableData = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
        self.checks = {}

    def columnCount(self, *args):
        return 3

    def rowCount(self, *args):
        return 3

    def checkState(self, index):
        if index in self.checks.keys():
            return self.checks[index]
        else:
            return Qt.Unchecked

    def data(self, index, role=Qt.DisplayRole):
        row = index.row()
        col = index.column()
        if role == Qt.DisplayRole:
            return '{0}'.format(self.tableData[row][col])
        elif role == Qt.CheckStateRole and col == 0:
            return self.checkState(QPersistentModelIndex(index))
        return None

    def setData(self, index, value, role=Qt.EditRole):

        if not index.isValid():
            return False
        if role == Qt.CheckStateRole:
            self.checks[QPersistentModelIndex(index)] = value
            return True
        return False

    def flags(self, index):
        fl = QAbstractTableModel.flags(self, index)
        if index.column() == 0:
            fl |= Qt.ItemIsEditable | Qt.ItemIsUserCheckable
        return fl
eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

1

You have to use the setData() method, in this method the dataChanged signal must be emitted when the value associated with a role changes:

def setData(self, index, value, role=Qt.EditRole):
    if not index.isValid():
        return False
    if role == Qt.CheckStateRole:
        self.checks[QPersistentModelIndex(index)] = value
        self.dataChanged.emit(index, index)
        return True
    return False

If you want to check and uncheck the items you must iterate over the items:

class Widget(QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.button = QPushButton("Checked", checkable=True)
        self.button.clicked.connect(self.on_clicked)

        self.view = QTableView()
        self.model = TableModel(self)
        self.view.setModel(self.model)

        lay = QVBoxLayout(self)
        lay.addWidget(self.button)
        lay.addWidget(self.view)

    @pyqtSlot(bool)
    def on_clicked(self, state):
        c = 0
        for r in range(self.model.rowCount()):
            ix = self.model.index(r, c)
            self.model.setData(
                ix, Qt.Checked if state else Qt.Unchecked, Qt.CheckStateRole
            )
        self.button.setText("Unchecked" if state else "Checked")
eyllanesc
  • 235,170
  • 19
  • 170
  • 241