diff --git a/dzgui/const/constants.py b/dzgui/const/constants.py index c3b586f..b98c8c9 100644 --- a/dzgui/const/constants.py +++ b/dzgui/const/constants.py @@ -4,7 +4,7 @@ UDP_PORT = 27016 VM_FILE = "/proc/sys/vm/max_map_count" MIN_COUNT = 1048576 -REQUEST_TIMEOUT = 3 +REQUEST_TIMEOUT = 1 APPNAME_DAYZ = "DayZ" APPNAME_DAYZ_EXP = "DayZ Experimental" diff --git a/dzgui/const/enum.py b/dzgui/const/enum.py index aa0dc9c..2c2ceed 100644 --- a/dzgui/const/enum.py +++ b/dzgui/const/enum.py @@ -435,3 +435,9 @@ HELP_MENU_ROWS = ( RowType.SEPARATOR, RowType.THANKS, ) + +class ServerTab(Enum): + BROWSER = 1 + SAVED = 2 + RECENT = 3 + LAN = 4 diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index a38ab75..9813734 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -652,7 +652,7 @@ class Controller: def populate_model(self) -> None: # TODO: always use same server model, store in servertreeview class - treeview = self.mediator.notebook.servers.get_active_treeview() + treeview = self.get_active_treeview() if treeview.get_loaded() is False: new_model = self.model_manager.new_model() # NOTE: set_query_func() @@ -671,13 +671,14 @@ class Controller: self.mediator.right_panel.focus_button_box() def present_servers(self) -> None: - tree = self.get_active_treeview() # TODO: abstract self.grab_active_treeview() self.update_server_status() crumbs = self.mediator.servers.get_cached_label() self.set_crumbs(crumbs) - tree.emit("on_distcalc_started") + # TODO: could emit this when treeview gains keyboard focus + #tree = self.get_active_treeview() + #tree.emit("on_distcalc_started") def toggle_check(self, event: Gdk.EventKey) -> None: keyname = Gdk.keyval_name(event.keyval) @@ -703,3 +704,6 @@ class Controller: def get_dist_cache(self) -> dict[str, "Haversine"]: return self.dist_cache + + def toggle_lan_panel(self, state: bool) -> None: + self.mediator.grid.conpan.set_visible(state) diff --git a/dzgui/init/update.py b/dzgui/init/update.py index 7449a61..f8c6c34 100644 --- a/dzgui/init/update.py +++ b/dzgui/init/update.py @@ -14,7 +14,8 @@ logger = logging.getLogger(__name__) def get_latest_release() -> str | None: tag = None - for url in [GITHUB_RELEASES, CODEBERG_RELEASES]: + # TODO: check order; github often has gateway errors + for url in [CODEBERG_RELEASES, GITHUB_RELEASES]: try: res = requests.get(url, timeout=REQUEST_TIMEOUT) if res.status_code == 200: diff --git a/dzgui/views/base.py b/dzgui/views/base.py index a1b5a13..3188e7b 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -217,6 +217,9 @@ class OuterWindow(Gtk.Window): css.load_css() MainController.open_page(NotebookPage.SERVERS) + # TODO: first run + MainController.mediator.grid.conpan.lan.set_visible(False) + self.grid.right_panel.sel_panel.hide() def _on_delete_event( self, window: "OuterWindow", event: Gdk.EventKey @@ -365,11 +368,11 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore status = enum.dict["statusbar"] MainController.set_crumbs(crumbs) - is_mods = True if enum is NotebookPage.MODS else False - is_servers = True if enum is NotebookPage.SERVERS else False - - MainController.toggle_mod_panel(is_mods) - MainController.toggle_server_panels(is_servers) + #is_mods = True if enum is NotebookPage.MODS else False + #is_servers = True if enum is NotebookPage.SERVERS else False + # TODO: use signals internal to servers.py + #MainController.toggle_mod_panel(is_mods) + #MainController.toggle_server_panels(is_servers) if status is False: MainController.set_statusbar("") diff --git a/dzgui/views/components/connect_panel.py b/dzgui/views/components/connect_panel.py index 7019ea0..d69b498 100644 --- a/dzgui/views/components/connect_panel.py +++ b/dzgui/views/components/connect_panel.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING from dzgui.api.servers import validate_ip +from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING from dzgui.util.css import add_class, remove_class from dzgui.util.strings import connect_panel from dzgui.views.components.buttons import WebButton @@ -13,10 +14,38 @@ from gi.repository import Gtk, Gdk # noqa E402 if TYPE_CHECKING: from dzgui.controllers.mc import Controller -class ConnectPanel(Gtk.Frame): +class LanPanel(Gtk.Frame): def __init__(self, controller: "Controller") -> None: super().__init__(margin_top=10, margin_bottom=5) + # TODO: use grid, more column spacing + # TODO: hide lan panel on other tabs + hbox = Gtk.Box(margin=10, spacing=5, halign=Gtk.Align.START) + # TODO: strings + label = BoldLabel("LAN query port") + radio1 = Gtk.RadioButton.new_with_label(None, "Default port (27016)") + radio2 = Gtk.RadioButton.new_from_widget(radio1) + radio2.set_label("Custom port") + self.entry = Gtk.Entry(placeholder_text="Query port") + self.button = Gtk.Button(label="Scan") + radio1.connect("toggled", self._on_radio_toggled) + hbox.pack_start(label, NO_EXPAND, NO_FILL, NO_PADDING) + hbox.pack_start(radio1, NO_EXPAND, NO_FILL, NO_PADDING) + hbox.pack_start(radio2, NO_EXPAND, NO_FILL, NO_PADDING) + hbox.pack_start(self.entry, NO_EXPAND, NO_FILL, NO_PADDING) + hbox.pack_start(self.button, NO_EXPAND, NO_FILL, NO_PADDING) + self.entry.set_sensitive(False) + self.button.set_sensitive(False) + self.add(hbox) + + def _on_radio_toggled(self, button: Gtk.RadioButton) -> None: + for el in self.entry, self.button: + el.set_sensitive(not button.get_active()) + +class ConnectPanel(Gtk.Box): + def __init__(self, controller: "Controller") -> None: + super().__init__(orientation=Gtk.Orientation.VERTICAL) + COLS = 1 ROWS = 1 self.classname = "invalid-entry" @@ -74,7 +103,14 @@ class ConnectPanel(Gtk.Frame): for el, sibling, pos, h_span, v_span in els: self.grid.attach_next_to(el, sibling, pos, h_span, v_span) - self.add(self.grid) + self.lan = LanPanel(self.controller) + self.add(self.lan) + + frame = Gtk.Frame(margin_top=10, margin_bottom=5) + frame.add(self.grid) + self.add(frame) + + self.lan.set_visible(False) def mark_valid(self) -> None: self.conn_server.set_sensitive(True) diff --git a/dzgui/views/pages/mods.py b/dzgui/views/pages/mods.py index 20e381f..77a76f4 100644 --- a/dzgui/views/pages/mods.py +++ b/dzgui/views/pages/mods.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import Self, TYPE_CHECKING from dzgui.views.trees.tree_mods import ModTreeView import gi @@ -17,3 +17,12 @@ class Mods(Gtk.ScrolledWindow): self.add(self.tree) self.controller.register_widget("modtreeview", self.tree) + + self.connect("map", self._on_map) + self.connect("unmap", self._on_unmap) + + def _on_unmap(self, widget: Self) -> None: + self.controller.toggle_mod_panel(False) + + def _on_map(self, widget: Self) -> None: + self.controller.toggle_mod_panel(True) diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index 89c5790..6a76d06 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -2,7 +2,7 @@ import logging from typing import Self, TYPE_CHECKING -from dzgui.const.enum import ContextMenuGroup +from dzgui.const.enum import ContextMenuGroup, ServerTab from dzgui.views.trees.tree_servers import ServerTreeView from dzgui.util.strings import server_labels @@ -24,10 +24,10 @@ class ServerNotebook(Gtk.ScrolledWindow): self.controller.register_widget("servers", self) self.notebook = Gtk.Notebook(show_tabs=True) - self.browser = ServerTreeView(controller) - self.saved = ServerTreeView(controller) - self.recent = ServerTreeView(controller) - self.lan = ServerTreeView(controller) + self.browser = ServerTreeView(controller, ServerTab.BROWSER) + self.saved = ServerTreeView(controller, ServerTab.SAVED) + self.recent = ServerTreeView(controller, ServerTab.RECENT) + self.lan = ServerTreeView(controller, ServerTab.LAN) self.lan.set_query_func(self.query_test) # TODO: set context menu on init @@ -50,7 +50,6 @@ class ServerNotebook(Gtk.ScrolledWindow): store = func() if label == "LAN": pass - #store.append(["BAR", "a", "a", "a", 1, 1, 1, "1:1", 0, 0, "a", False]) else: store.append(["BAR", "a", "a", "a", 0, 0, 0, "189.127.165.207:2302", 0, 0, "a", False]) store.append(["BAR", "a", "a", "a", 0, 0, 0, "189.127.165.207:2302", 0, 0, "a", False]) @@ -79,6 +78,14 @@ class ServerNotebook(Gtk.ScrolledWindow): self.add(self.notebook) self.notebook.connect_after("switch-page", self._on_page_changed) self.connect("key-press-event", self._on_keypress) + self.connect("map", self._on_map) + self.connect("unmap", self._on_unmap) + + def _on_map(self, widget: Self) -> None: + self.controller.toggle_server_panels(True) + + def _on_unmap(self, widget: Self) -> None: + self.controller.toggle_server_panels(False) def _on_keypress(self, widget: Self, event: Gdk.EventKey) -> None: @@ -94,7 +101,6 @@ class ServerNotebook(Gtk.ScrolledWindow): def _on_page_changed(self, notebook: Gtk.Notebook, child: Gtk.Widget, index: int) -> None: # TODO: abstract - # TODO: load on first run label = self.notebook.get_tab_label_text(child) if label is None: return @@ -105,20 +111,28 @@ class ServerNotebook(Gtk.ScrolledWindow): # TODO: strings string = f"Servers > {text}" self.controller.set_crumbs(string) - self.tab_cache = string + self.set_cached_label(string) - child.grab_focus() - - # FIXME: doesn't fire on first run - #self.controller.update_server_status() self.controller.present_servers() self.controller.populate_model() + # TODO: start with lan panel hidden + # FIXME: grid conpan is not set up at init + # TODO: refresh button only usable if LAN has servers? + # or just remove it + #if self.get_active_treeview() is self.lan: + # self.controller.mediator.grid.conpan.lan.set_visible(True) + #else: + # self.controller.mediator.grid.conpan.lan.set_visible(False) + # TODO: put in controller def query_test(self) -> None: data = (["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False]) return data + def set_cached_label(self, label: str) -> None: + self.tab_cache = label + def get_cached_label(self) -> str: return self.tab_cache diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 55ea5fb..d70aba8 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -12,6 +12,7 @@ from dzgui.const.enum import ( RowType, ) from dzgui.const.constants import UDP_PORT +from dzgui.const.enum import ServerTab from dzgui.api.servers import Record from dzgui.util.dist import CalcDist from dzgui.util.keys import is_navkey @@ -40,11 +41,12 @@ class ServerTreeView(TreeView): __gsignals__ = { "on_distcalc_started": (GObject.SignalFlags.RUN_FIRST, None, ()) } - def __init__(self, controller: "Controller") -> None: + def __init__(self, controller: "Controller", enum: ServerTab) -> None: super().__init__(controller) QUEUE_CHECK_DELAY = 200 + self.enum = enum self.loaded = False self.query_func: Callable = None @@ -97,9 +99,28 @@ class ServerTreeView(TreeView): self.connect("key-press-event", self._on_server_keypress) self.connect("generic_row_activated", self._parent_row_activated) self.connect("generic_treesel_changed", self._parent_selection_changed) + self.connect("map", self._on_map) + self.connect("unmap", self._on_unmap) + + self.connect("focus-in-event", self._on_kb_focus) GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue) + def _on_kb_focus(self, a, b) -> None: + self.emit("on_distcalc_started") + + def get_enum(self) -> None: + return self.enum + + def _on_map(self, a) -> None: + if self.get_enum() is ServerTab.LAN: + self.controller.mediator.grid.conpan.lan.set_visible(True) + + def _on_unmap(self, a) -> None: + # TODO: could be done just when changing pages? + if self.get_enum() is ServerTab.LAN: + self.controller.mediator.grid.conpan.lan.set_visible(False) + def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None: if not is_navkey(event.keyval): return False