diff --git a/dzgui/const/enum.py b/dzgui/const/enum.py index 111a5fc..224a5b9 100644 --- a/dzgui/const/enum.py +++ b/dzgui/const/enum.py @@ -297,6 +297,7 @@ 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} @@ -324,6 +325,7 @@ class ContextMenuGroup(Enum): SERVER_BROWSER = ( ContextMenu.CONNECT, ContextMenu.ADD_SERVER, + ContextMenu.ADD_FAV, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, ContextMenu.ADD_NOTE, @@ -333,6 +335,7 @@ class ContextMenuGroup(Enum): ) SCAN_LAN = ( ContextMenu.CONNECT, + ContextMenu.ADD_FAV, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, ContextMenu.ADD_NOTE, @@ -342,6 +345,7 @@ class ContextMenuGroup(Enum): ) SAVED = ( ContextMenu.CONNECT, + ContextMenu.ADD_FAV, ContextMenu.REMOVE_SERVER, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, @@ -353,6 +357,7 @@ class ContextMenuGroup(Enum): RECENT = ( ContextMenu.CONNECT, ContextMenu.ADD_SERVER, + ContextMenu.ADD_FAV, ContextMenu.REMOVE_HISTORY, ContextMenu.COPY_NAME, ContextMenu.COPY_CLIPBOARD, diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 61e071a..8fe3989 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -39,7 +39,7 @@ from dzgui.util.diag import write_diagnostic from dzgui.util import cooldown, strings from dzgui.util._json import read_json, write_json from dzgui.util.open_links import open_workshop_page -from dzgui.util.format import format_mods +from dzgui.util.format import format_mods, pluralize from dzgui.util.redact import redact_log from dzgui.views.dialogs.filepicker import FilePicker @@ -56,7 +56,6 @@ if TYPE_CHECKING: from dzgui.views.base import AppNavigation from dzgui.const.enum import ContextMenu, RowType from dzgui.views.base import OuterWindow - from dzgui.views.trees.tree_servers import ServerTreeView class Controller: def __init__(self) -> None: @@ -558,7 +557,6 @@ class Controller: return self.is_developer def update_server_status(self) -> None: - from dzgui.util.format import pluralize treeview = self.mediator.notebook.servers.get_active_treeview() model = treeview.get_model() if model is None: @@ -575,12 +573,24 @@ class Controller: formatted = ( f"Found {hits:n} {hits_pretty} with {players:n} {players_pretty}" ) - suffix = "| Distance: calculating..." + suffix = " | Distance: calculating..." if players == 0: suffix = "" self.mediator.statusbar.set_text(formatted + suffix) #self.players = formatted - def update_column_width(self, title: str, width: int) -> None: - self.mediator.servers.update_tab_widths(title, width) + def propagate_column_width(self, col: Gtk.TreeViewColumn) -> None: + GLib.idle_add(self.mediator.servers.update_tab_widths, col) +# tabs = self.mediator.servers.get_tabs() +# tree = self.mediator.servers.get_active_treeview() +# width = col.get_width() +# title = col.get_title() +# for tab in tabs: +# if tab == tree: +# continue +# for col in tab.get_columns(): +# if col.get_title() == title: +# self.suppress_signal(tab, col, "_on_col_width_changed", True) +# col.set_fixed_width(width) +# self.suppress_signal(tab, col, "_on_col_width_changed", False) diff --git a/dzgui/util/strings.py b/dzgui/util/strings.py index 88975cb..07690b4 100644 --- a/dzgui/util/strings.py +++ b/dzgui/util/strings.py @@ -53,7 +53,8 @@ copy_name = "Copy name to clipboard" copy_ip = "Copy IP to clipboard" copy_log = "Copy record(s) to clipboard" add = "Add to my servers" -remove = "Remove from Saved Servers" +add_fav = "Set as favorite" +remove = "Remove from my servers" remove_history = "Remove from history" connect = "Connect" diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 0276a03..f5834cb 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -505,15 +505,15 @@ class Grid(Gtk.Grid): self.breadcrumbs, self.notebook, Gtk.PositionType.TOP, 3, 1 ) - #from dzgui.views.components.connect_panel import ConnectPanel - #self.conpan = ConnectPanel() - #self.attach_next_to( - # self.conpan, self.notebook, Gtk.PositionType.BOTTOM, 3, 1 - #) + from dzgui.views.components.connect_panel import ConnectPanel + self.conpan = ConnectPanel() + self.attach_next_to( + self.conpan, self.notebook, Gtk.PositionType.BOTTOM, 3, 1 + ) self.attach_next_to( - self.statusbar, self.notebook, Gtk.PositionType.BOTTOM, 3, 1 + self.statusbar, self.conpan, Gtk.PositionType.BOTTOM, 3, 1 ) self.attach_next_to( self.right_panel, self.notebook, Gtk.PositionType.RIGHT, 1, 1 diff --git a/dzgui/views/components/connect_panel.py b/dzgui/views/components/connect_panel.py index 90bdd69..5cdc55c 100644 --- a/dzgui/views/components/connect_panel.py +++ b/dzgui/views/components/connect_panel.py @@ -4,29 +4,42 @@ from gi.repository import Gtk # noqa E402 from dzgui.views.components.web_button import WebButton -class ConnectPanel(Gtk.Grid): +class ConnectPanel(Gtk.Frame): def __init__(self) -> None: - super().__init__(vexpand=False, margin=20) + super().__init__(margin_top=10, margin_bottom=5) - self.label = Gtk.Label(label="Connect by IP/ID") + self.label = Gtk.Label(label="Add/connect") self.label2 = Gtk.Label(label="Favorite server") # TODO: embold function + #self.label2.set_markup("Favorite server") self.label2.set_markup("Favorite server") sep = Gtk.Separator() self.entry1 = Gtk.Entry(placeholder_text="Enter IP or Battlemetrics ID", hexpand=False) self.entry2 = Gtk.Entry() - self.fav = Gtk.Label("MY favorite server") + self.fav = Gtk.Label(label="MY favorite server very long title") self.favedit = Gtk.Button("Edit") self.edit = WebButton(label="EDIT") self.favbutton = Gtk.Button(label="Connect") - self.attach(self.label, 0, 0, 3, 1) - button = Gtk.Button(label="Connect") - self.attach_next_to(self.entry1, self.label, Gtk.PositionType.BOTTOM, 3, 1) - self.attach_next_to(button, self.entry1, Gtk.PositionType.RIGHT, 3, 1) + # TODO: dedent + long = """IP: Format as IP:Query port, e.g.\n192.168.1.1:27016\n + Battlemetrics: numeric server ID + """ - self.attach_next_to(sep, self.entry1, Gtk.PositionType.BOTTOM, 3, 1) - self.attach_next_to(self.label2, sep, Gtk.PositionType.BOTTOM, 3, 1) - self.attach_next_to(self.fav, self.label2, Gtk.PositionType.BOTTOM, 3, 1) - self.attach_next_to(self.edit, self.fav, Gtk.PositionType.RIGHT, 3, 1) - self.attach_next_to(self.favbutton, self.edit, Gtk.PositionType.RIGHT, 3, 1) + # TODO: add tooltips to all buttons + self.entry1.set_tooltip_text(long) + + self.con = Gtk.Button(label="Connect") + self.addb = Gtk.Button(label="Add") + + self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5) + self.grid.attach(self.label2, 0, 0, 3, 1) + button = Gtk.Button(label="Connect") + self.grid.attach_next_to(self.fav, self.label2, Gtk.PositionType.RIGHT, 3, 1) + self.grid.attach_next_to(self.favbutton, self.fav, Gtk.PositionType.RIGHT, 3, 1) + self.grid.attach_next_to(self.label, self.label2, Gtk.PositionType.BOTTOM, 3, 1) + self.grid.attach_next_to(self.entry1, self.label, Gtk.PositionType.RIGHT, 3, 1) + self.grid.attach_next_to(self.addb, self.entry1, Gtk.PositionType.RIGHT, 3, 1) + self.grid.attach_next_to(self.con, self.addb, Gtk.PositionType.RIGHT, 3, 1) + + self.add(self.grid) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 857ce1c..e428b0d 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -44,6 +44,7 @@ class ServerTreeView(TreeView): super().__init__(controller) self.menu = Gtk.Menu() + self.menu.connect("key-press-event", self._on_key) self.controller = controller self.resizable_cols: list[Gtk.TreeViewColumn] = [] @@ -85,6 +86,7 @@ class ServerTreeView(TreeView): if column_title == "Map": column.set_fixed_width(300) + self.resizable_cols.append(column) column.connect("notify::fixed-width", self._on_col_width_changed) self.append_column(column) @@ -97,9 +99,41 @@ class ServerTreeView(TreeView): GLib.timeout_add(200, self._check_result_queue) + def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None: + if not is_navkey(event.keyval): + return False + sel = menu.get_selected_item() + children = menu.get_children() + for i, child in enumerate(children): + if sel is child: + ind = i + break + + match event.keyval: + case Gdk.KEY_j: + if ind == len(children) - 1: + return True + menu.select_item(children[ind+1]) + case Gdk.KEY_k: + if ind - 1 < 0: + return True + menu.select_item(children[ind-1]) + case Gdk.KEY_g: + menu.select_item(children[0]) + case Gdk.KEY_G: + ind = len(children) - 1 + menu.select_item(children[ind]) + case _: + return False + return True + def _on_col_width_changed( self, col: Gtk.TreeViewColumn, width: GObject.ParamSpecInt ) -> None: + """ + Propagate width change to other tabs + """ + # TODO: only update res file on quit title = col.get_title() size = col.get_width() @@ -117,7 +151,8 @@ class ServerTreeView(TreeView): except Exception as e: logger.critical(e) - #self.controller.update_column_width(title, size) + # 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():