From 9fdb9ef76dad4859d9dcce38d4bf06bb5f0c434c Mon Sep 17 00:00:00 2001 From: Christoph Stahl Date: Thu, 9 Nov 2023 09:38:44 +0100 Subject: [PATCH] More unifying the gui code --- syng/gui.py | 210 ++++++++++++++++++++++++++++------------------------ 1 file changed, 115 insertions(+), 95 deletions(-) diff --git a/syng/gui.py b/syng/gui.py index 719879c..7656296 100644 --- a/syng/gui.py +++ b/syng/gui.py @@ -1,5 +1,4 @@ import builtins -from functools import partial from json import load import customtkinter import qrcode @@ -12,7 +11,88 @@ from syng.client import default_config from .sources import available_sources -class SourceTab(customtkinter.CTkFrame): +class OptionFrame(customtkinter.CTkFrame): + def add_option_label(self, text): + customtkinter.CTkLabel(self, text=text, justify="left").grid( + column=0, row=self.number_of_options, padx=5, pady=5 + ) + + def add_bool_option(self, name, description, value=False): + self.add_option_label(description) + self.bool_options[name] = customtkinter.CTkCheckBox( + self, + text="", + onvalue=True, + offvalue=False, + ) + if value: + self.bool_options[name].select() + else: + self.bool_options[name].deselect() + self.bool_options[name].grid(column=1, row=self.number_of_options) + self.number_of_options += 1 + + def add_string_option(self, name, description, value="", callback=None): + self.add_option_label(description) + if value is None: + value = "" + + self.string_options[name] = customtkinter.CTkTextbox( + self, wrap="none", height=1 + ) + self.string_options[name].grid(column=1, row=self.number_of_options) + self.string_options[name].insert("0.0", value) + if callback is not None: + self.string_options[name].bind("", callback) + self.string_options[name].bind("", callback) + self.number_of_options += 1 + + def add_list_option(self, name, description, value=[], callback=None): + self.add_option_label(description) + + self.list_options[name] = customtkinter.CTkTextbox(self, wrap="none", height=1) + self.list_options[name].grid(column=1, row=self.number_of_options) + self.list_options[name].insert("0.0", ", ".join(value)) + if callback is not None: + self.list_options[name].bind("", callback) + self.list_options[name].bind("", callback) + self.number_of_options += 1 + + def add_choose_option(self, name, description, values, value=""): + self.add_option_label(description) + self.choose_options[name] = customtkinter.CTkOptionMenu(self, values=values) + self.choose_options[name].grid(column=1, row=self.number_of_options) + self.choose_options[name].set(value) + self.number_of_options += 1 + + def __init__(self, parent): + super().__init__(parent) + self.number_of_options = 0 + self.string_options = {} + self.choose_options = {} + self.bool_options = {} + self.list_options = {} + + def get_config(self): + config = {} + for name, textbox in self.string_options.items(): + config[name] = textbox.get("0.0", "end").strip() + + for name, optionmenu in self.choose_options.items(): + config[name] = optionmenu.get().strip() + + for name, checkbox in self.bool_options.items(): + config[name] = checkbox.get() == 1 + + for name, textbox in self.list_options.items(): + config[name] = [ + v.strip() for v in textbox.get("0.0", "end").strip().split(",") + ] + + return config + + +class SourceTab(OptionFrame): def updateStrVar(self, var: str, element: customtkinter.CTkTextbox, event): value = element.get("0.0", "end").strip() self.vars[var] = value @@ -33,90 +113,32 @@ class SourceTab(customtkinter.CTkFrame): source.config_schema.items() ): value = config[name] if name in config else default - self.vars[name] = value - label = customtkinter.CTkLabel(self, text=f"{desc} ({name})") - label.grid(column=0, row=row) match typ: case builtins.bool: - checkbox = customtkinter.CTkCheckBox( - self, - text="", - onvalue=True, - offvalue=False, - ) - checkbox.bind( - "", partial(self.updateBoolVar, name, checkbox) - ) - checkbox.bind( - "", partial(self.updateBoolVar, name, checkbox) - ) - if value: - checkbox.select() - else: - checkbox.deselect() - checkbox.grid(column=1, row=row) + self.add_bool_option(name, desc, value=value) case builtins.list: - inputfield = customtkinter.CTkTextbox(self, wrap="none", height=1) - inputfield.bind( - "", partial(self.updateStrVar, name, inputfield) - ) - inputfield.bind( - "", partial(self.updateStrVar, name, inputfield) - ) - inputfield.insert("0.0", ", ".join(value)) - inputfield.grid(column=1, row=row) + self.add_list_option(name, desc, value=value) case builtins.str: - inputfield = customtkinter.CTkTextbox(self, wrap="none", height=1) - inputfield.bind( - "", partial(self.updateStrVar, name, inputfield) - ) - inputfield.bind( - "", partial(self.updateStrVar, name, inputfield) - ) - inputfield.insert("0.0", value) - inputfield.grid(column=1, row=row) - - def get_config(self): - return self.vars + self.add_string_option(name, desc, value=value) -class GeneralConfig(customtkinter.CTkFrame): - def add_option_label(self, text): - customtkinter.CTkLabel(self, text=text, justify="left").grid( - column=0, row=self.number_of_options, padx=5, pady=5 - ) - - def add_string_option(self, name, description, callback=None): - self.add_option_label(description) - - self.string_options[name] = customtkinter.CTkTextbox( - self, wrap="none", height=1 - ) - self.string_options[name].grid(column=1, row=self.number_of_options) - if callback is not None: - self.string_options[name].bind("", callback) - self.number_of_options += 1 - - def add_choose_option(self, name, description, values): - self.add_option_label(description) - self.choose_options[name] = customtkinter.CTkOptionMenu(self, values=values) - self.choose_options[name].grid(column=1, row=self.number_of_options) - self.number_of_options += 1 - +class GeneralConfig(OptionFrame): def __init__(self, parent, config, callback): super().__init__(parent) - self.number_of_options = 0 - self.string_options = {} - self.choose_options = {} - self.add_string_option("server", "Server", callback) - self.add_string_option("room", "Room", callback) - self.add_string_option("secret", "Secret") + self.add_string_option("server", "Server", config["server"], callback) + self.add_string_option("room", "Room", config["room"], callback) + self.add_string_option("secret", "Secret", config["secret"]) self.add_choose_option( - "waiting_room_policy", "Waiting room policy", ["forced", "optional", "none"] + "waiting_room_policy", + "Waiting room policy", + ["forced", "optional", "none"], + config["waiting_room_policy"], + ) + self.add_string_option("last_song", "Time of last song", config["last_song"]) + self.add_string_option( + "preview_duration", "Preview Duration", config["preview_duration"] ) - self.add_string_option("last_song", "Time of last song") - self.add_string_option("preview_duration", "Preview Duration") for name, textbox in self.string_options.items(): if config[name]: @@ -126,17 +148,12 @@ class GeneralConfig(customtkinter.CTkFrame): optionmenu.set(str(config[name]).lower()) def get_config(self): - config = {} - for name, textbox in self.string_options.items(): - config[name] = textbox.get("0.0", "end").strip() - - for name, optionmenu in self.choose_options.items(): - config[name] = optionmenu.get().strip() - + config = super().get_config() try: config["preview_duration"] = int(config["preview_duration"]) except ValueError: config["preview_duration"] = 0 + return config @@ -159,13 +176,6 @@ class SyngGui(customtkinter.CTk): ) self.wm_title("Syng") - tabview = customtkinter.CTkTabview(self) - tabview.pack(side="top") - - tabview.add("General") - for source in available_sources: - tabview.add(source) - tabview.set("General") fileframe = customtkinter.CTkFrame(self) fileframe.pack(side="bottom") @@ -182,14 +192,24 @@ class SyngGui(customtkinter.CTk): ) startbutton.pack(side="right") - frm = customtkinter.CTkFrame(tabview.tab("General")) - frm.grid(ipadx=10) + frm = customtkinter.CTkFrame(self) + frm.pack(ipadx=10, padx=10, fill="both", expand=True) + + tabview = customtkinter.CTkTabview(frm) + tabview.pack(side="right", padx=10, pady=10, fill="both", expand=True) + + tabview.add("General") + for source in available_sources: + tabview.add(source) + tabview.set("General") self.qrlabel = customtkinter.CTkLabel(frm, text="") - self.qrlabel.grid(column=0, row=0) + self.qrlabel.pack(side="left") - self.general_config = GeneralConfig(frm, config["config"], self.updateQr) - self.general_config.grid(column=1, row=0) + self.general_config = GeneralConfig( + tabview.tab("General"), config["config"], self.updateQr + ) + self.general_config.pack(ipadx=10, fill="y") self.tabs = {} @@ -202,7 +222,7 @@ class SyngGui(customtkinter.CTk): self.tabs[source_name] = SourceTab( tabview.tab(source_name), source_name, source_config ) - self.tabs[source_name].grid(ipadx=10) + self.tabs[source_name].pack(ipadx=10) self.updateQr()