diff --git a/CHANGELOG.md b/CHANGELOG.md index 50ed167..faf81e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Rearrange menus/breadcrumbs - Documentation ships with source - Open filepicker when generating system log +- Developers page (and -d flag) ## Changed - Reduce padding on keys button diff --git a/dzgui/const/enum.py b/dzgui/const/enum.py index 468dab7..4cc0ea1 100644 --- a/dzgui/const/enum.py +++ b/dzgui/const/enum.py @@ -88,6 +88,7 @@ class NotebookPage(EnumWithAttrs): OPTIONS = {"crumbs": strings.crumbs.options,} SERVERS = {"crumbs": strings.crumbs.servers,} THANKS = {"crumbs": strings.crumbs.thanks,} + DEVELOPERS = {"crumbs": strings.crumbs.developers,} class RowType(EnumWithAttrs): diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index f47ae7c..06973a2 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -70,6 +70,7 @@ class Controller: self.log_store = Gtk.ListStore(str, str, str, str) self.notes_cache: dict[str, str] = {} + self.is_developer: bool self.mediator: AppNavigation self.prefs: UserPrefs @@ -283,6 +284,9 @@ class Controller: def toggle_mod_panel(self, state: bool) -> None: self.mediator.grid.sel_panel.set_visible(state) + def show_developers_page(self) -> None: + self.open_page(NotebookPage.DEVELOPERS) + def open_page(self, page: NotebookPage) -> None: self.mediator.grid.notebook.set_page_by_enum(page) @@ -543,3 +547,9 @@ class Controller: h = WINDOW_DEFAULT_Y logger.info(f"Using default window size {w},{h}") window.set_default_size(w, h) + + def set_developer_mode(self, mode: bool) -> None: + self.is_developer = mode + + def get_developer_mode(self) -> bool: + return self.is_developer diff --git a/dzgui/data/CHANGELOG.md b/dzgui/data/CHANGELOG.md index 50ed167..faf81e5 100644 --- a/dzgui/data/CHANGELOG.md +++ b/dzgui/data/CHANGELOG.md @@ -12,6 +12,7 @@ - Rearrange menus/breadcrumbs - Documentation ships with source - Open filepicker when generating system log +- Developers page (and -d flag) ## Changed - Reduce padding on keys button diff --git a/dzgui/main.py b/dzgui/main.py index a609b5d..e08615b 100644 --- a/dzgui/main.py +++ b/dzgui/main.py @@ -37,6 +37,7 @@ parser = argparse.ArgumentParser(description=flags.description) parser.add_argument("-v", "--version", action="store_true", help=flags.version) parser.add_argument("-u", "--uninstall", action="store_true", help=flags.uninstall) +parser.add_argument("-d", "--developers", action="store_true", help=flags.developers) args = parser.parse_args() # TODO: profile load time @@ -112,4 +113,4 @@ def main() -> None: XDG ) print("All OK. Loading UI...") - App(prefs) + App(prefs, args.developers) diff --git a/dzgui/util/strings.py b/dzgui/util/strings.py index fe7fbff..c472474 100644 --- a/dzgui/util/strings.py +++ b/dzgui/util/strings.py @@ -265,6 +265,7 @@ class Crumbs: options: str servers: str thanks: str + developers: str @dataclass(slots=True, frozen=True) class Thanks: @@ -448,7 +449,8 @@ crumbs = Crumbs( my_servers="Main menu > Saved servers", options="Options", servers="Main menu > Server browser", - thanks="Help > Special thanks" + thanks="Help > Special thanks", + developers="Options > Developers", ) checkmark = "✓" @@ -459,11 +461,13 @@ class Flags: description: str version: str uninstall: str + developers: str flags = Flags( description="DayZ server browser and mod manager", version="Print version information", - uninstall="Uninstall data files (use prior to 'pip uninstall')" + uninstall="Uninstall data files (use prior to 'pip uninstall')", + developers="Enables developer debugging features", ) @dataclass(slots=True, frozen=True) @@ -477,3 +481,18 @@ picker = FilePicker( ) api_error = "API key validation error or timeout. See 'Help > Show debug log' for details." + + +@dataclass(slots=True, frozen=True) +class DevelopersPage: + header: str + paths_label: str + prefs_label: str + columns: list[str] + +developers = DevelopersPage( + header="Developers", + paths_label="Resolved XDG paths", + prefs_label="Boot preferences", + columns=["Key", "Value"] +) diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 248ca66..5983444 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -364,6 +364,10 @@ class Notebook(ScrollableMixin, Gtk.Notebook): self.thanks = ScrollableNote(Thanks(), back_button=False) + from dzgui.views.pages.devs import Developers + developers = Developers(MainController) + self.developers = ScrollableNote(developers) + self.pages = { self.scrollable_treelist: NotebookPage.MAIN, self.clog: NotebookPage.CHANGELOG, @@ -372,7 +376,8 @@ class Notebook(ScrollableMixin, Gtk.Notebook): self.ssu: NotebookPage.SERVERS, self.scroll_mod: NotebookPage.MODS, self.scroll_log: NotebookPage.LOG, - self.thanks: NotebookPage.THANKS + self.thanks: NotebookPage.THANKS, + self.developers: NotebookPage.DEVELOPERS, } self.indexes = {} @@ -621,9 +626,10 @@ class Grid(Gtk.Grid): class App(Gtk.Application): - def __init__(self, prefs) -> None: + def __init__(self, prefs, is_developer) -> None: GLib.set_prgname(APP_NAME) MainController.set_prefs(prefs) + MainController.set_developer_mode(is_developer) self.win = OuterWindow() diff --git a/dzgui/views/pages/devs.py b/dzgui/views/pages/devs.py new file mode 100644 index 0000000..80f53aa --- /dev/null +++ b/dzgui/views/pages/devs.py @@ -0,0 +1,84 @@ +import typing + +import gi # noqa E402 +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + +from dataclasses import fields +from typing import Union, TYPE_CHECKING + +from dzgui.const.enum import NotebookPage +from dzgui.util.strings import developers +from dzgui.util.css import add_class + +if TYPE_CHECKING: + from dzgui.controllers.mc import Controller + from dzgui.config.userprefs import UserPrefs + from dzgui.config.xdg import Xdg + +class Developers(Gtk.Box): + """ + Shows TreeViews displaying contents of parsed XDG paths + and user preferences + """ + def __init__(self, controller: "Controller") -> None: + super().__init__( + orientation=Gtk.Orientation.VERTICAL, + margin_start=10, + margin_end=10, + ) + + self.controller = controller + + heading = Gtk.Label(label=developers.header) + heading.set_halign(Gtk.Align.CENTER) + add_class(heading, "page-heading") + + back_button = Gtk.Button(label="Back", halign=Gtk.Align.START) + back_button.connect("clicked", self._on_back_clicked) + paths_label = Gtk.Label() + paths_label.set_markup(f"{developers.paths_label}") + + prefs_label = Gtk.Label() + prefs_label.set_markup(f"{developers.prefs_label}") + + paths_tree = self._make_tree(self.controller.prefs.paths) + prefs_tree = self._make_tree(self.controller.prefs) + trees_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) + + path = Gtk.TreePath.new_from_indices([0]) + paths_tree.set_cursor(path) + prefs_tree.set_cursor(path) + + for el in [ + paths_label, + paths_tree, + prefs_label, + prefs_tree + ]: + trees_box.add(el) + + self.add(heading) + self.add(back_button) + self.add(trees_box) + + def _on_back_clicked(self, button: Gtk.Button) -> None: + self.controller.open_page(NotebookPage.OPTIONS) + + def _make_tree(self, prefs: Union["Xdg", "UserPrefs"]) -> Gtk.TreeView: + view = Gtk.TreeView() + renderer = Gtk.CellRendererText() + for i, col in enumerate(developers.columns): + column = Gtk.TreeViewColumn(col, renderer, text=i) + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) + view.append_column(column) + + store = Gtk.ListStore(str, str) + for field in fields(prefs): + if field.name == "paths": + break + k, v = field.name, getattr(prefs, field.name) + store.append((k, str(v))) + + view.set_model(store) + return view diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 80f63f6..d9946de 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -166,6 +166,13 @@ class Options(Gtk.Box): hexpand=True, ) + developers=Gtk.Button(label="Developers", halign=Gtk.Align.START) + developers.connect("clicked", self._on_developers_clicked) + if self.controller.get_developer_mode(): + grid.attach( + developers, 1, 0, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT + ) + for frame in [ self.make_frame(api_box, strings.options.api_keys), self.make_frame(prefs_grid, strings.options.prefs), @@ -181,6 +188,9 @@ class Options(Gtk.Box): self.scrollable.add(grid) self.add(self.scrollable) + def _on_developers_clicked(self, button: Gtk.Button) -> None: + self.controller.show_developers_page() + def _on_link_button_clicked(self, button: Gtk.Button, url: str) -> None: open_links.open_link_by_url(url)