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