mirror of
https://github.com/aclist/dztui.git
synced 2026-10-25 12:12:31 +01:00
Normalized custom menu navigation keys to be in conformity with native keybindings for Gdk.KEY_uparrow and Gdk.KEY_downarrow.
120 lines
3.9 KiB
Python
120 lines
3.9 KiB
Python
import logging
|
|
|
|
from dzgui.const.constants import APP_NAME
|
|
from dzgui.const.enum import ContextMenu
|
|
from dzgui.util.keys import is_ctrl_mask, is_navkey
|
|
from dzgui.util.strings import edit_note
|
|
from dzgui.views.trees.tree_base import TreeView
|
|
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "3.0")
|
|
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402
|
|
|
|
logger = logging.getLogger(APP_NAME)
|
|
|
|
|
|
class ContextMixin(TreeView):
|
|
def present_menu(
|
|
self,
|
|
widget: Gtk.Widget,
|
|
event: Gdk.EventButton | Gdk.EventKey,
|
|
) -> bool:
|
|
|
|
if self.menu is None:
|
|
return False
|
|
if self.is_selection_empty():
|
|
return False
|
|
|
|
match event.type:
|
|
case Gdk.EventType.BUTTON_PRESS:
|
|
if event.button != 3:
|
|
return False
|
|
self._process_button_event(event) # type: ignore
|
|
case Gdk.EventType.KEY_PRESS:
|
|
if not is_ctrl_mask(event): # type: ignore
|
|
return False
|
|
if event.keyval is not Gdk.KEY_l: # type: ignore
|
|
return False
|
|
case _:
|
|
return False
|
|
|
|
group = self.menu
|
|
self.context_menu = Gtk.Menu()
|
|
self.context_menu.connect("key-press-event", self._on_key)
|
|
|
|
for row in group.value:
|
|
if row is None:
|
|
return False
|
|
item = self._process_dynamic_row(row)
|
|
self.context_menu.append(item)
|
|
|
|
self.context_menu.show_all()
|
|
|
|
match event.type:
|
|
case Gdk.EventType.KEY_PRESS:
|
|
self.context_menu.popup_at_widget(
|
|
widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST
|
|
)
|
|
case Gdk.EventType.BUTTON_PRESS | Gdk.EventType.BUTTON_RELEASE:
|
|
self.context_menu.popup_at_pointer(event)
|
|
|
|
self.context_menu.select_first(False)
|
|
return True
|
|
|
|
def _process_dynamic_row(self, row: ContextMenu) -> Gtk.MenuItem:
|
|
if row == ContextMenu.ADD_SERVER and self.is_in_favs(): # type: ignore
|
|
row = ContextMenu.REMOVE_SERVER
|
|
|
|
item = Gtk.MenuItem(label=row.dict["label"])
|
|
item.connect("activate", self._on_menu_click, row)
|
|
|
|
if row == ContextMenu.SHOW_MODS:
|
|
item.set_sensitive(self.is_modded()) # type: ignore
|
|
|
|
if row == ContextMenu.ADD_NOTE:
|
|
if self.controller.has_note():
|
|
item.set_label(edit_note)
|
|
|
|
return item
|
|
|
|
def _process_button_event(self, event: Gdk.EventButton) -> bool:
|
|
try:
|
|
pathinfo = self.get_path_at_pos(int(event.x), int(event.y))
|
|
if pathinfo is None:
|
|
return True
|
|
(path, col, cellx, celly) = pathinfo
|
|
if path is None:
|
|
return True
|
|
selection = self.get_selection()
|
|
model, selected_paths = selection.get_selected_rows()
|
|
if path not in selected_paths:
|
|
for p in selected_paths:
|
|
selection.unselect_path(p)
|
|
self.set_cursor(path, col, False)
|
|
return True
|
|
except AttributeError:
|
|
return False
|
|
|
|
def _on_menu_click(self, widget: Gtk.MenuItem, enum: ContextMenu) -> None:
|
|
self.controller.menu_action(enum, self) # type: ignore
|
|
|
|
def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None:
|
|
if not is_navkey(event.keyval):
|
|
return False
|
|
menu = self.context_menu
|
|
children = menu.get_children()
|
|
|
|
match event.keyval:
|
|
case Gdk.KEY_j:
|
|
menu.emit("move-current", Gtk.MenuDirectionType.NEXT)
|
|
case Gdk.KEY_k:
|
|
menu.emit("move-current", Gtk.MenuDirectionType.PREV)
|
|
case Gdk.KEY_g:
|
|
menu.select_item(children[0])
|
|
case Gdk.KEY_G:
|
|
menu.select_item(children[-1])
|
|
case _:
|
|
return False
|
|
return True
|