mirror of
https://github.com/aclist/dztui.git
synced 2026-10-25 12:12:31 +01:00
212 lines
6.8 KiB
Python
212 lines
6.8 KiB
Python
import logging
|
|
|
|
from typing import Any, Optional, TYPE_CHECKING
|
|
|
|
from dzgui.const.constants import APP_NAME, SEPARATOR
|
|
from dzgui.util.keys import is_ctrl_mask, is_navkey
|
|
from dzgui.views.mixins.cursor_mixin import CursorMixin
|
|
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "3.0")
|
|
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
|
|
|
logger = logging.getLogger(APP_NAME)
|
|
|
|
if TYPE_CHECKING:
|
|
from dzgui.controllers.mc import Controller
|
|
from dzgui.const.enum import ContextMenuGroup
|
|
|
|
|
|
class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
|
|
def __init__(
|
|
self, controller: "Controller", menu: Optional["ContextMenuGroup"]
|
|
) -> None:
|
|
super().__init__(
|
|
enable_search=False,
|
|
search_column=-1,
|
|
headers_visible=False,
|
|
)
|
|
|
|
self.menu = menu
|
|
self.controller = controller
|
|
self.sel_blocked = False
|
|
self.set_row_separator_func(self._separate)
|
|
self.emitter = self.controller.get_emitter()
|
|
|
|
self.selected_row = self.get_selection()
|
|
self.selected_row.set_mode(Gtk.SelectionMode.SINGLE)
|
|
self.selected_row.connect("changed", self._on_tree_selection_changed)
|
|
self.connect("row-activated", self._on_row_activated)
|
|
|
|
self.connect("key-press-event", self._on_keypress)
|
|
self.connect("key-release-event", self._on_key_release)
|
|
|
|
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(Gtk.TreeSelection,))
|
|
def generic_treesel_changed(self, selection: Gtk.TreeSelection) -> None:
|
|
pass
|
|
|
|
@GObject.Signal(
|
|
flags=GObject.SignalFlags.RUN_LAST, arg_types=(Gtk.TreePath, Gtk.TreeViewColumn)
|
|
)
|
|
def generic_row_activated(
|
|
self, path: Gtk.TreePath, column: Gtk.TreeViewColumn
|
|
) -> None:
|
|
pass
|
|
|
|
def _separate(self, model: Gtk.ListStore, _iter: Gtk.TreeIter) -> bool:
|
|
if model[_iter][0] == SEPARATOR:
|
|
return True
|
|
return False
|
|
|
|
def get_current_iter(self) -> Optional[Gtk.TreeIter]:
|
|
it = self.get_selection().get_selected()[1]
|
|
return it
|
|
|
|
def get_focused_row_iter(self) -> Gtk.TreeIter:
|
|
path = self.get_focused_row_path()
|
|
model = self.get_model()
|
|
if model is None:
|
|
raise AttributeError("No model attached to tree")
|
|
return model.get_iter(path)
|
|
|
|
def get_focused_row_path(self) -> Gtk.TreePath:
|
|
path, column = self.get_cursor()
|
|
return path
|
|
|
|
def get_focused_row_index(self) -> int:
|
|
path, column = self.get_cursor()
|
|
index = path.get_indices()[0]
|
|
return index
|
|
|
|
def get_selected_records(self) -> list:
|
|
sel = self.get_selection()
|
|
model, rows = sel.get_selected_rows()
|
|
return [model[row] for row in rows]
|
|
|
|
def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> bool:
|
|
from dzgui.views.trees.tree_servers import ServerTreeView
|
|
|
|
# NOTE: suppress popup search and delegate binding to server view (cf. request_keyword_focus)
|
|
if not isinstance(treeview, ServerTreeView):
|
|
if is_ctrl_mask(event) and event.keyval == Gdk.KEY_f:
|
|
return True
|
|
|
|
if is_navkey(event.keyval):
|
|
if self.get_model() is None:
|
|
return True
|
|
if self.sel_blocked is False:
|
|
self.sel_blocked = True
|
|
self.controller.suppress_signal(
|
|
self,
|
|
self.selected_row,
|
|
"_on_tree_selection_changed",
|
|
True,
|
|
)
|
|
self._vim_nav(event)
|
|
return False
|
|
|
|
def _on_key_release(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None:
|
|
"""
|
|
Suppresses spamming on keydown
|
|
TODO: explain this better
|
|
"""
|
|
# TODO: multisel
|
|
# if event.keyval is Gdk.KEY_space:
|
|
# it = self.get_focused_row_iter()
|
|
# self.get_selection().select_iter(it)
|
|
# return True
|
|
|
|
model = self.get_model()
|
|
if model is None:
|
|
return
|
|
if len(model) < 2:
|
|
return
|
|
if is_navkey(event.keyval):
|
|
if self.sel_blocked is True:
|
|
self.sel_blocked = False
|
|
self.controller.suppress_signal(
|
|
self,
|
|
self.selected_row,
|
|
"_on_tree_selection_changed",
|
|
False,
|
|
)
|
|
selection = self.get_selection()
|
|
self._on_tree_selection_changed(selection)
|
|
|
|
def _on_tree_selection_changed(self, selection: Gtk.TreeSelection) -> None:
|
|
self.emit("generic_treesel_changed", selection)
|
|
|
|
def toggle_selection(self, state: bool) -> None:
|
|
for i, row in enumerate(self.get_model()): # type: ignore
|
|
path = Gtk.TreePath.new_from_indices([i])
|
|
if state:
|
|
self.get_selection().select_path(path)
|
|
else:
|
|
self.get_selection().unselect_path(path)
|
|
|
|
def focus_first_row(self) -> None:
|
|
path = Gtk.TreePath.new_from_indices([0])
|
|
self.set_cursor(path)
|
|
|
|
def get_value_at_index(self, index: int) -> Any:
|
|
(model, pathlist) = self.get_model_and_pathlist()
|
|
if len(pathlist) < 1:
|
|
return ""
|
|
path = pathlist[0]
|
|
tree_iter = model.get_iter(path)
|
|
value = model.get_value(tree_iter, index)
|
|
return value
|
|
|
|
def get_name(self) -> str:
|
|
name = self.get_value_at_index(0)
|
|
return str(name)
|
|
|
|
def select_first_row(self) -> None:
|
|
sel = self.get_selection()
|
|
self._on_tree_selection_changed(sel)
|
|
|
|
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
|
|
|
|
def _on_row_activated(
|
|
self,
|
|
treeview: Gtk.TreeView,
|
|
path: Gtk.TreePath,
|
|
col: Gtk.TreeViewColumn,
|
|
) -> None:
|
|
self.emit("generic_row_activated", path, col)
|
|
|
|
def is_selection_empty(self) -> bool:
|
|
(model, pathlist) = self.get_model_and_pathlist()
|
|
if len(pathlist) < 1:
|
|
return True
|
|
return False
|
|
|
|
# @deprecated("unused")
|
|
# def get_selected_row(self) -> Optional[Gtk.TreeModelRow]:
|
|
# ind = self.get_selected_row_index()
|
|
# model = self.get_model()
|
|
# if model is None:
|
|
# return None
|
|
# row = model[ind]
|
|
# return row
|
|
|
|
def get_col_value_by_path_index(self, path: Gtk.TreePath, index: int) -> Any:
|
|
model = self.get_model()
|
|
if model is None:
|
|
return None
|
|
value = model[path][index]
|
|
return value
|