feat: server connection panel WIP

This commit is contained in:
aclist 2025-12-28 07:14:35 +09:00
parent ef2742443f
commit ad6bdb2e3c
6 changed files with 91 additions and 27 deletions

View File

@ -297,6 +297,7 @@ class RowType(EnumWithAttrs):
# TODO: rename to ContextItem # TODO: rename to ContextItem
class ContextMenu(EnumWithAttrs): class ContextMenu(EnumWithAttrs):
ADD_SERVER = {"label": strings.add} ADD_SERVER = {"label": strings.add}
ADD_FAV = {"label": strings.add_fav}
REMOVE_SERVER = {"label": strings.remove} REMOVE_SERVER = {"label": strings.remove}
COPY_NAME = {"label": strings.copy_name} COPY_NAME = {"label": strings.copy_name}
COPY_CLIPBOARD = {"label": strings.copy_ip} COPY_CLIPBOARD = {"label": strings.copy_ip}
@ -324,6 +325,7 @@ class ContextMenuGroup(Enum):
SERVER_BROWSER = ( SERVER_BROWSER = (
ContextMenu.CONNECT, ContextMenu.CONNECT,
ContextMenu.ADD_SERVER, ContextMenu.ADD_SERVER,
ContextMenu.ADD_FAV,
ContextMenu.COPY_NAME, ContextMenu.COPY_NAME,
ContextMenu.COPY_CLIPBOARD, ContextMenu.COPY_CLIPBOARD,
ContextMenu.ADD_NOTE, ContextMenu.ADD_NOTE,
@ -333,6 +335,7 @@ class ContextMenuGroup(Enum):
) )
SCAN_LAN = ( SCAN_LAN = (
ContextMenu.CONNECT, ContextMenu.CONNECT,
ContextMenu.ADD_FAV,
ContextMenu.COPY_NAME, ContextMenu.COPY_NAME,
ContextMenu.COPY_CLIPBOARD, ContextMenu.COPY_CLIPBOARD,
ContextMenu.ADD_NOTE, ContextMenu.ADD_NOTE,
@ -342,6 +345,7 @@ class ContextMenuGroup(Enum):
) )
SAVED = ( SAVED = (
ContextMenu.CONNECT, ContextMenu.CONNECT,
ContextMenu.ADD_FAV,
ContextMenu.REMOVE_SERVER, ContextMenu.REMOVE_SERVER,
ContextMenu.COPY_NAME, ContextMenu.COPY_NAME,
ContextMenu.COPY_CLIPBOARD, ContextMenu.COPY_CLIPBOARD,
@ -353,6 +357,7 @@ class ContextMenuGroup(Enum):
RECENT = ( RECENT = (
ContextMenu.CONNECT, ContextMenu.CONNECT,
ContextMenu.ADD_SERVER, ContextMenu.ADD_SERVER,
ContextMenu.ADD_FAV,
ContextMenu.REMOVE_HISTORY, ContextMenu.REMOVE_HISTORY,
ContextMenu.COPY_NAME, ContextMenu.COPY_NAME,
ContextMenu.COPY_CLIPBOARD, ContextMenu.COPY_CLIPBOARD,

View File

@ -39,7 +39,7 @@ from dzgui.util.diag import write_diagnostic
from dzgui.util import cooldown, strings from dzgui.util import cooldown, strings
from dzgui.util._json import read_json, write_json from dzgui.util._json import read_json, write_json
from dzgui.util.open_links import open_workshop_page 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.util.redact import redact_log
from dzgui.views.dialogs.filepicker import FilePicker from dzgui.views.dialogs.filepicker import FilePicker
@ -56,7 +56,6 @@ if TYPE_CHECKING:
from dzgui.views.base import AppNavigation from dzgui.views.base import AppNavigation
from dzgui.const.enum import ContextMenu, RowType from dzgui.const.enum import ContextMenu, RowType
from dzgui.views.base import OuterWindow from dzgui.views.base import OuterWindow
from dzgui.views.trees.tree_servers import ServerTreeView
class Controller: class Controller:
def __init__(self) -> None: def __init__(self) -> None:
@ -558,7 +557,6 @@ class Controller:
return self.is_developer return self.is_developer
def update_server_status(self) -> None: def update_server_status(self) -> None:
from dzgui.util.format import pluralize
treeview = self.mediator.notebook.servers.get_active_treeview() treeview = self.mediator.notebook.servers.get_active_treeview()
model = treeview.get_model() model = treeview.get_model()
if model is None: if model is None:
@ -575,12 +573,24 @@ class Controller:
formatted = ( formatted = (
f"Found {hits:n} {hits_pretty} with {players:n} {players_pretty}" f"Found {hits:n} {hits_pretty} with {players:n} {players_pretty}"
) )
suffix = "| Distance: calculating..." suffix = " | Distance: calculating..."
if players == 0: if players == 0:
suffix = "" suffix = ""
self.mediator.statusbar.set_text(formatted + suffix) self.mediator.statusbar.set_text(formatted + suffix)
#self.players = formatted #self.players = formatted
def update_column_width(self, title: str, width: int) -> None: def propagate_column_width(self, col: Gtk.TreeViewColumn) -> None:
self.mediator.servers.update_tab_widths(title, width) 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)

View File

@ -53,7 +53,8 @@ copy_name = "Copy name to clipboard"
copy_ip = "Copy IP to clipboard" copy_ip = "Copy IP to clipboard"
copy_log = "Copy record(s) to clipboard" copy_log = "Copy record(s) to clipboard"
add = "Add to my servers" 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" remove_history = "Remove from history"
connect = "Connect" connect = "Connect"

View File

@ -505,15 +505,15 @@ class Grid(Gtk.Grid):
self.breadcrumbs, self.notebook, Gtk.PositionType.TOP, 3, 1 self.breadcrumbs, self.notebook, Gtk.PositionType.TOP, 3, 1
) )
#from dzgui.views.components.connect_panel import ConnectPanel from dzgui.views.components.connect_panel import ConnectPanel
#self.conpan = ConnectPanel() self.conpan = ConnectPanel()
#self.attach_next_to( self.attach_next_to(
# self.conpan, self.notebook, Gtk.PositionType.BOTTOM, 3, 1 self.conpan, self.notebook, Gtk.PositionType.BOTTOM, 3, 1
#) )
self.attach_next_to( 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.attach_next_to(
self.right_panel, self.notebook, Gtk.PositionType.RIGHT, 1, 1 self.right_panel, self.notebook, Gtk.PositionType.RIGHT, 1, 1

View File

@ -4,29 +4,42 @@ from gi.repository import Gtk # noqa E402
from dzgui.views.components.web_button import WebButton from dzgui.views.components.web_button import WebButton
class ConnectPanel(Gtk.Grid): class ConnectPanel(Gtk.Frame):
def __init__(self) -> None: 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") self.label2 = Gtk.Label(label="Favorite server")
# TODO: embold function # TODO: embold function
#self.label2.set_markup("<b>Favorite server</b>")
self.label2.set_markup("<b>Favorite server</b>") self.label2.set_markup("<b>Favorite server</b>")
sep = Gtk.Separator() sep = Gtk.Separator()
self.entry1 = Gtk.Entry(placeholder_text="Enter IP or Battlemetrics ID", hexpand=False) self.entry1 = Gtk.Entry(placeholder_text="Enter IP or Battlemetrics ID", hexpand=False)
self.entry2 = Gtk.Entry() 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.favedit = Gtk.Button("Edit")
self.edit = WebButton(label="EDIT") self.edit = WebButton(label="EDIT")
self.favbutton = Gtk.Button(label="Connect") self.favbutton = Gtk.Button(label="Connect")
self.attach(self.label, 0, 0, 3, 1) # TODO: dedent
button = Gtk.Button(label="Connect") long = """IP: Format as IP:Query port, e.g.\n192.168.1.1:27016\n
self.attach_next_to(self.entry1, self.label, Gtk.PositionType.BOTTOM, 3, 1) Battlemetrics: numeric server ID
self.attach_next_to(button, self.entry1, Gtk.PositionType.RIGHT, 3, 1) """
self.attach_next_to(sep, self.entry1, Gtk.PositionType.BOTTOM, 3, 1) # TODO: add tooltips to all buttons
self.attach_next_to(self.label2, sep, Gtk.PositionType.BOTTOM, 3, 1) self.entry1.set_tooltip_text(long)
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.con = Gtk.Button(label="Connect")
self.attach_next_to(self.favbutton, self.edit, Gtk.PositionType.RIGHT, 3, 1) 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)

View File

@ -44,6 +44,7 @@ class ServerTreeView(TreeView):
super().__init__(controller) super().__init__(controller)
self.menu = Gtk.Menu() self.menu = Gtk.Menu()
self.menu.connect("key-press-event", self._on_key)
self.controller = controller self.controller = controller
self.resizable_cols: list[Gtk.TreeViewColumn] = [] self.resizable_cols: list[Gtk.TreeViewColumn] = []
@ -85,6 +86,7 @@ class ServerTreeView(TreeView):
if column_title == "Map": if column_title == "Map":
column.set_fixed_width(300) column.set_fixed_width(300)
self.resizable_cols.append(column) self.resizable_cols.append(column)
column.connect("notify::fixed-width", self._on_col_width_changed) column.connect("notify::fixed-width", self._on_col_width_changed)
self.append_column(column) self.append_column(column)
@ -97,9 +99,41 @@ class ServerTreeView(TreeView):
GLib.timeout_add(200, self._check_result_queue) 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( def _on_col_width_changed(
self, col: Gtk.TreeViewColumn, width: GObject.ParamSpecInt self, col: Gtk.TreeViewColumn, width: GObject.ParamSpecInt
) -> None: ) -> None:
"""
Propagate width change to other tabs
"""
# TODO: only update res file on quit
title = col.get_title() title = col.get_title()
size = col.get_width() size = col.get_width()
@ -117,7 +151,8 @@ class ServerTreeView(TreeView):
except Exception as e: except Exception as e:
logger.critical(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: def terminate_process(self) -> None:
if self.current_proc and self.current_proc.is_alive(): if self.current_proc and self.current_proc.is_alive():