I have a data structure which essentially amounts to a nested dictionary. Let's say it looks like this:
standard_dict = {
'section1': {
'category1': np.array([1, 2, 3, 5]),
'category2': 2
},
'section2': {
'category1': [4, 5, 6],
'category2': {'category2a': {'t': 1}}
}
}
Furthermore I have a recursive function with a for loop to generate a nested treeview out of this dictionary. Now I'm trying to ad in the for loop an index to every value, key pair. I tried it with QModelindex but I didn't get to the point where the code does what i want it to.
def add_object(self, v: object, prefix1: object) -> object:
if isinstance(v, dict):
for k, v2 in v.items():
prefix1.addChild(CustomNode(k))
prefix = prefix1.getlastChild()
self.add_object(v2, prefix)
elif isinstance(v, list):
for e in v:
prefix1.addChild(CustomNode(e))
Is there an simple way to implement and add the index to the value, key pair?
The result i'd like to have is to update only the changed single values in a PyQt5 Gui an not the whole Gui.
Here is my whole Project if someone wants to know.
""" import copy from typing import List, Any import sys from PyQt5 import QtCore, QtWidgets, uic import numpy as np from deepdiff import DeepDiff from lib.MainWindow import Ui_MainWindow class CustomNode(object): def __init__(self, data): self._data = data if type(data) == tuple: self._data = list(data) if type(data) is str or not hasattr(data, '__getitem__'): self._data = [data] self._columncount = len(self._data) self._children = [] self._parent = None self._row = 0 def getlastChild(self): return self._children[-1] def data(self, column): if column >= 0 and column < len(self._data): return self._data[column] def columnCount(self): return self._columncount def childCount(self): return len(self._children) def child(self, row): if row >= 0 and row < self.childCount(): return self._children[row] def parent(self): return self._parent def row(self): return self._row def addChild(self, child): child._parent = self child._row = len(self._children) self._children.append(child) self._columncount = max(child.columnCount(), self._columncount) class CustomModel(QtCore.QAbstractItemModel): def __init__(self, nodes): QtCore.QAbstractItemModel.__init__(self) self._root = CustomNode(None) for node in nodes: self._root.addChild(node) def rowCount(self, index: object) -> object: if index.isValid(): return index.internalPointer().childCount() return self._root.childCount() def addChild(self, node, _parent): if not _parent or not _parent.isValid(): parent = self._root else: parent = _parent.internalPointer() parent.addChild(node) def index(self, row, column, _parent=None): if not _parent or not _parent.isValid(): parent = self._root else: parent = _parent.internalPointer() if not QtCore.QAbstractItemModel.hasIndex(self, row, column, _parent): return QtCore.QModelIndex() child = parent.child(row) if child: return QtCore.QAbstractItemModel.createIndex(self, row, column, child) else: return QtCore.QModelIndex() def parent(self, index): if index.isValid(): p = index.internalPointer().parent() if p: return QtCore.QAbstractItemModel.createIndex(self, p.row(), 0, p) return QtCore.QModelIndex() def columnCount(self, index): if index.isValid(): return index.internalPointer().columnCount() return self._root.columnCount() def data(self, index, role): if not index.isValid(): return None node = index.internalPointer() if role == QtCore.Qt.DisplayRole: return node.data(index.column()) return None class MyTree(): def __init__(self, ref_dict, treeView): self.items = [] self.ref_dict = ref_dict self.items = [] self.index_dict = ref_dict '''Erzeugt eine List aus den Hauptitems''' for key in self.ref_dict: self.items += [CustomNode(key)] self.add_object(self.ref_dict[key], prefix1=self.items[-1]) '''Aufruf der View um die Anzeige darzustellen''' # self.tw = QtWidgets.QTreeView() self.tw = treeView self.tw.setModel(CustomModel(self.items)) #referenz auf das Modell, gibt das Modell zurück print(self.tw.model()) '''Funktion um das Dictionary zu iterieren und in einer Treeview darzustellen''' def add_object(self, v: object, prefix1: object) -> object: if isinstance(v, dict): for k, v2 in v.items(): prefix1.addChild(CustomNode(k)) prefix = prefix1.getlastChild() self.add_object(v2, prefix) elif isinstance(v, list): for e in v: prefix1.addChild(CustomNode(e)) elif isinstance(v, type(np.array([]))): [prefix1.addChild(CustomNode(int(i))) for i in v] else: prefix1.addChild(CustomNode(v)) class Compare(): def __init__(self, standard_dict): self.__standard_dict = copy.deepcopy(standard_dict) @property def standard_dict(self): return self.__standard_dict @standard_dict.setter def standard_dict(self, standard_dict): self.__standard_dict = standard_dict # Signal auslösen mit kompletten Update vom Model '''Funktion um mit DeepDiff die beiden Dictionaries zu vergleichen''' def compare(self, new_dict): return DeepDiff(self.__standard_dict, new_dict) class MainWindow(QtWidgets.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) mytree = MyTree(standard_dict, self.ui.treeView) mytree_2 = MyTree(standard_dict, self.ui.treeView_2) self.ui.pushButton.clicked.connect(self.compare_dict) self.comp = Compare(standard_dict=standard_dict) def compare_dict(self): standard_dict['section1']['category2'] += 1 diff = self.comp.compare(standard_dict) self.ui.plainTextEdit.insertPlainText(str(standard_dict)) self.ui.plainTextEdit.insertPlainText(str(diff)) #mytree_3 = MyTree(standard_dict, self.ui.treeView_2) #nur die Stelle des geänderten Indexes updaten und keine neue View erstellen if __name__ == "__main__": standard_dict = { 'section1': { 'category1': np.array([1, 2, 3, 5]), 'category2': 2 }, 'section2': { 'category1': [4, 5, 6], 'category2': {'category2a': {'t': 1}} } } app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
Thanks a lot in advance