Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import sys
- from PySide6 import (
- QtCore,
- QtWidgets
- )
- class Node(QtCore.QObject):
- def __init__(self, val: str, model, parent=None):
- super().__init__(parent)
- self.value = val
- self._model = model
- def child_count(self) -> int:
- return len(self.children())
- def get_child(self, row: int) -> "Node":
- if row < 0 or row >= self.child_count():
- return None
- else:
- return self.children()[row]
- def get_model_index(self) -> QtCore.QModelIndex:
- return self._model.index(self.get_row_in_parent(), 0, self.parent().get_model_index())
- def get_row_in_parent(self) -> int:
- p = self.parent()
- if p is not None:
- return p.children().index(self)
- return -1
- class RootNode(Node):
- def get_row_in_parent(self) -> int:
- return -1
- def get_model_index(self) -> QtCore.QModelIndex:
- return QtCore.QModelIndex()
- class Model(QtCore.QAbstractItemModel):
- def __init__(self, parent=None):
- super().__init__(parent)
- self.root_item = None
- # simulate the changing data
- self._data = [
- (1, 'child 1 of 1'),
- (1, 'child 2 of 1'),
- (1, 'child 3 of 1'),
- ]
- self._initialize_static_part()
- self.update()
- def _initialize_static_part(self):
- """This is the part of my model which never changes at runtime
- """
- self.root_item = RootNode('root', self, self)
- nodes_to_add = []
- for i in range(0, 5):
- new_node = Node(str(i), self)
- nodes_to_add.append(new_node)
- for node in nodes_to_add:
- self.add_node(node, self.root_item)
- def update(self):
- """This is the part which needs update during runtime
- """
- rows_to_add = []
- rows_to_delete = []
- for c in self.root_item.children():
- for d in c.children():
- rows_to_delete.append(d)
- for (parent_identifier, name) in self._data:
- node = Node(name, self)
- # actually, the future parent is a different function, but for the MWE this suffices
- future_parent = self.root_item.get_child(parent_identifier)
- rows_to_add.append((future_parent, node))
- for node in rows_to_delete:
- self.remove_node(node)
- for (parent, node) in rows_to_add:
- self.add_node(node, parent)
- def add_node(self, node: Node, parent: Node):
- self.beginInsertRows(parent.get_model_index(),
- parent.child_count(),
- parent.child_count())
- node.setParent(parent)
- self.endInsertRows()
- def remove_node(self, node):
- parent_node = node.parent()
- row = parent_node.get_model_index().row()
- self.beginRemoveRows(parent_node.get_model_index(
- ), row, row)
- print(parent_node.get_model_index().isValid())
- node.setParent(None)
- print(node)
- print(parent_node.children())
- self.endRemoveRows()
- # reimplement virtual method
- def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int:
- return 1
- # reimplement virtual method
- def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int:
- if not parent.isValid():
- parent_item = self.root_item
- else:
- parent_item = parent.internalPointer()
- return parent_item.child_count()
- # reimplement virtual method
- def index(self, row: int, column: int, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> QtCore.QModelIndex:
- if not self.hasIndex(row, column, parent):
- return QtCore.QModelIndex()
- if not parent.isValid():
- parent_item = self.root_item
- else:
- parent_item = parent.internalPointer()
- child_item: Node = parent_item.get_child(row)
- if child_item is not None:
- return self.createIndex(row, column, child_item)
- return QtCore.QModelIndex()
- # reimplement virtual method
- def parent(self, index: QtCore.QModelIndex) -> QtCore.QModelIndex:
- if not index.isValid():
- return QtCore.QModelIndex()
- child_item: Node = index.internalPointer()
- parent_item = child_item.parent()
- if parent_item is not None:
- return parent_item.get_model_index()
- return QtCore.QModelIndex()
- # reimplement virtual method
- def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole) -> object:
- if not index.isValid():
- return None
- if role == QtCore.Qt.DisplayRole:
- item: Node = index.internalPointer()
- if item is not None:
- return item.value
- return 'whats this?'
- return None
- class MyWindow(QtWidgets.QMainWindow):
- defaultsize = QtCore.QSize(780, 560)
- def __init__(self, app, parent=None):
- super().__init__(parent)
- self.app = app
- self.resize(self.defaultsize)
- main_layout = QtWidgets.QSplitter(QtCore.Qt.Vertical)
- self.panel = Panel(main_layout)
- self.setCentralWidget(main_layout)
- self.model = Model(self)
- proxy_model1 = QtCore.QSortFilterProxyModel(self)
- proxy_model1.setSourceModel(self.model)
- proxy_model2 = QtCore.QIdentityProxyModel(self)
- proxy_model2.setSourceModel(self.model)
- view1 = QtWidgets.QTreeView(self.panel)
- view1.setAlternatingRowColors(True)
- view1.setModel(proxy_model1)
- view1.expandAll()
- view2 = QtWidgets.QTreeView(self.panel)
- view2.setAlternatingRowColors(True)
- view2.setModel(proxy_model2)
- view2.expandAll()
- self.panel.addWidget(view1)
- self.panel.addWidget(view2)
- # we simulate a change, which would usually be triggered manually
- def manual_change_1():
- self.model._data = [
- (1, 'child 2 of 1'),
- (1, 'child 3 of 1'),
- ]
- self.model.update()
- QtCore.QTimer.singleShot(2000, manual_change_1)
- class App(QtWidgets.QApplication):
- def __init__(self):
- super().__init__()
- self.window = MyWindow(self)
- def run(self):
- self.window.show()
- result = self.exec_()
- self.exit()
- class Panel(QtWidgets.QSplitter):
- pass
- if __name__ == '__main__':
- app = App()
- app.startTimer(1000)
- sys.exit(app.run())
Advertisement
Add Comment
Please, Sign In to add comment