diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 63ad28a..c547b45 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -384,6 +384,57 @@ class Controller(GObject.GObject): self.open_page(button.opens) + def dump_favorites(self) -> None: + # TODO: if list is empty, return failure + ips = self.query_config(Preferences.IP_LIST) + if len(ips) == 0: + # FIXME: this is not a failure, just a quiet exit with custom statusbar + # TODO: add custom statusbar parameter + self.cleanup_func = StoredFunc(self.cleanup_on_failure, False) + return + self.dump_ips(ips) + + def dump_history(self) -> None: + history = self.prefs.paths.history + # TODO: customize statusbar to mention how records are added + try: + with open(history, "r") as f: + rows = [row.rstrip("\n") for row in f] + except OSError: + self.cleanup_func = StoredFunc(self.cleanup_on_failure, False) + return + if len(rows) == 0: + self.cleanup_func = StoredFunc(self.cleanup_on_failure, False) + return + self.dump_ips(rows) + + def dump_ips(self, ips: list) -> None: + # NOTE: block malformed records (TODO: add github issue no.) + ips = [ip for ip in ips if len(ip.split(":")) == 3 and ip.split(":")[2] != "" ] + with ThreadPoolExecutor() as executor: + futures = [ + executor.submit( + Servers.query_direct, + ip.split(":")[0], + int(ip.split(":")[2]), + ) + for ip in ips + ] + # TODO: update dialog in main loop + #wait(futures) + serv = [] + for future in as_completed(futures): + res = future.result() + # NOTE: discard failing entries + if res is None: + continue + serv.append(res) + if len(serv) == 0: + self.cleanup_func = StoredFunc(self.cleanup_on_failure) + return + parsed = Servers.parse_json(serv) + self.push_data_success(parsed, FilterMode.INITIAL) + def dump_api(self) -> None: key = self.query_config(Preferences.STEAM) job = Servers.query_api @@ -405,6 +456,7 @@ class Controller(GObject.GObject): except Exception as e: logger.critical(e) self.cleanup_func = StoredFunc(self.cleanup_on_failure) + return # NOTE: This step is allowed to fail, since this metadata is incidental res = Servers.query_api(key, APPID_DAYZ_EXP, "") @@ -693,7 +745,7 @@ class Controller(GObject.GObject): treeview.grab_focus() - def cleanup_on_failure(self) -> None: + def cleanup_on_failure(self, show_dialog=True) -> None: treeview = self.get_active_treeview() treeview.set_loaded(True) map_man = treeview.get_map_man() @@ -713,11 +765,12 @@ class Controller(GObject.GObject): map_man.set_unique_maps(None) context = self.get_active_context() - # TODO: distinguish signals, e.g. "servers_failed_to_load" - # may trigger different behavior + # TODO: distinguish signals, e.g. "servers_failed_to_load", "servers_loaded_empty" + # customize statusbar accordingly self.emitter.emit("servers_loaded", context) - dialog = ExceptionDialog(self, strings.api_warn_msg) - dialog.run() + if show_dialog: + dialog = ExceptionDialog(self, strings.api_warn_msg) + dialog.run() def push_data_success(self, data: tuple, mode: Optional[FilterMode]) -> None: # FIXME: set outside of thread diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 32753a6..ae6e930 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -37,6 +37,7 @@ logger = logging.getLogger(__name__) # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings("ignore", ".*g_value_get_int", Warning) + # TODO: move to controller # kilometer cache; note, user may change measurement it partway through, flush cache # cache: dict[str, int] = {} diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index fd41306..82c3a48 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -54,8 +54,8 @@ class GenericDialog(Gtk.MessageDialog): self.set_default_response(Gtk.ResponseType.OK) self.connect("response", self._on_response) - self.action_area.set_layout(Gtk.ButtonBoxStyle.CENTER) - self.action_area.set_margin_bottom(20) + self.get_action_area().set_layout(Gtk.ButtonBoxStyle.CENTER) + self.get_action_area().set_margin_bottom(20) self.outer = self.get_content_area() self.outer.set_margin_start(30) self.outer.set_margin_end(30) diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index 31bb2ed..1b0bb14 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -37,8 +37,9 @@ class ServerNotebook(Gtk.ScrolledWindow): ) self.lan = ServerTreeView(controller, ServerTab.LAN, ContextMenuGroup.SCAN_LAN) - self.recent.set_query_func(StoredFunc(self.controller.dump_test_2)) - # TODO: number of servers will not be known a priori until reading file during query phase + # TODO: number of jobs will not be known a priori unless files are read + self.recent.set_query_func(StoredFunc(self.controller.dump_history)) + self.saved.set_query_func(StoredFunc(self.controller.dump_favorites)) self.lan.set_query_func(StoredFunc(self.controller.dump_test_2)) self.browser.set_query_func(StoredFunc(self.controller.dump_api), jobs=11) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 11167b3..bc5085f 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -4,6 +4,7 @@ import threading from typing import Any, Optional, Self from warnings import deprecated + from dzgui.views.mixins.context_mixin import ContextMixin from dzgui.const.enum import ContextMenuGroup, ServerTab from dzgui.api.servers import Record