import collections from PySide6 import QtWidgets, QtCore class Item(object): def __init__(self, data, parent): self._data = data self.parent = parent self.children = [] self.can_fetch_more = True def __repr__(self): return "Item({!r})".format(self.alias) @property def alias(self): parent = self.parent alias = [self.data("name")] while parent: alias.append(parent.data("name")) parent = parent.parent return "/".join(reversed(alias)) def data(self, key, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole: return self._data.get(key, "") class TreeModel(QtCore.QAbstractItemModel): def __init__(self, columns, parent=None): super(TreeModel, self).__init__(parent=parent) self.root = Item({"name": "root"}, None) self.columns = columns def getItem(self, index): if index is None or not index.isValid(): return self.root if index.isValid(): item = index.internalPointer() if item: return item return None def data(self, index, role): item = self.getItem(index) key = list(self.columns.keys())[index.column()] return item.data(key, role) def index(self, row, column, parent=None): item = self.getItem(parent) child = item.children[row] return self.createIndex(row, column, child) def parent(self, index): item = self.getItem(index) if item.parent == self.root: return QtCore.QModelIndex() row = item.parent.children.index(item) return self.createIndex(row, 0, item.parent) def rowCount(self, index): return len(self.getItem(index).children) def columnCount(self, index): return len(list(self.columns.keys())) def flags(self, index): return QtCore.Qt.ItemIsSelectable \ | QtCore.Qt.ItemIsEnabled \ | QtCore.Qt.ItemIsDragEnabled \ | QtCore.Qt.ItemIsDropEnabled def setData(self, index, value, role): if role != QtCore.Qt.EditRole: return item = self.getItem(index) item.data[self.columns.keys()[index.column()]] = value def headerData(self, section, orientation, role): if role == QtCore.Qt.DisplayRole: return list(self.columns.values())[section] def canFetchMore(self, index): item = self.getItem(index) return item.can_fetch_more def fetchMore(self, index): item = self.getItem(index) self.beginInsertRows(index, 0, 9) for i in range(10): item.children.append(Item({"name": "Item #{}".format(i)}, item)) self.endInsertRows() item.can_fetch_more = False def hasChildren(self, index): item = self.getItem(index) return bool(item.children) or item.can_fetch_more def show(proxy=True): app = QtWidgets.QApplication([]) tree = QtWidgets.QTreeView() columns = collections.OrderedDict([ ["name", "Name"] ]) model = TreeModel(columns) if proxy: proxy_model = QtCore.QSortFilterProxyModel() proxy_model.setSourceModel(model) model = proxy_model tree.setModel(model) tree.show() app.exec_() if __name__ == "__main__": show()