Unsolved qtreeview not showing created items when a column other than the first is selected
-
Hello all,
I have experienced an strange behaviour with qtreeview in the code below, where the newly created items are not shown in the view if I created them clicking on a column other than the first one. The steps to reproduce are:
- Click on the "Add Child" button
- Click on the second column of the item created in the qtreeview.
- Click on the "Add Child" button
- Any subsequent click to the "Add Child" button creates a new item, but it is not shown in the qtreeview.
- Click on the first column of the item created in the qtreeview, instead of the second column
- Click on the "Add Child" button. All the previously created items show up now.
In step 2, if instead of clicking on the second column, I click on the first column the issue disappears, but it is quite disturbing for the users to keep in mind that they only should click on the first column to work properly.
I found a quick and dirty solution, which is activated by changing the variable fix to True, but I would like to know if there is a better way of fixing it.Many thanks,
#!/usr/bin/env python3 import sys import signal from PySide2 import QtCore, QtGui, QtWidgets class NodeClass(object): def __init__(self, data, parent=None): self.parentItem = parent self.itemData = data self.childItems = [] def child(self, row): return self.childItems[row] def childCount(self): return len(self.childItems) def childNumber(self): if self.parentItem != None: return self.parentItem.childItems.index(self) return 0 def columnCount(self): return len(self.itemData) def data(self, column): return self.itemData[column] def insertChildren(self, position, count, columns, kind): if position < 0 or position > len(self.childItems): insert_status = False else: for row in range(count): data = ["NA" for v in range(columns)] item = kind(data, self) self.childItems.insert(position, item) insert_status = True return insert_status def parent(self): return self.parentItem def setData(self, column, value): if column < 0 or column >= len(self.itemData): set_status = False else: self.itemData[column] = value set_status = True return set_status class ModelClass(QtCore.QAbstractItemModel): def __init__(self, parent=None): super(ModelClass, self).__init__(parent) headers = ["COL_1", "COL_2"] rootData = [header for header in headers] self.rootItem = NodeClass(rootData) def columnCount(self, parent=QtCore.QModelIndex()): return self.rootItem.columnCount() def data(self, index, role): if not index.isValid(): return None item = self.getItem(index) if role != QtCore.Qt.DisplayRole and role != QtCore.Qt.EditRole: return None return item.data(index.column()) def flags(self, index): if not index.isValid(): return 0 return QtCore.Qt.ItemIsEditable | super(ModelClass, self).flags(index) def getItem(self, index): if index.isValid(): item = index.internalPointer() if item: return item return self.rootItem def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: return self.rootItem.data(section) return None def index(self, row, column, parent=QtCore.QModelIndex()): if parent.isValid() and parent.column() != 0: return QtCore.QModelIndex() parentItem = self.getItem(parent) childItem = parentItem.child(row) if childItem: return self.createIndex(row, column, childItem) else: return QtCore.QModelIndex() def insertRows(self, position, rows, kind, parent=QtCore.QModelIndex()): parentItem = self.getItem(parent) self.beginInsertRows(parent, position, position + rows - 1) success = parentItem.insertChildren( position, rows, self.rootItem.columnCount(), kind) self.endInsertRows() self.initRow(position,parent) return success def initRow(self,row,index): for column in range(self.columnCount(index)): child = self.index(row, column, index) self.setData(child, "[No data]", QtCore.Qt.EditRole) def parent(self, index): if not index.isValid(): return QtCore.QModelIndex() childItem = self.getItem(index) parentItem = childItem.parent() if parentItem == self.rootItem: return QtCore.QModelIndex() return self.createIndex(parentItem.childNumber(), 0, parentItem) def rowCount(self, parent=QtCore.QModelIndex()): parentItem = self.getItem(parent) return parentItem.childCount() def setData(self, index, value, role=QtCore.Qt.EditRole): if role != QtCore.Qt.EditRole: set_data_status = False else: item = self.getItem(index) set_data_status = item.setData(index.column(), value) if set_data_status: self.dataChanged.emit(index, index) return set_data_status class WindowClass(QtWidgets.QMainWindow): def __init__(self): super(WindowClass, self).__init__() self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.treeView = QtWidgets.QTreeView(self.centralwidget) self.treeView.setObjectName("treeView") self.horizontalLayout.addWidget(self.treeView) self.verticalLayout.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self.toolBar = QtWidgets.QToolBar(self) self.toolBar.setIconSize(QtCore.QSize(48, 48)) self.toolBar.setObjectName("toolBar") self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionButton = QtWidgets.QAction(self) self.actionButton.setObjectName("actionButton") self.actionButton.setText("Add child") self.toolBar.addAction(self.actionButton) QtCore.QMetaObject.connectSlotsByName(self) self.__model = ModelClass() self.treeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.treeView.setModel(self.__model) self.treeView.setAlternatingRowColors(True) self.actionButton.triggered.connect(self.ButtonMethod) def ButtonMethod(self): fix = False if fix is True: if len(self.treeView.selectedIndexes()) > 0: index = self.treeView.selectedIndexes()[0] else: index = self.treeView.selectionModel().currentIndex() else: index = self.treeView.selectionModel().currentIndex() model = self.treeView.model() if not model.insertRows(0, 1, NodeClass, index): return self.treeView.setExpanded(index, True) def main(): app = QtWidgets.QApplication(sys.argv) main_window = WindowClass() main_window.show() sys.exit(app.exec_()) if __name__ == "__main__": main()