Skip to content
Snippets Groups Projects
Commit c9836bbe authored by Maryshca's avatar Maryshca
Browse files

v2

parent a1c08b56
Branches
No related tags found
No related merge requests found
import re import re
import ctypes import ctypes
import sys
import dearpygui.dearpygui as dpg import dearpygui.dearpygui as dpg
...@@ -8,69 +9,77 @@ from config import load_config, dump_config ...@@ -8,69 +9,77 @@ from config import load_config, dump_config
ctypes.windll.shcore.SetProcessDpiAwareness(1) ctypes.windll.shcore.SetProcessDpiAwareness(1)
def get_absolute_y(item):
y = dpg.get_item_pos(item)[1]
parent = dpg.get_item_parent(item)
while parent:
if dpg.get_item_type(parent) == 'mvAppItemType::mvChildWindow':
y += dpg.get_item_pos(parent)[1]
parent = dpg.get_item_parent(parent)
return y
def get_item_level(item):
level = 0
parent = dpg.get_item_parent(item)
while parent:
if dpg.get_item_type(parent) == 'mvAppItemType::mvTabBar':
level += 1
parent = dpg.get_item_parent(parent)
return level
def config_iter(config, prefix=""):
for path in config:
namespaces = path.split('.')
for i in range(len(namespaces)):
yield prefix + '.' + '.'.join(namespaces[:i+1])
class ConfigEditor: class ConfigEditor:
def __init__(self): def __init__(self):
dpg.create_context() dpg.create_context()
self.styles = GuiStyle() self.styles = GuiStyle()
self.config = dict() self.config = dict()
self.config_file_path = "" self.config_file_path = str()
self.construct_main_window()
def delete_config_window_and_clear_aliases(self, file_path): def delete_config_window_and_clear_aliases(self, file_path):
if dpg.does_item_exist(file_path): if dpg.does_item_exist(file_path):
if dpg.get_item_type(file_path) == "mvAppItemType::mvChildWindow":
uuid = dpg.get_item_parent(dpg.get_item_parent(file_path))
dpg.delete_item(uuid)
else:
dpg.delete_item(file_path) dpg.delete_item(file_path)
if dpg.does_item_exist(f"{file_path}_tab_bar"):
dpg.delete_item(f"{file_path}_tab_bar")
if dpg.does_item_exist(f"{file_path}_tab"):
dpg.delete_item(f"{file_path}_tab")
if dpg.does_alias_exist(file_path): if dpg.does_alias_exist(file_path):
dpg.remove_alias(file_path) dpg.remove_alias(file_path)
if dpg.does_alias_exist(f"{file_path}_tab_bar"): for path in config_iter(self.config, prefix=self.config_file_path):
dpg.remove_alias(f"{file_path}_tab_bar")
if dpg.does_alias_exist(f"{file_path}_tab"):
dpg.remove_alias(f"{file_path}_tab")
for path in self.config:
namespaces = path.split('.')
for i in range(len(namespaces)):
path = self.config_file_path + '.' + '.'.join(namespaces[:i+1])
if dpg.does_alias_exist(path): if dpg.does_alias_exist(path):
dpg.remove_alias(path) dpg.remove_alias(path)
if dpg.does_alias_exist(f"{path}_tab_bar"):
dpg.remove_alias(f"{path}_tab_bar")
if dpg.does_alias_exist(f"{path}_tab"):
dpg.remove_alias(f"{path}_tab")
if dpg.does_alias_exist(f"{path}_text"):
dpg.remove_alias(f"{path}_text")
def update_config(self): def update_config(self):
for path in self.config: for path in self.config:
if dpg.does_item_exist(f"{self.config_file_path}.{path}"):
self.config[path].value = dpg.get_value(f"{self.config_file_path}.{path}") self.config[path].value = dpg.get_value(f"{self.config_file_path}.{path}")
def manage_file(self, sender, sender_data, user_data): def check_tabview(self, root):
if user_data == "save": for uuid in dpg.get_item_children(root, 1):
if not self.config_file_path: if dpg.get_item_type(uuid) == "mvAppItemType::mvTabBar":
return return True, uuid
self.update_config() return False, None
dump_config(self.config, self.config_file_path)
dpg.show_item("file_save_popup")
return
def manage_file(self, sender, sender_data, user_data):
file_path = sender_data['file_path_name'] file_path = sender_data['file_path_name']
if not file_path:
return
if user_data == "open": if user_data == "open":
self.delete_config_window_and_clear_aliases(self.config_file_path) self.delete_config_window_and_clear_aliases(self.config_file_path)
self.config_file_path = file_path self.config_file_path = file_path
self.config = load_config(file_path) self.config = load_config(file_path)
self.construct_config_ui() self.construct_config_ui()
elif user_data == "save_as": elif user_data == "save_as" or user_data == "save":
if not self.config_file_path:
return
self.update_config() self.update_config()
dump_config(config, file_path) dump_config(self.config, file_path)
dpg.show_item("file_save_popup") dpg.show_item("file_save_popup")
def set_file_path(self, sender, sender_data, user_data): def set_file_path(self, sender, sender_data, user_data):
...@@ -86,6 +95,7 @@ class ConfigEditor: ...@@ -86,6 +95,7 @@ class ConfigEditor:
dpg.set_item_user_data("folder_dialog", user_data) dpg.set_item_user_data("folder_dialog", user_data)
def construct_config_ui(self): def construct_config_ui(self):
self.update_config()
self.delete_config_window_and_clear_aliases(self.config_file_path) self.delete_config_window_and_clear_aliases(self.config_file_path)
if dpg.get_value("use_tabs_ui"): if dpg.get_value("use_tabs_ui"):
self.construct_config_ui_tabs() self.construct_config_ui_tabs()
...@@ -96,21 +106,23 @@ class ConfigEditor: ...@@ -96,21 +106,23 @@ class ConfigEditor:
dpg.bind_font(self.styles.montserrat_font) dpg.bind_font(self.styles.montserrat_font)
dpg.bind_theme(self.styles.main_theme) dpg.bind_theme(self.styles.main_theme)
with dpg.window(label="config file editor", pos=(10, 10), width=800, height=600, tag="main", menubar=True): with dpg.window(label="config file editor", pos=(10, 10), width=dpg.get_viewport_client_width(), height=dpg.get_viewport_client_height(), tag="main", menubar=True):
with dpg.menu_bar(): with dpg.menu_bar(tag="main_menu_bar"):
with dpg.menu(label="file"): with dpg.menu(label="file"):
dpg.add_menu_item(label="open", callback=self.open_file_dialog, tag="open_btn", user_data="open") dpg.add_menu_item(label="open", callback=self.open_file_dialog, tag="open_btn", user_data="open")
dpg.add_menu_item(label="save", callback=self.manage_file, tag="save_btn", user_data="save") dpg.add_menu_item(label="save", callback=lambda: self.manage_file("", {'file_path_name': self.config_file_path}, "save"))
dpg.add_menu_item(label="save as", callback=self.open_file_dialog, tag="save_as_btn", user_data="save_as") dpg.add_menu_item(label="save as", callback=self.open_file_dialog, tag="save_as_btn", user_data="save_as")
with dpg.menu(label="view"): 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 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="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="use tabs [all entered data will be lost]", check=True, callback=lambda: self.construct_config_ui(), default_value=False, tag="use_tabs_ui") dpg.add_menu_item(label="use tabs", check=True, callback=lambda: self.construct_config_ui(), default_value=False, tag="use_tabs_ui")
dpg.add_menu_item(label="show theme editor", callback=dpg.show_style_editor) dpg.add_menu_item(label="show theme editor", callback=dpg.show_style_editor)
with dpg.menu(label="settings"): with dpg.menu(label="settings"):
dpg.add_menu_item(label="auto save [not impl]", check=True, callback=lambda: print("TODO"), default_value=False) dpg.add_menu_item(label="show mouse coords", check=True, callback=lambda _, v: dpg.show_item("mouse") if v else dpg.hide_item("mouse"), default_value=False)
dpg.add_text("", tag="mouse", show=False)
with dpg.file_dialog(directory_selector=False, show=False, callback=self.manage_file, tag="file_dialog", width=600, height=400): with dpg.file_dialog(directory_selector=False, show=False, callback=self.manage_file, tag="file_dialog", width=600, height=400):
dpg.add_file_extension(".txt", color=(0, 255, 0, 255)) dpg.add_file_extension(".txt", color=(0, 255, 0, 255))
...@@ -122,6 +134,17 @@ class ConfigEditor: ...@@ -122,6 +134,17 @@ class ConfigEditor:
with dpg.window(label="", autosize=True, no_resize=True, modal=True, tag="file_save_popup", show=False, pos=(40, 40)): with dpg.window(label="", autosize=True, no_resize=True, modal=True, tag="file_save_popup", show=False, pos=(40, 40)):
dpg.add_text("file saved successfully:)") dpg.add_text("file saved successfully:)")
with dpg.item_handler_registry(tag="main_handler") as handler:
dpg.add_item_resize_handler(callback=lambda: self.change_height(self.config_file_path))
dpg.bind_item_handler_registry("main", "main_handler")
dpg.set_viewport_resize_callback(lambda: self.change_height(self.config_file_path))
uuid = dpg.add_handler_registry()
def clb(s, a, u):
dpg.set_value("mouse", str(a))
dpg.add_mouse_move_handler(parent=uuid, callback=clb)
def construct_config_ui_collapsing_headers(self): def construct_config_ui_collapsing_headers(self):
dpg.add_collapsing_header(label=self.config_file_path, parent="main", tag=self.config_file_path, indent=0, default_open=True) dpg.add_collapsing_header(label=self.config_file_path, parent="main", tag=self.config_file_path, indent=0, default_open=True)
...@@ -138,18 +161,13 @@ class ConfigEditor: ...@@ -138,18 +161,13 @@ class ConfigEditor:
self.create_widget(full_path) self.create_widget(full_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_config_ui_tabs(self): def construct_config_ui_tabs(self):
tab_bar_exists, tab_bar_uuid = self.check_tabview("main") tab_bar_exists, tab_bar_uuid = self.check_tabview("main")
if not tab_bar_exists: if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent="main", tag=f"{self.config_file_path}_tab_bar") tab_bar_uuid = dpg.add_tab_bar(parent="main")
dpg.add_tab(label=self.config_file_path, parent=tab_bar_uuid, tag=f"{self.config_file_path}_tab") tab_uuid = dpg.add_tab(label=self.config_file_path, parent=tab_bar_uuid)
dpg.add_child_window(parent=f"{self.config_file_path}_tab", tag=self.config_file_path, border=True, autosize_y=True, autosize_x=True) dpg.add_child_window(parent=tab_uuid, tag=self.config_file_path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(self.config_file_path, 2 * SPACE)
for full_path in self.config: for full_path in self.config:
namespaces = full_path.split('.') namespaces = full_path.split('.')
...@@ -160,31 +178,48 @@ class ConfigEditor: ...@@ -160,31 +178,48 @@ class ConfigEditor:
tab_bar_exists, tab_bar_uuid = self.check_tabview(parent) tab_bar_exists, tab_bar_uuid = self.check_tabview(parent)
if not tab_bar_exists: if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent=parent, tag=f"{path}_tab_bar") tab_bar_uuid = dpg.add_tab_bar(parent=parent, callback=lambda s, a: self.change_height(a))
dpg.set_item_height(parent, dpg.get_item_height(parent) + 4 * SPACE + FONT_SIZE) dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 4 * SPACE + FONT_SIZE)
if not dpg.does_item_exist(path): if not dpg.does_item_exist(path):
dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid, tag=f"{path}_tab") tab_uuid = dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid)
dpg.add_child_window(parent=f"{path}_tab", tag=path, border=True, autosize_y=False, autosize_x=True, height=2 * SPACE) dpg.add_child_window(parent=tab_uuid, tag=path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(path, 2 * SPACE)
parent = path parent = path
self.create_widget(full_path) self.create_widget(full_path)
def change_height(self, item):
if not dpg.does_item_exist(item):
return
if dpg.get_item_type(item) == "mvAppItemType::mvChildWindow":
uuid = dpg.get_item_parent(item)
new_height = dpg.get_viewport_client_height() - get_absolute_y(uuid) - SPACE * get_item_level(item)
dpg.set_item_height(item, max(new_height, dpg.get_item_user_data(item)))
for child in dpg.get_item_children(item, 1):
self.change_height(child)
def create_widget(self, full_path): def create_widget(self, full_path):
tag = self.config_file_path + '.' + full_path tag = self.config_file_path + '.' + full_path
parent = '.'.join([self.config_file_path] + full_path.split('.')[:-1]) parent = '.'.join([self.config_file_path] + full_path.split('.')[:-1])
if dpg.get_value("use_tabs_ui") and parent != self.config_file_path:
dpg.set_item_height(parent, dpg.get_item_height(parent) + 2 * SPACE + FONT_SIZE + SPACE)
value = self.config[full_path].value value = self.config[full_path].value
value_type = self.config[full_path].value_type value_type = self.config[full_path].value_type
key = self.config[full_path].key key = self.config[full_path].key
comment = self.config[full_path].comment comment = self.config[full_path].comment
with dpg.group(horizontal=True, parent=parent, indent=INDENT): if dpg.get_value("use_tabs_ui") and parent != self.config_file_path and full_path != key:
dpg.add_text(key, tag=f"{tag}_text") dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 2 * SPACE + FONT_SIZE + SPACE)
indent = INDENT
if dpg.get_value("use_tabs_ui"):
indent = 0
with dpg.group(horizontal=True, parent=parent, indent=indent):
text_uuid = dpg.add_text(key)
if value_type == 'BOOLEAN': if value_type == 'BOOLEAN':
dpg.add_checkbox(default_value=value, tag=tag) dpg.add_checkbox(default_value=value, tag=tag)
elif value_type == 'DOUBLE': elif value_type == 'DOUBLE':
...@@ -197,16 +232,28 @@ class ConfigEditor: ...@@ -197,16 +232,28 @@ class ConfigEditor:
else: else:
dpg.add_input_text(default_value=value, tag=tag) dpg.add_input_text(default_value=value, tag=tag)
if comment: if comment:
dpg.add_text(comment, parent=dpg.add_tooltip(parent=f"{tag}_text")) dpg.add_text(comment, parent=dpg.add_tooltip(parent=text_uuid))
def run(self): def run(self):
dpg.create_viewport(title='config file editor', width=800, height=600, small_icon=ICON_PATH) dpg.create_viewport(
title='config file editor',
small_icon=ICON_PATH,
large_icon=ICON_PATH
)
dpg.setup_dearpygui() dpg.setup_dearpygui()
dpg.show_viewport() dpg.show_viewport()
self.construct_main_window()
if self.config_file_path:
self.construct_config_ui()
dpg.set_primary_window("main", True) dpg.set_primary_window("main", True)
dpg.start_dearpygui() dpg.start_dearpygui()
dpg.destroy_context() dpg.destroy_context()
if __name__ == "__main__": if __name__ == "__main__":
app = ConfigEditor() app = ConfigEditor()
if len(sys.argv) > 1:
app.config_file_path = sys.argv[1]
app.config = load_config(sys.argv[1])
app.run() app.run()
...@@ -7,6 +7,7 @@ ROUNDING = 10 ...@@ -7,6 +7,7 @@ ROUNDING = 10
SPACE = 10 SPACE = 10
INDENT = 40 INDENT = 40
ICON_PATH = "icons\\icon.ico" ICON_PATH = "icons\\icon.ico"
BORDER = 3
class GuiStyle: class GuiStyle:
def __init__(self): def __init__(self):
...@@ -59,7 +60,7 @@ class GuiStyle: ...@@ -59,7 +60,7 @@ class GuiStyle:
dpg.add_theme_style(item, SPACE, SPACE, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(item, SPACE, SPACE, category=dpg.mvThemeCat_Core, parent=theme_all)
dpg.add_theme_style(dpg.mvStyleVar_IndentSpacing, 30, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(dpg.mvStyleVar_IndentSpacing, 30, category=dpg.mvThemeCat_Core, parent=theme_all)
dpg.add_theme_style(dpg.mvStyleVar_ChildBorderSize, 3, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(dpg.mvStyleVar_ChildBorderSize, BORDER, category=dpg.mvThemeCat_Core, parent=theme_all)
dpg.add_theme_style(dpg.mvStyleVar_WindowBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(dpg.mvStyleVar_WindowBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all)
dpg.add_theme_style(dpg.mvStyleVar_FrameBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(dpg.mvStyleVar_FrameBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all)
dpg.add_theme_style(dpg.mvStyleVar_WindowMinSize, 200, 200, category=dpg.mvThemeCat_Core, parent=theme_all) dpg.add_theme_style(dpg.mvStyleVar_WindowMinSize, 200, 200, category=dpg.mvThemeCat_Core, parent=theme_all)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment