[PyQt] Segfault when activating items in a view, more info

Hans-Peter Jansen hpj at urpla.net
Mon Aug 9 12:31:15 BST 2010


On Monday 09 August 2010, 12:20:36 Andreas Pakulat wrote:
> On 09.08.10 12:06:57, Hans-Peter Jansen wrote:
> > Hi Peter,
> >
> > while not of big help, here are a few more details and the backtrace.
> >
> > Qt 4.6.3, sip 4.10.5, PyQt4 4.7.4.
> >
> > On Monday 09 August 2010, 09:42:05 peter at lohmanders.se wrote:
> > > Yes, the connect signal had the wrong signature, but that doesn't
> > > matter. I do not get a warning when trying to connect invalid
> > > signals, but even if I have no activated-signal connected, the darn
> > > thing still segfaults when I double click any cell.
> >
> > Well, even with a correct signal, this crashes (after executing the
> > signal handler):
> >
> > import sys
> > from PyQt4 import QtGui, QtCore
> >
> > class TestModel(QtCore.QAbstractTableModel):
> >
> >     def headerData(self, section, orientation, role =
> >                    QtCore.Qt.DisplayRole):
> >         return QtCore.QVariant("a")
> >
> >     def data(self, index, role = QtCore.Qt.DisplayRole):
> >         if (role == QtCore.Qt.DisplayRole
> >             and index.isValid()
> >             and 0 <= index.row() < 2
> >             and 0 <= index.column() < 2):
> >             return QtCore.QVariant("t")
> >         return QtCore.QVariant()
> >
> >     def columnCount(self, index):
> >         return 2
> >
> >     def rowCount(self, index):
> >         return 2
>
> If you use this model on a treeview you'll probably end up in an infinite
> tree size. The reason is that you're returning a child-count of 2 for
> each and every index (and the treeview is going to ask for the row-count
> of each toplevel entry). Try to add a check for index.isValid() and only
> return 2 if its not a valid index.

Yes, that did the trick. As Peter said, this is rather counterintuitive as 
an table API, but anyway. For any descendants:


import sys
from PyQt4 import QtGui, QtCore

class TestModel(QtCore.QAbstractTableModel):

    def headerData(self, section, orientation, role =
                   QtCore.Qt.DisplayRole):
        return QtCore.QVariant("a")

    def data(self, index, role = QtCore.Qt.DisplayRole):
        if (role == QtCore.Qt.DisplayRole
            and index.isValid()
            and 0 <= index.row() < 2
            and 0 <= index.column() < 2):
            return QtCore.QVariant("t")
        return QtCore.QVariant()

    def columnCount(self, index):
        if not index.isValid():
            return 2
        return 0

    def rowCount(self, index):
        if not index.isValid():
            return 2
        return 0


def onActivated():
    print "activated"


if __name__ == "__main__":
    app = QtGui.QApplication([])
    win = QtGui.QMainWindow()
    model = TestModel()
    view = QtGui.QTreeView()
    view.setModel(model)
    view.setRootIsDecorated(False)
    view.activated.connect(onActivated)
    win.setCentralWidget(view)
    win.show()
    app.exec_()


BTW, this model reveals another issue: the focus can be set to all table 
items by clicking with the mouse, but only to the left column items by 
keyboard. Is that to be expected? Given, above is enough to implement a 
read only table, shouldn't it handle keyboard navigation properly, too? 

@Peter: now that you got a solution for free, how about returning something 
by sticking this into the wiki: http://diotavelli.net/PyQtWiki

Cheers,
Pete


More information about the PyQt mailing list