pythonpyqtpyqt5qtableviewqabstracttablemodel

Why do boolean values create a dropdown menu in QAbstractTableModel?


In my custom model setting a bool value automatically creates a combobox/dropdown menu with True/False options, whereas string values create a regular line edit type of editor.

I'm trying to understand why this is? and can I access that editor from the delegate to connect its signals (i.e. currentIndexChanged)?

Screnshot

enter image description here

Here is a simple snippet of code to reproduce:

from PySide2 import QtCore, QtGui, QtWidgets
import sys

class BoolModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None):
        super(BoolModel, self).__init__(parent)
        self.bool_value = True

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled

    def rowCount(self, parent=QtCore.QModelIndex()):
        return 5

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 1

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
            return self.bool_value

    def setData(self, index, value, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.EditRole:
            self.bool_value = value
            return True
        return False

app = QtWidgets.QApplication([])
model = BoolModel()
table = QtWidgets.QTableView()
table.show()
table.setModel(model)
sys.exit(app.exec_())

Solution

  • QItemEditorFactory is a class that allows setting an editor type for each type of data as shown in the docs:

    Standard Editing Widgets
    The standard factory implementation provides editors for a variety of data types. These are created whenever a delegate needs to provide an editor for data supplied by a model. The following table shows the relationship between types and the standard editors provided. enter image description here

    And as you can see in the case of Booleans then a QComboBox is used as editor, and in the case of QString (or string in the case of python) a QLineEdit is used.

    You can also access that editor using the delegate:

    class StyledItemDelegate(QtWidgets.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            editor = super(StyledItemDelegate, self).createEditor(parent, option, index)
            if isinstance(editor, QtWidgets.QComboBox):
                editor.currentIndexChanged.connect(print)
            return editor
    
    table.setItemDelegate(StyledItemDelegate(table))