import logging from typing import Any, TYPE_CHECKING from dzgui.const.constants import APP_NAME, HEX_RED from dzgui.const.enum import ContextMenuGroup from dzgui.managers.mods import ModManager from dzgui.util import strings, localize from dzgui.views.mixins.context_mixin import ContextMixin from dzgui.views.mixins.mods_mixin import ModsMixin 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 if TYPE_CHECKING: from dzgui.controllers.mc import Controller from dzgui.controllers.emitter import Emitter logger = logging.getLogger(APP_NAME) class ModTreeView(ModsMixin, ContextMixin, TreeView): # type: ignore def __init__( self, controller: "Controller", menu: ContextMenuGroup = ContextMenuGroup.MOD ) -> None: super().__init__(controller, menu=menu) self.controller = controller self.mod_man = ModManager(self, controller) emitter = self.controller.get_emitter() emitter.connect("mods_updated", self._on_mods_updated) emitter.connect("mods_highlighted", self._on_mods_highlighted) self.set_fixed_height_mode(True) self.set_model(None) for i, column_title in enumerate(strings.mod_cols): renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(column_title, renderer, text=i) column.set_cell_data_func(renderer, self._format_color, func_data=None) if i == 3: column.set_cell_data_func(renderer, self._format_float, func_data=None) if column_title == "Mod": column.set_fixed_width(500) else: column.set_fixed_width(150) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_sort_column_id(i) if i != 4: self.append_column(column) self.selected_row = self.get_selection() self.selected_row.set_mode(Gtk.SelectionMode.MULTIPLE) 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.present_menu) self.connect("key-press-event", self.present_menu) self.connect("button-press-event", self.on_row_click) def on_row_click(self, widget: Gtk.TreeView, event: Gdk.EventButton) -> bool: if event.state is Gdk.ModifierType.CONTROL_MASK and event.button == 1: path_info = widget.get_path_at_pos(int(event.x), int(event.y)) if path_info is None: return False path, column, cellx, celly = path_info model = self.get_model() if model is None: return False if path is None: return False _iter = model.get_iter(path) if self.get_selection().iter_is_selected(_iter): self.get_selection().unselect_iter(_iter) else: self.get_selection().select_iter(_iter) return True return False def get_mod_man(self) -> ModManager: return self.mod_man def load_mods(self) -> None: self.mod_man.load_mods() def _on_mods_highlighted(self, emitter: "Emitter") -> None: self.get_selection().unselect_all() def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None: if mods < 1: return self.set_headers_visible(True) path = Gtk.TreePath.new_from_indices([0]) self.set_cursor(path) def get_selected_mod(self) -> str: path = self.get_focused_row_path() model = self.get_model() if model is None: raise AttributeError("Trying to call a method on a non-existent model") tree_iter = model.get_iter(path) mod = model.get_value(tree_iter, 2) return str(mod) def _parent_selection_changed( self, base_class: TreeView, sel: Gtk.TreeSelection ) -> None: pass def _format_color( self, column: Gtk.TreeViewColumn, cell: Gtk.CellRendererText, model: Gtk.TreeModel, it: Gtk.TreeIter, data: Any, ) -> None: state = model[it][4] if state is True: cell.set_property("foreground", HEX_RED) else: cell.set_property("foreground", None) def _format_float( self, column: Gtk.TreeViewColumn, cell: Gtk.CellRendererText, model: Gtk.TreeModel, it: Gtk.TreeIter, data: Any, ) -> None: val = model[it][3] formatted = localize.number(val) cell.set_property("text", formatted) # NOTE: reapply color property after float conversion self._format_color(column, cell, model, it, data) def set_menu(self, context: ContextMenuGroup) -> None: self.menu = context class OfflineModTreeView(ModTreeView): def __init__(self, controller: "Controller") -> None: super().__init__(controller)