import dearpygui.dearpygui as dpg import re import ctypes from dpg_gui_styles import GuiStyle, INDENT from config_manager import ConfigManager ctypes.windll.shcore.SetProcessDpiAwareness(1) class ConfigEditor: def __init__(self): dpg.create_context() self.construct_main_window() self.styles = GuiStyle() # self.cfg_manager = ConfigManager() dpg.bind_font(self.styles.montserrat_font) dpg.bind_theme(self.styles.main_theme) self.config_data = [] dpg.create_viewport(title='config file editor', width=800, height=600) dpg.setup_dearpygui() dpg.show_viewport() dpg.set_primary_window("main", True) def open_file(self, sender, app_data, user_data): file_path = app_data['file_path_name'] if file_path: for line in open(file_path, 'r', encoding='utf-8'): match = re.match(r" > (\w+) '([\w.]+)' = (.*)", line) if match: self.config_data.append(match.groups()) self.construct_config_window(file_path) def check_tabview(self, root): for uuid in dpg.get_item_children(root, 1): if dpg.get_item_type(uuid) == "mvAppItemType::mvTabBar": return True, uuid return False, None def construct_main_window(self): with dpg.window(label="config file editor", width=800, height=600, tag="main"): with dpg.menu_bar(): with dpg.menu(label="file"): dpg.add_menu_item(label="open config file", callback=lambda _: dpg.show_item("file_dialog"), tag="open_file_btn") with dpg.menu(label="view"): dpg.add_menu_item(label="use default theme", check=True, callback=lambda _, v: dpg.bind_theme(None if v else self.styles.main_theme), default_value=False) dpg.add_menu_item(label="use default font", check=True, callback=lambda _, v: dpg.bind_font(None if v else self.styles.montserrat_font), default_value=False) dpg.add_menu_item(label="show theme editor", callback=dpg.show_style_editor) with dpg.file_dialog(directory_selector=False, show=False, callback=self.open_file, tag="file_dialog", width=500, height=400): dpg.add_file_extension(".txt", color=(0, 255, 0, 255)) dpg.add_file_extension(".*", color=(255, 255, 255, 255)) def construct_config_window(self, filename): for var_type, full_path, value in self.config_data: namespaces = full_path.split('.') root = "main" for level in range(len(namespaces) - 1): path = '.'.join(namespaces[:level+1]) if not dpg.does_item_exist(path): dpg.add_collapsing_header(label=namespaces[level], parent=root, tag=path, indent=INDENT) root = path self.create_widget('.'.join(namespaces[:-1]), namespaces[-1], value, var_type) def construct_config_window_tabs(self, filename): for var_type, full_path, value in self.config_data: namespaces = full_path.split('.') root = "main" for level in range(len(namespaces) - 1): path = '.'.join(namespaces[:level+1]) tab_bar_exists, tab_bar_uuid = self.check_tabview(root) if not tab_bar_exists: tab_bar_uuid = dpg.add_tab_bar(parent=root, tag=f"{path}_tb") if not dpg.does_item_exist(path): dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid, tag=f"{path}_tab") dpg.add_child_window(parent=f"{path}_tab", tag=path, border=True, autosize_x=True, autosize_y=True) root = path self.create_widget('.'.join(namespaces[:-1]), namespaces[-1], value, var_type) def create_widget(self, path, key, value, value_type): parent = path with dpg.group(horizontal=True, parent=parent): dpg.add_text(key) if value_type == 'BOOLEAN': dpg.add_checkbox(default_value=(value.lower() == "true")) elif value_type == 'DOUBLE': dpg.add_input_float(default_value=float(value)) elif value_type == 'INT': dpg.add_input_int(default_value=int(value)) elif "dir" in key.lower(): dpg.add_input_text(default_value=value, tag=f"{path}.{key}") dpg.add_button(label="...", callback=lambda s, a, u: self.file_dialog(f"{path}.{key}")) else: dpg.add_input_text(default_value=value) def file_dialog(self, var_tag): with dpg.file_dialog(directory_selector=True, show=True, callback=lambda s, a, u: dpg.set_value(var_tag, a['file_path_name'])): dpg.add_file_extension(".*", color=(255, 255, 255, 255)) def run(self): dpg.start_dearpygui() dpg.destroy_context() if __name__ == "__main__": app = ConfigEditor() app.run()