fix: reapply filters when map changed

This commit is contained in:
aclist 2026-03-04 11:36:30 +09:00
parent 3bb30887ca
commit 5391cdde1e
6 changed files with 39 additions and 59 deletions

View File

@ -551,6 +551,8 @@ class Controller(GObject.GObject):
if tv.is_loaded():
self.emitter.emit("servers_loaded", tv.get_enum())
return
# TODO: placeholder logic, wipe statusbar when changing page
self.mediator.statusbar.set_text("", "")
ServerModelManager(self, tv).load()
def get_dist_cache(self) -> dict[str, "Haversine", "ServerTab"]:
@ -586,17 +588,17 @@ class Controller(GObject.GObject):
return treeview.get_model() is not None
def _on_check_toggled(self, emitter: Emitter, label: str, state: bool) -> None:
print("check toggled, refiltering")
print("DEBUG: check toggled, refiltering")
filter_man = self.get_filter_man()
filter_man.set_filter(label, state)
mode = FilterMode.TOGGLE_ON if state else FilterMode.TOGGLE_OFF
ServerModelManager(self, self.get_active_treeview()).refilter(mode, label)
ServerModelManager(self, self.get_active_treeview()).refilter(mode)
def _on_map_selection_changed(self, emitter: Emitter, selection: str) -> None:
print("map sel changed, refiltering")
print("DEBUG: map sel changed, refiltering")
smm = ServerModelManager(self, self.get_active_treeview())
smm.refilter(FilterMode.MAP, selection)
smm.refilter(FilterMode.MAP)
def get_notebook(self) -> "Notebook":
return self.mediator.notebook

View File

@ -39,9 +39,6 @@ class FilterManager:
# def reinit_filters(self) -> None:
# self.enabled_filters = dict(self.default_filters)
def get_prior_map(self) -> str:
return self.prior_map
def set_prior_map(self, name: str) -> None:
self.prior_map = name
@ -79,9 +76,6 @@ class FilterManager:
self.map_store = model
self.active_map = (0, all_maps)
def get_prior_map(self) -> str:
return self.prior_map
def append_map(self, row: list[str]) -> None:
self.map_store.append(row)
@ -95,6 +89,9 @@ class FilterManager:
for m in maps:
self.append_map([m])
def get_unique_maps(self) -> list[str]:
return [row[0] for row in self.map_store]
def get_all_filters(self) -> tuple:
map_name = self.get_active_map_name()
enabled = self.get_filters()

View File

@ -7,15 +7,7 @@ from dzgui.const.enum import FilterMode
from dzgui.model.model_factory import ModelFactory
from dzgui.util import strings
# import gi
#
# gi.require_version("Gtk", "3.0")
# from gi.repository.Gtk import ListStore # noqa E402
# from gi.repository import GObject, GLib # noqa E402
if TYPE_CHECKING:
# from dzgui.controllers.mc import Controller
# from dzgui.controllers.emitter import Emitter
from dzgui.managers.filter_man import FilterManager
from dzgui.model.model_factory import FastInsertListStore
@ -33,9 +25,6 @@ class ProxyModelManager:
"""
def __init__(self, filter_man: "FilterManager") -> None:
# self.emitter = controller.get_emitter()
# self.emitter.connect("keyword_set", self._on_keyword_set)
self.filter_cache = {}
self.ping_cache: dict[str, int] = {}
@ -46,13 +35,6 @@ class ProxyModelManager:
self.filtered: list = None
self.success = True
# def get_keyword_filter(self) -> str:
# return self.keyword_filter
# def _on_keyword_set(self, emitter: "Emitter", keyword: str) -> None:
# self.keyword_filter = keyword
def append_row(self, row: list) -> None:
self.proxy_model.append(row)
@ -62,16 +44,14 @@ class ProxyModelManager:
def get_proxy_model(self) -> "FastInsertListStore":
return self.proxy_model
# def new_model_from_class(self, cls: type) -> ListStore:
# store = ListStore(*[ftype for field, ftype in cls.__annotations__.items()])
# return store
#
def filter(self, mode: FilterMode, *args, **kwargs) -> None:
print("proxy model filtering now")
# TODO: proxy model can fetch args directly from filter man, no need to process extra input
"""
Native Gtk.TreeView.refilter() method was not performant enough
when running in the main loop with 40k+ records
"""
# TODO: return a dataclass object with clearly enumerated map, keyword, and filter values
# instead of just a serial list of strings
filters = self.filter_man.get_all_filters()
if filters in self.filter_cache:
@ -84,24 +64,18 @@ class ProxyModelManager:
case FilterMode.INITIAL:
rows = self.filter_initial(filters)
case FilterMode.MAP:
prior_map = self.filter_man.get_prior_map()
if prior_map == strings.all_maps:
rows = self.filter_map(filters)
else:
rows = self.filter_toggle_on(filters, *args)
case FilterMode.KEYWORD:
rows = self.filter_toggle_on(filters, *args)
# TODO: consolidate into one enum
case FilterMode.MAP | FilterMode.KEYWORD | FilterMode.TOGGLE_ON:
rows = self.filter_toggle_on(filters)
case FilterMode.TOGGLE_OFF:
for f in filters[2:]:
self.set_filtered(self.filter_toggle_off(filters, f))
rows = self.filtered
case FilterMode.TOGGLE_ON:
rows = self.filter_toggle_on(filters, *args)
# case FilterMode.TOGGLE_ON:
# rows = self.filter_toggle_on(filters)
# # rows = self.filter_toggle_on(filters, *args)
# TODO: unimplemented
# just write pings into control model instead
@ -212,7 +186,7 @@ class ProxyModelManager:
rows = [row for row in rows if not row[11]]
return rows
def filter_toggle_on(self, filters: tuple, *args: str) -> list:
def filter_toggle_on(self, filters: tuple) -> list:
"""Effectively applies all filters"""
self.set_filtered(self.control_model)
self.set_filtered(self.filter_map(filters))
@ -222,7 +196,9 @@ class ProxyModelManager:
self.set_filtered(self.filter_toggle_off(filters, f))
return self.filtered
def set_cache(self, filters: tuple, model: Optional["FastInsertListStore"], rows: list) -> None:
def set_cache(
self, filters: tuple, model: Optional["FastInsertListStore"], rows: list
) -> None:
self.filter_cache[filters] = (model, rows)
def resync_model(self, addr: str, qport: int) -> None:

View File

@ -235,8 +235,11 @@ class ServerModelManager:
# for example, non-empty will only show up in empty because it is not cached
proxy_man.filter(FilterMode.INITIAL)
self._sort_unique_maps(records)
filter_man = self.tv.get_filter_man()
old_maps = filter_man.get_unique_maps()
cur_map = records[0][1]
if cur_map not in old_maps:
self._set_new_maps([cur_map])
self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_single_ip))
def _dump_history(self) -> None:
@ -280,9 +283,12 @@ class ServerModelManager:
# TODO: if current tab != self.saved, add label
self.emitter.emit("servers_loaded", self.enum)
# NOTE: adding a row may update available maps
# TODO: test this
self._update_maps()
# TODO: consolidate methods and handle multi/single map addition
filter_man = self.tv.get_filter_man()
filter_man.append_map(self._get_new_maps())
self.emitter.emit("servers_loaded_init")
self.first_iteration = False
def _update_maps(self) -> None:
filter_man = self.tv.get_filter_man()
@ -309,8 +315,6 @@ class ServerModelManager:
if self.first_iteration:
self._update_maps()
# def _cleanup_on_empty():
def _cleanup_on_failure(self, show_dialog=True) -> None:
# TODO: disable map, keyword, and filter widgets if model is None
# -> signal driven (servers_empty, servers_failed_to_load)
@ -348,7 +352,7 @@ class ServerModelManager:
def _sort_unique_maps(self, data: list) -> None:
u_maps = set([row[1] for row in data])
self._set_new_maps(u_maps)
self._set_new_maps(sorted(u_maps))
def _set_new_maps(self, maps: list[str]) -> None:
self.new_maps = maps
@ -360,10 +364,11 @@ class ServerModelManager:
return self.proxy_man
@call_on_thread(dialog.filtering)
def refilter(self, mode: FilterMode, label: str) -> None:
def refilter(self, mode: FilterMode) -> None:
# FIXME: causes two wait dialogs when map selection change signal emits after loading servers
self.first_iteration = False
proxy_man = self._get_proxy_man()
proxy_man.filter(mode, label)
proxy_man.filter(mode)
# proxy_man.filter(mode, label)
self.to_insert = proxy_man.get_proxy_model()
self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_on_success))

View File

@ -129,7 +129,7 @@ class KeywordEntry(Gtk.Entry):
ServerModelManager(
self.controller, self.controller.get_active_treeview()
).refilter(FilterMode.KEYWORD, keyword)
).refilter(FilterMode.KEYWORD)
class FilterPanel(Gtk.Box):

View File

@ -6,7 +6,7 @@ from dzgui.views.components.buttonbox import ButtonBox
from dzgui.views.components.filter_panel import FilterPanel
from dzgui.views.components.mod_panel import ModSelectionPanel
from dzgui.views.components.buttons import RefreshButton, KeysButton
from dzgui.const.constants import NO_EXPAND, NO_FILL, FILL, NO_PADDING, EXPAND
from dzgui.const.constants import NO_EXPAND, NO_FILL, FILL, NO_PADDING
import gi