diff --git a/dzgui/api/servers.py b/dzgui/api/servers.py index 9a07193..f08c29b 100644 --- a/dzgui/api/servers.py +++ b/dzgui/api/servers.py @@ -1,5 +1,4 @@ import ipaddress -import json import logging import math import os @@ -23,6 +22,7 @@ import dayzquery logger = logging.getLogger(__name__) # TODO: confirm that patches from testing are incorporated here +# particularly around malformed values. check commit log params = [ r"\nor\1\map\chernarusplus\nor\1\map\sakhal\nor\1\map\enoch\empty\1\nor\1\map\namalsk", # noqa @@ -180,7 +180,7 @@ def parse_json(json: list) -> list: return rows -def query_direct(ip: str, qport: int, TIMEOUT: float=3.0) -> dict | None: +def query_direct(ip: str, qport: int, TIMEOUT: float = 3.0) -> dict | None: try: info = a2s.info((ip, qport), TIMEOUT) @@ -248,6 +248,7 @@ class Record: """ The gameport field is manipulated by the RowType.CONN_BY_IP method """ + ip: str gameport: int qport: int @@ -391,7 +392,7 @@ def ping(iteration: int, row: list) -> Ping: def query_api(key: str, appid: int, param: str) -> Res: LIMIT = 10000 payload: dict[str, Union[int, str]] = { - "filter": r"\appid" + fr"\{appid}" + param, + "filter": r"\appid" + rf"\{appid}" + param, "limit": LIMIT, "key": key, } @@ -401,7 +402,7 @@ def query_api(key: str, appid: int, param: str) -> Res: res.raise_for_status() parsed = True data = res.json() - except Exception as e: + except Exception: status = res.status_code parsed = False data = None @@ -435,6 +436,7 @@ def validate_ip(addr: str) -> Record: record = Record(ip, 0, qport) return record + def get_rules(ip: str, qport: int) -> list[int]: try: mods = dayzquery.dayz_rules((ip, int(qport))).mods diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 43641a1..3d16eec 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -92,7 +92,7 @@ class Controller: self.model_man = ModelManager() # TODO: poc - self.loaded = False + # self.loaded = False def register_widget(self, attr: str, widget: Gtk.Widget) -> None: try: @@ -231,9 +231,6 @@ class Controller: Gtk.main_quit() - def get_statusbar(self) -> str: - return self.mediator.statusbar.get_text() - @deprecated("use statusbar internal contexts") def remove_statusbar(self, context: str) -> None: c = self.mediator.statusbar.statusbar.get_context_id(context) @@ -264,6 +261,7 @@ class Controller: if haversine is None: dist = "Unknown" else: + # FIXME: always opens file; cache distance pref if self.query_config(Preferences.DIST) is True: raw = round(haversine.as_miles()) separated = number(raw) @@ -711,10 +709,9 @@ class Controller: def get_player_count(self) -> str: treeview = self.get_active_treeview() - context = treeview.get_enum() model = treeview.get_model() - status = format_player_count(model) - return status + count = format_player_count(model) + return count def get_statusbar(self) -> None: return self.mediator.statusbar @@ -777,3 +774,16 @@ class Controller: # TODO: deprecated in favor of map/unmap def toggle_lan_panel(self, state: bool) -> None: self.mediator.grid.conpan.set_visible(state) + + # TODO: use model manager, map and keyword caches + def get_filters(self) -> list: + self.mediator.filters.get_filters() + + def get_keyword(self) -> str: + self.mediator.filters.get_keyword_filter() + + def get_map(self) -> str: + self.mediator.filters.get_selected_map() + + def get_prio_map(self) -> str: + self.mediator.filters.get_prior_map() diff --git a/dzgui/model/filtered_model.py b/dzgui/model/filtered_model.py index 06010b5..b5a0f81 100644 --- a/dzgui/model/filtered_model.py +++ b/dzgui/model/filtered_model.py @@ -1,15 +1,20 @@ import re from dataclasses import dataclass -from typing import Self +from typing import TYPE_CHECKING from dzgui.const.enum import FilterMode 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 + + @dataclass(slots=True, frozen=True) class ServerColumns: name: str @@ -35,7 +40,8 @@ class FilteredModelManager: A FilteredModelManager is attached to each ServerTreeView. Filter methods are not thread-safe in themselves. """ - def __init__(self) -> None: + + def __init__(self, controller: "Controller") -> None: self.filter_cache: tuple self.ping_cache: dict[str, int] = {} @@ -63,13 +69,15 @@ class FilteredModelManager: Native Gtk.TreeView.refilter() method was not performant enough when running in the main loop with 40k+ records """ - filters = AppNav.right_panel.filters_vbox.get_filters() + filters = self.controller.get_filters() if filters in self.filter_cache: cache = self.filter_cache[filters] self.set_store(cache[0]) self.set_filtered(cache[1]) - GLib.idle_add(AppNav.treeview._filter_cleanup) + GLib.idle_add( + self.controller.mediator.get_active_treeview()._filter_cleanup + ) return match mode: @@ -77,8 +85,7 @@ class FilteredModelManager: rows = self.filter_initial(filters) case FilterMode.MAP: - panel = AppNav.right_panel.filters_vbox - prior_map = panel.get_prior_map() + prior_map = self.controller.get_prior_map() if prior_map == "All maps": rows = self.filter_map(filters) @@ -111,7 +118,7 @@ class FilteredModelManager: self.set_cache(filters, clone, rows) self.set_store(clone) - GLib.idle_add(AppNav.treeview._filter_cleanup) + GLib.idle_add(self.controller.mediator.get_active_treeview()._filter_cleanup) def sort_rows(self, rows: list) -> list: rows.sort(key=lambda x: re.sub(r"[^A-Za-z0-9]+", "", x[0].lower())) @@ -131,7 +138,7 @@ class FilteredModelManager: Multi-filtration for any context starts by narrowing by map """ rows = self.filtered - panel = AppNav.right_panel.filters_vbox + panel = self.controller.get_map() sel_map = panel.get_selected_map() if sel_map == "All maps": @@ -141,7 +148,7 @@ class FilteredModelManager: return rows def filter_keyword(self, filters: tuple) -> list: - keyword = AppNav.right_panel.filters_vbox.get_keyword_filter() + keyword = self.controller.get_keyword() rows = self.filtered if keyword == "": @@ -163,7 +170,7 @@ class FilteredModelManager: pairs = { strings.filter_3pp: strings.filter_1pp, strings.filter_day: strings.filter_night, - strings.filter_official: strings.filter_unofficial + strings.filter_official: strings.filter_unofficial, } for k, v in pairs.items(): if k in filters and v in filters: @@ -217,9 +224,7 @@ class FilteredModelManager: self.set_filtered(self.filter_toggle_off(filters, f)) return self.filtered - def set_cache( - self, filters: tuple, model: ListStore | None, rows: list - ) -> None: + def set_cache(self, filters: tuple, model: ListStore | None, rows: list) -> None: self.filter_cache[filters] = (model, rows) def resync_model(self, addr: str, qport: int) -> None: @@ -233,11 +238,11 @@ class FilteredModelManager: self.control_model.remove(row) self.wipe_cache() - filters = AppNav.right_panel.filters_vbox.get_filters() + filters = self.controller.get_filters() refiltered = self.filter_toggle_on(filters) self.set_filtered(refiltered) self.set_success(True) - GLib.idle_add(AppNav.treeview._filter_cleanup) + GLib.idle_add(self.controller.mediator.get_active_treeview()._filter_cleanup) def convert_model_to_list(self, model: ListStore) -> list: return [[el for el in row] for row in model] diff --git a/dzgui/views/components/statusbar.py b/dzgui/views/components/statusbar.py index b9e89c7..bd228e7 100644 --- a/dzgui/views/components/statusbar.py +++ b/dzgui/views/components/statusbar.py @@ -1,7 +1,7 @@ from warnings import deprecated from typing import Self, Union, TYPE_CHECKING -from dzgui.const.enum import NotebookPage, RowType +from dzgui.const.enum import NotebookPage, Preferences, RowType from dzgui.util import strings import gi diff --git a/dzgui/views/mixins/context_mixin.py b/dzgui/views/mixins/context_mixin.py index 7b37313..ca021bd 100644 --- a/dzgui/views/mixins/context_mixin.py +++ b/dzgui/views/mixins/context_mixin.py @@ -3,20 +3,23 @@ from dzgui.views.trees.tree_base import TreeView from dzgui.const.enum import ContextMenu import gi + gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 logger = logging.getLogger(__name__) + class ContextMixin(TreeView): - def present_menu(self, + def present_menu( + self, widget: Gtk.Widget, event: Gdk.EventButton | Gdk.EventKey, ) -> None: - #if self.is_selection_empty(): - # return + if self.is_selection_empty(): + return if event.type is Gdk.EventType.BUTTON_PRESS: try: diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 36bb31f..f940663 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -50,7 +50,7 @@ class ServerTreeView(TreeView): self.query_func: Callable = None self.filter_man = FilteredModelManager() - model = self.filter_man.get_model() + model = self.filter_man.get_model(controller) self.set_model(model) self.menu = Gtk.Menu()