Hi, I am having lots of crashes with my implementation of a dummy proxy model. Could someone please look at this and tell me at which point I am being stupid (and blind) or whether this is a problem with [Py]Qt?
I have attached a stripped down test case that crashes for me (i.e. segfault/ bus error/glibc double free). For now, I just want to have a model that wraps another model and forwards all calls (for future expansion of course). Could there be a simpler model? There are two obvious ways to implement such a proxy model, one is to let the internalPointer() point to the corresponding model index of the proxied Views model, and one is to let the internalPointer() point to the corresponding *parent* model. The former leads to slightly simpler code in the pure dummy model case, but leads to a duplication of the row/column information. Although this is quite ugly, I attached this (simpler) variant. I am getting crashes when accessing internalPointer(), as I can see by single- stepping through the code in pdb. I also tried using QPersistentModelIndex for the internalPointer() (although I am just dealing with static models), but that did not resolve the crashes either. In the attached test case, in which I set up a QStringListModel for testing, it additonally fails with "TypeError: QAbstractListModel.parent() is a private method". (Maybe I am too tired now, but that looks like a bug in QAbstractListModel to me; parent() should not be private.) Thanks for looking at it, Hans
from PyQt4 import QtCore, QtGui # I tried two variants, this should be even safer: needPersistentModelIndex = True class DummyProxyModel(QtCore.QAbstractItemModel): def __init__(self, baseModel, parent = None): QtCore.QAbstractItemModel.__init__(self, parent) self._baseModel = baseModel def _baseIndex(self, index): """Map an index of this model back to the _baseModel.""" if not index.isValid(): return QtCore.QModelIndex() baseIndex = index.internalPointer() if needPersistentModelIndex: # convert QPersistentModelIndex into QModelIndex: baseIndex = self._baseModel.index( baseIndex.row(), baseIndex.column(), baseIndex.parent()) return baseIndex def index(self, row, column, parent = QtCore.QModelIndex()): baseParent = self._baseIndex(parent) baseIndex = self._baseModel.index(row, column, baseParent) if needPersistentModelIndex: baseIndex = QtCore.QPersistentModelIndex(baseIndex) return self.createIndex(row, column, baseIndex) def parent(self, index): baseParent = self._baseModel.parent(self._baseIndex(index)) if not baseParent.isValid(): return QtCore.QModelIndex() if needPersistentModelIndex: baseParent = QtCore.QPersistentModelIndex(baseParent) return self.createIndex( baseParent.row(), baseParent.column(), baseParent) def rowCount(self, index): baseIndex = self._baseIndex(index) return self._baseModel.rowCount(baseIndex) def columnCount(self, index): baseIndex = self._baseIndex(index) return self._baseModel.columnCount(baseIndex) def data(self, index, role): baseIndex = self._baseIndex(index) return self._baseModel.data(baseIndex, role) def headerData(self, section, orientation, role): return self._baseModel.data(section, orientation, role) def flags(self, index): baseIndex = self._baseIndex(index) return self._baseModel.flags(baseIndex) # -------------------------------------------------------------------- # improve debug output # -------------------------------------------------------------------- def QModelIndex__repr__(index): parent = "" if index.parent().isValid(): parent = ", %r" % (index.parent(), ) internal = "" if index.internalPointer() is not None: internal = " [%r]" % index.internalPointer() invalid = "" if not index.isValid(): invalid = ", INVALID!" return "Index(%d, %d%s%s%s)" % ( index.row(), index.column(), parent, internal, invalid) QtCore.QModelIndex.__repr__ = QModelIndex__repr__ # -------------------------------------------------------------------- # test code (__main__) # -------------------------------------------------------------------- app = QtCore.QCoreApplication([]) base = QtGui.QStringListModel(map(str, range(10)), app) model = DummyProxyModel(base, app) print "1) rowCount: %d" % model.rowCount(QtCore.QModelIndex()) print i = model.index(0, 0) print "2) got root index %s (isValid: %s)" % (i, i.isValid()) print j = model._baseIndex(i) print "3) got base index", j
_______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt