diff --git a/dzgui/api/servers.py b/dzgui/api/servers.py index e921d8b..6f56094 100644 --- a/dzgui/api/servers.py +++ b/dzgui/api/servers.py @@ -59,14 +59,8 @@ class Details: success: bool -@dataclass(slots=True) +@dataclass(slots=True, frozen=True) class Record: - # TODO: investigate whether this enum is still being used; - # can this be frozen? - """ - The gameport field is manipulated by the RowType.CONN_BY_IP method - """ - ip: str gameport: int qport: int diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 8f35fc5..200cc1b 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -7,11 +7,12 @@ import dzgui.util._json as JSON # noqa from dzgui.const.enum import ( - FilterMode, - Preferences, - NotebookPage, ButtonType, ContextMenu, + FilterMode, + NotebookPage, + Preferences, + ServerTab, ) from dzgui.config.userprefs import UserPrefs @@ -37,7 +38,6 @@ logger = logging.getLogger(APP_NAME) if TYPE_CHECKING: from dzgui.api.servers import Record - from dzgui.const.enum import ServerTab from dzgui.managers.connection import Prerequisites from dzgui.managers.filter import FilterManager from dzgui.util.dist import Haversine @@ -498,6 +498,9 @@ class Controller(GObject.GObject): def set_active_keyword(self, keyword: str) -> None: self.get_filter_man().set_active_keyword(keyword) + ServerModelManager(self, self.get_active_treeview()).refilter( + FilterMode.TOGGLE_ON + ) def get_modtreeview(self) -> "ModTreeView": return self.mediator.modtreeview diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index a429ffb..e3ef6c9 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -21,7 +21,7 @@ from dzgui.views.dialogs.generic import ExceptionDialog import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk, GLib # noqa E402 if TYPE_CHECKING: from dzgui.api.servers import A2SInfo, Record @@ -390,6 +390,8 @@ class ServerModelManager: def _cleanup_on_success(self) -> None: proxy = self.proxy_man.get_proxy_model() self.tv.set_model(proxy) + if self.tv.enum == ServerTab.BROWSER: + GLib.idle_add(self.tv.wipe_cache) if self.preserve_on_fail is True: self.proxy_man.wipe_cache() diff --git a/dzgui/views/components/filter_panel.py b/dzgui/views/components/filter_panel.py index 35a6ea4..b9f29a9 100644 --- a/dzgui/views/components/filter_panel.py +++ b/dzgui/views/components/filter_panel.py @@ -9,8 +9,6 @@ from dzgui.const.constants import ( NO_PADDING, SEARCH_ICON, ) -from dzgui.const.enum import FilterMode -from dzgui.model.servers import ServerModelManager from dzgui.util.format import format_exception from dzgui.util.strings import all_maps from dzgui.views.components.maps_combo import MapsCombo @@ -148,10 +146,6 @@ class KeywordEntry(Gtk.Entry): self.controller.set_active_keyword(keyword) logger.info(f"User filtered by keyword '{keyword}'") - ServerModelManager( - self.controller, self.controller.get_active_treeview() - ).refilter(FilterMode.TOGGLE_ON) - class FilterPanel(Gtk.Box): def __init__(self, controller: "Controller") -> None: diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index b504955..cff1e2a 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -309,6 +309,14 @@ class ExceptionDialog(TextBufferDialog): content.set_spacing(0) content.add(scrollable) + self.connect("map", self._on_map) + + def _on_map(self, dialog: Self) -> None: + button = self.get_widget_for_response(Gtk.ResponseType.OK) + if button is None: + return + button.grab_focus() + def _on_page_changed( self, notebook: Gtk.Notebook, child: Gtk.Box | Gtk.ScrolledWindow, index: int ) -> None: diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 2ec2f32..f910c6f 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -66,7 +66,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore self.handler_id: int self.queue: Queue = Queue() - self.seen_cache: list[str] = [] + self.seen_cache: list[Record] = [] prefs = self.controller.get_prefs() columns = prefs.paths.columns @@ -341,16 +341,24 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore control = self.proxy_man.get_control() return model, control - @staticmethod def ping_server( + self, model: "FastInsertListStore", _iter: Gtk.TreeIter, - ip: str, - qport: int, - ping_column: int, + record: Record, ) -> None: - _ping = ping(ip, qport) - GLib.idle_add(lambda: model.set(_iter, ping_column, _ping)) + _ping = ping(record.ip, record.qport) + GLib.idle_add(self._redraw, model, _iter, _ping) + + def _redraw( + self, model: "FastInsertListStore", _iter: Gtk.TreeIter, _ping: int + ) -> None: + ping_column = 9 + model.set(_iter, ping_column, _ping) + self.queue_draw() + + def wipe_cache(self) -> None: + self.seen_cache = [] def _get_ping( self, @@ -363,13 +371,12 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore addr_column = 7 qport_column = 8 - ping_column = 9 addr = model.get_value(_iter, addr_column).split(":") ip = addr[0] - gameport = addr[1] + gameport = int(addr[1]) qport = model.get_value(_iter, qport_column) - record = f"{addr}:{gameport}:{qport}" + record = Record(ip, gameport, qport) if record in self.seen_cache: return @@ -378,7 +385,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore thread = threading.Thread( daemon=True, target=self.ping_server, - args=(model, _iter, ip, qport, ping_column), + args=(model, _iter, record), ) thread.start()