Issue
I have this mostly working code that enables the user to add items to a tree structure. This is working fine as long as you are not adding items to a leaf item (item with no children).
If the item has no children then on the first time adding a child item, view will not update at all. You can get cause the view to update by rolling up the parent item and re-expanding it. Alternatively, adding a second child item causes the view to update (and you can see both items added).
How do I get the view to update after adding the first child to a leaf item?
UPDATE: You can also double click the new parent and its child will be displayed, but no expansion widget. It appears what is not happening is the little expand item widget is not displaying until one of the above conditions has been met.
from PySide import QtCore, QtGui
import sys
model_data = [
[1, [2, [3, 4]]],
[5, [6, 7]],
[8, [9]],
[10]
]
class MyData:
def __init__(self, number, parent=None):
''''''
self.number = number
self.children = []
self.parent = parent
if parent is not None:
parent.addChild(self)
def row(self):
''''''
row = None
if self.parent is None:
row = 0
else:
for i, item in enumerate(self.parent.children):
if item == self:
row = i
break
return row
def addChild(self, item):
''''''
self.children.append(item)
item.parent = self
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, top, *args, **kwargs):
''''''
super(TreeModel, self).__init__(*args, **kwargs)
self.__top = top
def index(self, row, column, parent=QtCore.QModelIndex()):
''''''
if parent.isValid():
parent_node = parent.internalPointer()
node = parent_node.children[row]
index = self.createIndex(row, column, node)
else:
index = self.createIndex(row, column, self.__top)
return index
def parent(self, index):
''''''
if index.isValid():
node = index.internalPointer()
parent = node.parent
if parent is None:
parent_index = QtCore.QModelIndex()
else:
parent_index = self.createIndex(parent.row(), 0, parent)
else:
parent_index = QtCore.QModelIndex()
return parent_index
def rowCount(self, index=QtCore.QModelIndex()):
''''''
node = index.internalPointer()
if node is None:
count = 1
else:
count = len(node.children)
return count
def columnCount(self, index=QtCore.QModelIndex()):
''''''
return 1
def data(self, index, role=QtCore.Qt.DisplayRole):
''''''
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
node = index.internalPointer()
data = str(node.number)
else:
data = None
return data
def addChild(self, index, child):
self.beginInsertRows(index, self.rowCount(index), self.rowCount(index)+1)
parent = index.internalPointer()
parent.addChild(child)
self.endInsertRows()
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.build_model()
self.add_item_action = QtGui.QAction('New &Item', self)
self.add_item_action.triggered.connect(self.add_item)
self.view = QtGui.QTreeView()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.show()
def build_model(self):
def recurse(parent, children_data):
for child_data in children_data:
if isinstance(child_data, list):
recurse(child, child_data)
else:
child = MyData(child_data, parent=parent)
top = MyData(0)
for i, next in enumerate(model_data):
recurse(top, next)
self.model = TreeModel(top)
def add_item(self):
''''''
index = self.view.currentIndex()
new_item = MyData(0)
self.model.addChild(index, new_item)
def contextMenuEvent(self, event):
''''''
contextMenu = QtGui.QMenu()
contextMenu.addAction(self.add_item_action)
contextMenu.exec_(event.globalPos())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
Solution
The model won't always update properly unless it knows that a change to the layout has occured. So try this:
def addChild(self, index, child):
...
self.endInsertRows()
self.layoutChanged.emit()
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.