From 24125a74920b23647ac26297d77ae94cee3b073e Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Fri, 13 Feb 2026 00:59:13 +0900 Subject: [PATCH] feat: update fav server dynamically --- CHANGELOG.md | 1 + dzgui/api/servers.py | 2 + dzgui/const/enum.py | 30 ++--- dzgui/controllers/emitter.py | 4 + dzgui/controllers/mc.py | 44 ++++--- dzgui/data/CHANGELOG.md | 1 + dzgui/model/misc_model.py | 13 +- dzgui/util/strings.py | 2 + dzgui/views/components/buttons.py | 18 +-- dzgui/views/components/connect_panel.py | 24 ++-- dzgui/views/components/crumbs.py | 7 +- dzgui/views/components/filter_panel.py | 3 +- dzgui/views/components/mod_panel.py | 3 + dzgui/views/dialogs/generic.py | 10 +- dzgui/views/dialogs/lan.py | 153 ------------------------ dzgui/views/mixins/context_mixin.py | 3 +- dzgui/views/pages/servers.py | 1 - dzgui/views/trees/tree_base.py | 31 +++-- dzgui/views/trees/tree_servers.py | 8 +- 19 files changed, 127 insertions(+), 231 deletions(-) delete mode 100644 dzgui/views/dialogs/lan.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e292e4..83ca4b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - Boldface breadcrumbs - Bold labels inside frames - Unsticky keys when clicking sidebar +- Copy IP copies IP:queryport only instead of IP:gameport:queryport, mimics syntax needed by add by ip method ## Fixed - Longstanding issue with left clicks not registering as tree selection changes after spamming keyboard input diff --git a/dzgui/api/servers.py b/dzgui/api/servers.py index f2a3aaf..a643bea 100644 --- a/dzgui/api/servers.py +++ b/dzgui/api/servers.py @@ -389,6 +389,8 @@ def ping(iteration: int, row: list) -> Ping: def query_api(key: str, appid: int, param: str) -> Res: + import time + LIMIT = 10000 payload: dict[str, Union[int, str]] = { "filter": r"\appid" + rf"\{appid}" + param, diff --git a/dzgui/const/enum.py b/dzgui/const/enum.py index 490317a..d5b50a0 100644 --- a/dzgui/const/enum.py +++ b/dzgui/const/enum.py @@ -209,20 +209,20 @@ class RowType(EnumWithAttrs): # TODO: rename to ContextItem class ContextMenu(EnumWithAttrs): - ADD_SERVER = {"label": strings.add} - ADD_FAV = {"label": strings.add_fav} - REMOVE_SERVER = {"label": strings.remove} - COPY_NAME = {"label": strings.copy_name} - COPY_CLIPBOARD = {"label": strings.copy_ip} ADD_NOTE = {"label": strings.add_note} - SHOW_MODS = {"label": strings.show_mods} - SHOW_DETAILS = {"label": strings.show_details} + ADD_SERVER = {"label": strings.add} + CONNECT = {"label": strings.connect} + COPY_CLIPBOARD = {"label": strings.copy_ip} + COPY_LOG_CLIPBOARD = {"label": strings.copy_log} + COPY_NAME = {"label": strings.copy_name} + DELETE_MOD = {"label": strings.delete_mod} + OPEN_WORKSHOP = {"label": strings.open_workshop} REFRESH_PLAYERS = {"label": strings.refresh_players} REMOVE_HISTORY = {"label": strings.remove_history} - OPEN_WORKSHOP = {"label": strings.open_workshop} - DELETE_MOD = {"label": strings.delete_mod} - COPY_LOG_CLIPBOARD = {"label": strings.copy_log} - CONNECT = {"label": strings.connect} + REMOVE_SERVER = {"label": strings.remove} + SET_FAV = {"label": strings.add_fav} + SHOW_DETAILS = {"label": strings.show_details} + SHOW_MODS = {"label": strings.show_mods} class ContextMenuGroup(Enum): @@ -235,7 +235,7 @@ class ContextMenuGroup(Enum): SERVER_BROWSER = ( ContextMenu.CONNECT, ContextMenu.ADD_SERVER, - ContextMenu.ADD_FAV, + ContextMenu.SET_FAV, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, ContextMenu.ADD_NOTE, @@ -245,7 +245,7 @@ class ContextMenuGroup(Enum): ) SCAN_LAN = ( ContextMenu.CONNECT, - ContextMenu.ADD_FAV, + ContextMenu.SET_FAV, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, ContextMenu.ADD_NOTE, @@ -255,7 +255,7 @@ class ContextMenuGroup(Enum): ) SAVED = ( ContextMenu.CONNECT, - ContextMenu.ADD_FAV, + ContextMenu.SET_FAV, ContextMenu.REMOVE_SERVER, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, @@ -267,7 +267,7 @@ class ContextMenuGroup(Enum): RECENT = ( ContextMenu.CONNECT, ContextMenu.ADD_SERVER, - ContextMenu.ADD_FAV, + ContextMenu.SET_FAV, ContextMenu.REMOVE_HISTORY, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, diff --git a/dzgui/controllers/emitter.py b/dzgui/controllers/emitter.py index ee43b00..8c15495 100644 --- a/dzgui/controllers/emitter.py +++ b/dzgui/controllers/emitter.py @@ -41,6 +41,10 @@ class Emitter(GObject.GObject): """User invoked right movement keybinding from ServerTreeView""" pass + @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(str, str)) + def fav_server_changed(self, name: str, addr: str) -> None: + """Change favorite server via context menu""" + @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(int,)) def check_button_pressed(self, keyval: int) -> None: """User toggled filter panel check button via keyboard""" diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index b047d1f..c2cdcb5 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -359,7 +359,8 @@ class Controller(GObject.GObject): # TODO: reload using refresh button, rather than on demand? self.load_mods() - self.mediator.notebook.set_page_by_enum(button.opens) + self.open_page(button.opens) + #self.mediator.notebook.set_page_by_enum(button.opens) def dump_api(self) -> None: self.first_iteration = True @@ -443,23 +444,22 @@ class Controller(GObject.GObject): self.clipboard.set_text(text, -1) def open_mod_page(self, path: Gtk.TreePath) -> None: - mod, it = self.get_mod_from_tree_path(path) + mod, it = self.model_man.get_mod_from_tree_path(path) cmd = self.query_config(Preferences.CLIENT) 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]: - model = self.model_man.get_mod_store() - tree_iter = model.get_iter(tree_path) - mod = model.get(tree_iter, 2)[0] - return mod, tree_iter + #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] + # return mod, tree_iter def delete_single_mod(self, tree_path: Gtk.TreePath) -> None: config = self.prefs.paths.config - - mod, it = self.get_mod_from_tree_path(tree_path) + mod, it = self.model_man.get_mod_from_tree_path(tree_path) path = lookup(config, Preferences.DEFAULT) steam_path = Path(path) @@ -502,8 +502,6 @@ class Controller(GObject.GObject): # TODO: unimplemented case ContextMenu.ADD_SERVER: pass - case ContextMenu.ADD_FAV: - pass case ContextMenu.ADD_NOTE: pass case ContextMenu.COPY_CLIPBOARD: @@ -516,6 +514,17 @@ class Controller(GObject.GObject): pass case ContextMenu.REMOVE_SERVER: pass + case ContextMenu.SET_FAV: + treeview = self.get_active_treeview() + name = treeview.get_value_at_index(0) + record = treeview.get_record_string() + + self.update_config(Preferences.FAV_LBL, name) + self.update_config(Preferences.FAV_SRV, record) + # TODO: consider a failure dialog here + + simple_ip = treeview.get_simplified_ip() + self.emitter.emit("fav_server_changed", name, simple_ip) case ContextMenu.SHOW_DETAILS: pass case ContextMenu.SHOW_MODS: @@ -611,6 +620,8 @@ class Controller(GObject.GObject): ) self.push_data(data, FilterMode.INITIAL, success=True) + # TODO: eg cleanup on failure, cleanup on sucess + # separate methods def cleanup(self) -> None: treeview = self.get_active_treeview() @@ -759,7 +770,7 @@ class Controller(GObject.GObject): return self.mediator.statusbar @call_on_thread - def thread_data_func(self, func: Callable) -> None: + def run_query_func(self, func: Callable) -> None: func() @call_on_thread @@ -789,12 +800,11 @@ class Controller(GObject.GObject): if func is None: self.emitter.emit("servers_loaded", treeview.get_enum()) return - # TODO: on legacy version, model clearing happens in thread - # (compare) + # TODO: # manager = treeview.get_filter_man() # manager.clear_model() self.set_callback(None, None) - self.thread_data_func(func) + self.run_query_func(func) def get_favorite(self) -> tuple[str, str] | tuple[None, None]: fav = str(self.query_config(Preferences.FAV_LBL)) diff --git a/dzgui/data/CHANGELOG.md b/dzgui/data/CHANGELOG.md index 8e292e4..83ca4b5 100644 --- a/dzgui/data/CHANGELOG.md +++ b/dzgui/data/CHANGELOG.md @@ -28,6 +28,7 @@ - Boldface breadcrumbs - Bold labels inside frames - Unsticky keys when clicking sidebar +- Copy IP copies IP:queryport only instead of IP:gameport:queryport, mimics syntax needed by add by ip method ## Fixed - Longstanding issue with left clicks not registering as tree selection changes after spamming keyboard input diff --git a/dzgui/model/misc_model.py b/dzgui/model/misc_model.py index 4646514..08b6978 100644 --- a/dzgui/model/misc_model.py +++ b/dzgui/model/misc_model.py @@ -2,9 +2,11 @@ from dataclasses import dataclass from dzgui.const.enum import HELP_MENU_ROWS import gi + gi.require_version("Gtk", "3.0") from gi.repository.Gtk import ListStore # noqa E402 -from gi.repository import GObject, GLib # noqa E402 +from gi.repository import GLib, GObject, Gtk # noqa E402 + @dataclass(slots=True, frozen=True) class ModCols: @@ -40,6 +42,7 @@ class ModelManager: """ Manager for miscellaneous ListStores """ + def __init__(self) -> None: self.map_store = ListStore(str) @@ -77,3 +80,11 @@ class ModelManager: def append_map(self, row: list) -> None: self.map_store.append(row) + + def get_mod_from_tree_path( + self, tree_path: Gtk.TreePath + ) -> tuple[str, Gtk.TreeIter]: + model = self.get_mod_store() + tree_iter = model.get_iter(tree_path) + mod = model.get(tree_iter, 2)[0] + return mod, tree_iter diff --git a/dzgui/util/strings.py b/dzgui/util/strings.py index b94eb7c..f53a695 100644 --- a/dzgui/util/strings.py +++ b/dzgui/util/strings.py @@ -268,6 +268,7 @@ class Crumbs: servers: str thanks: str developers: str + default: str @dataclass(slots=True, frozen=True) @@ -453,6 +454,7 @@ crumbs = Crumbs( servers="Servers > Server browser", thanks="Help > Special thanks", developers="Options > Developers", + default="Servers > ", ) checkmark = "✓" diff --git a/dzgui/views/components/buttons.py b/dzgui/views/components/buttons.py index 47e4803..afd72f2 100644 --- a/dzgui/views/components/buttons.py +++ b/dzgui/views/components/buttons.py @@ -1,4 +1,4 @@ -from typing import Literal, Self, TYPE_CHECKING +from typing import Callable, Literal, Self, TYPE_CHECKING from dzgui.util.strings import atomic_buttons, connect_panel from dzgui.const.constants import ( @@ -11,6 +11,7 @@ from dzgui.const.constants import ( ) import gi + gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib # noqa E402 @@ -21,7 +22,8 @@ if TYPE_CHECKING: class Icon(Gtk.Image): def __init__(self, name: str, l_margin: int = 0) -> None: - super().__init__(icon_name=name, + super().__init__( + icon_name=name, icon_size=Gtk.IconSize.BUTTON, margin_start=l_margin, ypad=2, @@ -30,9 +32,8 @@ class Icon(Gtk.Image): class LargeIcon(Gtk.Image): def __init__(self, name: str, l_margin: int = 5) -> None: - super().__init__(icon_name=name, - icon_size=Gtk.IconSize.LARGE_TOOLBAR, - margin_start=l_margin + super().__init__( + icon_name=name, icon_size=Gtk.IconSize.LARGE_TOOLBAR, margin_start=l_margin ) @@ -59,14 +60,15 @@ class LargeIconTextButton(IconButton): class ClipboardButton(IconTextButton): - def __init__(self, controller: "Controller", data: str) -> None: + def __init__(self, controller: "Controller", func: Callable) -> None: super().__init__(CLIPBOARD, atomic_buttons.copy) self.controller = controller - self.connect("clicked", self._on_button_clicked, data) + self.connect("clicked", self._on_button_clicked, func) self.set_tooltip_text("Copy IP to clipboard") - def _on_button_clicked(self, button: Self, data: str) -> None: + def _on_button_clicked(self, button: Self, func: Callable) -> None: + data = func() self.controller.copy_clipboard(data) diff --git a/dzgui/views/components/connect_panel.py b/dzgui/views/components/connect_panel.py index 4bdcb08..10f1db9 100644 --- a/dzgui/views/components/connect_panel.py +++ b/dzgui/views/components/connect_panel.py @@ -73,12 +73,14 @@ class FavPanel(Gtk.Frame): self.set_label_widget(label) self.controller = controller + emitter = self.controller.get_emitter() + emitter.connect("fav_server_changed", self._on_fav_server_changed) # TODO: improve upon this, cache fav ip when changed globally - user_fav, self.fav_ip = self.controller.get_favorite() + self.server_name, self.server_ip = self.controller.get_favorite() server_name = ( - f"{user_fav} ({self.fav_ip})" - if user_fav is not None + f"{self.server_name} ({self.server_ip})" + if self.server_name is not None else connect_panel.no_fav ) self.fav_label = Gtk.Label( @@ -94,9 +96,8 @@ class FavPanel(Gtk.Frame): self.fav_button = SteamConnectButton() if server_name is None: self.fav_button.set_sensitive(False) - copy = ClipboardButton(self.controller, self.get_fav_ip()) + copy = ClipboardButton(self.controller, self.get_fav_ip) - # FIXME: height of connect buttons is not equivalent grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5) grid.attach(scrollable_label, 0, 0, 3, ROWS) grid.attach_next_to(copy, scrollable_label, Gtk.PositionType.RIGHT, COLS, ROWS) @@ -105,11 +106,16 @@ class FavPanel(Gtk.Frame): self.add(grid) def get_fav_ip(self) -> str: - return self.fav_ip + return self.server_ip - def set_fav_label(self, text: str) -> None: - # TODO: called by controller when changing fav - self.fav_label.set_text(text) + from dzgui.api.servers import Record + + def _on_fav_server_changed( + self, emitter: "Emitter", name: str, record: str + ) -> None: + self.server_name = name + self.server_ip = record + self.fav_label.set_text(f"{name} ({record})") class AddPanel(Gtk.Frame): diff --git a/dzgui/views/components/crumbs.py b/dzgui/views/components/crumbs.py index cd83488..63c16f2 100644 --- a/dzgui/views/components/crumbs.py +++ b/dzgui/views/components/crumbs.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING from dzgui.const.enum import NotebookPage -from dzgui.util.strings import label_main_menu +from dzgui.util.strings import label_main_menu, crumbs from dzgui.util.format import embolden import gi @@ -43,9 +43,8 @@ class Breadcrumbs(Gtk.Label): crumbs = enum.dict["crumbs"] self.set_crumbs(crumbs) - def set_server_crumbs(self, crumbs: str) -> None: - # TODO: strings - self.set_crumbs("Servers > " + crumbs) + def set_server_crumbs(self, suffix: str) -> None: + self.set_crumbs(crumbs.default + suffix) def set_crumbs(self, crumbs: str) -> None: text = embolden(crumbs) diff --git a/dzgui/views/components/filter_panel.py b/dzgui/views/components/filter_panel.py index 0e12fc1..bd80573 100644 --- a/dzgui/views/components/filter_panel.py +++ b/dzgui/views/components/filter_panel.py @@ -149,7 +149,8 @@ class FilterPanel(Gtk.Box): filters.append(k) return tuple(filters) - # TODO: currently unused + # TODO: should be used when switching ServerTab contexts + # use signals here # def reinit_panel(self) -> None: # self.keyword_entry.set_text("") # self.keyword_filter = "" diff --git a/dzgui/views/components/mod_panel.py b/dzgui/views/components/mod_panel.py index 0704136..9f6fbae 100644 --- a/dzgui/views/components/mod_panel.py +++ b/dzgui/views/components/mod_panel.py @@ -64,6 +64,8 @@ class ModSelectionPanel(Gtk.Box): self.set_visible(state) def after_colorize(self) -> None: + # TODO: split into signal that touches two widgets, + # modtreeview and this widget self.controller.unselect_all_mods() self.swap_sensitive(True) @@ -77,6 +79,7 @@ class ModSelectionPanel(Gtk.Box): def _on_button_clicked(self, button: EnumeratedModButton) -> None: match button.enum: case ModButton.SELECT_ALL: + # TODO: signals self.controller.toggle_mod_selection(True) case ModButton.UNSELECT_ALL: self.controller.toggle_mod_selection(False) diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index ef91879..6e704fc 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -75,6 +75,7 @@ class ConfirmationDialog(GenericDialog): secondary=secondary, ) + class IgnoreDialog(GenericDialog): def __init__(self, controller: "Controller", secondary: str): super().__init__( @@ -88,7 +89,6 @@ class IgnoreDialog(GenericDialog): cancel.set_label("Ignore") - class NotifyDialog(GenericDialog): def __init__(self, controller: "Controller", secondary: str): super().__init__( @@ -169,6 +169,7 @@ class ExceptionDialog(GenericDialog): secondary=strings.something_wrong, ) + self.trace = trace # NOTE: box expands to end of content area scrollable = Gtk.ScrolledWindow( propagate_natural_height=True, max_content_height=500 @@ -177,7 +178,7 @@ class ExceptionDialog(GenericDialog): textview = Gtk.TextView( wrap_mode=Gtk.WrapMode.WORD, editable=False, left_margin=10, right_margin=10 ) - textview.set_buffer(Gtk.TextBuffer(text=trace)) + textview.set_buffer(Gtk.TextBuffer(text=self.trace)) box.pack_start(textview, EXPAND, FILL, 10) scrollable.add(box) @@ -186,7 +187,7 @@ class ExceptionDialog(GenericDialog): # FIXME: padding around top of content area when traceback is long content.add(scrollable) - copy_button = ClipboardButton(controller, trace) + copy_button = ClipboardButton(controller, self.get_trace) self.add_action_widget(copy_button, Gtk.ResponseType.NONE) self.add_button("OK", Gtk.ResponseType.OK) @@ -194,6 +195,9 @@ class ExceptionDialog(GenericDialog): self.action_area.get_children()[1].grab_focus() self.connect("response", self._on_response) + def get_trace(self) -> str: + return self.trace + def _on_response( self, dialog: Self, response: Gtk.ResponseType ) -> None | Literal[True]: diff --git a/dzgui/views/dialogs/lan.py b/dzgui/views/dialogs/lan.py deleted file mode 100644 index dd061e1..0000000 --- a/dzgui/views/dialogs/lan.py +++ /dev/null @@ -1,153 +0,0 @@ -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.constants import NO_EXPAND, NO_FILL, NO_PADDING -from dzgui.util.import strings - -class LanDialog(Gtk.MessageDialog): - """ - Performs integer validation on the provided port - and blocks if out of range. Returns None if user cancels - """ - def __init__(self) -> None: - super().__init__( - transient_for=AppNav.window, #FIXME - flags=0, - message_type=Gtk.MessageType.INFO, - buttons=Gtk.ButtonsType.OK_CANCEL, - text=strings.scan_servers, - secondary_text=strings.select_port, - title=strings.dialog_header, - modal=True, - ) - - self.set_size_request(500, 0) - self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) - - buttons = [ - (strings.default_port, Port.DEFAULT), - (strings.custom_port, Port.CUSTOM), - ] - - self.button_box = Gtk.Box() - self.button_box.set_orientation(Gtk.Orientation.VERTICAL) - self.button_box.active_button = None - - for k, v in buttons: - button = Gtk.RadioButton(label=k) - button.port = v - button.connect("toggled", self._on_button_toggled) - self.button_box.add(button) - if v == Port.DEFAULT: - self.button_box.active_button = button - else: - button.join_group(self.button_box.active_button) - - self.entry = Gtk.Entry() - self.button_box.add(self.entry) - self.entry.set_no_show_all(True) - - # TODO: strings - self.warn_label = Gtk.Label(label="Invalid port") - self.warn_label.set_no_show_all(True) - self.button_box.add(self.warn_label) - - content = self.get_content_area() - content.pack_start(self.button_box, NO_EXPAND, NO_FILL, NO_PADDING) - content.set_margin_start(30) - content.set_margin_end(30) - content.show_all() - - self.action_area.set_layout(Gtk.ButtonBoxStyle.CENTER) - self.action_area.set_margin_bottom(20) - - self.port = None - self.ok = self.action_area.get_children()[1] - - self.connect("response", self._on_dialog_response) - self.connect("key-press-event", self._on_keypress) - self.connect("delete-event", self.restore_context) - - self.entry.connect("insert-text", self._on_text_typed) - self.entry.get_property("buffer").connect( - "deleted-text", self._on_text_deleted - ) - - def _validate(self, text: str) -> None: - state = ip.is_valid_port(text) - self.ok.set_sensitive(not state) - self.warn_label.set_visible(state) - - # TODO: can put in validation method - if len(text) == 0: - self.warn_label.set_visible(False) - - def _on_text_deleted( - self, buffer: Gtk.EntryBuffer, position: int, chars: int - ) -> None: - text = buffer.get_text() - self._validate(text) - - def _on_text_typed( - self, entry: Gtk.Entry, text: str, length: int, pos: int) -> None: - self._validate(entry.get_text() + text) - - def restore_context(self, *args: Any) -> None: - context = WindowContext.MAIN_MENU - AppNav.treeview.set_view(context) - - def _on_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None: - if event.keyval == Gdk.KEY_Return: - if self.ok.is_sensitive(): - self.response(Gtk.ResponseType.OK) - if self.button_box.get_children()[0].is_focus(): - self.response(Gtk.ResponseType.OK) - else: - self.restore_context() - - if event.keyval == Gdk.KEY_Up: - self.ok.set_sensitive(True) - self.entry.set_text("") - self.button_box.get_children()[0].grab_focus() - - def _on_dialog_response( - self, dialog: Self, response: Gtk.ResponseType - ) -> None: - cancel_events = [ - Gtk.ResponseType.CLOSE, - Gtk.ResponseType.CANCEL, - Gtk.ResponseType.DELETE_EVENT, - ] - - if response in cancel_events: - self.restore_context() - return - - string = self.entry.get_text() - port = self.button_box.active_button.port - - match port: - case Port.DEFAULT: - self.port = UDP_PORT - case Port.CUSTOM: - if ip.is_valid_port(string): - self.stop_emission_by_name("response") - else: - self.port = int(string) - - def get_selected_port(self) -> int: - return self.port - - def _on_button_toggled(self, button: Gtk.Button) -> None: - if button.get_active(): - self.button_box.active_button = button - match button.port: - case Port.DEFAULT: - self.entry.set_visible(False) - case Port.CUSTOM: - self.entry.set_visible(True) - self.entry.grab_focus() - self.ok.set_sensitive(False) diff --git a/dzgui/views/mixins/context_mixin.py b/dzgui/views/mixins/context_mixin.py index c9e5079..b75515c 100644 --- a/dzgui/views/mixins/context_mixin.py +++ b/dzgui/views/mixins/context_mixin.py @@ -18,7 +18,8 @@ class ContextMixin(TreeView): widget: Gtk.Widget, event: Gdk.EventButton | Gdk.EventKey, ) -> None: - + # FIXME: double click causes issue + # split into present by click and present by key if self.is_selection_empty(): return False diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index ab58bc4..f5df268 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -61,7 +61,6 @@ class ServerNotebook(Gtk.ScrolledWindow): self.emitter.emit("server_page_toggled", True) # FIXME: only applies to server notebook, not atomic page # this can be delegated to the map/unmap signal of the ServerTreeView itself - # print("page changed, starting queue checker") # self.get_active_treeview().start_timeout() def _on_unmap(self, widget: Self) -> None: diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index 61dacee..b2423b5 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -1,6 +1,7 @@ import logging from typing import Optional, TYPE_CHECKING +from warnings import deprecated from dzgui.const.constants import SEPARATOR from dzgui.util.keys import is_navkey @@ -39,8 +40,6 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore self.selected_row.connect("changed", self._on_tree_selection_changed) self.connect("row-activated", self._on_row_activated) - self.connect("button-press-event", lambda x, y: print(self.sel_blocked)) - self.connect("key-press-event", self._on_keypress) self.connect("key-release-event", self._on_key_release) @@ -56,12 +55,12 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore ) -> None: pass - def _separate(self, model: Gtk.ListStore, iter_: Gtk.TreeIter) -> bool: - if model[iter_][0] == SEPARATOR: + def _separate(self, model: Gtk.ListStore, _iter: Gtk.TreeIter) -> bool: + if model[_iter][0] == SEPARATOR: return True return False - def get_current_iter(self) -> Gtk.TreeIter | None: + def get_current_iter(self) -> Optional[Gtk.TreeIter]: it = self.get_selection().get_selected()[1] return it @@ -82,7 +81,6 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return [model[row] for row in rows] def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: - if is_navkey(event.keyval): if self.get_model() is None: return @@ -98,9 +96,9 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return def _on_key_release(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: - # TODO: explain this better """ Suppresses spamming on keydown + TODO: explain this better """ # TODO: multisel # if event.keyval is Gdk.KEY_space: @@ -139,9 +137,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore self.set_cursor(0) def get_value_at_index(self, index: int) -> str: - select = self.get_selection() - sels = select.get_selected_rows() - (model, pathlist) = sels + (model, pathlist) = self.get_model_and_pathlist() if len(pathlist) < 1: return "" path = pathlist[0] @@ -157,16 +153,20 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore sel = self.get_selection() self._on_tree_selection_changed(sel) - def get_mpath(self) -> Gtk.TreePath | None: + def get_model_and_pathlist(self) -> tuple: select = self.get_selection() sels = select.get_selected_rows() (model, pathlist) = sels + return (model, pathlist) + + @deprecated("Currently unused") + def get_mpath(self) -> Optional[Gtk.TreePath]: + (model, pathlist) = self.get_model_and_pathlist() if len(pathlist) < 1: return None path = pathlist[0] return path - # @signal_emission def _on_row_activated( self, treeview: Gtk.TreeView, @@ -176,15 +176,12 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore self.emit("generic_row_activated", path, col) def is_selection_empty(self) -> bool: - # TODO: reduce duplicated methods - sel = self.get_selection() - sels = sel.get_selected_rows() - (model, pathlist) = sels + (model, pathlist) = self.get_model_and_pathlist() if len(pathlist) < 1: return True return False - def get_selected_row(self) -> Gtk.TreeModelRow | None: + def get_selected_row(self) -> Optional[Gtk.TreeModelRow]: ind = self.get_selected_row_index() model = self.get_model() if model is None: diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 79bf462..52f0055 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -307,13 +307,19 @@ class ServerTreeView(ContextMixin, TreeView): return self.start_distcalc() + def get_simplified_ip(self) -> str: + addr = self.get_value_at_index(7) + qport = self.get_value_at_index(8) + ip = addr.split(":")[0] + return f"{ip}:{qport}" + def get_record_string(self) -> str: addr = self.get_value_at_index(7) qport = self.get_value_at_index(8) return f"{addr}:{qport}" def get_record(self) -> Record | None: - # TODO: delegate to controller + # TODO: use tree_base.get_selected_row() select = self.get_selection() sels = select.get_selected_rows() (model, pathlist) = sels