From 6b669e5c2144399a3d393d93e954ab45493acba3 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:41:54 +0900 Subject: [PATCH 01/14] fix: reset window context on cooldown --- helpers/ui.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helpers/ui.py b/helpers/ui.py index af1b553..9b51720 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1721,6 +1721,8 @@ class TreeView(Gtk.TreeView): cooldown = call_out(self, "test_cooldown", "", "") if cooldown.returncode == 1: spawn_dialog(outer, cooldown.stdout, Popup.NOTIFY) + # reset context to main menu if navigation was blocked + self.view = WindowContext.MAIN_MENU return 1 for check in checks: toggle_signal(filters_vbox, check, '_on_check_toggle', False) From 0fdc132873dfcd85eda3e3d58d29b059f80ba23e Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:03:04 +0900 Subject: [PATCH 02/14] fix: array syntax --- helpers/funcs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers/funcs b/helpers/funcs index f8f0c2f..d538109 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -930,7 +930,7 @@ remove_from_favs(){ break fi done - if [[ ${#ip_list} -gt 0 ]]; then + if [[ ${#ip_list[@]} -gt 0 ]]; then readarray -t ip_list < <(printf "%s\n" "${ip_list[@]}") fi update_config @@ -938,6 +938,7 @@ remove_from_favs(){ local cache="$(< "$_cache_my_servers")" <<< "$cache" grep -v -P "$r$" > $_cache_my_servers logger INFO "Removed the record $record from saved servers" + echo "Removed $record from saved servers" return 90 } update_favs_from_table(){ From ac3055ce39f2d777dfcf2b53d7b21a02e5f226fe Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:04:00 +0900 Subject: [PATCH 03/14] fix: non blocking workshop open --- helpers/funcs | 2 +- helpers/ui.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/helpers/funcs b/helpers/funcs index d538109..8d4faec 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -1020,7 +1020,7 @@ open_workshop_page(){ shift local id="$1" local workshop_uri="steam://url/CommunityFilePage/$id" - $steam_cmd "$workshop_uri" $id + $steam_cmd "$workshop_uri" $id & } open_link(){ shift diff --git a/helpers/ui.py b/helpers/ui.py index 9b51720..e64caee 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1139,7 +1139,8 @@ class TreeView(Gtk.TreeView): process_tree_option([self.view, RowType.DELETE_SELECTED], self) case "Open in Steam Workshop": record = self.get_column_at_index(2) - call_out(parent, "open_workshop_page", record) + base_cmd = "open_workshop_page" + subprocess.Popen(['/usr/bin/env', 'bash', funcs, base_cmd, record]) def toggle_selection(self, bool): l = len(mod_store) From ef3fffca47a179dbf87d664fdb1a511be79b1311 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:04:29 +0900 Subject: [PATCH 04/14] change: use printf --- helpers/funcs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/funcs b/helpers/funcs index 8d4faec..5df388a 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -343,7 +343,7 @@ list_mods(){ local base_dir local size if [[ -z $(installed_mods) ]] || [[ -z $(find $workshop_dir -maxdepth 2 -name "*.cpp" | grep .cpp) ]]; then - echo "No mods currently installed or incorrect path set." + printf "No mods currently installed or incorrect path set." logger WARN "Found no locally installed mods" return 1 else From eaa6c1154323c417af7d8ba02e6b4714509247a8 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:06:46 +0900 Subject: [PATCH 05/14] fix: typo --- helpers/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index e64caee..fa57d14 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -156,7 +156,7 @@ class RowType(EnumWithAttrs): } RECENT_SERVERS = { "label": "Recent servers", - "tooltip": "Shows the last to servers you connected to (includes attempts)", + "tooltip": "Shows the last 10 servers you connected to (includes attempts)", } CONN_BY_IP = { "label": "Connect by IP", From a4f076fbdb6ab12485246df7f73d931d4c3cc0e9 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:07:16 +0900 Subject: [PATCH 06/14] chore: clarify comments --- helpers/ui.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/ui.py b/helpers/ui.py index fa57d14..ff5a1ac 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1090,6 +1090,7 @@ class TreeView(Gtk.TreeView): def _on_menu_click(self, menu_item): #TODO: context menus use old stringwise parsing + # use enumerated contexts parent = self.get_outer_window() context = self.get_first_col() value = self.get_column_at_index(0) From 5619d55840e1bbeb563006c642e36a780d99e377 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:09:25 +0900 Subject: [PATCH 07/14] fix: update statusbar when removing rows --- helpers/ui.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index ff5a1ac..a573d80 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1261,8 +1261,11 @@ class TreeView(Gtk.TreeView): if self.view == WindowContext.TABLE_API or self.view == WindowContext.TABLE_SERVER: addr = self.get_column_at_index(7) if addr is None: + server_tooltip[0] = format_tooltip() + grid.update_statusbar(server_tooltip[0]) return if addr in cache: + server_tooltip[0] = format_tooltip() dist = format_distance(cache[addr][0]) ping = format_ping(cache[addr][1]) @@ -1390,7 +1393,7 @@ class TreeView(Gtk.TreeView): self.grab_focus() for column in self.get_columns(): column.connect("notify::width", self._on_col_width_changed) - if hits == 0: + if len(server_store) == 0: call_out(self, "start_cooldown", "", "") api_warn_msg = """\ No servers returned. Possible network issue or API key on cooldown? @@ -1405,10 +1408,8 @@ class TreeView(Gtk.TreeView): data = call_out(self, "dump_servers", mode, *filters) toggle_signal(self, self.selected_row, '_on_tree_selection_changed', False) - row_metadata = parse_server_rows(data) - sum = row_metadata[0] - hits = row_metadata[1] - server_tooltip[0] = format_tooltip(sum, hits) + parse_server_rows(data) + server_tooltip[0] = format_tooltip() grid.update_statusbar(server_tooltip[0]) map_data = call_out(self, "get_unique_maps", mode) @@ -1790,7 +1791,11 @@ def format_metadata(row_sel): return prefix -def format_tooltip(players, hits): +def format_tooltip(): + hits = len(server_store) + players = 0 + for row in server_store: + players+= row[4] hits_pretty = pluralize("matches", hits) players_pretty = pluralize("players", players) tooltip = f"Found {hits:n} {hits_pretty} with {players:n} {players_pretty}" @@ -1800,10 +1805,8 @@ def format_tooltip(players, hits): def filter_servers(transient_parent, filters_vbox, treeview, context): def filter(dialog): def clear_and_destroy(): - row_metadata = parse_server_rows(data) - sum = row_metadata[0] - hits = row_metadata[1] - server_tooltip[0] = format_tooltip(sum, hits) + parse_server_rows(data) + server_tooltip[0] = format_tooltip() transient_parent.grid.update_statusbar(server_tooltip[0]) toggle_signal(treeview, treeview.selected_row, '_on_tree_selection_changed', True) @@ -2279,6 +2282,7 @@ class Grid(Gtk.Grid): self.scrollable_treelist.treeview.terminate_process() def _on_calclat_started(self, treeview): + server_tooltip[0] = format_tooltip() server_tooltip[1] = server_tooltip[0] + "| Distance: calculating..." self.update_statusbar(server_tooltip[1]) From 75e247b83156da8b59ef8936cc54bc93a20ec504 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:10:08 +0900 Subject: [PATCH 08/14] fix: remove return values from parse_server_rows() --- helpers/ui.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index a573d80..7dea8e5 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -539,19 +539,14 @@ def parse_mod_rows(data): def parse_server_rows(data): - sum = 0 lines = data.stdout.splitlines() reader = csv.reader(lines, delimiter=delimiter) - hits = len(lines) try: rows = [[row[0], row[1], row[2], row[3], int(row[4]), int(row[5]), int(row[6]), row[7], int(row[8])] for row in reader if row] except IndexError: return 1 for row in rows: server_store.append(row) - players = int(row[4]) - sum += players - return [sum, hits] def query_config(widget, key=""): From 43a639005f3fcb3b88ccf8d99e0dd1621179ade6 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:10:31 +0900 Subject: [PATCH 09/14] chore: move comments --- helpers/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index 7dea8e5..7d42ae2 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -2420,7 +2420,6 @@ class ModSelectionPanel(Gtk.Box): def _iterate_mod_deletion(self, model, pathlist, ct): - # hedge against large number of arguments widgets = relative_widget(self) parent = widgets["outer"] treeview = widgets["treeview"] @@ -2441,6 +2440,7 @@ class ModSelectionPanel(Gtk.Box): path = model.get_value(it, 2) concat = symlink + " " + path + "\n" mods.append(concat) + # hedge against large number of arguments passed to shell with open(mods_temp_file, "w") as outfile: outfile.writelines(mods) process_tree_option([treeview.view, RowType.DELETE_SELECTED], treeview) From 13c6813c8e0d9fe9a1ab8cdb3eee7c78b4bf7919 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:11:39 +0900 Subject: [PATCH 10/14] feat: resolve ip when saving records --- helpers/ui.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 7d42ae2..652ea92 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -123,6 +123,11 @@ class RowType(EnumWithAttrs): "label": None, "tooltip": None, } + RESOLVE_IP = { + "label": "Resolve IP", + "tooltip": None, + "wait_msg": "Resolving remote IP" + } HIGHLIGHT = { "label": "Highlight stale", "tooltip": None, @@ -696,6 +701,11 @@ def process_tree_option(input, treeview): msg = out[-1] process_shell_return_code(transient_parent, msg, rc, input) + if command == RowType.RESOLVE_IP: + record = "%s:%s" %(treeview.get_column_at_index(7), treeview.get_column_at_index(8)) + wait_msg = command.dict["wait_msg"] + call_on_thread(True, cmd_string, wait_msg, record) + return # help pages if context == WindowContext.TABLE_MODS and command == RowType.HIGHLIGHT: wait_msg = command.dict["wait_msg"] @@ -1095,12 +1105,10 @@ class TreeView(Gtk.TreeView): match context_menu_label: case "Add to my servers" | "Remove from my servers": record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) - proc = call_out(parent, context_menu_label, record) + process_tree_option([self.view, RowType.RESOLVE_IP], self) if context == "Name (My saved servers)": iter = self.get_current_iter() server_store.remove(iter) - msg = proc.stdout - res = spawn_dialog(parent, msg, Popup.NOTIFY) case "Remove from history": record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) call_out(parent, context_menu_label, record) From a46c2e17abf16132768ca47723358ee19b1c87ff Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:12:20 +0900 Subject: [PATCH 11/14] chore: remove unused values --- helpers/ui.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index 652ea92..cd61034 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1152,12 +1152,10 @@ class TreeView(Gtk.TreeView): case True: for i in range (0, l): path = Gtk.TreePath(i) - it = mod_store.get_iter(path) self.get_selection().select_path(path) case False: for i in range (0, l): path = Gtk.TreePath(i) - it = mod_store.get_iter(path) self.get_selection().unselect_path(path) def _on_button_release(self, widget, event): From 6d332f613e3f254773b7318119f52950b461c603 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:13:29 +0900 Subject: [PATCH 12/14] chore: guard clause --- helpers/ui.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/helpers/ui.py b/helpers/ui.py index cd61034..7d1f81e 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -1132,15 +1132,16 @@ class TreeView(Gtk.TreeView): success_msg = "Successfully deleted the mod '%s'." %(value) fail_msg = "An error occurred during deletion. Aborting." res = spawn_dialog(parent, conf_msg, Popup.CONFIRM) - if res == 0: - mods = [] - symlink = self.get_column_at_index(1) - dir = self.get_column_at_index(2) - concat = symlink + " " + dir + "\n" - mods.append(concat) - with open(mods_temp_file, "w") as outfile: - outfile.writelines(mods) - process_tree_option([self.view, RowType.DELETE_SELECTED], self) + if res != 0: + return + mods = [] + symlink = self.get_column_at_index(1) + dir = self.get_column_at_index(2) + concat = symlink + " " + dir + "\n" + mods.append(concat) + with open(mods_temp_file, "w") as outfile: + outfile.writelines(mods) + process_tree_option([self.view, RowType.DELETE_SELECTED], self) case "Open in Steam Workshop": record = self.get_column_at_index(2) base_cmd = "open_workshop_page" From 336b9882820057093ef40c9e90e3ef0e1f342ffc Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:15:45 +0900 Subject: [PATCH 13/14] fix: untoggle highlight button (#169, 170) --- helpers/ui.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/helpers/ui.py b/helpers/ui.py index 7d1f81e..0747b7a 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -642,16 +642,35 @@ def process_shell_return_code(transient_parent, msg, code, original_input): spawn_dialog(transient_parent, msg, Popup.NOTIFY) return case 95: - # reload mods list + # successful mod deletion spawn_dialog(transient_parent, msg, Popup.NOTIFY) treeview = transient_parent.grid.scrollable_treelist.treeview + grid = treeview.get_parent().get_parent() + (model, pathlist) = treeview.get_selection().get_selected_rows() + for p in reversed(pathlist): + it = model.get_iter(p) + model.remove(it) + total_size = 0 + total_mods = len(model) + for row in model: + total_size += row[3] + size = locale.format_string('%.3f', total_size, grouping=True) + pretty = pluralize("mods", total_mods) + grid.update_statusbar(f"Found {total_mods:n} {pretty} taking up {size} MiB") + # untoggle selection for visibility of other stale rows + treeview.toggle_selection(False) + case 96: + # unsuccessful mod deletion + spawn_dialog(transient_parent, msg, Popup.NOTIFY) # re-block this signal before redrawing table contents + treeview = transient_parent.grid.scrollable_treelist.treeview toggle_signal(treeview, treeview, '_on_keypress', False) treeview.update_quad_column(RowType.LIST_MODS) case 99: # highlight stale mods panel = transient_parent.grid.sel_panel panel.colorize_cells(True) + panel.toggle_select_stale_button(True) case 100: # final handoff before launch final_conf = spawn_dialog(transient_parent, msg, Popup.CONFIRM) @@ -1431,6 +1450,7 @@ class TreeView(Gtk.TreeView): right_panel.set_filter_visibility(False) else: grid.sel_panel.set_visible(True) + grid.sel_panel.initialize() self.set_model(mod_store) self.grab_focus() @@ -2373,6 +2393,19 @@ class ModSelectionPanel(Gtk.Box): button.connect("clicked", self._on_button_clicked) self.pack_start(button, False, True, 0) + + def initialize(self): + l = len(self.get_children()) + last = self.get_children()[l-1] + last_label = last.get_label() + for i in self.get_children(): + match i.get_label(): + case "Select stale": + i.destroy() + case "Unhighlight stale": + i.set_label("Highlight stale") + + def _on_button_clicked(self, button): self.active_button = button label = button.get_label() @@ -2394,6 +2427,22 @@ class ModSelectionPanel(Gtk.Box): process_tree_option([treeview.view, RowType.HIGHLIGHT], treeview) case "Unhighlight stale": self.colorize_cells(False) + self._remove_last_button() + case "Select stale": + for i in range (0, len(mod_store)): + if mod_store[i][4] == "#FF0000": + path = Gtk.TreePath(i) + treeview.get_selection().select_path(path) + + + def toggle_select_stale_button(self, bool): + if bool is True: + button = Gtk.Button(label="Select stale") + button.set_margin_start(10) + button.set_margin_end(10) + button.connect("clicked", self._on_button_clicked) + self.pack_start(button, False, True, 0) + self.show_all() def colorize_cells(self, bool): def _colorize(path, color): From 8fdc29d47df45c8099b3d3149db934dd62c49911 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:23:51 +0900 Subject: [PATCH 14/14] chore: bump version --- CHANGELOG.md | 8 ++++++++ dzgui.sh | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b52b56a..45c7290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [5.6.0-beta.10] 2024-12-04 +### Fixed +- Untoggle highlight button when repopulating mod list +- Resolve remote IP when saving records for game servers with multiple hosts +- Update statusbar when removing servers from list/repopulating +### Added: +- "Select stale" button to bulk select mods marked as obsolete + ## [5.6.0-beta.9] 2024-12-03 ### Fixed - Normalize user locale when parsing floats diff --git a/dzgui.sh b/dzgui.sh index 5ac52ad..766915b 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -o pipefail -version=5.6.0-beta.9 +version=5.6.0-beta.10 #CONSTANTS aid=221100 @@ -569,10 +569,10 @@ fetch_helpers_by_sum(){ [[ -f "$config_file" ]] && source "$config_file" declare -A sums sums=( - ["ui.py"]="1c6e5b996eccd891a3e56930e28246da" + ["ui.py"]="3b90cd522e52131e7ae396671e1c1ad2" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" - ["funcs"]="d98d8626a1d61b2d5947b53155a14928" + ["funcs"]="62f6b3fb2dcb56a78b7642c0f0aa7abe" ["lan"]="c62e84ddd1457b71a85ad21da662b9af" ) local author="aclist"