Sheena
Sheena

Reputation: 16242

PyQt4.9.1 view never calls model.data

I'm trying to figure out how to work with the models and views in PyQt4.9.1 and I've run into a bit of a problem.

Here's the code that matters:

class TestModel(QtGui.QStandardItemModel):
    def __init__(self,parent=None):
        QtGui.QStandardItemModel.__init__(self,parent)
        self.initData()
        self.headings = ['name','value','']

    def initData(self):
        self.rows = [['name {0}'.format(i), i] for i in range(20)]

    def data(self, index, value, role):
        print ("foo")
        if not index.isValid():
            return 
        if (role == QtCore.Qt.DisplayRole):
            row = index.row()
            col = index.column()
            if  (col == 3):
                return "BUTTON GOES HERE"
        return self.rows[row][col]

    def headerData(self,section,orientation,role):
        if (role == QtCore.Qt.DisplayRole):
            if (orientation == QtCore.Qt.Horizontal):
                 return self.headings[section]

    def rowCount(self,parent):
        return len(self.rows)

    def columnCount(self,parent):
        return 3

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.m = TestModel()
        self.initUi()

    def initUi(self):   
        layout = QtGui.QVBoxLayout()
        widget = QtGui.QTableView()
        widget.setModel(self.m)
        layout.addWidget(widget)
        self.setLayout(layout)
        self.show()

Here's what happens when I launch my application's MainWindow: There are no error messages, the table is drawn with the right number of rows and columns and the correct headings, but the table is empty. You might notice that the model's draw method starts off with a print statement. That statement is never reached. Is there something I'm missing? I cant find any tutorials at all for PyQt4.9.1.

Upvotes: 1

Views: 359

Answers (1)

alexisdm
alexisdm

Reputation: 29896

data() doesn't have any value parameter, but removing it doesn't solve the problem.

The virtual method index(row, column, parent), which is called whenever a QModelIndex needs to be created, always returns an invalid index for QStandardItemModel, unless a QStandardItem was explicitly created for the requested index. The view probably doesn't try to display cells when the index is invalid, so data() is never called.

If you kept inheriting from QStandardItemModel, you would need to reimplement index() to create valid indexes, but since you are using your own structure to store the data instead of using QStandardItem, you could simply inherit from QtCore.QAbstractTableModel:

class TestModel(QtCore.QAbstractTableModel):
    def __init__(self,parent=None):
        super(TestModel, self).__init__(parent)
        self.initData()
        self.headings = ['name','value','']

    def initData(self):
        self.rows = [['name {0}'.format(i), i] for i in range(20)]

    def data(self, index, role):
        if index.parent().isValid():
            return None             
        if (role == QtCore.Qt.DisplayRole):
            row = index.row()
            col = index.column()
            # 3rd column index is 2 not 3
            if  (col == 2):
                return "BUTTON GOES HERE"
            # that return should also be "inside" the role DisplayRole
            return self.rows[row][col]
        return None

    def headerData(self,section,orientation,role):
        if (role == QtCore.Qt.DisplayRole):
            if (orientation == QtCore.Qt.Horizontal):
                return self.headings[section]

Also, you should only return a non-zero row/column count for top-level items (the one without parent), if you are not representing a tree model :

    def rowCount(self,parent):
        if not parent.isValid():
            return len(self.rows)
        return 0

    def columnCount(self,parent):
        if not parent.isValid():
            return 3
        return 0

Upvotes: 1

Related Questions