import sys
import json
from PyQt5.QtWidgets import QApplication, QFileDialog, QTreeView, QWidget, QVBoxLayout, QPushButton
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt

class JsonTreeView(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("JSON Tree Viewer")
        self.resize(600, 400)

        self.tree = QTreeView()
        self.tree.setEditTriggers(self.tree.SelectedClicked | self.tree.EditKeyPressed)

        self.tree.setAnimated(True)

        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(['Key', 'Value'])
        self.model.dataChanged.connect(self.dataChanged)

        self.tree.setModel(self.model)
        self.tree.header().setStretchLastSection(True)

        open_btn = QPushButton("Open JSON File")
        open_btn.clicked.connect(self.open_json_file)

        layout = QVBoxLayout()
        layout.addWidget(open_btn)
        layout.addWidget(self.tree)

        self.setLayout(layout)

    def dataChanged(self, topLeft, bottomRight, roles):
        if Qt.EditRole in roles:
            key = self.model.itemData(topLeft.siblingAtColumn(0))[Qt.DisplayRole]
            value = self.model.itemData(topLeft.siblingAtColumn(1))[Qt.DisplayRole]
            print(f"Data changed: Key = {key}, Value = {value}")

    def toData(self, text: str):
        try:
            data = eval(text)
            return data
        except Exception as e:            
            return text   
        
    def open_json_file(self):
        path, _ = QFileDialog.getOpenFileName(self, "Open JSON File", "", "JSON Files (*.json)")
        if path:
            with open(path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            self.model.clear()
            self.add_items(self.model, repr(data), "base")

    def add_items(self, parent, value, key):
        key_item = QStandardItem(repr(key))
        value_item = QStandardItem(repr(value))

        parent.appendRow([key_item, value_item])    
                
        data = self.toData(value)
        if parent == self.model:
            parent.appendRow([key_item, value_item])
        if isinstance(data, dict):
            for k, v in data.items():
                self.add_items(key_item, v, k)
        elif isinstance(data, list):
            for idx, v in enumerate(data):
                self.add_items(key_item, v, idx)        

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = JsonTreeView()
    window.show()
    sys.exit(app.exec_())