mirror of
https://github.com/aclist/dztui.git
synced 2026-08-28 02:37:20 +02:00
feat: add navigable context menu to mixins
This commit is contained in:
parent
ac7700ec23
commit
56b32a0048
@ -434,6 +434,20 @@ class Controller(GObject.GObject):
|
||||
text = "\n".join(final)
|
||||
return text
|
||||
|
||||
def copy_ip(self, path: Gtk.TreePath) -> None:
|
||||
treeview = self.get_active_treeview()
|
||||
model = treeview.get_model()
|
||||
if not model:
|
||||
return None
|
||||
addr = model[path][7]
|
||||
if addr is None:
|
||||
return
|
||||
qport = model[path][8]
|
||||
ip = addr.split(":")[0]
|
||||
gameport = int(addr.split(":")[1])
|
||||
record = Servers.Record(ip, gameport, qport)
|
||||
self.copy_clipboard(f"{record.ip}:{record.qport}")
|
||||
|
||||
def copy_clipboard(self, text: str) -> None:
|
||||
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
self.clipboard.set_text(text, -1)
|
||||
@ -503,8 +517,9 @@ class Controller(GObject.GObject):
|
||||
case ContextMenu.ADD_NOTE:
|
||||
pass
|
||||
case ContextMenu.COPY_CLIPBOARD:
|
||||
pass
|
||||
self.copy_ip(path)
|
||||
case ContextMenu.COPY_NAME:
|
||||
self.copy_name(path)
|
||||
pass
|
||||
case ContextMenu.REFRESH_PLAYERS:
|
||||
pass
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from dzgui.views.trees.tree_base import TreeView
|
||||
from dzgui.const.enum import ContextMenu
|
||||
from dzgui.util.keys import is_navkey
|
||||
from dzgui.views.trees.tree_base import TreeView
|
||||
|
||||
import gi
|
||||
|
||||
@ -21,7 +22,7 @@ class ContextMixin(TreeView):
|
||||
if self.is_selection_empty():
|
||||
return
|
||||
|
||||
if event.type is Gdk.EventType.BUTTON_PRESS:
|
||||
if event.type is Gdk.EventType.BUTTON_PRESS and event.button == 3:
|
||||
try:
|
||||
pathinfo = self.get_path_at_pos(int(event.x), int(event.y))
|
||||
if pathinfo is None:
|
||||
@ -41,6 +42,8 @@ class ContextMixin(TreeView):
|
||||
|
||||
group = self.menu
|
||||
self.context_menu = Gtk.Menu()
|
||||
self.context_menu.connect("key-press-event", self._on_key)
|
||||
|
||||
for row in group.value:
|
||||
item = Gtk.MenuItem(label=row.dict["label"])
|
||||
item.connect("activate", self._on_menu_click, row)
|
||||
@ -63,11 +66,11 @@ class ContextMixin(TreeView):
|
||||
Local mods page allows multi selection, so ensure that only focused row
|
||||
is selected. Used by ContextMenu.OPEN_WORKSHOP and ContextMenu.DELETE_MOD.
|
||||
|
||||
Mod tree right panel supports multi-delete, but context menu enforces
|
||||
ModTreeView supports multi-delete, but context menu enforces
|
||||
single deletion on the focused row.
|
||||
|
||||
Debug log page allows multi selection and copy of rows, so special handling
|
||||
is used.
|
||||
is used per below.
|
||||
"""
|
||||
if enum == ContextMenu.COPY_LOG_CLIPBOARD:
|
||||
model, records = self.get_selection().get_selected_rows()
|
||||
@ -76,3 +79,32 @@ class ContextMixin(TreeView):
|
||||
else:
|
||||
path = self.get_focused_row_path()
|
||||
self.controller.menu_action(enum, path)
|
||||
|
||||
def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None:
|
||||
if not is_navkey(event.keyval):
|
||||
return False
|
||||
menu = self.context_menu
|
||||
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
|
||||
|
||||
@ -50,28 +50,28 @@ class ModTreeView(ModsMixin, ContextMixin, TreeView):
|
||||
|
||||
self.connect("generic_row_activated", self._on_mod_row_activated)
|
||||
self.connect("generic_treesel_changed", self._parent_selection_changed)
|
||||
self.connect("button-press-event", self._on_mods_button_press)
|
||||
self.connect("key-press-event", self._on_mods_keypress)
|
||||
self.connect("button-press-event", self.present_menu)
|
||||
self.connect("key-press-event", self.present_menu)
|
||||
self.connect("map", self._on_map)
|
||||
|
||||
def _on_map(self, tree: Self) -> None:
|
||||
# TODO: placeholder logic
|
||||
# FIXME: placeholder logic
|
||||
# identify root cause of row unfocus on init
|
||||
self.set_cursor(0)
|
||||
|
||||
def _on_mods_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None:
|
||||
# TODO: multiselect
|
||||
# if event.keyval is Gdk.KEY_space:
|
||||
# it = self.get_focused_row_iter()
|
||||
# self.get_selection().select_iter(it)
|
||||
# path = self.get_focused_row_path()
|
||||
# self.set_cursor(path)
|
||||
# return False
|
||||
self.present_menu(widget, event)
|
||||
# def _on_mods_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None:
|
||||
# # TODO: multiselect
|
||||
# # if event.keyval is Gdk.KEY_space:
|
||||
# # it = self.get_focused_row_iter()
|
||||
# # self.get_selection().select_iter(it)
|
||||
# # path = self.get_focused_row_path()
|
||||
# # self.set_cursor(path)
|
||||
# # return False
|
||||
# self.present_menu(widget, event)
|
||||
|
||||
def _on_mods_button_press(self, widget: Gtk.Widget, event: Gdk.EventButton) -> None:
|
||||
if event.button == 3:
|
||||
self.present_menu(widget, event)
|
||||
# def _on_mods_button_press(self, widget: Gtk.Widget, event: Gdk.EventButton) -> None:
|
||||
# if event.button == 3:
|
||||
# self.present_menu(widget, event)
|
||||
|
||||
def _parent_selection_changed(self, base_class: TreeView, sel: Gtk.TreeSelection):
|
||||
pass
|
||||
|
||||
@ -3,11 +3,11 @@ import multiprocessing
|
||||
from typing import Any, Self
|
||||
from warnings import deprecated
|
||||
|
||||
from dzgui.const.enum import ContextMenu, ContextMenuGroup, ServerTab
|
||||
from dzgui.views.mixins.context_mixin import ContextMixin
|
||||
from dzgui.const.enum import ContextMenuGroup, ServerTab
|
||||
from dzgui.api.servers import Record
|
||||
from dzgui.model.filtered_model import FilteredModelManager
|
||||
from dzgui.util.dist import CalcDist
|
||||
from dzgui.util.keys import is_navkey
|
||||
from dzgui.util import strings
|
||||
from typing import Callable, Literal, TYPE_CHECKING
|
||||
|
||||
@ -26,17 +26,11 @@ if TYPE_CHECKING:
|
||||
from dzgui.controllers.mc import Controller
|
||||
|
||||
|
||||
class EnumeratedMenuItem(Gtk.MenuItem):
|
||||
def __init__(self, enum: ContextMenu):
|
||||
super().__init__(label=enum.dict["label"])
|
||||
self.enum = enum
|
||||
|
||||
|
||||
class ServerTreeView(TreeView):
|
||||
class ServerTreeView(ContextMixin, TreeView):
|
||||
def __init__(
|
||||
self, controller: "Controller", enum: ServerTab, menu: ContextMenuGroup
|
||||
) -> None:
|
||||
super().__init__(controller)
|
||||
super().__init__(controller, menu=ContextMenuGroup.SERVER_BROWSER)
|
||||
|
||||
QUEUE_CHECK_DELAY = 200
|
||||
|
||||
@ -51,10 +45,6 @@ class ServerTreeView(TreeView):
|
||||
model = self.filter_man.get_model()
|
||||
self.set_model(model)
|
||||
|
||||
self.menu = Gtk.Menu()
|
||||
self.menu.connect("key-press-event", self._on_key)
|
||||
|
||||
self.set_context_menu(menu)
|
||||
self.set_fixed_height_mode(True)
|
||||
self.set_headers_visible(True)
|
||||
|
||||
@ -104,13 +94,15 @@ class ServerTreeView(TreeView):
|
||||
self.append_column(column)
|
||||
|
||||
self.connect("distcalc_started", self._on_distcalc_started)
|
||||
self.connect("button-release-event", self._on_server_button_release)
|
||||
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("key-press-event", self.present_menu)
|
||||
self.connect("button-press-event", self.present_menu)
|
||||
|
||||
GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue)
|
||||
|
||||
@GObject.Signal(flags=GObject.SignalFlags.RUN_FIRST, arg_types=())
|
||||
@ -154,35 +146,6 @@ class ServerTreeView(TreeView):
|
||||
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:
|
||||
# TODO: abstract as navigable context menu
|
||||
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 set_query_func(self, func: Callable) -> None:
|
||||
self.query_func = func
|
||||
|
||||
@ -241,8 +204,6 @@ class ServerTreeView(TreeView):
|
||||
) -> bool | None:
|
||||
if event.state is Gdk.ModifierType.CONTROL_MASK:
|
||||
match event.keyval:
|
||||
case Gdk.KEY_l:
|
||||
self._on_server_button_release(self, event)
|
||||
case Gdk.KEY_r:
|
||||
self.refresh_player_count()
|
||||
case Gdk.KEY_f:
|
||||
@ -255,7 +216,8 @@ class ServerTreeView(TreeView):
|
||||
if self.enum is ServerTab.LAN:
|
||||
self.emitter.emit("request_lan_entry_focus", self.enum)
|
||||
case Gdk.KEY_c:
|
||||
print("UNIMPLEMENTED: copy to clipboard")
|
||||
record = self.get_record()
|
||||
self.controller.copy_ip(record)
|
||||
else:
|
||||
match event.keyval:
|
||||
case Gdk.KEY_l | Gdk.KEY_Right:
|
||||
@ -263,37 +225,7 @@ class ServerTreeView(TreeView):
|
||||
case _:
|
||||
self.emitter.emit("check_button_pressed", event.keyval)
|
||||
|
||||
def set_context_menu(self, items: ContextMenuGroup) -> None:
|
||||
# TODO: if debug is on, add raw command copy to context menu
|
||||
for item in items.value:
|
||||
menu_item = EnumeratedMenuItem(item)
|
||||
menu_item.connect("activate", self._on_menu_click)
|
||||
self.menu.append(menu_item)
|
||||
self.menu.show_all()
|
||||
|
||||
def _on_menu_click(self, item) -> None:
|
||||
print(f"UNIMPLEMENTED: {item.enum}")
|
||||
pass
|
||||
|
||||
def _on_server_button_release(
|
||||
self, widget: Gtk.Widget, event: Gdk.EventButton
|
||||
) -> None:
|
||||
# TODO: use ContextMixin
|
||||
if event.type is Gdk.EventType.BUTTON_RELEASE and event.button != 3:
|
||||
return
|
||||
try:
|
||||
pathinfo = self.get_path_at_pos(int(event.x), int(event.y))
|
||||
if pathinfo is None:
|
||||
return
|
||||
(path, col, cellx, celly) = pathinfo
|
||||
if path is None:
|
||||
return
|
||||
self.set_cursor(path, col, False)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# mod_context_items = [ContextMenu.OPEN_WORKSHOP, ContextMenu.DELETE_MOD]
|
||||
|
||||
# TODO: dynamic menu entries
|
||||
# for row in items:
|
||||
# if row == ContextMenu.ADD_SERVER:
|
||||
@ -310,13 +242,13 @@ class ServerTreeView(TreeView):
|
||||
# if self.get_record_string() in notes_cache:
|
||||
# item.set_label(strings.edit_note)
|
||||
|
||||
if event.type is Gdk.EventType.KEY_PRESS and event.keyval is Gdk.KEY_l:
|
||||
if self.is_selection_empty():
|
||||
return
|
||||
self.menu.popup_at_widget(widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST)
|
||||
else:
|
||||
self.menu.popup_at_pointer(event)
|
||||
self.menu.select_first(False)
|
||||
# if event.type is Gdk.EventType.KEY_PRESS and event.keyval is Gdk.KEY_l:
|
||||
# if self.is_selection_empty():
|
||||
# return
|
||||
# self.menu.popup_at_widget(widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST)
|
||||
# else:
|
||||
# self.menu.popup_at_pointer(event)
|
||||
# self.menu.select_first(False)
|
||||
|
||||
def _parent_row_activated(
|
||||
self, tree: TreeView, path: Gtk.TreePath, column: Gtk.TreeViewColumn
|
||||
|
||||
Loading…
Reference in New Issue
Block a user