-
-
Save hdary85/64c3c7f1ab97e603195380b5aac4b19d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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