I have a 2 column treeView with a simple heirarchy depth of 2; root > parent > child. I have a removeRows call in my treeView subclass that gets evaluated when the delete key is pressed. This seems to work fine when I delete any row but the last one.
I receive an IndexError: list index out of range
, that seems to be coming from the node class child
method. This seems to occur when the self.beginRemoveRows
method is called in the model's removeRows
. Strangely, the order of operations appears to be reversed, or threading is somehow causing a refresh to occur before the model knows about it's recent update.
With these code snippets I was hoping someone could provide a possible explanation or some ideas of what to try next to debug this.
from the QTreeView subclass,
def keyPressEvent(self, event):
if event.key() == Qt.Key_Delete:
index = self.currentIndex()
self.model().removeRow(index.row())
else:
# call base class keyPressEvent
QTreeView.keyPressEvent(self, event)
from the QAbstractItemModel subclass,
def index(self, row, column, parent=QModelIndex()):
parent_node = self.getNode(parent)
child_item = parent_node.child(row)
if child_item:
return self.createIndex(row, column, child_item)
else:
return QModelIndex()
def getNode(self, index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self._root
def removeRows(self, position, rows, parent=QModelIndex()):
parent_node = self.getNode(parent)
self.beginRemoveRows(parent, position, position + rows - 1)
parent_node.removeChild(position)
self.endRemoveRows()
return True
from the node class,
def child(self, row):
return self._children[row]
def removeChild(self, position):
if position < 0 or position >= len(self._children):
return False
child = self._children.pop(position)
child._parent = None
return True
It took me some time, but I finally found the cause of the bug: according to this mail in the index
method you should check if the index exists before proceeding. Annoyingly it's not written in the method description, nor in qt4 or qt5 documentation.
The correct implementation of the index
method should be something on the line:
def index(self, row, column, parent=QModelIndex()):
if self.hasIndex(row, column, parentIndex):
parent_node = self.getNode(parent)
child_item = parent_node.child(row)
if child_item:
return self.createIndex(row, column, child_item)
else:
return QModelIndex()
In my application this solved the issue.