From 2dbdc3f92826262ffc61f6a16d803600f1df0549 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Mon, 4 May 2026 01:43:41 +0900 Subject: [PATCH] feat: HeadingFrame class --- dzgui/controllers/mc.py | 2 +- dzgui/views/components/frame.py | 21 +++++++++ dzgui/views/pages/options.py | 28 ++++------- dzgui/views/pages/preconnect.py | 84 +++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 dzgui/views/components/frame.py create mode 100644 dzgui/views/pages/preconnect.py diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 53af881..785c790 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -37,9 +37,9 @@ from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402 logger = logging.getLogger(APP_NAME) if TYPE_CHECKING: + from dayzquery import DayzMod from dzgui.api.servers import Record from dzgui.const.enum import ServerTab - from dzgui.lib.dayzquery import DayzMod from dzgui.managers.filter import FilterManager from dzgui.util.dist import Haversine from dzgui.views.base import Notebook, Grid, OuterWindow diff --git a/dzgui/views/components/frame.py b/dzgui/views/components/frame.py new file mode 100644 index 0000000..d08c16d --- /dev/null +++ b/dzgui/views/components/frame.py @@ -0,0 +1,21 @@ +from dzgui.util import strings, css, open_links + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk # noqa + +class HeadingFrame(Gtk.Box): + def __init__(self, widget: Gtk.Widget, heading: str) -> None: + super().__init__(orientation=Gtk.Orientation.VERTICAL) + + label = Gtk.Label(label=heading) + label.set_halign(Gtk.Align.START) + # TODO: rename selector + css.add_class(label, "settings-subheading") + + frame = Gtk.Frame(hexpand=True) + frame.add(widget) + frame.set_label_widget(label) + + self.add(frame) diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 62ba69b..0a82df2 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -9,6 +9,7 @@ from dzgui.util import strings, css, open_links from dzgui.views.components.labels import LeftLabel from dzgui.views.components.eventbox import InfoEventBox from dzgui.views.components.buttons import WebButton +from dzgui.views.components.frame import HeadingFrame from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.dialogs.link_dialog import WorkshopLinkDialog @@ -178,10 +179,10 @@ class Options(Gtk.Box): 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), - self.make_frame(mods_grid, strings.options.mods), - self.make_frame(version_grid, strings.options.version), + HeadingFrame(api_box, strings.options.api_keys), + HeadingFrame(prefs_grid, strings.options.prefs), + HeadingFrame(mods_grid, strings.options.mods), + HeadingFrame(version_grid, strings.options.version), ]: grid.attach(frame, col, row, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT) row += 1 @@ -405,29 +406,16 @@ class Options(Gtk.Box): return hbox - def make_frame(self, widget: Gtk.Widget, text: str) -> Gtk.Box: - label = Gtk.Label(label=text) - label.set_halign(Gtk.Align.START) - css.add_class(label, "settings-subheading") - - frame = Gtk.Frame(hexpand=True) - frame.add(widget) - frame.set_label_widget(label) - - box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - box.add(frame) - - return box - def populate_settings(self) -> None: prefs = self.controller.get_prefs() + # NOTE: re-check in case file was removed by user between runs if prefs.paths.config.is_file() is False: - # NOTE: in case file got deleted locally dialog = ExceptionDialog(self.controller, strings.config_not_found) dialog.run() raise Exception config = query.get_config(prefs.paths.config) + # TODO: use newer config enums name = config["name"] default_steam_path = config["default_steam_path"] steam = config["steam_api"] @@ -435,6 +423,7 @@ class Options(Gtk.Box): install = config["auto_install"] steam_path = Path(default_steam_path) + # NOTE: this is a best effort guess at the most recent user uid = find_user_id(steam_path) self.uid = "" if uid is None else uid @@ -468,6 +457,7 @@ class Options(Gtk.Box): if field[0] == "": field[1].get_children()[1].set_sensitive(False) + # TODO: abstract this logic try: pe_file_path = PeFile.get_pefile_path(steam_path, APPID_DAYZ) vers = PeFile.get_dayz_version(pe_file_path) diff --git a/dzgui/views/pages/preconnect.py b/dzgui/views/pages/preconnect.py new file mode 100644 index 0000000..8eb0a4a --- /dev/null +++ b/dzgui/views/pages/preconnect.py @@ -0,0 +1,84 @@ +from typing import Any, TYPE_CHECKING + +from dzgui.api import pefile as PeFile +from dzgui.const.constants import ( + APPID_DAYZ, + APPID_DAYZ_EXP, + APPNAME_DAYZ, + APPNAME_DAYZ_EXP, +) +from dayzquery import DayzMod +from dzgui.views.components.frame import HeadingFrame + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk # type: ignore # noqa E402 + + +if TYPE_CHECKING: + from dzgui.controllers.mc import Controller + + +class PreConnectionAssistant(Gtk.Box): + def __init__(self, controller: "Controller") -> None: + super().__init__() + + self.controller = controller + + self.button_box = Gtk.Box( + orientation=Gtk.Orientation.HORIZONTAL, + halign=Gtk.Align.END, + valign=Gtk.Align.END, + hexpand=True, + spacing=10, + ) + + self.rules: dict[Any] + self.mods: list["DayzMod"] + + # TODO: pack in scrolled window + + # TODO: strings + self.back = Gtk.Button(label="Back") + # TODO: dynamic button text if no mods needed + self.ok = Gtk.Button(label="Download mods and connect") + self.button_box.add(self.back) + self.button_box.add(self.ok) + + self.ok.connect("clicked", self._on_ok_clicked) + self.back.connect("clicked", self._on_back_clicked) + + self.warnings = [] + # TODO: populate with strings and icons + # set visibility if warnings > 1 + frame = HeadingFrame(Gtk.Label(label="ITEM ONE"), "Warnings") + self.add(frame) + + self.add(self.button_box) + + def _on_ok_clicked(self, button: Gtk.Button) -> None: + # TODO: update mod store in place with spinner/toast + # TODO: cancel mod downloads + pass + + def _on_back_clicked(self, button: Gtk.Button) -> None: + page = self.controller.get_prior_page() + self.controller.open_page(page) + + def populate(self, res: dict[Any], mods: list["DayzMod"]) -> None: + # TODO: compare remote and local build versions + # try: + # pe_file_path = PeFile.get_pefile_path(steam_path, APPID_DAYZ) + # vers = PeFile.get_dayz_version(pe_file_path) + # dayz_version = PeFile.dayz_version_to_str(vers) + # except Exception: + # dayz_version = strings.null + + # try: + # exp_file_path = PeFile.get_pefile_path(steam_path, APPID_DAYZ_EXP) + # vers = PeFile.get_dayz_version(exp_file_path) + # dayz_exp_version = PeFile.dayz_version_to_str(vers) + # except Exception: + # dayz_exp_version = strings.null + pass