From 0283baf3a97c1c9957c97274327cbbe18a01fb58 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Mon, 23 Feb 2026 21:53:20 +0900 Subject: [PATCH] chore: rename to ProxyModelManager --- dzgui/controllers/mc.py | 22 +++---- dzgui/managers/thread_man.py | 1 + dzgui/model/map_model.py | 18 +++--- .../{filtered_model.py => proxy_model.py} | 10 ++- dzgui/model/servers.py | 24 ++++---- dzgui/views/components/filter_panel.py | 61 ++++++++++--------- dzgui/views/trees/tree_servers.py | 12 ++-- 7 files changed, 82 insertions(+), 66 deletions(-) rename dzgui/model/{filtered_model.py => proxy_model.py} (97%) diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 9f7b648..b555fb3 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -41,7 +41,7 @@ from dzgui.config.userprefs import UserPrefs from dzgui.controllers.emitter import Emitter from dzgui.managers.config import ConfigManager from dzgui.managers.contextmenu import ContextMenuManager -from dzgui.model.filtered_model import FilteredModelManager +from dzgui.model.proxy_model import ProxyModelManager from dzgui.model.servers import ServerModelManager from dzgui.model.model_factory import ModelFactory from dzgui.util import strings @@ -585,20 +585,20 @@ class Controller(GObject.GObject): def get_player_count(self) -> str: treeview = self.get_active_treeview() model = treeview.get_model() - filter_man = treeview.get_filter_man() - control_model = filter_man.get_control() + proxy_man = treeview.get_proxy_man() + control_model = proxy_man.get_control() count = format_player_count(model, control_model) return count def get_statusbar(self) -> None: return self.mediator.statusbar - def get_filter_man(self) -> "FilteredModelManager": - return self.filter_man + def get_proxy_man(self) -> "ProxyModelManager": + return self.proxy_man - def set_filter_man(self, filter_man: "FilteredModelManager") -> None: - # TODO: used when staging filter man outside of thread - self.filter_man = filter_man + # def set_proxy_man(self, proxy_man: "ProxyModelManager") -> None: + # # TODO: used when staging filter man outside of thread + # self.proxy_man = proxy_man def populate_model(self, tv: Gtk.TreeView) -> None: # NOTE: skip on previously loaded tabs @@ -624,8 +624,8 @@ class Controller(GObject.GObject): # TODO: filterman calls back to here, gets convoluted def get_keyword(self) -> str: tv = self.get_active_treeview() - filter_man = tv.get_filter_man() - return filter_man.get_keyword_filter() + proxy_man = tv.get_proxy_man() + return proxy_man.get_keyword_filter() def get_map_store(self) -> Gtk.ListStore: map_man = self.get_map_man() @@ -677,7 +677,7 @@ class Controller(GObject.GObject): map_man = self.get_map_man() map_man.set_selected_map(selection) # FIXME: label should not be mandatory - ServerModelManager(self, self.get_active_treeview()).refilter(FilterMode.MAP) + ServerModelManager(self, self.get_active_treeview()).refilter(FilterMode.MAP, selection) def get_notebook(self) -> "Notebook": return self.mediator.notebook diff --git a/dzgui/managers/thread_man.py b/dzgui/managers/thread_man.py index e51e3c9..18a520c 100644 --- a/dzgui/managers/thread_man.py +++ b/dzgui/managers/thread_man.py @@ -1,6 +1,7 @@ import inspect import logging import threading +from typing import Any from functools import wraps from typing import Callable, Optional diff --git a/dzgui/model/map_model.py b/dzgui/model/map_model.py index 2083f76..42739cb 100644 --- a/dzgui/model/map_model.py +++ b/dzgui/model/map_model.py @@ -1,18 +1,18 @@ -import gi +from typing import TYPE_CHECKING +from dzgui.model.model_factory import ModelFactory from dzgui.util import strings from dzgui.util.strings import all_maps -gi.require_version("Gtk", "3.0") -from gi.repository.Gtk import ListStore # noqa E402 -from gi.repository import Gtk # noqa E402 +if TYPE_CHECKING: + from dzgui.model.model_factory import FastInsertListStore # TODO: rename class to MetaManager class MapManager: def __init__(self) -> None: - self.map_store = ListStore(str) + self.map_store = ModelFactory().make_map_store() self.prior_map: str self.selected_map = all_maps @@ -54,11 +54,11 @@ class MapManager: def set_filter(self, label: str, state: bool) -> None: self.enabled_filters[label] = state - def get_map_store(self) -> ListStore: + def get_map_store(self) -> "FastInsertListStore": return self.map_store def reinit_map_store(self) -> None: - model = ListStore(str) + model = ModelFactory().make_map_store() model.append([all_maps]) self.map_store = model self.selected_map = all_maps @@ -88,3 +88,7 @@ class MapManager: self.reinit_map_store() for m in maps: self.append_map([m]) + + # when switching views, just grab the map store, active keyword, active map, and selected checks + # for that view and apply them to filter panel outside of thread + # initialize proxyman with access to filterman diff --git a/dzgui/model/filtered_model.py b/dzgui/model/proxy_model.py similarity index 97% rename from dzgui/model/filtered_model.py rename to dzgui/model/proxy_model.py index ba3ccd2..33df8e6 100644 --- a/dzgui/model/filtered_model.py +++ b/dzgui/model/proxy_model.py @@ -17,13 +17,13 @@ if TYPE_CHECKING: from dzgui.controllers.emitter import Emitter -class FilteredModelManager: +class ProxyModelManager: """ Manages access to cached ListStore resources and performs filtering on behalf of atomic TreeViews, which share the same column structure. - A FilteredModelManager is attached to each ServerTreeView. + A ProxyModelManager is attached to each ServerTreeView. Raw data is cached before being packed into a ListStore, see get_control() Filtration creates a proxy of the TreeView's model, see get_proxy_model() @@ -282,3 +282,9 @@ class FilteredModelManager: self.ping_cache = {} # if full: # self.control_model = None + + def set_active_map(self, _map: str) -> None: + self.active_map = _map + + def get_active_map(self) -> str: + return self.active_map diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index c8ac7a2..c9887c5 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -24,7 +24,7 @@ API_TIMEOUT = 3 if TYPE_CHECKING: from dzgui.controllers.mc import Controller - from dzgui.model.filtered_model import FilteredModelManager + from dzgui.model.proxy_model import ProxyModelManager logger = logging.getLogger(__name__) @@ -46,7 +46,7 @@ class ServerModelManager: self.jobs = 1 # NOTE: store filter man for access inside thread - self.filter_man = tv.get_filter_man() + self.proxy_man = tv.get_proxy_man() # FIXME: change WaitDialog to use parent window only self.thread_man = ThreadingManager(parent=controller) @@ -195,8 +195,8 @@ class ServerModelManager: record = Servers.parse_json([res]) - filter_man = self._get_filter_man() - raw_model = filter_man.get_control() + proxy_man = self._get_proxy_man() + raw_model = proxy_man.get_control() fqip = Servers.response_to_fq_ip(res) config_man = self.controller.get_config_man() @@ -209,7 +209,7 @@ class ServerModelManager: raw_model.append(record[0]) # TODO: if all filters are already applied, strange behavior may occur # -> need to insert and update per current filters - filter_man.filter(FilterMode.INITIAL) + proxy_man.filter(FilterMode.INITIAL) self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_single_ip)) @@ -249,7 +249,7 @@ class ServerModelManager: self._dump_ips(ips) def _cleanup_single_ip(self) -> None: - proxy = self._get_filter_man().get_proxy_model() + proxy = self._get_proxy_man().get_proxy_model() self.tv.set_model(proxy) # TODO: if current tab != self.saved, add label @@ -307,7 +307,7 @@ class ServerModelManager: # FIXME: filterman calls GTK methods in thread # if mode == FilterMode.INITIAL: - manager = self._get_filter_man() + manager = self._get_proxy_man() manager.wipe_cache() manager.set_control(data) manager.filter(FilterMode.INITIAL) @@ -324,13 +324,13 @@ class ServerModelManager: def _get_new_maps(self) -> list[str]: return self.new_maps - def _get_filter_man(self) -> "FilteredModelManager": - return self.filter_man + def _get_proxy_man(self) -> "ProxyModelManager": + return self.proxy_man @call_on_thread(dialog.filtering) def refilter(self, mode: FilterMode, label: str) -> None: self.first_iteration = False - filter_man = self._get_filter_man() - filter_man.filter(mode, label) - self.to_insert = filter_man.get_proxy_model() + proxy_man = self._get_proxy_man() + proxy_man.filter(mode, label) + self.to_insert = proxy_man.get_proxy_model() self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_on_success)) diff --git a/dzgui/views/components/filter_panel.py b/dzgui/views/components/filter_panel.py index 38e9359..5ec8678 100644 --- a/dzgui/views/components/filter_panel.py +++ b/dzgui/views/components/filter_panel.py @@ -4,7 +4,6 @@ from typing import Literal, TYPE_CHECKING from dzgui.const.enum import FilterMode from dzgui.const.constants import EXPAND, NO_EXPAND, NO_FILL, NO_PADDING, SEARCH_ICON from dzgui.model.servers import ServerModelManager -from dzgui.util.margins import set_surrounding_margins from dzgui.views.components.labels import BoldLabel import gi @@ -128,12 +127,24 @@ class KeywordEntry(Gtk.Entry): class FilterPanel(Gtk.Box): def __init__(self, controller: "Controller") -> None: - super().__init__(spacing=6, vexpand=False, orientation=Gtk.Orientation.VERTICAL) + super().__init__( + spacing=6, + vexpand=False, + orientation=Gtk.Orientation.VERTICAL, + margin_top=1, + margin_bottom=10, + margin_left=10, + margin_right=10, + ) self.controller = controller self.controller.register_widget("filters", self) self.emitter = self.controller.get_emitter() + # TODO: strings + self.sel_map = "All maps" + + # TODO: each treeview for that tab context has its own filter manager, independent of this # self.selected_map: str = strings.all_maps # self.prior_map: str = strings.all_maps # self.set_orientation(Gtk.Orientation.VERTICAL) @@ -147,11 +158,6 @@ class FilterPanel(Gtk.Box): self.keyword_entry = KeywordEntry(self.controller) self.button_grid = ButtonGrid(self.controller, defaults) - # TODO: unintended legacy behavior? - self.connect("button-release-event", lambda *args: True) - set_surrounding_margins(self, 10) - self.set_margin_top(1) - # TODO: strings self.filters_label = BoldLabel("Filters") @@ -201,11 +207,13 @@ class FilterPanel(Gtk.Box): model = self.maps_combo.get_model() if text is None: return + if text == self.sel_map: + return for i, row in enumerate(model): if text == row[0]: self.maps_combo.set_active(i) - self._on_map_changed(self.maps_combo) - self.controller.set_active_map(i) + # self.controller.set_active_map(i) + # print("HERE3") def _on_maps_loaded(self, emitter: "Emitter", store: Gtk.ListStore) -> None: self.maps_combo.set_model(store) @@ -272,8 +280,8 @@ class FilterPanel(Gtk.Box): store = self.controller.get_map_store() if len(text) >= completion.get_minimum_key_length(): completion.set_model(store) - ind = self.get_active_combo() - self.controller.set_active_map(ind) + # ind = self.get_active_combo() + # self.controller.set_active_map(ind) def restore_focus_to_treeview(self) -> Literal[False]: view = self.controller.get_active_treeview() @@ -282,17 +290,17 @@ class FilterPanel(Gtk.Box): def _on_combo_keypress(self, combo: Gtk.ComboBox, event: Gdk.EventKey) -> bool: match event.keyval: - case Gdk.KEY_Down: + case Gdk.KEY_Down | Gdk.KEY_Up: self.maps_combo.popup() return True case _: return False - def get_active_combo(self) -> int: - return self.maps_combo.get_active() - - def set_active_combo(self, row: int) -> None: - self.maps_combo.set_active(row) + # def get_active_combo(self) -> int: + # return self.maps_combo.get_active() + # + # def set_active_combo(self, row: int) -> None: + # self.maps_combo.set_active(row) def toggle_check_by_key(self, emitter: "Emitter", keyval: int) -> bool: mappings = { @@ -322,16 +330,13 @@ class FilterPanel(Gtk.Box): check.set_active(not state) def _on_map_changed(self, combo: Gtk.ComboBox) -> None: - old_sel = self.controller.get_selected_map() - model = combo.get_model() - tree_iter = combo.get_active_iter() - if tree_iter is None: + ind = combo.get_active() + if ind < 0: return - selection = model[tree_iter][0] - if selection == old_sel: - return - if not selection: - return - self.maps_entry.set_text(selection) - logger.info(f"User selected map '{selection}'") + selection = self.maps_entry.get_text() + self.sel_map = selection self.emitter.emit("map_selection_changed", selection) + + tv = self.controller.get_active_treeview() + proxy_man = tv.get_proxy_man() + proxy_man.set_active_map(selection) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 20341b4..79f79b3 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -9,7 +9,7 @@ from dzgui.views.mixins.context_mixin import ContextMixin from dzgui.const.enum import ContextMenu, ContextMenuGroup, ServerTab from dzgui.api.servers import Record from dzgui.model.map_model import MapManager -from dzgui.model.filtered_model import FilteredModelManager +from dzgui.model.proxy_model import ProxyModelManager from dzgui.util.dist import CalcDist from dzgui.util import strings from typing import Literal, TYPE_CHECKING @@ -45,8 +45,8 @@ class ServerTreeView(ContextMixin, TreeView): self.loaded = False - self.filter_man = FilteredModelManager(controller) - model = self.filter_man.get_proxy_model() + self.proxy_man = ProxyModelManager(controller) + model = self.proxy_man.get_proxy_model() self.set_model(model) # NOTE: each tab context has its own unique maps @@ -132,8 +132,8 @@ class ServerTreeView(ContextMixin, TreeView): def get_map_man(self) -> MapManager: return self.map_man - def get_filter_man(self) -> FilteredModelManager: - return self.filter_man + def get_proxy_man(self) -> ProxyModelManager: + return self.proxy_man # def shrink_to_fit(self) -> None: # cols = self.get_columns() @@ -372,6 +372,6 @@ class ServerTreeView(ContextMixin, TreeView): return if row_index >= start[0] <= end[0]: # NOTE: fetch raw data rows - real_model = self.filter_man.get_control() + real_model = self.proxy_man.get_control() value = real_model[row_index][col_index] cell.set_property("text", str(value))