import customtkinter as ctk from tkinter import filedialog from tkinter import messagebox import json ctk.set_appearance_mode("System") ctk.set_default_color_theme("blue") class ConfigEditor: def __init__(self, root): self.root = root self.root.title("Config File Editor") self.config_data = {} self.open_button = ctk.CTkButton(self.root, text="Open Config File", command=self.open_file) self.open_button.pack(pady=20) def open_file(self): file_path = filedialog.askopenfilename(filetypes=[("Config Files", "*.txt"), ("All Files", "*.*")]) if file_path: try: with open(file_path, 'r') as file: self.config_data = self.parse_config(file.read()) self.display_config() except Exception as e: messagebox.showerror("Error", f"Failed to read config file: {e}") def parse_config(self, filename): result = subprocess.run(["./parser-cli", filename], capture_output=True, text=True) output = result.stdout data = {} lines = output.splitlines() for line in lines: match = re.match(r" > (\w+) '([\w.]+)' = (.*)", line) if match: var_type, full_name, value = match.groups() keys = full_name.split('.') d = data for key in keys[:-1]: if key not in d: d[key] = {} d = d[key] d[keys[-1]] = value.strip() return data def parse_config(self, content): data = {} lines = content.split("\n") print(lines) current_namespace = data namespace_stack = [] for line in lines: line = line.split("#")[0].strip() # Remove comments if not line: continue if line.endswith("{"): namespace_name = line[:-1].strip() namespace_stack.append(current_namespace) if namespace_name not in current_namespace: current_namespace[namespace_name] = {} current_namespace = current_namespace[namespace_name] elif line.endswith("}"): current_namespace = namespace_stack.pop() else: if "=" in line: key, value = [x.strip() for x in line.split("=", 1)] current_namespace[key] = value.strip(";").strip() return data def display_config(self): for widget in self.root.winfo_children(): if isinstance(widget, ctk.CTkFrame): widget.destroy() self.tabview = ctk.CTkTabview(self.root) self.tabview.pack(expand=1, fill="both") self.create_tabs(self.tabview, self.config_data) def create_tabs(self, parent, data, tab_name="Main"): tab = parent.add(tab_name) row = 0 for key, value in data.items(): if isinstance(value, dict): sub_tabview = ctk.CTkTabview(tab) sub_tabview.pack(expand=1, fill="both", pady=10) self.create_tabs(sub_tabview, value, key) else: self.create_widget(tab, key, value, row) row += 1 def create_widget(self, parent, key, value, row): ctk.CTkLabel(parent, text=key).grid(row=row, column=0, padx=10, pady=5) if value.lower() in ("true", "false"): var = ctk.BooleanVar(value=value.lower() == "true") ctk.CTkSwitch(parent, variable=var, text="").grid(row=row, column=1, padx=10, pady=5) elif value.replace(".", "", 1).isdigit(): var = ctk.DoubleVar(value=value) ctk.CTkEntry(parent, textvariable=var).grid(row=row, column=1, padx=10, pady=5) elif "||" in value: options = [opt.strip().strip('"') for opt in value.split("||")] var = ctk.StringVar(value=options[0]) ctk.CTkOptionMenu(parent, variable=var, values=options).grid(row=row, column=1, padx=10, pady=5) else: var = ctk.StringVar(value=value) ctk.CTkEntry(parent, textvariable=var).grid(row=row, column=1, padx=10, pady=5) ctk.CTkButton(parent, text="...", command=lambda: self.file_dialog(var)).grid(row=row, column=2, padx=10, pady=5) def file_dialog(self, var): file_path = filedialog.askopenfilename() if file_path: var.set(file_path) if __name__ == "__main__": root = ctk.CTk() app = ConfigEditor(root) root.mainloop()