feat: update fav server dynamically

This commit is contained in:
aclist 2026-02-13 00:59:13 +09:00
parent 502b574085
commit 24125a7492
19 changed files with 127 additions and 231 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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"""

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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 = ""

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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 = ""

View File

@ -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)

View File

@ -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]:

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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