Hi, the attached script implements a minimal tree model featuring rows deletion. It works just fine with (Qt 4.4, PyQt 4.4.4). However, with (Qt 4.5.2, PyQt 4.5.4) and (Qt 4.5.2, PyQt 4.6.1) deleting the last row raises the following error:
v...@rachael:/tmp$ python tmTester.py & [2] 6819 v...@rachael:/tmp$ Traceback (most recent call last): File "tmTester.py", line 189, in index return self.createIndex(row, column, branch.childAtRow(row)) File "tmTester.py", line 86, in childAtRow return self.children[row] IndexError: list index out of range Is it a bug in the recent versions of PyQt? Or should I fix some problem in the script? I would really appreciate your help. Vicent :: Share what you know, learn what you don't
# -*- coding: utf-8 -*- #!/usr/bin/env python import sys from PyQt4.QtCore import * from PyQt4.QtGui import * class TreeModelTester(QMainWindow): """Test correctness of tree models/views """ def __init__(self): """Initialize the application.""" QMainWindow.__init__(self) self.counter = 0 # Make the GUI self.setWindowTitle('TreeView tester') self.setupMenus() central_widget = QWidget(self) central_layout = QVBoxLayout(central_widget) self.setCentralWidget(central_widget) self.dbs_tree_view = QTreeView(central_widget) central_layout.addWidget(self.dbs_tree_view) # The tree of databases model/view self.dbs_tree_model = DBsTreeModel(self) self.dbs_tree_view.setModel(self.dbs_tree_model) def setupMenus(self): """Set up the main window menus.""" remove_action = QAction('&Remove', self) remove_action.setShortcut(QKeySequence.Delete) self.connect(remove_action, SIGNAL("triggered()"), self.slotRemoveBranch) menu = self.menuBar().addMenu('&Menu') menu.addAction(remove_action) def closeEvent(self, event): """Handle close events.""" qApp.quit() def slotRemoveBranch(self): """Delete a given branch from the tree model and its views.""" current = self.dbs_tree_view.currentIndex() if current is None: return # Delete the node self.dbs_tree_model.deleteNode(current) class GroupNode(object): """A group node in the tree of databases model.""" def __init__(self, parent, name): """Create a group node for the tree of databases model.""" self.children = [] self.parent = parent self.name = name def __len__(self): return len(self.children) def insertChild(self, child, position=0): """Insert a child in a group node.""" self.children.insert(position, child) def childAtRow(self, row): """The row-th child of this node.""" assert 0 <= row <= len(self.children) return self.children[row] def row(self): """The position of this node in the parent's list of children.""" if self.parent: return self.parent.children.index(self) return 0 class DBsTreeModel(QAbstractItemModel): """The tree of databases model.""" def __init__(self, parent=None): """Create the model.""" QAbstractItemModel.__init__(self, parent) # Populate the model self.root = GroupNode(None, 'root') self.addBranch(QModelIndex(), 'First node') self.addBranch(QModelIndex(), 'Second node') self.addBranch(QModelIndex(), 'Third node') def flags(self, index): """Returns the item flags for the given index. """ return Qt.ItemIsEnabled|Qt.ItemIsSelectable def data(self, index, role): """Returns the data stored under the given role for the item referred to by the index.""" if not index.isValid(): return QVariant() node = self.nodeFromIndex(index) if role == Qt.DisplayRole: return QVariant(node.name) else: return QVariant() def setData(self, index, value, role=Qt.DisplayRole): """Sets the role data for the item at index to value.""" if not index.isValid(): return False node = self.nodeFromIndex(index) if role == Qt.DisplayRole: node.name = value self.emit(SIGNAL( 'dataChanged(QModelIndex, QModelIndex)'), index, index) return True return False def headerData(self, section, orientation, role): """Returns the data for the given role and section in the header with the specified orientation. """ if (orientation, role) == (Qt.Horizontal, \ Qt.DisplayRole): return QVariant('Sample tree') return QVariant() def columnCount(self, parent): """The number of columns for the children of the given index.""" return 1 def rowCount(self, parent): """The number of rows of the given index.""" if not parent.isValid(): parent_node = self.root else: parent_node = parent.internalPointer() return len(parent_node) def hasChildren(self, index): """Finds out if a node has children.""" if not index.isValid(): # self.root fulfils this condition return True parent = self.nodeFromIndex(index) if parent.children != []: return True else: return False def index(self, row, column, parent): """Creates an index in the model for a given node and returns it.""" assert self.root branch = self.nodeFromIndex(parent) assert branch is not None return self.createIndex(row, column, branch.childAtRow(row)) def nodeFromIndex(self, index): """Retrieves the tree node with a given index.""" if index.isValid(): return index.internalPointer() else: return self.root def parent(self, child): """The parent index of a given index.""" node = self.nodeFromIndex(child) if node is None: return QModelIndex() parent = node.parent if parent is None: return QModelIndex() grandparent = parent.parent if grandparent is None: return QModelIndex() row = grandparent.rowOfChild(parent) assert row != -1 return self.createIndex(row, 0, parent) def deleteNode(self, index): """Delete a node from the model.""" node = self.nodeFromIndex(index) # Deletes the node from the tree of databases model/view parent = self.parent(index) position = node.row() self.removeRows(position, 1, parent) def addBranch(self, index, childname): """Create a new branch under the given parent.""" self.insertRows(0, 1, index) child_idx = self.index(0, 0, index) self.setData(child_idx, childname) return True def insertRows(self, position=0, count=1, parent=QModelIndex()): """Insert `count` rows after the given row.""" node = self.nodeFromIndex(parent) self.beginInsertRows(parent, position, position + count - 1) child = GroupNode(node, 'Unknown') node.insertChild(child, position) self.endInsertRows() return True def removeRows(self, position, count=1, parent=QModelIndex()): """Removes `count` rows before the given row.""" node = self.nodeFromIndex(parent) self.beginRemoveRows(parent, position, position + count - 1) for row in range(count): del node.children[position + row] self.endRemoveRows() return True if __name__ == '__main__': app = QApplication(sys.argv) tester = TreeModelTester() tester.show() app.exec_()
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt