From eaedde7ee5543da1768cbf855a215a0da940dce9 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:39:52 +0900 Subject: [PATCH 01/30] fix: clarify wording --- dzgui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui.sh b/dzgui.sh index b090543..a726ba5 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -513,7 +513,7 @@ lock(){ ps -p $pid -o pid= >/dev/null 2>&1 res=$? if [[ $res -eq 0 ]]; then - local msg="DZGUI already running ($pid)" + local msg="DZGUI is already running ($pid)" raise_error_and_quit "$msg" elif [[ $pid == $$ ]]; then : From acc356d3a0871a6a4339617684dad0d34720c5ce Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:40:38 +0900 Subject: [PATCH 02/30] chore: resolve QA errors --- helpers/servers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/helpers/servers.py b/helpers/servers.py index 12f65ce..dc0de57 100644 --- a/helpers/servers.py +++ b/helpers/servers.py @@ -14,10 +14,10 @@ from typing import Union sys.path.append("a2s") import a2s # noqa -from a2s import dayzquery +from a2s import dayzquery # noqa params = [ - r"\nor\1\map\chernarusplus\nor\1\map\sakhal\nor\1\map\enoch\empty\1\nor\1\map\namalsk", + r"\nor\1\map\chernarusplus\nor\1\map\sakhal\nor\1\map\enoch\empty\1\nor\1\map\namalsk", # noqa r"\map\namalsk\empty\1", r"\map\namalsk\noplayers\1", r"\map\chernarusplus\empty\1", @@ -223,7 +223,7 @@ def details(ip: str, qport: int) -> Details: except AttributeError: return Details(None, default_str, False) - battleeye = "Disabled" + battleye = "Disabled" if "battleye" in keywords: battleye = "Enabled" @@ -289,7 +289,7 @@ def ping(iteration: int, row: list) -> Ping: try: res = query_direct(ip, qport, 0.5) - except Exception as e: + except Exception: pass if res is None: From 51308e788ec76c15076892c54c68460859961dd8 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:41:38 +0900 Subject: [PATCH 03/30] feat: parse server details --- helpers/servers.py | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/helpers/servers.py b/helpers/servers.py index dc0de57..5565b28 100644 --- a/helpers/servers.py +++ b/helpers/servers.py @@ -206,6 +206,19 @@ class Details: success: bool +def is_passworded(ip: str, qport: int) -> bool: + try: + info = a2s.info((ip, qport)) + except TimeoutError: + return False + + try: + password = info.password_protected + except AttributeError: + return False + return password + + def details(ip: str, qport: int) -> Details: default_str = "None provided" @@ -237,6 +250,29 @@ def details(ip: str, qport: int) -> Details: night_accel = float(keyword.lstrip("entm")) night_accel = f"{night_accel:g}" + try: + password = info.password_protected + if password is False: + password = "Disabled" + else: + password = "Enabled" + except AttributeError: + password = "-" + + try: + vac = info.vac_enabled + if vac is False: + vac = "Disabled" + else: + vac = "Enabled" + except AttributeError: + vac = "-" + + try: + version = info.version + except AttributeError: + version = "-" + try: dlc = rules.dlc_flags if dlc == 0: @@ -263,11 +299,14 @@ def details(ip: str, qport: int) -> Details: description = default_str rows = [ - ["DLC", dlc], ["Battleye", battleye], ["Daytime acceleration", f"{day_accel}x"], + ["DLC", dlc], ["Night-time acceleration", f"{night_accel}x"], + ["Password", password], ["Platform", platform], + ["Valve Anti-Cheat", vac], + ["Version", version], ] return Details(rows, description, True) From 562f6453dc7b1432bcee67d5d402cc84167422ae Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:46:58 +0900 Subject: [PATCH 04/30] fix: use correct path --- helpers/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 4c441e0..985bc1d 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -63,8 +63,8 @@ funcs = f"{helpers_path}/funcs" mods_temp_file = f"{cache_path}/{app_name_abbr}.mods_temp" stale_mods_temp_file = f"{cache_path}/{app_name_abbr}.stale_mods_temp" servers_path = f"{cache_path}/{app_name_abbr}.servers" -config_path = f"{user_path}/.config" -config_file = f"{user_path}/.config/dztuirc" +config_path = f"{user_path}/.config/dztui" +config_file = f"{config_path}/dztuirc" history_file = f"{state_path}/{app_name_abbr}.history" logger = logging.getLogger(__name__) From ee0fd7b78cd38e98e74f2cf2fed627c37225c9f0 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:47:37 +0900 Subject: [PATCH 05/30] fix: handle unspecified args --- helpers/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 985bc1d..da4b476 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -611,7 +611,7 @@ def block_signals(state: bool = True) -> None: ) -def save_res_and_quit() -> None: +def save_res_and_quit(*args) -> None: if App.window.props.is_maximized: Gtk.main_quit() return @@ -622,7 +622,7 @@ def save_res_and_quit() -> None: j = json.dumps(data, indent=2) with open(res_path, "w") as outfile: outfile.write(j) - logger.info(f"Wrote initial window size to '{res_path}'") + logger.info(f"Wrote window size to '{res_path}'") if os.path.isfile(res_path): with open(res_path, "r") as infile: From 437ea2a2188443b709f224aadde506164932e898 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:48:26 +0900 Subject: [PATCH 06/30] fix: breadcrums not updating correctly --- helpers/ui.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index da4b476..8dfdac4 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3507,12 +3507,7 @@ class Notebook(Gtk.Notebook): def _on_page_changed( self, notebook: "Notebook", page: Gtk.Widget, page_num: int ) -> None: - pass - if page.type is None: - App.treeview.subpage = self.prior_subpage - else: - self.prior_subpage = App.treeview.subpage - App.treeview.subpage = page.type + App.treeview.subpage = page.type class Statusbar(Gtk.Statusbar): From 6c192741ec1c2541ea8ae9c5af773a0f794a0d23 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:48:55 +0900 Subject: [PATCH 07/30] chore: consolidate vars --- helpers/ui.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 8dfdac4..301291f 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3420,8 +3420,7 @@ class Notebook(Gtk.Notebook): def __init__(self): super().__init__(show_tabs=False, show_border=False) - clog = Changelog() - self.clog = ScrollableNote(clog) + self.clog = ScrollableNote(Changelog()) self.clog.type = RowType.CHANGELOG self.clog.show_all() self.append_page(self.clog) From 63beb61878b2c06f585e4c33171444cb5c7b4d64 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:50:37 +0900 Subject: [PATCH 08/30] feat: make back button optional --- helpers/ui.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 301291f..82a307e 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3224,7 +3224,7 @@ class EntryDialog(GenericDialog): class ScrollableNote(Gtk.Box): - def __init__(self, content_box: Gtk.Box): + def __init__(self, content_box: Gtk.Box, back_button=True): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.scrollable = Gtk.ScrolledWindow() @@ -3233,12 +3233,13 @@ class ScrollableNote(Gtk.Box): self.back_button = Gtk.Button( label="Back", hexpand=True, halign=Gtk.Align.CENTER ) - self.back_button.connect("clicked", self._on_back_clicked) self.gutter = Gtk.Box( orientation=Gtk.Orientation.HORIZONTAL, valign=Gtk.Align.END ) - self.gutter.add(self.back_button) + if back_button: + self.gutter.add(self.back_button) + self.back_button.connect("clicked", self._on_back_clicked) self.scrollable.add(content_box) self.add(self.scrollable) From ff0c5caf30c4eea06505458e14684c9d914d0480 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:51:29 +0900 Subject: [PATCH 09/30] feat: add quit dialog --- helpers/ui.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 82a307e..9837192 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -101,6 +101,7 @@ class Popup(Enum): RETURN = 5 MODLIST = 6 DETAILS = 7 + QUIT = 8 class NotebookPage(Enum): @@ -860,8 +861,7 @@ def process_shell_return_code( process_tree_option(RowType.HANDSHAKE) case 255: # dzgui version update msg = "Update complete. Please close DZGUI and restart." - spawn_dialog(msg, Popup.NOTIFY) - save_res_and_quit() + spawn_dialog(msg, Popup.QUIT) def call_on_thread( @@ -2697,11 +2697,7 @@ class GenericDialog(Gtk.MessageDialog): dialog_type = Gtk.MessageType.INFO button_type = Gtk.ButtonsType.NONE header_text = "Please wait" - case Popup.NOTIFY: - dialog_type = Gtk.MessageType.INFO - button_type = Gtk.ButtonsType.OK - header_text = "Notice" - case Popup.RETURN: + case Popup.NOTIFY | Popup.RETURN | Popup.QUIT: dialog_type = Gtk.MessageType.INFO button_type = Gtk.ButtonsType.OK header_text = "Notice" @@ -2748,6 +2744,13 @@ class GenericDialog(Gtk.MessageDialog): ok.connect("clicked", self._return_to_main_menu) self.connect("delete-event", self._return_to_main_menu) + if mode == Popup.QUIT: + button_label = "Exit" + ok = self.action_area.get_children()[0] + ok.set_label(button_label) + ok.connect("clicked", save_res_and_quit) + self.connect("delete-event", save_res_and_quit) + self.set_default_response(Gtk.ResponseType.OK) self.set_size_request(500, 0) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) From 12d971a5cf4b86392f8dde4c2932d37fe25598a4 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:54:32 +0900 Subject: [PATCH 10/30] fix: no statusbar in special pages --- helpers/ui.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 9837192..187f0b4 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -665,6 +665,10 @@ def pluralize(plural: str, count: int) -> str: def format_metadata(row_sel: str) -> str: + """ + Currently only being used for legacy + favorite server tooltip, cf Statusbar.update_app_meta() + """ row = None for i in RowType: if i.dict["label"] == row_sel: @@ -956,7 +960,6 @@ def process_toggle(command: RowType) -> None: case RowType.TGL_INSTALL: if query_config("auto_install")[0] == "1": proc = call_out("toggle", cmd_string) - App.grid.statusbar.refresh() return # manual -> auto mode proc = call_out("find_id", "") @@ -969,7 +972,6 @@ def process_toggle(command: RowType) -> None: LinkDialog(manual_sub_msg, link, command, user_id) case _: proc = call_out("toggle", cmd_string) - App.grid.statusbar.refresh() def process_user_input(enum: RowType) -> None: @@ -3537,7 +3539,15 @@ class Statusbar(Gtk.Statusbar): self.push(meta, string) def refresh(self) -> None: - self.update_app_meta() + unsupported_contexts = [ + RowType.KEYBINDINGS, + RowType.SHOW_LOG, + RowType.CHANGELOG, + RowType.OPTIONS, + ] + if App.treeview.subpage in unsupported_contexts: + self.set_text("") + return command = App.treeview.get_value_at_index(0) formatted = format_metadata(command) if len(formatted) > 0: @@ -3578,14 +3588,7 @@ class Statusbar(Gtk.Statusbar): config_vals.clear() for i in query_config(): config_vals.append(i) - _branch = config_vals[0] - _branch = _branch.upper() - _debug = config_vals[1] - if _debug == "": - _debug = "NORMAL" - else: - _debug = "DEBUG" - concat_label = f"{_branch} | {_debug} | {_VERSION}" + concat_label = f"{_VERSION}" self.status_right_label.set_text(concat_label) From 4795aeb3f94558e1a334c951715d42075c945663 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:55:40 +0900 Subject: [PATCH 11/30] chore: rename function --- helpers/ui.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 187f0b4..926494c 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -931,7 +931,7 @@ def process_tree_option(choice: RowType) -> None: return if command == RowType.CHANGELOG: - App.grid.notebook.set_page_enum(NotebookPage.CHANGELOG) + App.grid.notebook.set_page_by_enum(NotebookPage.CHANGELOG) return match command.dict["type"]: @@ -1032,7 +1032,7 @@ class OuterWindow(Gtk.Window): load_css() App.ready = True - App.grid.notebook.set_page_enum(NotebookPage.MAIN) + App.grid.notebook.set_page_by_enum(NotebookPage.MAIN) App.treeview.grab_focus() def _on_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None: @@ -2494,7 +2494,7 @@ class TreeView(Gtk.TreeView): row = (label,) row_store.append(row) App.grid.statusbar.refresh() - App.grid.notebook.set_page_enum(NotebookPage.MAIN) + App.grid.notebook.set_page_by_enum(NotebookPage.MAIN) self.grab_focus() @signal_emission @@ -3487,7 +3487,7 @@ class Notebook(Gtk.Notebook): self.set_current_page(self.prior_page) else: self.prior_page = self.get_current_page() - self.set_page_enum(NotebookPage.KEYS) + self.set_page_by_enum(NotebookPage.KEYS) def focus_current(self) -> None: widget = self.get_page() @@ -3502,7 +3502,7 @@ class Notebook(Gtk.Notebook): return None return widget - def set_page_enum(self, enum: NotebookPage) -> None: + def set_page_by_enum(self, enum: NotebookPage) -> None: self.prior_page = self.get_current_page() self.set_current_page(enum.value) self.focus_current() From 9d94b4ff0977a8d2a10349239d49a7339297a9af Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:57:43 +0900 Subject: [PATCH 12/30] chore: clear linting errors --- helpers/ui.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 926494c..96ddd42 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1071,9 +1071,7 @@ class OuterWindow(Gtk.Window): self.set_default_size(w, h) def _on_delete_event( - self, - window: "OuterWindow", - event: Gdk.EventKey + self, window: "OuterWindow", event: Gdk.EventKey ) -> None: self.halt_proc_and_quit() @@ -2951,7 +2949,7 @@ class DetailsDialog(GenericDialog): enable_search=False, search_column=-1, headers_visible=False, - fixed_height_mode=True + fixed_height_mode=True, ) self.view.connect("row-activated", self._on_row_activated) @@ -3040,19 +3038,15 @@ class ModDialog(GenericDialog): self.scrollable = Gtk.ScrolledWindow() self.view = Gtk.TreeView( - enable_search=False, - search_column=-1, - fixed_height_mode=True - ) + enable_search=False, search_column=-1, fixed_height_mode=True + ) self.scrollable.add(self.view) set_surrounding_margins(self.scrollable, 20) self.view.connect("row-activated", self._on_row_activated) for i, column_title in enumerate(["Mod", "ID", "Installed"]): - renderer = Gtk.CellRendererText( - ellipsize=Pango.EllipsizeMode.END - ) + renderer = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn(column_title, renderer, text=i) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.view.append_column(column) From 8c7ae8aceeab7aab131eb2020e08bb48471d806e Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:58:33 +0900 Subject: [PATCH 13/30] fix: wrap description text --- helpers/ui.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index 96ddd42..cf03aa0 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -2969,6 +2969,7 @@ class DetailsDialog(GenericDialog): scrollable_tree = Gtk.ScrolledWindow() scrollable_tree.add(self.view) + scrollable_tree.set_size_request(700, 200) scrollable_message = Gtk.ScrolledWindow() desc = Gtk.Label(label="Server message", valign=Gtk.Align.START) @@ -2976,7 +2977,9 @@ class DetailsDialog(GenericDialog): box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, halign=Gtk.Align.CENTER ) - self.description = Gtk.Label(justify=Gtk.Justification.CENTER) + self.description = Gtk.Label( + justify=Gtk.Justification.CENTER, wrap=True + ) sep = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL) sep.set_margin_bottom(10) for el in desc, sep, self.description: From 8f3238e4de8a11f3e655aee2a0eb9a600bfb2170 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:59:10 +0900 Subject: [PATCH 14/30] feat: prompt on locked servers --- helpers/ui.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/helpers/ui.py b/helpers/ui.py index cf03aa0..47de1c6 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -2677,6 +2677,17 @@ class TreeView(Gtk.TreeView): case WindowContext.TABLE_MODS | WindowContext.TABLE_LOG: self.update_quad_column(cr) case WindowContext.TABLE_SERVER | WindowContext.TABLE_API: + record = self.get_record_dict() + if record is None: + return + if Servers.is_passworded(record["ip"], int(record["qport"])): + msg = ( + "This server is password-protected and you will be " + "prompted when connecting. Do you want to proceed?" + ) + res = spawn_dialog(msg, Popup.CONFIRM) + if res is True: + return self._attempt_connection() case _: # any other non-server option from the main menu process_tree_option(output) From 9c6847ba39dbcebcfb9e86e345d07616e0a70527 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:00:33 +0900 Subject: [PATCH 15/30] feat: toast notification --- helpers/ui.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index 47de1c6..7b2d903 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -551,6 +551,9 @@ def load_css() -> None: .frame { border: 0px; } + .toast-label { + padding: 10px; + } .frame > border { border-radius: 5px; padding: 5px; @@ -1016,8 +1019,14 @@ class OuterWindow(Gtk.Window): self._set_resolution() self.grid = Grid() - self.add(self.grid) + self.toast = Toast() + self.overlay = Gtk.Overlay() + self.overlay.add_overlay(self.grid) + self.overlay.add_overlay(self.toast) + self.add(self.overlay) + self.show_all() + self.toast.set_visible(False) self.grid.right_panel.filters_vbox.set_visible(False) self.grid.right_panel.enable_ping_button(False) @@ -1080,6 +1089,47 @@ class OuterWindow(Gtk.Window): save_res_and_quit() +class Toast(Gtk.EventBox): + def __init__(self): + super().__init__() + + self.label = Gtk.Label() + self.box = Gtk.Box( + orientation=Gtk.Orientation.HORIZONTAL, + halign=Gtk.Align.CENTER, + valign=Gtk.Align.CENTER, + ) + self.box.add(self.label) + self.add(self.box) + self.box.set_size_request(200, 100) + + add_class(self.box, "toast-label") + + def set_text(self, text: str) -> None: + self.label.set_text(text) + + def set_text_and_fade(self, text: str) -> None: + self.set_text(text) + self.pop() + self._defer_fade() + + def fade_out(self) -> bool: + if self.get_opacity() == 0: + self.set_visible(False) + self.set_opacity(1) + return False + self.set_opacity(self.get_opacity() - 0.03) + return True + + def pop(self) -> None: + self.set_visible(True) + + def _defer_fade(self) -> Literal[False]: + """Defers fade out of toast""" + GLib.timeout_add(30, self.fade_out) + return False + + class ScrollableTree(Gtk.ScrolledWindow): def __init__(self): super().__init__() From 5b9309a6bde1e92b98b39a2d596beb2b848934df Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:01:05 +0900 Subject: [PATCH 16/30] fix: discard key input in entry field --- helpers/ui.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helpers/ui.py b/helpers/ui.py index 7b2d903..eabd05f 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1201,6 +1201,8 @@ class RightPanel(Gtk.Box): self.filters_vbox.set_unique_maps(rows) def toggle_debug(self) -> None: + if type(App.window.get_focus()) is Gtk.Entry: + return state = self.debug_toggle.get_active() self.debug_toggle.set_active(not state) From 6f5f9ecb7bccf74703afe8fda7d99b3acb16c04b Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:01:37 +0900 Subject: [PATCH 17/30] fix: resolution not updating when returning from fullscreen --- helpers/ui.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index eabd05f..c73866f 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1059,8 +1059,7 @@ class OuterWindow(Gtk.Window): return elif query_config("fullscreen")[0] == "true": logger.info("User preference for 'fullscreen' is 'true'") - self.maximize() - return + self.fullscreen() try: with open(res_path, "r") as infile: From 5dd0cd416b417799d6b00b055f3f3ab75c46f966 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:02:02 +0900 Subject: [PATCH 18/30] chore: reword comment --- helpers/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index c73866f..bfc5857 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -2719,7 +2719,7 @@ class TreeView(Gtk.TreeView): return App.grid.right_panel.filters_vbox.reinit_filters() else: - # local server lists need not be restricted + # local server lists need not be filter-restricted App.right_panel.filters_vbox.enable_all_filters() self._update_multi_column(cr) return From 5dfa51dc1554fdd1044e0c9c1549791aea0c73e0 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:04:17 +0900 Subject: [PATCH 19/30] feat: options page --- helpers/ui.py | 504 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 491 insertions(+), 13 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index bfc5857..ef1b6f8 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -88,6 +88,15 @@ If this issue persists, your API key may be defunct. """ +class Preferences(Enum): + STEAM = 1 + BM = 2 + WINDOW = 3 + CLIENT = 4 + NAME = 5 + INSTALL = 6 + + class Port(Enum): DEFAULT = 1 CUSTOM = 2 @@ -105,10 +114,11 @@ class Popup(Enum): class NotebookPage(Enum): + # enums correspond to the page in linear order MAIN = 0 CHANGELOG = 1 KEYS = 2 - SETTINGS = 3 + OPTIONS = 3 class Command(Enum): @@ -206,6 +216,7 @@ class RowType(EnumWithAttrs): "label": "View changelog", "tooltip": "Opens the DZGUI changelog in a dialog window", } + OPTIONS = {"label": "Options", "tooltip": None} KEYBINDINGS = {"label": "Keybindings", "tooltip": None} SHOW_LOG = { "label": "Show debug log", @@ -435,13 +446,17 @@ class WindowContext(EnumWithAttrs): } MANAGE = { "label": "Manage", - "rows": [RowType.ADD_BY_IP, RowType.ADD_BY_ID, RowType.CHNG_FAV], + "rows": [ + RowType.ADD_BY_IP, + RowType.ADD_BY_ID, + RowType.CHNG_FAV, + RowType.LIST_MODS, + ], "called_by": [], } OPTIONS = { - "label": "Options", + "label": "OPTIONS", "rows": [ - RowType.LIST_MODS, RowType.TGL_BRANCH, RowType.TGL_INSTALL, RowType.TGL_STEAM, @@ -450,7 +465,6 @@ class WindowContext(EnumWithAttrs): RowType.CHNG_STEAM_API, RowType.CHNG_BM_API, RowType.FORCE_UPDATE, - RowType.DUMP_LOG, ], "called_by": [], } @@ -459,6 +473,7 @@ class WindowContext(EnumWithAttrs): "rows": [ RowType.CHANGELOG, RowType.SHOW_LOG, + RowType.DUMP_LOG, RowType.DOCS, RowType.DOCS_FALLBACK, RowType.BUGS, @@ -563,6 +578,10 @@ def load_css() -> None: font-weight: 800; margin-bottom: 0.5rem; } + .settings-subheading { + font-size: 1.2rem; + font-weight: 700; + } .left-label { font-size: 1.3rem; } @@ -843,6 +862,20 @@ def process_shell_return_code( process_tree_option(RowType.CHNG_STEAM_API) case 6: # return silently pass + case 78: # failed settings update + spawn_dialog("Invalid Steam API key, reverting", Popup.NOTIFY) + App.notebook.settings.revert(Preferences.STEAM) + case 79: # failed settings update + spawn_dialog( + "Invalid Battlemetrics API key, reverting", Popup.NOTIFY + ) + App.notebook.settings.revert(Preferences.BM) + case 80: # pop toast after successful settings change + config_vals.clear() + for i in query_config(): + config_vals.append(i) + App.window.toast.set_text_and_fade("Settings updated!") + App.notebook.settings.populate_settings() case 90: # used to update configs and metadata in-place config_vals.clear() for i in query_config(): @@ -991,9 +1024,6 @@ def process_user_input(enum: RowType) -> None: logger.info(f"User entered: '{response}'") show_wait_dialog = True - # this is the only instantaneous toggle, no wait dialog necessary - if enum == RowType.CHNG_PLAYER: - show_wait_dialog = False wait_msg = "Working" call_on_thread( show_wait_dialog, cmd_string, wait_msg, response, choice=enum @@ -1285,6 +1315,11 @@ class ButtonBox(Gtk.Box): save_res_and_quit() return + if context == ButtonType.OPTIONS: + App.notebook.settings.populate_settings() + App.notebook.set_page_by_enum(NotebookPage.OPTIONS) + return + cols = App.treeview.get_columns() if len(cols) > 1: # restores tree from multi column view to main menu @@ -3311,10 +3346,436 @@ class ScrollableNote(Gtk.Box): @update_window_labels def _on_back_clicked(self, button: Gtk.Button) -> None: - if App.notebook.get_page() == NotebookPage.KEYS.value: - App.notebook.toggle_keybindings() + App.notebook.return_prior() + + +class InfoEventBox(Gtk.EventBox): + def __init__(self, text: str): + super().__init__(margin_start=10) + + self.text = text + + self.icon = Gtk.Image.new_from_icon_name( + "help-about-symbolic", Gtk.IconSize.LARGE_TOOLBAR + ) + self.icon.set_opacity(0.8) + box = Gtk.Box() + box.add(self.icon) + + self.connect("enter-notify-event", self._on_enter_tooltip) + self.connect("leave-notify-event", self._on_leave_tooltip) + self.add(box) + + def _on_enter_tooltip( + self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing + ) -> None: + self.icon.set_opacity(1) + App.grid.statusbar.set_text(self.text) + + def _on_leave_tooltip( + self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing + ) -> None: + self.icon.set_opacity(0.8) + App.grid.statusbar.set_text("") + + +class LeftLabel(Gtk.Label): + def __init__(self, text: str, tooltip: str = ""): + super().__init__( + label=text, + halign=Gtk.Align.START, + ) + self.set_tooltip_text(tooltip) + pass + + +class Options(Gtk.Box): + def __init__(self): + super().__init__( + orientation=Gtk.Orientation.VERTICAL, + margin_start=10, + margin_end=10, + ) + + self.DEFAULT_WIDTH = 1 + self.DEFAULT_HEIGHT = 1 + + label = Gtk.Label(label="Options") + label.set_halign(Gtk.Align.CENTER) + add_class(label, "page-heading") + self.add(label) + + self.steam_entry = None + self.bm_entry = None + + self.steam_box = self._make_submit_field( + "Enter your Steam API key", Preferences.STEAM, True + ) + self.bm_box = self._make_submit_field( + "Enter your Battlemetrics API key", Preferences.BM, True + ) + api_rows = [ + [LeftLabel("Steam API key"), self.steam_box], + [LeftLabel("Battlemetrics API key"), self.bm_box], + ] + + self.player_box = self._make_submit_field( + "Identifies you to other players in-game", Preferences.NAME + ) + self.fullscreen_toggle = self.make_binary_radio( + "Last used dimensions", + "Always fullscreen", + Preferences.WINDOW, + ) + self.steam_toggle = self.make_binary_radio( + "Steam", "Flatpak (experimental)", Preferences.CLIENT + ) + + pref_rows = [ + [LeftLabel("Steam client"), self.steam_toggle], + [LeftLabel("Window size at boot"), self.fullscreen_toggle], + [LeftLabel("Player name"), self.player_box], + ] + + self.mod_install_toggle = self.make_binary_radio( + "Manual", "Auto", Preferences.INSTALL + ) + self.force_button = Gtk.Button(label="Update") + self.force_button.connect("clicked", self._on_force_update_clicked) + # sensitivity state is set after config file is loaded + self.force_button.set_sensitive(False) + + msg = ( + "Manual: prompt to subscribe to mods in Steam. " + "Auto: unmanned downloads." + ) + eb = InfoEventBox(msg) + + msg = "Synchronize all local mods. Automatic mode must be enabled." + eb2 = InfoEventBox(msg) + + mod_rows = [ + [LeftLabel("Mod install mode"), self.mod_install_toggle, eb], + [LeftLabel("Force update local mods"), self.force_button, eb2], + ] + + self.branch_combo = Gtk.ComboBoxText() + self.branch_combo.append_text("Stable") + self.branch_combo.append_text("Testing") + self.branch_combo.set_active(0) + self.branch_combo.connect("changed", self._on_branch_changed) + + msg = ( + "Stable: only contains stable features. " + "Testing: pre-release beta, contains new features." + ) + eb = InfoEventBox(msg) + + version_rows = [[LeftLabel("Branch"), self.branch_combo, eb]] + + api_grid = self._make_grid(api_rows) + prefs_grid = self._make_grid(pref_rows) + mods_grid = self._make_grid(mod_rows) + version_grid = self._make_grid(version_rows) + + col = 1 + row = 1 + grid = Gtk.Grid( + orientation=Gtk.Orientation.VERTICAL, + row_spacing=30, + hexpand=True, + ) + + for frame in [ + self.make_frame(api_grid, "API Keys"), + self.make_frame(prefs_grid, "Preferences"), + self.make_frame(mods_grid, "Mods"), + self.make_frame(version_grid, "Version"), + ]: + grid.attach( + frame, col, row, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT + ) + row += 1 + + self.scrollable = Gtk.ScrolledWindow(vexpand=True) + self.scrollable.add(grid) + self.add(self.scrollable) + + def _make_submit_field( + self, + placeholder: str, + context: Preferences, + private: bool = False, + ) -> Gtk.Box: + + entry = Gtk.Entry(placeholder_text=placeholder, hexpand=True) + button = Gtk.Button(label="Save") + + entry.sibling = button + entry.get_property("buffer").sibling = button + + button.connect("clicked", self._on_save_clicked, entry, context) + entry.connect("insert-text", self._on_text_typed, context) + entry.connect("activate", self._on_field_activated, context) + entry.get_property("buffer").connect( + "deleted-text", self._on_text_deleted, context + ) + + if private: + entry.set_icon_from_icon_name( + Gtk.EntryIconPosition.SECONDARY, "view-reveal-symbolic" + ) + entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) + entry.connect("icon-release", self._on_icon_release) + entry.set_visibility(False) + + if context == Preferences.STEAM: + self.steam_entry = entry + else: + self.bm_entry = entry + + box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) + box.add(entry) + box.add(button) + + return box + + def _on_field_activated( + self, entry: Gtk.Entry, context: Preferences + ) -> None: + text = entry.get_text() + if not self._is_valid_text(text, context): return - App.notebook.set_page_enum(NotebookPage.MAIN) + self._on_save_clicked(None, entry, context) + + def _make_grid(self, rows: list) -> Gtk.Grid: + grid = Gtk.Grid( + orientation=Gtk.Orientation.VERTICAL, + column_spacing=10, + row_spacing=5, + margin_start=5, + margin_end=5, + margin_top=10, + margin_bottom=10, + ) + row = 1 + for record in rows: + col = 1 + for el in record: + grid.attach( + el, col, row, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT + ) + col += 1 + row += 1 + return grid + + def _on_save_clicked( + self, button: Gtk.Button | None, entry: Gtk.Entry, context: Preferences + ) -> None: + show_wait_dialog = True + wait_msg = "Working" + button.set_sensitive(False) + match context: + case Preferences.NAME: + toggle = RowType.CHNG_PLAYER + show_wait_dialog = False + text = entry.get_text().strip() + case Preferences.STEAM: + toggle = RowType.CHNG_STEAM_API + text = "".join(entry.get_text().split()) + case Preferences.BM: + toggle = RowType.CHNG_BM_API + text = "".join(entry.get_text().split()) + cmd_string = toggle.dict["label"] + call_on_thread(show_wait_dialog, cmd_string, wait_msg, text) + + def revert(self, mode: Preferences) -> None: + if mode == Preferences.STEAM: + self.steam_entry.set_text(self.old_steam) + else: + self.bm_entry.set_text(self.old_bm) + pass + + def _on_force_update_clicked(self, button: Gtk.Button) -> None: + wait_msg = "Updating mods" + cmd = "Force update local mods" + show_wait_dialog = True + call_on_thread(show_wait_dialog, cmd, wait_msg, "") + + def _on_branch_changed(self, combo: Gtk.ComboBoxText) -> None: + # prevent triggering on initial init + if App.treeview.subpage is None: + return + # TODO: process_toggle(RowType.TGL_BRANCH) + + def _on_radio_toggled( + self, button: Gtk.RadioButton, context: Preferences + ) -> None: + if App.treeview.subpage is None: + return + match context: + case Preferences.CLIENT: + toggle = RowType.TGL_STEAM + case Preferences.INSTALL: + toggle = RowType.TGL_INSTALL + state = button.get_group()[0].get_active() + self.force_button.set_sensitive(state) + case Preferences.WINDOW: + toggle = RowType.TGL_FULLSCREEN + process_toggle(toggle) + + def _is_valid_text(self, text: str, context: Preferences) -> bool: + if text.isspace(): + return False + if len(text) == 0: + return False + + match context: + case Preferences.NAME: + old = self.old_name + case Preferences.STEAM: + old = self.old_steam + case Preferences.BM: + old = self.old_bm + if text == old: + return False + return True + + def _on_text_deleted( + self, + buffer: Gtk.EntryBuffer, + position: int, + chars: int, + context: Preferences, + ) -> None: + + text = buffer.get_text() + state = self._is_valid_text(text, context) + buffer.sibling.set_sensitive(state) + + def _on_text_typed( + self, + entry: Gtk.Entry, + text: str, + length: int, + pos: int, + context: Preferences, + ) -> None: + + buffer = entry.get_property("buffer") + text = buffer.get_text() + text + state = self._is_valid_text(text, context) + entry.sibling.set_sensitive(state) + + def make_binary_radio( + self, + first_option: str, + second_option: str, + context: Preferences, + ) -> Gtk.Box: + + hbox = Gtk.Box(spacing=5, halign=Gtk.Align.START) + radio1 = Gtk.RadioButton.new_with_label(None, first_option) + radio2 = Gtk.RadioButton.new_from_widget(radio1) + radio2.set_label(second_option) + radio1.connect("toggled", self._on_radio_toggled, context) + hbox.pack_start(radio1, False, False, 0) + hbox.pack_start(radio2, False, False, 0) + + return hbox + + def make_frame(self, widget: Gtk.Widget, text: str) -> Gtk.Box: + label = Gtk.Label(label=text) + label.set_halign(Gtk.Align.START) + add_class(label, "settings-subheading") + + frame = Gtk.Frame(hexpand=True) + frame.add(widget) + + box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + box.add(label) + box.add(frame) + + return box + + def populate_settings(self) -> None: + if not os.path.isfile(config_file): + msg = ( + "DZGUI configuration file not found. " + "Please exit and restart to regenerate it." + ) + spawn_dialog(msg, Popup.QUIT) + config_vals.clear() + for i in query_config(): + config_vals.append(i) + + branch = config_vals[0] + install = config_vals[2] + name = config_vals[3] + client = config_vals[5] + fullscreen = config_vals[6] + + try: + steam = query_config("steam_api")[0] + bm = query_config("api_key")[0] + except IndexError: + return + + self.old_steam = steam + self.old_bm = bm + self.old_name = name + + self.steam_entry.set_text(steam) + self.bm_entry.set_text(bm) + self.player_box.get_children()[0].set_text(name) + + if install == "1": + radio = 1 + self.force_button.set_sensitive(True) + else: + radio = 0 + self.mod_install_toggle.get_children()[radio].set_active(True) + + if client == "flatpak": + radio = 1 + else: + radio = 0 + self.steam_toggle.get_children()[radio].set_active(True) + + if fullscreen == "true": + radio = 1 + else: + radio = 0 + self.fullscreen_toggle.get_children()[radio].set_active(True) + + for field in ( + [name, self.player_box], + [steam, self.steam_box], + [bm, self.bm_box], + ): + if field[0] == "": + field[1].get_children()[1].set_sensitive(False) + + if branch == "testing": + self.branch_combo.set_active(1) + else: + self.branch_combo.set_active(0) + + def _on_icon_release( + self, + widget: Gtk.Entry, + icon_pos: Gtk.EntryIconPosition, + event: Gdk.Event, + ) -> None: + visible = widget.get_visibility() + if visible: + icon = "view-reveal-symbolic" + state = False + else: + icon = "view-conceal-symbolic" + state = True + widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon) + widget.set_visibility(state) class KeybindingsDialog(Gtk.Box): @@ -3490,13 +3951,17 @@ class Notebook(Gtk.Notebook): self.clog.show_all() self.append_page(self.clog) self.prior_page: int - self.prior_subpage = None self.keys = ScrollableNote(KeybindingsDialog()) self.keys.type = RowType.KEYBINDINGS self.keys.show_all() self.append_page(self.keys) + self.settings = Options() + self.settings.type = RowType.OPTIONS + self.settings.show_all() + self.append_page(self.settings) + self.connect("switch-page", self._on_page_changed) self.connect("key-press-event", self._on_keypress) @@ -3541,9 +4006,22 @@ class Notebook(Gtk.Notebook): case Gdk.KEY_G: self._set_adjustment(VAdjustment.BOTTOM) + def return_prior(self) -> None: + page = self.get_nth_page(self.prior_page) + if hasattr(page, "steam_entry"): + # Gtk.Notebook focuses the first input field when changing pages + entries = page.steam_entry, page.bm_entry + for entry in entries: + entry.set_position(-1) + entry.set_can_focus(False) + self.set_current_page(self.prior_page) + for entry in entries: + entry.set_can_focus(True) + self.set_current_page(self.prior_page) + def toggle_keybindings(self) -> None: if self.get_current_page() == NotebookPage.KEYS.value: - self.set_current_page(self.prior_page) + self.return_prior() else: self.prior_page = self.get_current_page() self.set_page_by_enum(NotebookPage.KEYS) From 2bb575cd9774cf9d8f8c17332c647a10a784b748 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:04:32 +0900 Subject: [PATCH 20/30] chore: update return codes --- helpers/funcs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helpers/funcs b/helpers/funcs index f9d0686..689cec8 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -1128,14 +1128,14 @@ update_config_val(){ key="steam_api" if [[ ${#value} -lt 32 ]] || [[ $(test_steam_api "$value") -eq 1 ]]; then printf "Invalid API key" - return 2 + return 78 fi ;; "Change Battlemetrics API key") key="api_key" if [[ $(test_bm_api "$value") -eq 1 ]]; then printf "Invalid API key" - return 2 + return 79 fi ;; esac @@ -1143,7 +1143,7 @@ update_config_val(){ nr="$value" update_config echo "Updated the key '$key' to '$value'" - return 90 + return 80 } show_log(){ < "$debug_log" sed 's/Keyword␞/Keyword/' From 3ace15d78af61860d6d2ba8636edd2141dc4dd0d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:04:49 +0900 Subject: [PATCH 21/30] chore: bump version --- dzgui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui.sh b/dzgui.sh index a726ba5..f7421b2 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -o pipefail -version=6.0.0.beta-1 +version=6.0.0.beta-3 #CONSTANTS aid=221100 From 9508bfd416854c113f3097ee67fc43207469384f Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:09:53 +0900 Subject: [PATCH 22/30] chore: update changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a698357..30817c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [6.0.0-beta.3] 2025-08-08 +## Added +- Additional server metadata to details dialog +- Prompt user when connecting if a server is locked +- Dedicated settings page ("Options") + +## Fixed +- Statusbar contents not updating on certain pages +- Breadcrumbs not updating when returning from keybindings page +- Wrap long descriptions in server details +- Prevent debug button from activating when in certain input fields +- Window size not updating correctly when unmaximizing window after changing "fullscreen at boot" setting + ## [6.0.0-beta.2] 2025-07-29 ## Fixed - Missing parameters when closing application via window decorations From 94cabc9d7095c5448f6ee5d4ba1e1f6c4bff05a7 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:11:26 +0900 Subject: [PATCH 23/30] chore: update checksums --- dzgui.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dzgui.sh b/dzgui.sh index f7421b2..5d33af8 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -585,11 +585,11 @@ fetch_helpers_by_sum(){ [[ -f "$config_file" ]] && source "$config_file" declare -A sums sums=( - ["ui.py"]="52183c5d29d10ebd0bf91693e41f197b" + ["funcs"]="b3a45a42bc748dbcbebcd1a7748609cd" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" + ["servers.py"]="4c5013aaf694806cfecd4f1c905bdc9a" + ["ui.py"]="3dfddc8260449d59f4ca71bc4b8d2989" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" - ["funcs"]="19440a79345b66154a49882b25cfa7c5" - ["servers.py"]="51839211af7f65bdc04bab5557bf9466" ) local author="aclist" local repo="dztui" From 5d8741edfae99fcfa4f054fb54cd1b3daa36d72d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:15:28 +0900 Subject: [PATCH 24/30] chore: drop unnecessary comment --- helpers/ui.py | 1 - 1 file changed, 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index ef1b6f8..c559fd5 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1154,7 +1154,6 @@ class Toast(Gtk.EventBox): self.set_visible(True) def _defer_fade(self) -> Literal[False]: - """Defers fade out of toast""" GLib.timeout_add(30, self.fade_out) return False From 4f3f17450c81e5fd2e188188158e85ffb397ca28 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:22:51 +0900 Subject: [PATCH 25/30] chore: comments and clerical changes --- helpers/ui.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index c559fd5..a6e7a7d 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -455,7 +455,7 @@ class WindowContext(EnumWithAttrs): "called_by": [], } OPTIONS = { - "label": "OPTIONS", + "label": "Options", "rows": [ RowType.TGL_BRANCH, RowType.TGL_INSTALL, @@ -862,10 +862,10 @@ def process_shell_return_code( process_tree_option(RowType.CHNG_STEAM_API) case 6: # return silently pass - case 78: # failed settings update + case 78: # failed settings update (steam) spawn_dialog("Invalid Steam API key, reverting", Popup.NOTIFY) App.notebook.settings.revert(Preferences.STEAM) - case 79: # failed settings update + case 79: # failed settings update (bm) spawn_dialog( "Invalid Battlemetrics API key, reverting", Popup.NOTIFY ) @@ -4008,7 +4008,12 @@ class Notebook(Gtk.Notebook): def return_prior(self) -> None: page = self.get_nth_page(self.prior_page) if hasattr(page, "steam_entry"): - # Gtk.Notebook focuses the first input field when changing pages + """ + Gtk.Notebook focuses the first input field when changing pages; + this workaround unhighlights the selected region and makes entry fields + unfocusable prior to the page 'switch-page' signal, + then makes them focusable again + """ entries = page.steam_entry, page.bm_entry for entry in entries: entry.set_position(-1) From cff4a2e1e77daf29c5c4caa8b618751a246da124 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 Aug 2025 11:32:43 +0900 Subject: [PATCH 26/30] chore: update checksums --- dzgui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui.sh b/dzgui.sh index 5d33af8..11db2f9 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -588,7 +588,7 @@ fetch_helpers_by_sum(){ ["funcs"]="b3a45a42bc748dbcbebcd1a7748609cd" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["servers.py"]="4c5013aaf694806cfecd4f1c905bdc9a" - ["ui.py"]="3dfddc8260449d59f4ca71bc4b8d2989" + ["ui.py"]="4bddab2e4672cb2fadb80575576ce5b2" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" ) local author="aclist" From 3d91e07d25e38322c8de14f848424c70f335ca77 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 Aug 2025 15:47:22 +0900 Subject: [PATCH 27/30] chore: uncomment todo --- dzgui.sh | 2 +- helpers/ui.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dzgui.sh b/dzgui.sh index 11db2f9..9773334 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -588,7 +588,7 @@ fetch_helpers_by_sum(){ ["funcs"]="b3a45a42bc748dbcbebcd1a7748609cd" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["servers.py"]="4c5013aaf694806cfecd4f1c905bdc9a" - ["ui.py"]="4bddab2e4672cb2fadb80575576ce5b2" + ["ui.py"]="5335d86ef1dae543894cd8bdff67b018" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" ) local author="aclist" diff --git a/helpers/ui.py b/helpers/ui.py index a6e7a7d..19a9770 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3605,7 +3605,7 @@ class Options(Gtk.Box): # prevent triggering on initial init if App.treeview.subpage is None: return - # TODO: process_toggle(RowType.TGL_BRANCH) + process_toggle(RowType.TGL_BRANCH) def _on_radio_toggled( self, button: Gtk.RadioButton, context: Preferences From f4f3e61b83c3cedefae061fecdcd983b450b779c Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 Aug 2025 16:01:00 +0900 Subject: [PATCH 28/30] fix: pass correct button to submit method --- dzgui.sh | 6 +++--- helpers/ui.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dzgui.sh b/dzgui.sh index 9773334..a4e05d8 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -588,7 +588,7 @@ fetch_helpers_by_sum(){ ["funcs"]="b3a45a42bc748dbcbebcd1a7748609cd" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["servers.py"]="4c5013aaf694806cfecd4f1c905bdc9a" - ["ui.py"]="5335d86ef1dae543894cd8bdff67b018" + ["ui.py"]="294a7daf544a96e2a108d252df5e0676" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" ) local author="aclist" @@ -1029,13 +1029,13 @@ initial_setup(){ watcher_deps check_architecture test_connection - fetch_helpers > >(pdialog "Checking helper files") +# fetch_helpers > >(pdialog "Checking helper files") varcheck source "$config_file" lock legacy_vars legacy_cols - check_version +# check_version check_map_count steam_deps migrate_files diff --git a/helpers/ui.py b/helpers/ui.py index 19a9770..42e326e 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -3543,9 +3543,10 @@ class Options(Gtk.Box): self, entry: Gtk.Entry, context: Preferences ) -> None: text = entry.get_text() + button = entry.sibling if not self._is_valid_text(text, context): return - self._on_save_clicked(None, entry, context) + self._on_save_clicked(button, entry, context) def _make_grid(self, rows: list) -> Gtk.Grid: grid = Gtk.Grid( @@ -3569,7 +3570,7 @@ class Options(Gtk.Box): return grid def _on_save_clicked( - self, button: Gtk.Button | None, entry: Gtk.Entry, context: Preferences + self, button: Gtk.Button, entry: Gtk.Entry, context: Preferences ) -> None: show_wait_dialog = True wait_msg = "Working" From da5a5999f0913c6ddef2ba28cc571d1162635850 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 Aug 2025 16:01:30 +0900 Subject: [PATCH 29/30] chore: uncomment --- dzgui.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dzgui.sh b/dzgui.sh index a4e05d8..5f33f40 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -1029,13 +1029,13 @@ initial_setup(){ watcher_deps check_architecture test_connection -# fetch_helpers > >(pdialog "Checking helper files") + fetch_helpers > >(pdialog "Checking helper files") varcheck source "$config_file" lock legacy_vars legacy_cols -# check_version + check_version check_map_count steam_deps migrate_files From a5be4d9d316d03ad7dc395c41420e68a2c6d68e1 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 Aug 2025 16:06:07 +0900 Subject: [PATCH 30/30] chore: bump version --- dzgui.sh | 2 +- helpers/funcs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dzgui.sh b/dzgui.sh index 5f33f40..3c4de36 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -585,7 +585,7 @@ fetch_helpers_by_sum(){ [[ -f "$config_file" ]] && source "$config_file" declare -A sums sums=( - ["funcs"]="b3a45a42bc748dbcbebcd1a7748609cd" + ["funcs"]="c2aec0a2fc153a2535e6493b3751ca81" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["servers.py"]="4c5013aaf694806cfecd4f1c905bdc9a" ["ui.py"]="294a7daf544a96e2a108d252df5e0676" diff --git a/helpers/funcs b/helpers/funcs index 689cec8..b4a6d03 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -o pipefail -version="6.0.0-beta.2" +version="6.0.0-beta.3" #CONSTANTS aid=221100