mirror of
https://github.com/aclist/dztui.git
synced 2025-01-01 15:12:05 +01:00
feat: highlight stale mods (#162)
This commit is contained in:
parent
e9cd457233
commit
08af994361
4 changed files with 92 additions and 14 deletions
|
@ -1,5 +1,11 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [5.6.0-beta.5] 2024-11-21
|
||||||
|
### Added
|
||||||
|
- Highlight stale mods in mods list
|
||||||
|
### Fixed
|
||||||
|
- Duplicate dialog title on Steam Deck
|
||||||
|
|
||||||
## [5.6.0-beta.4] 2024-11-20
|
## [5.6.0-beta.4] 2024-11-20
|
||||||
### Added
|
### Added
|
||||||
- Application header bar and controls
|
- Application header bar and controls
|
||||||
|
|
6
dzgui.sh
6
dzgui.sh
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
version=5.6.0-beta.4
|
version=5.6.0-beta.5
|
||||||
|
|
||||||
#CONSTANTS
|
#CONSTANTS
|
||||||
aid=221100
|
aid=221100
|
||||||
|
@ -569,10 +569,10 @@ fetch_helpers_by_sum(){
|
||||||
[[ -f "$config_file" ]] && source "$config_file"
|
[[ -f "$config_file" ]] && source "$config_file"
|
||||||
declare -A sums
|
declare -A sums
|
||||||
sums=(
|
sums=(
|
||||||
["ui.py"]="549b0415af9ccad6a882b640615b9a22"
|
["ui.py"]="15fd3fc32e96db8345c5a3ac8564ecc2"
|
||||||
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
||||||
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
||||||
["funcs"]="75afe0be7e73af2fb6a7e423b5ac9159"
|
["funcs"]="d1f0d32e3ad34a34d561305ffa597e79"
|
||||||
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
||||||
)
|
)
|
||||||
local author="aclist"
|
local author="aclist"
|
||||||
|
|
|
@ -39,6 +39,7 @@ lock_file="$state_path/$prefix.lock"
|
||||||
cache_dir="$HOME/.cache/$app_name"
|
cache_dir="$HOME/.cache/$app_name"
|
||||||
_cache_servers="$cache_dir/$prefix.servers"
|
_cache_servers="$cache_dir/$prefix.servers"
|
||||||
_cache_mods_temp="$cache_dir/$prefix.mods_temp"
|
_cache_mods_temp="$cache_dir/$prefix.mods_temp"
|
||||||
|
_cache_stale_mods_temp="$cache_dir/$prefix.stale_mods_temp"
|
||||||
_cache_temp="$cache_dir/$prefix.temp"
|
_cache_temp="$cache_dir/$prefix.temp"
|
||||||
_cache_my_servers="$cache_dir/$prefix.my_servers"
|
_cache_my_servers="$cache_dir/$prefix.my_servers"
|
||||||
_cache_history="$cache_dir/$prefix.history"
|
_cache_history="$cache_dir/$prefix.history"
|
||||||
|
@ -95,6 +96,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
declare -A funcs=(
|
declare -A funcs=(
|
||||||
|
["Highlight stale"]="find_stale_mods"
|
||||||
["My servers"]="dump_servers"
|
["My servers"]="dump_servers"
|
||||||
["Change player name"]="update_config_val"
|
["Change player name"]="update_config_val"
|
||||||
["Change Steam API key"]="update_config_val"
|
["Change Steam API key"]="update_config_val"
|
||||||
|
@ -144,6 +146,20 @@ lan_scan(){
|
||||||
printf "%s\n" "$res"
|
printf "%s\n" "$res"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
find_stale_mods(){
|
||||||
|
local res
|
||||||
|
local mods=()
|
||||||
|
> $_cache_stale_mods_temp
|
||||||
|
for i in "${ip_list[@]}"; do
|
||||||
|
local ip=$(<<< "$i" awk -F: '{print $1}')
|
||||||
|
local qport=$(<<< "$i" awk -F: '{print $3}')
|
||||||
|
res=$(a2s $ip $qport rules)
|
||||||
|
if [[ -n $res ]]; then
|
||||||
|
printf "%s\n" "$res" >> $_cache_stale_mods_temp
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 99
|
||||||
|
}
|
||||||
get_player_count(){
|
get_player_count(){
|
||||||
shift
|
shift
|
||||||
local res
|
local res
|
||||||
|
|
|
@ -34,8 +34,8 @@ checks = list()
|
||||||
map_store = Gtk.ListStore(str)
|
map_store = Gtk.ListStore(str)
|
||||||
row_store = Gtk.ListStore(str)
|
row_store = Gtk.ListStore(str)
|
||||||
modlist_store = Gtk.ListStore(str, str, str)
|
modlist_store = Gtk.ListStore(str, str, str)
|
||||||
#cf. mod_cols
|
#cf. mod_cols, last column holds hex color
|
||||||
mod_store = Gtk.ListStore(str, str, str, float)
|
mod_store = Gtk.ListStore(str, str, str, float, str)
|
||||||
#cf. log_cols
|
#cf. log_cols
|
||||||
log_store = Gtk.ListStore(str, str, str, str)
|
log_store = Gtk.ListStore(str, str, str, str)
|
||||||
#cf. browser_cols
|
#cf. browser_cols
|
||||||
|
@ -53,6 +53,7 @@ changelog_path = '%s/CHANGELOG.md' %(state_path)
|
||||||
geometry_path = '%s/dzg.cols.json' %(state_path)
|
geometry_path = '%s/dzg.cols.json' %(state_path)
|
||||||
funcs = '%s/funcs' %(helpers_path)
|
funcs = '%s/funcs' %(helpers_path)
|
||||||
mods_temp_file = '%s/dzg.mods_temp' %(cache_path)
|
mods_temp_file = '%s/dzg.mods_temp' %(cache_path)
|
||||||
|
stale_mods_temp_file = '%s/dzg.stale_mods_temp' %(cache_path)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
log_file = '%s/DZGUI_DEBUG.log' %(log_path)
|
log_file = '%s/DZGUI_DEBUG.log' %(log_path)
|
||||||
|
@ -77,7 +78,8 @@ mod_cols = [
|
||||||
"Mod",
|
"Mod",
|
||||||
"Symlink",
|
"Symlink",
|
||||||
"Dir",
|
"Dir",
|
||||||
"Size (MiB)"
|
"Size (MiB)",
|
||||||
|
"Color"
|
||||||
]
|
]
|
||||||
log_cols = [
|
log_cols = [
|
||||||
"Timestamp",
|
"Timestamp",
|
||||||
|
@ -121,6 +123,11 @@ class RowType(EnumWithAttrs):
|
||||||
"label": None,
|
"label": None,
|
||||||
"tooltip": None,
|
"tooltip": None,
|
||||||
}
|
}
|
||||||
|
HIGHLIGHT = {
|
||||||
|
"label": "Highlight stale",
|
||||||
|
"tooltip": None,
|
||||||
|
"wait_msg": "Looking for stale mods"
|
||||||
|
}
|
||||||
HANDSHAKE = {
|
HANDSHAKE = {
|
||||||
"label": "Handshake",
|
"label": "Handshake",
|
||||||
"tooltip": None,
|
"tooltip": None,
|
||||||
|
@ -519,8 +526,9 @@ def parse_mod_rows(data):
|
||||||
lines = data.stdout.splitlines()
|
lines = data.stdout.splitlines()
|
||||||
hits = len(lines)
|
hits = len(lines)
|
||||||
reader = csv.reader(lines, delimiter=delimiter)
|
reader = csv.reader(lines, delimiter=delimiter)
|
||||||
|
# Nonetype inherits default GTK color
|
||||||
try:
|
try:
|
||||||
rows = [[row[0], row[1], row[2], locale.atof(row[3], func=float)] for row in reader if row]
|
rows = [[row[0], row[1], row[2], locale.atof(row[3], func=float), None] for row in reader if row]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return 1
|
return 1
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
@ -640,6 +648,10 @@ def process_shell_return_code(transient_parent, msg, code, original_input):
|
||||||
# re-block this signal before redrawing table contents
|
# re-block this signal before redrawing table contents
|
||||||
toggle_signal(treeview, treeview, '_on_keypress', False)
|
toggle_signal(treeview, treeview, '_on_keypress', False)
|
||||||
treeview.update_quad_column(RowType.LIST_MODS)
|
treeview.update_quad_column(RowType.LIST_MODS)
|
||||||
|
case 99:
|
||||||
|
# highlight stale mods
|
||||||
|
panel = transient_parent.grid.sel_panel
|
||||||
|
panel.colorize_cells(msg, True)
|
||||||
case 100:
|
case 100:
|
||||||
# final handoff before launch
|
# final handoff before launch
|
||||||
final_conf = spawn_dialog(transient_parent, msg, Popup.CONFIRM)
|
final_conf = spawn_dialog(transient_parent, msg, Popup.CONFIRM)
|
||||||
|
@ -690,6 +702,10 @@ def process_tree_option(input, treeview):
|
||||||
process_shell_return_code(transient_parent, msg, rc, input)
|
process_shell_return_code(transient_parent, msg, rc, input)
|
||||||
|
|
||||||
# help pages
|
# help pages
|
||||||
|
if context == WindowContext.TABLE_MODS and command == RowType.HIGHLIGHT:
|
||||||
|
wait_msg = command.dict["wait_msg"]
|
||||||
|
call_on_thread(True, cmd_string, wait_msg, '')
|
||||||
|
return
|
||||||
if context == WindowContext.HELP:
|
if context == WindowContext.HELP:
|
||||||
match command:
|
match command:
|
||||||
case RowType.CHANGELOG:
|
case RowType.CHANGELOG:
|
||||||
|
@ -1589,11 +1605,13 @@ class TreeView(Gtk.TreeView):
|
||||||
|
|
||||||
for i, column_title in enumerate(cols):
|
for i, column_title in enumerate(cols):
|
||||||
renderer = Gtk.CellRendererText()
|
renderer = Gtk.CellRendererText()
|
||||||
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
|
column = Gtk.TreeViewColumn(column_title, renderer, text=i, foreground=4)
|
||||||
if mode == RowType.LIST_MODS:
|
if mode == RowType.LIST_MODS:
|
||||||
if i == 3:
|
if i == 3:
|
||||||
column.set_cell_data_func(renderer, self._format_float, func_data=None)
|
column.set_cell_data_func(renderer, self._format_float, func_data=None)
|
||||||
column.set_sort_column_id(i)
|
column.set_sort_column_id(i)
|
||||||
|
# hidden color property column
|
||||||
|
if i != 4:
|
||||||
self.append_column(column)
|
self.append_column(column)
|
||||||
|
|
||||||
widgets = relative_widget(self)
|
widgets = relative_widget(self)
|
||||||
|
@ -1848,7 +1866,7 @@ class GenericDialog(Gtk.MessageDialog):
|
||||||
text=header_text,
|
text=header_text,
|
||||||
secondary_text=textwrap.fill(text, 50),
|
secondary_text=textwrap.fill(text, 50),
|
||||||
buttons=button_type,
|
buttons=button_type,
|
||||||
title=app_name,
|
title="DZGUI - Dialog",
|
||||||
modal=True,
|
modal=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1939,7 +1957,7 @@ class LanDialog(Gtk.MessageDialog):
|
||||||
buttons=Gtk.ButtonsType.OK_CANCEL,
|
buttons=Gtk.ButtonsType.OK_CANCEL,
|
||||||
text=text,
|
text=text,
|
||||||
secondary_text="Select the query port",
|
secondary_text="Select the query port",
|
||||||
title=app_name,
|
title="DZGUI - Dialog",
|
||||||
modal=True,
|
modal=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2328,9 +2346,12 @@ class ModSelectionPanel(Gtk.Box):
|
||||||
labels = [
|
labels = [
|
||||||
"Select all",
|
"Select all",
|
||||||
"Unselect all",
|
"Unselect all",
|
||||||
"Delete selected"
|
"Delete selected",
|
||||||
|
"Highlight stale"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.active_button = None
|
||||||
|
|
||||||
for l in labels:
|
for l in labels:
|
||||||
button = Gtk.Button(label=l)
|
button = Gtk.Button(label=l)
|
||||||
button.set_margin_start(10)
|
button.set_margin_start(10)
|
||||||
|
@ -2339,22 +2360,57 @@ class ModSelectionPanel(Gtk.Box):
|
||||||
self.pack_start(button, False, True, 0)
|
self.pack_start(button, False, True, 0)
|
||||||
|
|
||||||
def _on_button_clicked(self, button):
|
def _on_button_clicked(self, button):
|
||||||
|
self.active_button = button
|
||||||
label = button.get_label()
|
label = button.get_label()
|
||||||
widgets = relative_widget(self)
|
widgets = relative_widget(self)
|
||||||
parent = widgets["outer"]
|
parent = widgets["outer"]
|
||||||
treeview = widgets["treeview"]
|
treeview = widgets["treeview"]
|
||||||
|
(model, pathlist) = treeview.get_selection().get_selected_rows()
|
||||||
match label:
|
match label:
|
||||||
case "Select all":
|
case "Select all":
|
||||||
treeview.toggle_selection(True)
|
treeview.toggle_selection(True)
|
||||||
case "Unselect all":
|
case "Unselect all":
|
||||||
treeview.toggle_selection(False)
|
treeview.toggle_selection(False)
|
||||||
case "Delete selected":
|
case "Delete selected":
|
||||||
(model, pathlist) = treeview.get_selection().get_selected_rows()
|
|
||||||
ct = len(pathlist)
|
ct = len(pathlist)
|
||||||
if ct < 1:
|
if ct < 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._iterate_mod_deletion(model, pathlist, ct)
|
self._iterate_mod_deletion(model, pathlist, ct)
|
||||||
|
case "Highlight stale":
|
||||||
|
process_tree_option([treeview.view, RowType.HIGHLIGHT], treeview)
|
||||||
|
case "Unhighlight stale":
|
||||||
|
self.colorize_cells(None, False)
|
||||||
|
|
||||||
|
def colorize_cells(self, mods, bool):
|
||||||
|
def _colorize(path, color):
|
||||||
|
mod_store[path][4] = color
|
||||||
|
|
||||||
|
widgets = relative_widget(self)
|
||||||
|
parent = widgets["outer"]
|
||||||
|
treeview = widgets["treeview"]
|
||||||
|
(model, pathlist) = treeview.get_selection().get_selected_rows()
|
||||||
|
|
||||||
|
if bool is False:
|
||||||
|
default = None
|
||||||
|
for i in range (0, len(mod_store)):
|
||||||
|
path = Gtk.TreePath(i)
|
||||||
|
it = mod_store.get_iter(path)
|
||||||
|
_colorize(path, None)
|
||||||
|
self.active_button.set_label("Highlight stale")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(stale_mods_temp_file, "r") as infile:
|
||||||
|
lines = [line.rstrip('\n') for line in infile]
|
||||||
|
|
||||||
|
for i in range (0, len(mod_store)):
|
||||||
|
red = "#FF0000"
|
||||||
|
path = Gtk.TreePath(i)
|
||||||
|
it = mod_store.get_iter(path)
|
||||||
|
if model.get_value(it, 2) not in lines:
|
||||||
|
_colorize(path, red)
|
||||||
|
treeview.toggle_selection(False)
|
||||||
|
self.active_button.set_label("Unhighlight stale")
|
||||||
|
|
||||||
|
|
||||||
def _iterate_mod_deletion(self, model, pathlist, ct):
|
def _iterate_mod_deletion(self, model, pathlist, ct):
|
||||||
# hedge against large number of arguments
|
# hedge against large number of arguments
|
||||||
|
|
Loading…
Reference in a new issue