diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 1bf179e..3870b8e 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -1,7 +1,6 @@ import logging import shutil import threading -import textwrap import traceback from pathlib import Path @@ -17,23 +16,16 @@ from dzgui.api.mods import ( get_local_mod_path, find_stale_mods, _hash, - remove_stale_signatures -) -from dzgui.const.enum import ( - Preferences, - Popup, - NotebookPage, - ButtonType, - ContextMenu, - RowType + remove_stale_signatures, ) +from dzgui.const.enum import Preferences, NotebookPage, ButtonType, ContextMenu, RowType from dzgui.const.constants import ( APPID_DAYZ, APPID_DAYZ_EXP, HEX_RED, WINDOW_DEFAULT_X, - WINDOW_DEFAULT_Y + WINDOW_DEFAULT_Y, ) from dzgui.config import update @@ -45,19 +37,20 @@ from dzgui.util.diag import write_diagnostic from dzgui.util._json import read_json, write_json from dzgui.util.localize import number from dzgui.util.open_links import open_workshop_page, open_user_workshop -from dzgui.util.format import format_mods, format_player_count, pluralize +from dzgui.util.format import format_mods, format_player_count from dzgui.util.redact import redact_log from dzgui.views.dialogs.filepicker import FilePicker -from dzgui.views.dialogs.generic import GenericDialog import gi + gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402 +from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402 logger = logging.getLogger(__name__) if TYPE_CHECKING: + from dzgui.const.enum import ServerTab from dzgui.util.dist import Haversine from dzgui.views.base import Notebook, Grid, OuterWindow from dzgui.views.components.buttonbox import ContextualButton @@ -65,12 +58,12 @@ if TYPE_CHECKING: from dzgui.views.components.right_panel import RightPanel from dzgui.views.components.statusbar import Statusbar from dzgui.views.pages.servers import ServerNotebook - from dzgui.views.trees.tree_base import TreeView from dzgui.views.trees.tree_log import LogTreeView from dzgui.views.trees.tree_menu import MenuTreeView from dzgui.views.trees.tree_mods import ModTreeView from dzgui.views.trees.tree_servers import ServerTreeView + class AppNavigation: window: "OuterWindow" grid: "Grid" @@ -80,16 +73,16 @@ class AppNavigation: modtreeview: "ModTreeView" menu: "MenuTreeView" servers: "ServerNotebook" - browser: "ServerTreeView" saved: "ServerTreeView" recent: "ServerTreeView" lan: "ServerTreeView" logtreeview: "LogTreeView" filters: "FilterPanel" + class Controller: def __init__(self) -> None: - self.dist_cache: dict[str, "Haversine"] = {} + self.dist_cache: dict[str, "Haversine", "ServerTab"] = {} self.crumbs_cache = "" self.mediator = AppNavigation() self.prefs: UserPrefs @@ -128,7 +121,8 @@ class Controller: def terminate_process(self) -> None: # TODO: only used by server table multiprocessing queue - self.mediator.notebook.servers.browser.terminate_process() + tv = self.get_active_treeview() + tv.terminate_process() def get_prefs(self) -> UserPrefs: return self.prefs @@ -165,7 +159,9 @@ class Controller: "_on_tree_selection_changed", state, ) - self.suppress_signal(self.mediator.menu, self.mediator.menu, "_on_keypress", state) + self.suppress_signal( + self.mediator.menu, self.mediator.menu, "_on_keypress", state + ) for check in self.mediator.filters.checks: self.suppress_signal( self.mediator.filters, @@ -184,7 +180,7 @@ class Controller: else: widget.handler_unblock_by_func(func) # TODO: deprecated? - #self.mediator.menu.sel_blocked = state + # self.mediator.menu.sel_blocked = state def toggle_debug_mode(self) -> None: self.toggle_config(Preferences.DEBUG) @@ -234,14 +230,22 @@ class Controller: def get_statusbar(self) -> str: return self.mediator.statusbar.get_text() - def set_statusbar(self, text: str) -> None: - self.mediator.statusbar.set_text(text) + def remove_statusbar(self, context: str) -> None: + c = self.mediator.statusbar.statusbar.get_context_id(context) + self.mediator.statusbar.statusbar.remove_all(c) + + def set_statusbar(self, text: str, context: str) -> None: + self.mediator.statusbar.set_text(text, context) def set_statusbar_placeholder(self, text: str) -> None: # TODO: use statusbar stacks instead self.statusbar_placeholder = text - def set_statusbar_dist(self, haversine: "Haversine") -> None: + def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None: + tv = self.get_active_treeview() + if tv.get_enum() != enum: + self.mediator.statusbar.spinner.stop() + return dist: str if haversine is None: dist = "Unknown" @@ -255,7 +259,8 @@ class Controller: separated = number(raw) dist = str(separated) + " km" text = self.statusbar_placeholder - self.set_statusbar(f"{text} | Distance: {dist}") + # TODO: abstract + self.set_statusbar(f"{text} | Distance: {dist}", "Servers") self.mediator.statusbar.spinner.stop() def delete_multiple_mods(self) -> None: @@ -328,7 +333,7 @@ class Controller: def show_developers_page(self) -> None: self.open_page(NotebookPage.DEVELOPERS) # TODO: put cursor on first row - #self.mediator.developers.focus_first_row() + # self.mediator.developers.focus_first_row() def open_page(self, page: NotebookPage) -> None: self.mediator.grid.notebook.set_page_by_enum(page) @@ -386,7 +391,9 @@ class Controller: open_workshop_page(mod, cmd) # TODO: put in model manager (dedicated manager for mod store) - def get_mod_from_tree_path(self, tree_path: Gtk.TreePath) -> tuple[str, Gtk.TreeIter]: + def get_mod_from_tree_path( + self, tree_path: Gtk.TreePath + ) -> tuple[str, Gtk.TreeIter]: model = self.model_man.get_mod_store() tree_iter = model.get_iter(tree_path) mod = model.get(tree_iter, 2)[0] @@ -403,7 +410,7 @@ class Controller: app_path = PeFile.get_nested_app_path(steam_path, APPID_DAYZ) md5 = _hash(mod) - symlink = app_path / md5 + symlink = app_path / md5 symlink.unlink() shutil.rmtree(mods_path / mod) @@ -419,15 +426,13 @@ class Controller: model = self.model_man.get_mod_store() model.remove(it) - def update_mod_statusbar(self) -> None: total_mods, total_size = self.calc_mod_size() msg = format_mods(total_size, total_mods) # TODO: combine - meta = self.mediator.statusbar.statusbar.get_context_id("Mods") - self.mediator.statusbar.statusbar.push(meta, msg) - #meta = self.mediator.statusbar.set_text(msg) - + # meta = self.mediator.statusbar.statusbar.get_context_id("Mods") + # self.mediator.statusbar.statusbar.push(meta, msg) + self.mediator.statusbar.set_text(msg, "Mods") def calc_mod_size(self) -> tuple[int, int]: model = self.model_man.get_mod_store() @@ -437,7 +442,6 @@ class Controller: total_size += mod[3] return total_mods, total_size - def menu_action(self, action: ContextMenu, path: Gtk.TreePath) -> None: match action: # NOTE: manipulates server stores @@ -470,14 +474,12 @@ class Controller: # Gtk.TreeModel, row-inserted/row-deleted self.update_mod_statusbar() remove_stale_signatures( - self.prefs.paths.config, - self.prefs.paths.version + self.prefs.paths.config, self.prefs.paths.version ) case ContextMenu.OPEN_WORKSHOP: self.open_mod_page(path) - def toggle_mod_selection(self, state: bool) -> None: sel = self.mediator.modtreeview.get_selection() if state: @@ -493,7 +495,9 @@ class Controller: # NOTE: this model is reloaded each time as log changes try: with open(log, "r") as f: - lines = [line.split(strings.delimiter) for line in f.read().splitlines()] + lines = [ + line.split(strings.delimiter) for line in f.read().splitlines() + ] for record in lines: clean = redact_log(record) store.append(clean) @@ -535,6 +539,7 @@ class Controller: def dump_test_1(self) -> None: import time + time.sleep(1) # TODO: use model managers, etc. self.data = ( @@ -561,6 +566,7 @@ class Controller: def dump_test_2(self) -> None: import time + time.sleep(1) # TODO: use model managers, etc. self.data = ( @@ -570,7 +576,7 @@ class Controller: self.get_func_data() self.destroy_on_idle() - def get_func_data(self): + def get_func_data(self) -> None: def test(): # NOTE: do not insert model until main thread is idle # TODO: grab from model manager and insert entire model @@ -580,6 +586,7 @@ class Controller: treeview.set_loaded(True) self.update_server_status() treeview.grab_focus() + treeview = self.get_active_treeview() manager = treeview.get_filter_man() @@ -591,6 +598,7 @@ class Controller: def call_on_thread(self, func: Callable, *args) -> None: from dzgui.views.dialogs.generic import WaitDialog + self.wait_dialog = WaitDialog(self, strings.dialog.fetching) self.wait_dialog.show_all() thread = threading.Thread(target=func, args=args) @@ -607,7 +615,7 @@ class Controller: Lets calling widgets register a callback function when spawning a threaded process """ - self.callback = { "func": callback, "args": args } + self.callback = {"func": callback, "args": args} def destroy_on_idle(self) -> None: self.wait_dialog.destroy() @@ -642,7 +650,6 @@ class Controller: dialog = ExceptionDialog(self, strings.api_error) dialog.run() - def update_api_key(self, text: str, key: Preferences) -> None: self.call_on_thread(self.test_api_response, text, key) @@ -688,13 +695,15 @@ class Controller: def update_server_status(self) -> None: # TODO: emit signal on statusbar only if page changed treeview = self.get_active_treeview() + context = str(treeview.enum) model = treeview.get_model() status = format_player_count(model) self.set_statusbar_placeholder(status) - self.set_statusbar(status) - self.mediator.statusbar.spinner.start() - if len(model) < 1: - self.mediator.statusbar.spinner.stop() + + self.set_statusbar(status, context) + if len(model) >= 1: + self.mediator.statusbar.spinner.start() + # self.mediator.statusbar.spinner.stop() def populate_model(self) -> None: treeview = self.get_active_treeview() @@ -718,8 +727,8 @@ class Controller: crumbs = self.mediator.servers.get_cached_label() self.set_crumbs(crumbs) # TODO: could emit this when treeview gains keyboard focus - #tree = self.get_active_treeview() - #tree.emit("on_distcalc_started") + # tree = self.get_active_treeview() + # tree.emit("on_distcalc_started") def toggle_check(self, event: Gdk.EventKey) -> None | Literal[False]: mappings = { @@ -739,7 +748,6 @@ class Controller: if event.keyval not in mappings: return False index = mappings[event.keyval] - # TODO: register filter panel widget self.mediator.filters.toggle_check(index) def get_favorite(self) -> tuple[str, str] | tuple[None, None]: diff --git a/dzgui/main.py b/dzgui/main.py index a2bcd57..de1124a 100644 --- a/dzgui/main.py +++ b/dzgui/main.py @@ -44,10 +44,12 @@ args = parser.parse_args() if TYPE_CHECKING: from pathlib import Path + # TODO: profile load time def make_parents(path: "Path") -> None: path.parent.mkdir(parents=True, exist_ok=True) + def uninstall() -> None: # TODO: uninstall data files (-u) # -u removes state, log, freedesktop @@ -56,6 +58,7 @@ def uninstall() -> None: # XDG_DATA_HOME/dzgui pass + def main() -> None: lock = lock_acquire() # noqa @@ -85,7 +88,9 @@ def main() -> None: migrate_cols_file(XDG.columns) copy_state_files(xdg_paths["XDG_STATE_HOME"]) - _format = "%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s" + _format = ( + "%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s" + ) logging.basicConfig(filename=XDG.debug, format=_format, level=logging.DEBUG) with open(XDG.debug, "w") as f: f.truncate(0) @@ -126,7 +131,7 @@ def main() -> None: local_coords, version, allow, - XDG + XDG, ) print("All OK. Loading UI...") App(prefs) diff --git a/dzgui/util/dist.py b/dzgui/util/dist.py index 1d6ed0c..70da21f 100644 --- a/dzgui/util/dist.py +++ b/dzgui/util/dist.py @@ -4,19 +4,20 @@ from math import radians, cos, sin, asin, sqrt from typing import TYPE_CHECKING from dzgui.util.ip import GeolocationError, get_coords -from dzgui.util.localize import number import gi + gi.require_version("Gtk", "3.0") from gi.repository import Gtk # noqa E402 if TYPE_CHECKING: - from dzgui.util.ip import Coords + from dzgui.const.enum import ServerTab from dzgui.controllers.mc import Controller logger = logging.getLogger(__name__) -class Haversine(): + +class Haversine: def __init__(self, lat1: float, lon1: float, lat2: float, lon2: float) -> None: R = 6371 * 1000 @@ -26,7 +27,7 @@ class Haversine(): lat1 = radians(lat1) lat2 = radians(lat2) - a = sin(dLat/2) ** 2 + cos(lat1) * cos(lat2) * sin(dLon/2) ** 2 + a = sin(dLat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dLon / 2) ** 2 c = 2 * asin(sqrt(a)) self.dist = R * c @@ -37,15 +38,18 @@ class Haversine(): def as_miles(self) -> float: return self.dist / 1609.344 + class CalcDist(multiprocessing.Process): def __init__( self, addr: str, + enum: "ServerTab", result_queue: multiprocessing.Queue, controller: "Controller", ) -> None: super().__init__() + self.enum = enum self.controller = controller self.result_queue = result_queue self.addr = addr @@ -55,11 +59,11 @@ class CalcDist(multiprocessing.Process): cache = self.controller.get_dist_cache() if self.addr in cache: logger.info(f"Address '{self.addr}' already in cache") - self.result_queue.put([self.addr, cache[self.addr]]) + self.result_queue.put([self.addr, cache[self.addr], self.enum]) return dist = self.compare(self.ip) - self.result_queue.put([self.addr, dist]) + self.result_queue.put([self.addr, dist, self.enum]) def compare(self, remote: str) -> int | None: prefs = self.controller.get_prefs() diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 3fbb341..fa407b6 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -1,13 +1,7 @@ import logging -#import multiprocessing import signal -#import threading -import typing # noqa import warnings -#from concurrent.futures import wait -#from concurrent.futures import ThreadPoolExecutor - from typing import TYPE_CHECKING, Literal from dzgui.const.enum import NotebookPage @@ -37,6 +31,7 @@ if TYPE_CHECKING: from dzgui.config.userprefs import UserPrefs import gi + gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 @@ -46,10 +41,10 @@ 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] = {} +# cache: dict[str, int] = {} ## TODO: move to configs/servers -#def query_history() -> list | None: +# def query_history() -> list | None: # history_file = MainController.get_prefs().paths.history # try: # with open(history_file, "r") as f: @@ -58,7 +53,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning) # rows = None # return rows # -#def process_tree_option(choice: RowType) -> None: +# def process_tree_option(choice: RowType) -> None: # # server tables # if command == RowType.RESOLVE_IP: # record = treeview.get_record() @@ -91,18 +86,18 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning) # return # ## TODO: belongs in model -#def str_to_record(record: str) -> Record | None: +# def str_to_record(record: str) -> Record | None: # r = record.split(":") # if len(r) != 3: # return None # return Record(r[0], int(r[1]), int(r[2])) # ## TODO: ibid -#def record_to_str(record: Record) -> str: +# def record_to_str(record: Record) -> str: # return f"{record.ip}:{record.gameport}:{record.qport}" # # -#def connect_by_ip(enum: RowType, response: str) -> None: +# def connect_by_ip(enum: RowType, response: str) -> None: # def _prep(response: str) -> None: # record = Servers.validate_ip(response) # proc = treeview.prepare_connection(record) @@ -114,7 +109,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning) # return # # -#def connect_by_id(enum: RowType, uid: str, key: str) -> None: +# def connect_by_id(enum: RowType, uid: str, key: str) -> None: # def _prep(key: str, response: str) -> None: # # TODO: if response is non numeric, raise dialog # if response.isnumeric() is False: @@ -139,6 +134,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning) # # + class OuterWindow(Gtk.Window): def __init__(self) -> None: super().__init__(title=APP_NAME, border_width=10, icon_name=APP_NAME_LOWER) @@ -168,9 +164,7 @@ class OuterWindow(Gtk.Window): MainController.loaded = True MainController.populate_model() - def _on_delete_event( - self, window: "OuterWindow", event: Gdk.EventKey - ) -> None: + def _on_delete_event(self, window: "OuterWindow", event: Gdk.EventKey) -> None: self.halt_proc_and_quit() def halt_proc_and_quit(self) -> None: @@ -316,7 +310,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore MainController.set_crumbs(crumbs) if status is False: - MainController.set_statusbar("") + MainController.set_statusbar("", "") if enum is NotebookPage.SERVERS: MainController.present_servers() @@ -351,8 +345,20 @@ class Grid(Gtk.Grid): els = ( (self.crumb_box, self.notebook, Gtk.PositionType.TOP, MAX_COLS, SINGLE_ROW), (self.conpan, self.notebook, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW), - (self.statusbar, self.conpan, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW), - (self.right_panel, self.notebook, Gtk.PositionType.RIGHT, SINGLE_COL, MAX_ROWS), + ( + self.statusbar, + self.conpan, + Gtk.PositionType.BOTTOM, + MAX_COLS, + SINGLE_ROW, + ), + ( + self.right_panel, + self.notebook, + Gtk.PositionType.RIGHT, + SINGLE_COL, + MAX_ROWS, + ), ) for el, sibling, pos, h_span, v_span in els: self.attach_next_to(el, sibling, pos, h_span, v_span) @@ -372,7 +378,7 @@ class Grid(Gtk.Grid): def toggle_refresh_button(self, state: bool) -> None: self.right_panel.refresh_button.set_visible(state) - # TODO make this method internal to Statusbar + # TODO: make this method internal to Statusbar def get_breadcrumbs(self) -> str: return self.breadcrumbs.get_text() @@ -397,9 +403,7 @@ class App(Gtk.Application): ) self.win.add_accel_group(accel) - GLib.unix_signal_add( - GLib.PRIORITY_DEFAULT, signal.SIGINT, self._catch_sigint - ) + GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._catch_sigint) Gtk.main() def _catch_sigint(self) -> Literal[True]: @@ -415,9 +419,11 @@ class App(Gtk.Application): ) -> None: self.win.halt_proc_and_quit() + MainController = Controller() # TODO: icon sanity check, log result -#theme = Gtk.IconTheme.get_default() -#icons = theme.list_icons(None) -#print("steam_tray_mono" in icons) +# theme = Gtk.IconTheme.get_default() +# icons = theme.list_icons(None) +# print("steam_tray_mono" in icons) +# FIXME: diff --git a/dzgui/views/components/buttons.py b/dzgui/views/components/buttons.py index 6a997c6..47e4803 100644 --- a/dzgui/views/components/buttons.py +++ b/dzgui/views/components/buttons.py @@ -93,6 +93,9 @@ class RefreshButton(IconTextButton): self.connect("clicked", self._on_refresh_clicked) def _on_refresh_clicked(self, button: Self) -> None: + # TODO: get page enum + print(self.controller.mediator.notebook.get_page_by_enum()) + # if .MODS, .LOG, .OPTIONS, reload in place self.set_sensitive(False) self.show_time(True) GLib.timeout_add_seconds(1, self.decrement) diff --git a/dzgui/views/components/eventbox.py b/dzgui/views/components/eventbox.py index aa607de..2294ba7 100644 --- a/dzgui/views/components/eventbox.py +++ b/dzgui/views/components/eventbox.py @@ -26,13 +26,14 @@ class InfoEventBox(Gtk.EventBox): self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing ) -> None: self.icon.set_opacity(1) - self.parent.controller.set_statusbar(self.text) + self.parent.controller.set_statusbar(self.text, "Options") def _on_leave_tooltip( self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing ) -> None: self.icon.set_opacity(0.8) - self.parent.controller.set_statusbar("") + #self.parent.controller.set_statusbar("", "Options") + self.parent.controller.remove_statusbar("Options") def set_text(self, text: str) -> None: self.text = text diff --git a/dzgui/views/components/statusbar.py b/dzgui/views/components/statusbar.py index 47a52ff..43524be 100644 --- a/dzgui/views/components/statusbar.py +++ b/dzgui/views/components/statusbar.py @@ -19,6 +19,7 @@ class Statusbar(Gtk.Grid): help_text = strings.statusbar_helptext + self.context: int self.statusbar = Gtk.Statusbar() self.spinner = Gtk.Spinner() @@ -31,7 +32,7 @@ class Statusbar(Gtk.Grid): self.attach_next_to(self.spinner, self.statusbar, Gtk.PositionType.RIGHT, 3, 1) self.attach_next_to(self.status_right_label, self.spinner, Gtk.PositionType.RIGHT, 3, 1) - self.set_text(help_text) + self.set_text(help_text, "Help") self.players = "" def get_text(self) -> str: @@ -39,20 +40,41 @@ class Statusbar(Gtk.Grid): label = area.get_children()[0] return label.get_text() - def set_text(self, string: str) -> None: - if string is None: - return - meta = self.statusbar.get_context_id("Statusbar") + def set_text(self, string: str, context: str) -> None: + # if string is None: + # return + meta = self.statusbar.get_context_id(context) + #tv = self.controller.get_active_treeview() + #cur_context = tv.get_enum() + #cid = self.get_context_by_enum(cur_context) + #if cid != meta: + # print("requested: ", meta) + # print("current: ", cid) + # return # TODO: substacks # get_context_id(ServerTab) self.statusbar.push(meta, string) + #self.set_context(meta) + + + # TODO: type checking + # def get_context_by_enum(self, context: "ServerTab") -> int: + # cid = self.statusbar.get_context_id(str(context)) + # # TODO: substacks + # return cid + # + # def get_context(self) -> int: + # return self.context + # + # def set_context(self, context: int) -> None: + # self.context = context def refresh(self, row: "RowType") -> None: if row is None: formatted = "" else: formatted = self.format_metadata(row) - self.set_text(formatted) + self.set_text(formatted, "Help") def append_distance(self, dist: str) -> None: # TODO: process strings in controller diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index e96f10f..ca065e4 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -78,6 +78,8 @@ class ServerNotebook(Gtk.ScrolledWindow): def _on_page_changed(self, notebook: Gtk.Notebook, child: Gtk.Widget, index: int) -> None: if self.controller.loaded is False: return + + # self.controller.remove_statusbar("Servers") # TODO: abstract label = self.notebook.get_tab_label_text(child) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index ab54f7b..3d00fb5 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -1,29 +1,24 @@ import logging import multiprocessing -import subprocess from typing import Self -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa - -from dzgui.const.enum import ( - ContextMenu, - ContextMenuGroup, - RowType, - ) -from dzgui.const.constants import UDP_PORT -from dzgui.const.enum import FilterMode, ServerTab +from dzgui.const.enum import ContextMenu, ContextMenuGroup, FilterMode, ServerTab from dzgui.api.servers import Record from dzgui.model.filtered_model import FilteredModelManager from dzgui.util.dist import CalcDist from dzgui.util.keys import is_navkey from dzgui.util import strings -from typing import Any, Callable, Literal, TYPE_CHECKING +from typing import Callable, Literal, TYPE_CHECKING from dzgui.views.trees.tree_base import TreeView import dzgui.util._json as JSON # noqa +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa + + logger = logging.getLogger(__name__) if TYPE_CHECKING: @@ -31,6 +26,7 @@ if TYPE_CHECKING: # TODO: restore missing methods + class EnumeratedMenuItem(Gtk.MenuItem): def __init__(self, enum: ContextMenu): super().__init__(label=enum.dict["label"]) @@ -38,10 +34,11 @@ class EnumeratedMenuItem(Gtk.MenuItem): class ServerTreeView(TreeView): - __gsignals__ = { - "on_distcalc_started": (GObject.SignalFlags.RUN_FIRST, None, ()) - } - def __init__(self, controller: "Controller", enum: ServerTab, menu: ContextMenuGroup) -> None: + __gsignals__ = {"on_distcalc_started": (GObject.SignalFlags.RUN_FIRST, None, ())} + + def __init__( + self, controller: "Controller", enum: ServerTab, menu: ContextMenuGroup + ) -> None: super().__init__(controller) QUEUE_CHECK_DELAY = 200 @@ -181,11 +178,11 @@ class ServerTreeView(TreeView): case Gdk.KEY_j: if ind == len(children) - 1: return True - menu.select_item(children[ind+1]) + menu.select_item(children[ind + 1]) case Gdk.KEY_k: if ind - 1 < 0: return True - menu.select_item(children[ind-1]) + menu.select_item(children[ind - 1]) case Gdk.KEY_g: menu.select_item(children[0]) case Gdk.KEY_G: @@ -207,15 +204,12 @@ class ServerTreeView(TreeView): """ Propagate width change to other tabs """ - title = col.get_title() - size = col.get_width() - # NOTE: get final width after drag action completes GLib.idle_add(self.controller.propagate_column_width, col) def terminate_process(self) -> None: - if self.current_proc and self.current_proc.is_alive(): - self.current_proc.terminate() + if self.current_proc and self.current_proc.is_alive(): + self.current_proc.terminate() def _on_distcalc_started(self, treeview: Self): record = self.get_record() @@ -223,8 +217,9 @@ class ServerTreeView(TreeView): return # TODO: self.controller.mediator.statusbar.spinner.start() - ip = record.ip - self.current_proc = CalcDist(record.ip, self.queue, self.controller) + self.current_proc = CalcDist( + record.ip, self.get_enum(), self.queue, self.controller + ) self.current_proc.start() def _check_result_queue(self) -> Literal[True]: @@ -235,13 +230,15 @@ class ServerTreeView(TreeView): latest_result = self.queue.get() cache = self.controller.get_dist_cache() + if latest_result: + # NOTE: if CalcDist was spawned on other tab addr = latest_result[0] haversine = latest_result[1] if addr not in cache: cache[addr] = haversine # FIXME - self.controller.set_statusbar_dist(haversine) + self.controller.set_statusbar_dist(haversine, self.get_enum()) return True def _on_server_keypress( @@ -308,7 +305,7 @@ class ServerTreeView(TreeView): mod_context_items = [ContextMenu.OPEN_WORKSHOP, ContextMenu.DELETE_MOD] # TODO: dynamic menu entries - #for row in items: + # for row in items: # if row == ContextMenu.ADD_SERVER: # if self.is_in_favs(): # row = ContextMenu.REMOVE_SERVER @@ -326,18 +323,14 @@ class ServerTreeView(TreeView): if event.type is Gdk.EventType.KEY_PRESS and event.keyval is Gdk.KEY_l: if self.is_selection_empty(): return - self.menu.popup_at_widget( - widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST - ) + self.menu.popup_at_widget(widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST) else: self.menu.popup_at_pointer(event) self.menu.select_first(False) - def _parent_row_activated(self, - tree: TreeView, - path: Gtk.TreePath, - column: Gtk.TreeViewColumn - ) -> None: + def _parent_row_activated( + self, tree: TreeView, path: Gtk.TreePath, column: Gtk.TreeViewColumn + ) -> None: # TODO: process server connection # TODO: get record print(self.get_value_at_index(0))