Skip to content

Instantly share code, notes, and snippets.

@hdary85
Created January 23, 2024 01:58
Show Gist options
  • Save hdary85/64c3c7f1ab97e603195380b5aac4b19d to your computer and use it in GitHub Desktop.
Save hdary85/64c3c7f1ab97e603195380b5aac4b19d to your computer and use it in GitHub Desktop.
from PyQt5.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QPushButton, QWidget, QLineEdit, QMessageBox, QLabel
class NestedDictManager(QApplication):
def __init__(self, original_data):
super(NestedDictManager, self).__init([])
self.original_data = original_data.copy()
self.data = original_data.copy()
self.tree = QTreeWidget()
self.tree.setHeaderLabels(["Key", "Value"])
self.display_dict(self.data)
self.update_btn = QPushButton("Update")
self.delete_btn = QPushButton("Delete")
self.rename_btn = QPushButton("Rename")
self.add_btn = QPushButton("Add Key")
self.update_btn.clicked.connect(self.update_key)
self.delete_btn.clicked.connect(self.delete_key)
self.rename_btn.clicked.connect(self.rename_key)
self.add_btn.clicked.connect(self.add_key)
self.selected_item_path = None
layout = QVBoxLayout()
layout.addWidget(self.tree)
layout.addWidget(self.update_btn)
layout.addWidget(self.delete_btn)
layout.addWidget(self.rename_btn)
layout.addWidget(self.add_btn)
main_widget = QWidget()
main_widget.setLayout(layout)
main_widget.show()
self.exec_()
def display_dict(self, dictionary, parent=None):
for key, value in dictionary.items():
item = QTreeWidgetItem(parent)
item.setText(0, str(key))
if isinstance(value, dict):
self.display_dict(value, item)
else:
item.setText(1, str(value))
def update_key(self):
if self.selected_item_path is not None:
key = self.selected_item_path
new_value, ok = QInputDialog.getText(self.tree, 'Update Value', f'Enter new value for \'{key}\':')
if ok:
item = self.find_item_by_path(self.tree.invisibleRootItem(), key)
item.setText(1, new_value)
self.update_original_dict(key, new_value)
def delete_key(self):
if self.selected_item_path is not None:
confirm = QMessageBox.question(self.tree, 'Confirm Deletion', 'Are you sure you want to delete this key?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if confirm == QMessageBox.Yes:
key = self.selected_item_path
item = self.find_item_by_path(self.tree.invisibleRootItem(), key)
parent = item.parent()
if parent is not None:
parent.removeChild(item)
self.delete_from_original_dict(key)
def rename_key(self):
if self.selected_item_path is not None:
old_key = self.selected_item_path
new_key, ok = QInputDialog.getText(self.tree, 'Rename Key', f'Enter new key name for \'{old_key}\':')
if ok:
item = self.find_item_by_path(self.tree.invisibleRootItem(), old_key)
item.setText(0, new_key)
self.rename_in_original_dict(old_key, new_key)
def add_key(self):
if self.selected_item_path is not None:
new_key, ok = QInputDialog.getText(self.tree, 'Add New Key', 'Enter the new key name:')
if ok and new_key != "":
parent_path = self.selected_item_path
parent_dict = self.get_dict_by_path(self.original_data, parent_path)
parent_dict[new_key] = "New Value"
parent_item = self.find_item_by_path(self.tree.invisibleRootItem(), parent_path)
new_item = QTreeWidgetItem(parent_item)
new_item.setText(0, new_key)
new_item.setText(1, "New Value")
def find_item_by_path(self, parent, key_path):
if not key_path:
return parent
keys = key_path.split('/')
for row in range(parent.childCount()):
item = parent.child(row)
if item.text(0) == keys[0]:
return self.find_item_by_path(item, '/'.join(keys[1:]))
def get_dict_by_path(self, dictionary, key_path):
keys = key_path.split('/')
current_dict = dictionary
for key in keys:
current_dict = current_dict[key]
return current_dict
def update_original_dict(self, key, new_value):
keys = key.split('/')
current_dict = self.original_data
for key in keys[:-1]:
current_dict = current_dict[key]
current_dict[keys[-1]] = new_value
def delete_from_original_dict(self, key):
keys = key.split('/')
current_dict = self.original_data
for key in keys[:-1]:
current_dict = current_dict[key]
del current_dict[keys[-1]]
def rename_in_original_dict(self, old_key, new_key):
keys = old_key.split('/')
current_dict = self.original_data
for key in keys[:-1]:
current_dict = current_dict[key]
current_dict[new_key] = current_dict.pop(keys[-1])
if __name__ == "__main__":
original_dictionary = {
'key1': 'value1',
'key2': {
'key3': 'value3',
'key4': 'value4'
},
'key5': {
'key6': {
'key7': 'value7'
}
}
}
app = NestedDictManager(original_dictionary)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment