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

Reply via email to