diff --git a/dzgui/model/model_factory.py b/dzgui/model/model_factory.py index 333db09..d395cd8 100644 --- a/dzgui/model/model_factory.py +++ b/dzgui/model/model_factory.py @@ -115,9 +115,12 @@ class FastInsertListStore(ListStore): For this reason, it is recommended to use the extend() method to insert an entire list of lists """ - total = len(row) - i = len(self) - tree_iter = self.insert_with_values(i, tuple(range(total)), row) + if row is not None: + total = len(row) + i = len(self) + tree_iter = self.insert_with_values(i, tuple(range(total)), row) + else: + tree_iter = super().append(row) return tree_iter diff --git a/dzgui/model/proxy_model.py b/dzgui/model/proxy_model.py index 1cdc3dc..2585d1d 100644 --- a/dzgui/model/proxy_model.py +++ b/dzgui/model/proxy_model.py @@ -57,9 +57,10 @@ class ProxyModelManager: self.proxy_model[treeiter][4] = playercount.players self.proxy_model[treeiter][6] = playercount.queue - # FIXME: typehint -> tuple + # TODO: use dataclass for record rows def append_row_to_history( - self, history: list[str, str, str, str, int, int, int, str, int, int, str, bool] + self, + history: tuple[str, str, str, str, int, int, int, str, int, int, str, bool], ) -> None: addr = history[7] qport = history[8] @@ -247,8 +248,8 @@ class ProxyModelManager: self.filter_cache[filters] = (model, rows) @deprecated("Currently unused") - def convert_model_to_list(self, model: "FastInsertListStore") -> list: - return [[el for el in row] for row in model] + # def convert_model_to_list(self, model: "FastInsertListStore") -> list: + # return [[el for el in row] for row in model] def set_filtered(self, rows: list | None) -> None: if rows is None: diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index bf7837d..2e23e16 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -236,6 +236,7 @@ class ServerModelManager: def add_to_history(self, record: dict[str, Any]) -> None: proxy_man = self._get_proxy_man() row = Servers.parse_json([record]) + print(type(row[0])) proxy_man.append_row_to_history(row[0]) self.update_history() diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 7672a4c..082d218 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -199,6 +199,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore for k, v in self.indexes.items(): if v == self.get_current_page(): return k + raise ValueError("No notebook pages set") def toggle_keybindings(self) -> None: cur_page = self.get_page_by_enum() diff --git a/dzgui/views/components/buttonbox.py b/dzgui/views/components/buttonbox.py index 3e056f6..496f237 100644 --- a/dzgui/views/components/buttonbox.py +++ b/dzgui/views/components/buttonbox.py @@ -68,7 +68,7 @@ class ButtonBox(Gtk.Box): def _focus_first_button(self, emitter: "Emitter") -> None: self.buttons[0].grab_focus() - def _on_selection_button_clicked(self, button: Gtk.Button) -> None: + def _on_selection_button_clicked(self, button: ContextualButton) -> None: self.controller.open_page_by_button(button) def _walk_buttons(self, increment: int) -> None: @@ -79,8 +79,8 @@ class ButtonBox(Gtk.Box): return if n == -1: return - n = self.buttons[n] - n.grab_focus() + b = self.buttons[n] + b.grab_focus() return def _on_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None: diff --git a/dzgui/views/dialogs/early_alert.py b/dzgui/views/dialogs/early_alert.py index 3d68925..a404a32 100644 --- a/dzgui/views/dialogs/early_alert.py +++ b/dzgui/views/dialogs/early_alert.py @@ -5,22 +5,26 @@ from typing import Self from dzgui.util.strings import dialog_error, dialog_header import gi + gi.require_version("Gtk", "3.0") from gi.repository import Gtk # noqa E402 + class EarlyAlertDialog(Gtk.MessageDialog): def __init__(self, string: str) -> None: super().__init__( title=dialog_header, text=dialog_error, transient_for=None, - buttons=Gtk.ButtonsType.OK + buttons=Gtk.ButtonsType.OK, ) msg = textwrap.fill(string, 50) self.format_secondary_text(msg) - self.action_area.set_margin_bottom(20) + aa = self.get_action_area() + aa.set_margin_bottom(20) + # self.action_area.set_margin_bottom(20) self.outer = self.get_content_area() self.outer.set_margin_start(30) self.outer.set_margin_end(30) @@ -28,7 +32,8 @@ class EarlyAlertDialog(Gtk.MessageDialog): self.set_default_size(250, 100) abort = self.get_widget_for_response(Gtk.ResponseType.OK) - abort.set_label("Exit") + if abort is not None and hasattr(abort, "set_label"): + abort.set_label("Exit") self.connect("response", self._on_response) self.run() @@ -41,10 +46,10 @@ class EarlyAlertDialog(Gtk.MessageDialog): case Gtk.ResponseType.CANCEL: return + class EarlyIgnoreDialog(EarlyAlertDialog): def __init__(self, string: str) -> None: super().__init__(string=string) # TODO: reverse order self.add_button("Ignore", Gtk.ResponseType.CANCEL) - diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index 7e25da2..eb10d58 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -205,7 +205,9 @@ class ExceptionDialog(GenericDialog): self.add_button("OK", Gtk.ResponseType.OK) self.show_all() - self.action_area.get_children()[1].grab_focus() + self.ok = self.get_widget_for_response(Gtk.ResponseType.OK) + if self.ok is not None: + self.ok.grab_focus() self.connect("response", self._on_response) def get_trace(self) -> str: diff --git a/dzgui/views/dialogs/servers.py b/dzgui/views/dialogs/servers.py index 9ea36bf..14cb719 100644 --- a/dzgui/views/dialogs/servers.py +++ b/dzgui/views/dialogs/servers.py @@ -1,6 +1,7 @@ from typing import Self, TYPE_CHECKING from dzgui.const.constants import EXPAND, FILL +from dzgui.const.enum import ContextMenuGroup from dzgui.model.model_factory import ModelFactory from dzgui.util import css from dzgui.util import strings @@ -20,7 +21,13 @@ if TYPE_CHECKING: class ServerDialog(GenericDialog): - def __init__(self, controller: "Controller", title: str, secondary: str) -> None: + def __init__( + self, + controller: "Controller", + title: str, + secondary: str, + menu: ContextMenuGroup | None, + ) -> None: super().__init__( controller=controller, text=title, @@ -32,7 +39,7 @@ class ServerDialog(GenericDialog): self.set_default_response(Gtk.ResponseType.OK) self.set_size_request(800, 700) - self.view = TreeView(controller) + self.view = TreeView(controller, menu) self.view.set_fixed_height_mode(True) self.connect("response", self._on_response) @@ -59,7 +66,7 @@ class ServerDialog(GenericDialog): class ServerDetailsDialog(ServerDialog): def __init__(self, controller: "Controller", details: "Details"): name = controller.get_server_name() - super().__init__(controller, strings.server_details, name) + super().__init__(controller, strings.server_details, name, menu=None) self.store = Gtk.ListStore(str, str, Pango.Weight) self.view.connect("row-activated", self._on_row_activated) @@ -116,10 +123,16 @@ class ServerDetailsDialog(ServerDialog): class ServerModDialog(ServerDialog): - def __init__(self, controller: "Controller", mods: list[list[str]]): + def __init__( + self, + controller: "Controller", + mods: list[list[str]], + ): name = controller.get_server_name() - super().__init__(controller, server_mods.modlist, name) + super().__init__( + controller, server_mods.modlist, name, menu=ContextMenuGroup.SERVER_MOD + ) self.controller = controller self.mod_store = ModelFactory().make_server_mod_store() diff --git a/dzgui/views/mixins/context_mixin.py b/dzgui/views/mixins/context_mixin.py index 66c6eed..0d1144d 100644 --- a/dzgui/views/mixins/context_mixin.py +++ b/dzgui/views/mixins/context_mixin.py @@ -21,6 +21,8 @@ class ContextMixin(TreeView): event: Gdk.EventButton | Gdk.EventKey, ) -> bool: + if self.menu is None: + return False if self.is_selection_empty(): return False diff --git a/dzgui/views/pages/devs.py b/dzgui/views/pages/devs.py index a58adcf..7c95255 100644 --- a/dzgui/views/pages/devs.py +++ b/dzgui/views/pages/devs.py @@ -64,7 +64,7 @@ class Developers(Gtk.ScrolledWindow): self.controller.open_page(NotebookPage.OPTIONS) def _make_tree(self, prefs: Union["Xdg", "UserPrefs"]) -> Gtk.TreeView: - tree = TreeView(self.controller) + tree = TreeView(self.controller, menu=None) renderer = Gtk.CellRendererText() for i, col in enumerate(developers.columns): column = Gtk.TreeViewColumn(col, renderer, text=i) @@ -73,12 +73,6 @@ class Developers(Gtk.ScrolledWindow): store = self._make_store(prefs) tree.set_model(store) - # store = Gtk.ListStore(str, str) - # for field in fields(prefs): - # if field.name == "paths": - # continue - # k, v = field.name, getattr(prefs, field.name) - # store.append((k, str(v))) return tree diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 01f8f11..367fe12 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -237,7 +237,7 @@ class Options(Gtk.Box): def get_client_name(self) -> str: model = self.client_combo.get_model() ind = self.client_combo.get_active() - return model[ind][0] + return str(model[ind][0]) def block_text_entry(self) -> None: for entry in self.steam_entry, self.bm_entry: @@ -352,12 +352,16 @@ class Options(Gtk.Box): def _on_start_tab_changed(self, combo: Gtk.ComboBoxText) -> None: _iter = combo.get_active_iter() + if _iter is None: + raise ValueError(f"No active iterator set on {combo}") enum = combo.get_model()[_iter][1] index = enum.value self.controller.update_config(Preferences.START_TAB, index) def _on_client_changed(self, combo: Gtk.ComboBoxText) -> None: _iter = combo.get_active_iter() + if _iter is None: + raise ValueError(f"No active iterator set on {combo}") real_cmd = combo.get_model()[_iter][1] self.controller.update_config(Preferences.CLIENT, real_cmd) diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index 63fb091..4c0ef6c 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -153,14 +153,14 @@ class ServerNotebook(Gtk.ScrolledWindow): if tv is not None: self.controller.populate_model(tv) - def get_active_treeview(self) -> ServerTreeView | None: + def get_active_treeview(self) -> ServerTreeView: index = self.notebook.get_current_page() scrollable = self.notebook.get_nth_page(index) if scrollable is not None and hasattr(scrollable, "get_children"): tv = scrollable.get_children()[0] if isinstance(tv, ServerTreeView): return tv - return None + raise ValueError("No treeview set") def add_notification(self) -> None: saved = self.notebook.get_nth_page(1) diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index 6b66222..ac0733a 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -21,7 +21,7 @@ if TYPE_CHECKING: class TreeView(CursorMixin, Gtk.TreeView): # type: ignore def __init__( - self, controller: "Controller", menu: Optional["ContextMenuGroup"] = None + self, controller: "Controller", menu: Optional["ContextMenuGroup"] ) -> None: super().__init__( enable_search=False, @@ -72,10 +72,13 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return model.get_iter(path) def get_focused_row_path(self) -> Gtk.TreePath: - return self.get_cursor().path + path, column = self.get_cursor() + return path def get_focused_row_index(self) -> int: - return self.get_cursor().path[0] + path, column = self.get_cursor() + index = path.get_indices()[0] + return index def get_selected_records(self) -> list: sel = self.get_selection() @@ -140,7 +143,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore path = Gtk.TreePath.new_from_indices([0]) self.set_cursor(path) - def get_value_at_index(self, index: int) -> str: + def get_value_at_index(self, index: int) -> Any: (model, pathlist) = self.get_model_and_pathlist() if len(pathlist) < 1: return "" @@ -151,7 +154,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore def get_name(self) -> str: name = self.get_value_at_index(0) - return name + return str(name) def select_first_row(self) -> None: sel = self.get_selection() @@ -164,7 +167,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return (model, pathlist) @deprecated("Currently unused") - #def get_mpath(self) -> Optional[Gtk.TreePath]: + # def get_mpath(self) -> Optional[Gtk.TreePath]: # (model, pathlist) = self.get_model_and_pathlist() # if len(pathlist) < 1: # return None @@ -186,7 +189,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return False @deprecated("unused") - #def get_selected_row(self) -> Optional[Gtk.TreeModelRow]: + # def get_selected_row(self) -> Optional[Gtk.TreeModelRow]: # ind = self.get_selected_row_index() # model = self.get_model() # if model is None: diff --git a/dzgui/views/trees/tree_log.py b/dzgui/views/trees/tree_log.py index 855b41e..c4c71f7 100644 --- a/dzgui/views/trees/tree_log.py +++ b/dzgui/views/trees/tree_log.py @@ -91,7 +91,7 @@ class LogTreeView(ContextMixin, TreeView): # type: ignore return None for record in records: raw_record = model[record] - els = tuple(raw_record) + els: tuple[Any] = tuple(raw_record) # type: ignore concat = strings.delimiter.join(map(str, els)) final.append(concat) text = "\n".join(final) diff --git a/dzgui/views/trees/tree_menu.py b/dzgui/views/trees/tree_menu.py index e800998..04a17f2 100644 --- a/dzgui/views/trees/tree_menu.py +++ b/dzgui/views/trees/tree_menu.py @@ -25,7 +25,7 @@ class MenuTreeView(TreeView): """ def __init__(self, controller: "Controller") -> None: - super().__init__(controller) + super().__init__(controller, menu=None) self.controller = controller @@ -73,6 +73,8 @@ class MenuTreeView(TreeView): def get_row_enum(self) -> str: # NOTE: col 1 contains a RowType enum model = self.get_model() + if model is None: + raise ValueError("Trying to call a method on non-existent model") _iter = self.get_focused_row_iter() rowtype = model.get_value(_iter, 1) return str(rowtype.dict["tooltip"]) diff --git a/dzgui/views/trees/tree_mods.py b/dzgui/views/trees/tree_mods.py index 108f9ef..130708f 100644 --- a/dzgui/views/trees/tree_mods.py +++ b/dzgui/views/trees/tree_mods.py @@ -73,7 +73,7 @@ class ModTreeView(ModsMixin, ContextMixin, TreeView): # type: ignore 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(tree_iter, 2)[0] + mod = model.get_value(tree_iter, 2) return str(mod) def _parent_selection_changed( diff --git a/dzgui/views/trees/tree_server_mods.py b/dzgui/views/trees/tree_server_mods.py index d3eb436..570f9f1 100644 --- a/dzgui/views/trees/tree_server_mods.py +++ b/dzgui/views/trees/tree_server_mods.py @@ -65,7 +65,7 @@ class ServerModTreeView(ContextMixin, TreeView): # type: ignore raise AttributeError("Trying to call a method on a non-existent model") tree_iter = model.get_iter(path) # FIXME: https://docs.gtk.org/gtk3/method.TreeModel.get.html - mod = model.get(tree_iter, 1)[0] + mod = model.get_value(tree_iter, 1) return str(mod) def populate(self, mods: list[list[str]]) -> None: diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index cf1ada5..8020506 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -292,7 +292,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore self.start_distcalc() def get_name(self) -> str: - return self.get_value_at_index(0) + return str(self.get_value_at_index(0)) def get_simplified_ip(self) -> str: addr = self.get_value_at_index(7) diff --git a/tests/test_config.py b/tests/test_config.py index 601eb9b..4cfd754 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -23,7 +23,6 @@ def keys(): "name", "fullscreen", "steam_api", - "auto_install", "default_steam_path", "client", "ip_list", @@ -32,6 +31,7 @@ def keys(): ] +# TODO: use a static fixture instead of system config @pytest.fixture def config(): paths = get_xdg_paths() @@ -69,7 +69,6 @@ def test_bool_conversion(fixture, expect): j = convert.rc2json(fixture) j = json.loads(j) assert j["fullscreen"] == expect[0] - assert j["auto_install"] == expect[2] assert not j["use_miles"]