From e2d6a462db4398ca251eebcb69de78fc53e41a7d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 20:17:32 +0900 Subject: [PATCH 1/7] fix: suppress headers if no model is loaded --- dzgui/views/trees/tree_mods.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dzgui/views/trees/tree_mods.py b/dzgui/views/trees/tree_mods.py index e8340d7..b39daf0 100644 --- a/dzgui/views/trees/tree_mods.py +++ b/dzgui/views/trees/tree_mods.py @@ -30,8 +30,6 @@ class ModTreeView(ModsMixin, ContextMixin, TreeView): # type: ignore emitter.connect("mods_highlighted", self._on_mods_highlighted) self.set_fixed_height_mode(True) - self.set_headers_visible(True) - self.set_model(None) for i, column_title in enumerate(strings.mod_cols): @@ -64,6 +62,7 @@ class ModTreeView(ModsMixin, ContextMixin, TreeView): # type: ignore def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None: if mods < 1: return + self.set_headers_visible(True) path = Gtk.TreePath.new_from_indices([0]) self.set_cursor(path) From 3af53775cdfd967a471bbc67cae61770e3af7607 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:20:32 +0900 Subject: [PATCH 2/7] fix: grab focus on tree --- dzgui/views/pages/preconnect.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dzgui/views/pages/preconnect.py b/dzgui/views/pages/preconnect.py index 90dbcf6..964f27b 100644 --- a/dzgui/views/pages/preconnect.py +++ b/dzgui/views/pages/preconnect.py @@ -327,10 +327,7 @@ class PreConnectionAssistant(Gtk.Box): self.connect_last.hide() self._process_warnings(prereqs) - if self.tree.is_visible(): - self.tree.grab_focus() - else: - self.grab_focus() + self.tree.grab_focus() def mark_finished(self) -> None: self.mod_count.set_label(preconnect.all_updated) From 8ee3b368166fe17a1a2f0a2b38e6b953a6026ce5 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:20:56 +0900 Subject: [PATCH 3/7] fix: restore mod statusbar when returning from other pages --- dzgui/views/components/statusbar.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/dzgui/views/components/statusbar.py b/dzgui/views/components/statusbar.py index a6c1519..54dae5d 100644 --- a/dzgui/views/components/statusbar.py +++ b/dzgui/views/components/statusbar.py @@ -1,5 +1,4 @@ from typing import Self, Union, TYPE_CHECKING -from warnings import deprecated from dzgui.const.enum import NotebookPage, ServerTab from dzgui.util.strings import esc_to_return, question_to_return @@ -26,6 +25,8 @@ class Statusbar(Gtk.Grid): self.controller.register_widget("statusbar", self) self.emitter = controller.get_emitter() + self.prior_enum: NotebookPage + self.prior_status: str self.playercount = "" self.statusbar = Gtk.Statusbar() @@ -71,6 +72,7 @@ class Statusbar(Gtk.Grid): NotebookPage.LOG, NotebookPage.CONNECTION, ): + self.prior_enum = enum self.set_by_context(enum, esc_to_return) return @@ -80,8 +82,9 @@ class Statusbar(Gtk.Grid): case NotebookPage.KEYS: bar = question_to_return case _: - return + bar = self.prior_status + self.prior_enum = enum self.set_by_context(enum, bar) def _on_server_row_changed(self, statusbar: Self) -> None: @@ -97,6 +100,10 @@ class Statusbar(Gtk.Grid): context: Union["ServerTab", NotebookPage], ) -> None: self.spinner.stop() + + if type(context) is NotebookPage: + self.prior_enum = context + self.prior_status = "" # FIXME: CalcDist is being called when table is not loaded if dist is None: return @@ -121,6 +128,8 @@ class Statusbar(Gtk.Grid): def set_by_context( self, context: Union[NotebookPage, "ServerTab"], string: str ) -> None: + if context != NotebookPage.KEYS: + self.prior_status = string meta = self.statusbar.get_context_id(str(context)) self.statusbar.push(meta, string) self.set_cache(string) From a96699399933617814db44f47e7d054d13d14e04 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:21:49 +0900 Subject: [PATCH 4/7] fix: invoke steam client directly (#348) --- dzgui/api/steam.py | 13 ++++--------- dzgui/managers/connection.py | 10 ++++++---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/dzgui/api/steam.py b/dzgui/api/steam.py index 0fa126d..f079bf8 100644 --- a/dzgui/api/steam.py +++ b/dzgui/api/steam.py @@ -73,14 +73,9 @@ def get_local_signatures(version_file: Path) -> dict[str, int]: return hashes -def enqueue_mod(mod: str, appid: int) -> None: - args = [ - "steam", - f"steam://url/CommunityFilePage/{mod}+workshop_download_item", - str(appid), - mod, - ] - subprocess.Popen(["/usr/bin/env", "bash", *args]) +def enqueue_mod(client: str, mod: str, appid: int) -> None: + client_args = concat_bash_args(client) + subprocess.Popen([*client_args, "+workshop_download_item", str(appid), mod]) def get_needs_update( @@ -146,7 +141,7 @@ def connect(client: str, addr: str, appid: int, name: str, mods: list[str]) -> i return proc.returncode -def load_to_menu(client: str, addr: str, appid: int, name: str, mods: list[str]) -> int: +def load_to_menu(client: str, appid: int, name: str, mods: list[str]) -> int: """Loads to the menu screen with the selected mods; used for AFK/pre-joining""" concat = concat_mods(mods) client_args = concat_bash_args(client) diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 7570dfd..e8784be 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -88,6 +88,7 @@ class ConnectionManager: self.record: Record self.workshop: Path + self.client: str self.remote_mod_ids: list[str] = [] self.missing_mods: list[tuple[str, str, int, int]] = [] @@ -171,6 +172,7 @@ class ConnectionManager: client = self.controller.query_config(Preferences.CLIENT) running = is_steam_running(client) steam_proc = SteamProcess(client_name, running) + self.client = client game_mode = prefs.is_game_mode @@ -263,11 +265,10 @@ class ConnectionManager: def _connect_steam(self, menu_only: bool) -> None: addr = f"{self.record.ip}:{self.record.gameport}" playername = self.controller.query_config(Preferences.NAME) - client = self.controller.query_config(Preferences.CLIENT) if menu_only: - rc = load_to_menu(client, addr, self.appid, playername, self.remote_mod_ids) + rc = load_to_menu(self.client, self.appid, playername, self.remote_mod_ids) else: - rc = connect(client, addr, self.appid, playername, self.remote_mod_ids) + rc = connect(self.client, addr, self.appid, playername, self.remote_mod_ids) if rc != 0: # TODO: log/pop the error func = StoredFunc(self.controller.update_status) @@ -298,7 +299,8 @@ class ConnectionManager: for title, mod, stamp, size in self.missing_mods: if self.controller.is_cancel_pending(): return - enqueue_mod(mod, self.appid) + enqueue_mod(self.client, mod, self.appid) + # NOTE: prevents rate limiting time.sleep(3) if raise_window is True: From 94fe3f9dff24b58e7bf2c3d5c922397c4fd69cab Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:49:41 +0900 Subject: [PATCH 5/7] fix: suppress search popup (#353) --- dzgui/views/trees/tree_base.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index ac0733a..8a32e2f 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -4,7 +4,7 @@ from typing import Any, Optional, TYPE_CHECKING from warnings import deprecated from dzgui.const.constants import APP_NAME, SEPARATOR -from dzgui.util.keys import is_navkey +from dzgui.util.keys import is_ctrl_mask, is_navkey from dzgui.views.mixins.cursor_mixin import CursorMixin import gi @@ -86,6 +86,12 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return [model[row] for row in rows] def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: + from dzgui.views.trees.tree_servers import ServerTreeView + # NOTE: suppress popup search and delegate binding to server view (cf. request_keyword_focus) + if not isinstance(treeview, ServerTreeView): + if is_ctrl_mask(event) and event.keyval == Gdk.KEY_f: + return True + if is_navkey(event.keyval): if self.get_model() is None: return From d605447fca468821dafa53cf38a33cf12d1fee81 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:51:55 +0900 Subject: [PATCH 6/7] chore: clear typehinting errors --- dzgui/views/trees/tree_base.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index 8a32e2f..fbb3a1f 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -85,8 +85,9 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore model, rows = sel.get_selected_rows() return [model[row] for row in rows] - def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: + def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> bool: from dzgui.views.trees.tree_servers import ServerTreeView + # NOTE: suppress popup search and delegate binding to server view (cf. request_keyword_focus) if not isinstance(treeview, ServerTreeView): if is_ctrl_mask(event) and event.keyval == Gdk.KEY_f: @@ -94,7 +95,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore if is_navkey(event.keyval): if self.get_model() is None: - return + return True if self.sel_blocked is False: self.sel_blocked = True self.controller.suppress_signal( @@ -104,7 +105,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore True, ) self._vim_nav(event) - return + return False def _on_key_release(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: """ From 1ddc4a5ff111c6edcf15f3c5bb5b930b1ce1cebe Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:58:44 +0900 Subject: [PATCH 7/7] chore: bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8a5e8dc..8e1cddc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux" authors = [ {name = "aclist"} ] -version = "7.0.0b10" +version = "7.0.0b11" license = "GPL-3.0-or-later" license-files = ["LICENSE"] readme = "README.md"