From 87d76e83badcc8fd12284ad70ebabf19c9e14e62 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 06:57:56 +0900 Subject: [PATCH 01/23] chore: update DEVELOPERS.md --- DEVELOPERS.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/DEVELOPERS.md b/DEVELOPERS.md index b201138..abecac9 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -5,7 +5,7 @@ ### Fetch submodules git submodule update --recursive --init -### Install with dev dependencies +### Install into editable venv with dev dependencies uv pip install -e '.[dev]' This includes all dependencies for building, linting, testing, and checking in code. @@ -16,7 +16,7 @@ docs: documentation tools lint: code linting, fixing, and type checking test: unit and integration tests -## Miscellaneous +## Build process ### Setting up precommit hooks pre-commit install @@ -25,6 +25,7 @@ pre-commit install sphinx-build -M html source build -a ### Building standalone release binaries -1. Set up the build target: `rustup target add x86_64-unknown-linux-musl` -2. Run `python3 scripts/release.py` -3. Generate a release and tag against the resulting tarfile generated in `dist` +1. Install the applicable system package containing the 'musl-gcc' wrapper +2. Set up the build target: `rustup target add x86_64-unknown-linux-musl` +3. Run `python3 scripts/release.py` +4. Generate a release and tag against the resulting tarfile generated in `dist` From b98a6f95a6e1370d5a206a3f127f258665f9573c Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:00:17 +0900 Subject: [PATCH 02/23] drop: unused imports --- dzgui/api/mods.py | 1 - dzgui/app_init.py | 3 +-- dzgui/controllers/mc.py | 11 +++-------- dzgui/views/components/box.py | 6 +++--- dzgui/views/components/frame.py | 9 +++++---- dzgui/views/components/misc.py | 5 ++--- dzgui/views/components/scrollable.py | 2 +- dzgui/views/dialogs/boot.py | 16 +++++----------- dzgui/views/dialogs/servers.py | 2 +- dzgui/views/mixins/colorscheme.py | 6 +++--- dzgui/views/mixins/help_menu_mixin.py | 2 +- dzgui/views/mixins/scrollable_mixin.py | 6 +++--- dzgui/views/pages/mods.py | 5 ++--- dzgui/views/pages/offline.py | 12 ++++++------ dzgui/views/pages/options.py | 11 ++++------- dzgui/views/trees/tree_base.py | 5 ++--- dzgui/views/trees/tree_menu.py | 2 +- dzgui/views/trees/tree_mods.py | 6 +++--- dzgui/views/trees/tree_server_mods.py | 10 +++++----- dzgui/views/trees/tree_servers.py | 12 ++++-------- dzgui/views/trees/tree_simple.py | 10 +++++----- tests/test_colorscheme.py | 5 ++--- 22 files changed, 62 insertions(+), 85 deletions(-) diff --git a/dzgui/api/mods.py b/dzgui/api/mods.py index 234835d..1d59528 100644 --- a/dzgui/api/mods.py +++ b/dzgui/api/mods.py @@ -3,7 +3,6 @@ import logging import re from concurrent.futures import ThreadPoolExecutor, wait -from dataclasses import dataclass from pathlib import Path from typing import Any diff --git a/dzgui/app_init.py b/dzgui/app_init.py index 96ff4d1..30e3a6d 100644 --- a/dzgui/app_init.py +++ b/dzgui/app_init.py @@ -6,7 +6,6 @@ from importlib import resources from pathlib import Path from typing import TYPE_CHECKING - from dzgui.const.constants import ( APP_NAME, APP_NAME_LOWER, @@ -107,7 +106,7 @@ def load_steam_icon() -> None: import gi gi.require_version("Gtk", "3.0") - from gi.repository import Gtk # noqa + from gi.repository import Gtk try: traversable = resources.files(APP_NAME_LOWER).joinpath(ICONS_PATH) diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 58de7d2..151e6ed 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -1,11 +1,11 @@ +import gi import logging import threading from typing import Any, TYPE_CHECKING, Union -import dzgui.util._json as JSON # noqa - - +from dzgui.config.userprefs import UserPrefs +from dzgui.const.constants import APP_NAME from dzgui.const.enum import ( ButtonType, ContextMenuItem, @@ -14,9 +14,6 @@ from dzgui.const.enum import ( Preferences, ServerTab, ) - -from dzgui.config.userprefs import UserPrefs -from dzgui.const.constants import APP_NAME from dzgui.controllers.emitter import Emitter from dzgui.managers.config import ConfigManager from dzgui.managers.connection import ConnectionManager @@ -29,8 +26,6 @@ from dzgui.util.open_links import open_user_workshop, open_workshop_page from dzgui.views.dialogs.filepicker import FilePicker from dzgui.views.dialogs.generic import ExceptionDialog -import gi - gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk, GLib, GObject diff --git a/dzgui/views/components/box.py b/dzgui/views/components/box.py index d581255..b48b29a 100644 --- a/dzgui/views/components/box.py +++ b/dzgui/views/components/box.py @@ -1,9 +1,9 @@ -from typing import Sequence - import gi +from typing import Sequence + gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa +from gi.repository import Gtk class GenericBox(Gtk.Box): diff --git a/dzgui/views/components/frame.py b/dzgui/views/components/frame.py index dab2671..e245dff 100644 --- a/dzgui/views/components/frame.py +++ b/dzgui/views/components/frame.py @@ -1,10 +1,11 @@ -from typing import Self -from dzgui.util import css - import gi +from typing import Self + +from dzgui.util import css + gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa +from gi.repository import Gtk # TODO: subclass Gtk.Frame directly diff --git a/dzgui/views/components/misc.py b/dzgui/views/components/misc.py index 80e694e..dbef1f6 100644 --- a/dzgui/views/components/misc.py +++ b/dzgui/views/components/misc.py @@ -1,3 +1,4 @@ +import gi from typing import Self from warnings import deprecated @@ -8,10 +9,8 @@ from dzgui.strings import options from dzgui.views.components.box import HBox from dzgui.views.components.buttons import Icon -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa +from gi.repository import Gtk @deprecated("Client choice is determined at setup time") diff --git a/dzgui/views/components/scrollable.py b/dzgui/views/components/scrollable.py index 294ca53..c592549 100644 --- a/dzgui/views/components/scrollable.py +++ b/dzgui/views/components/scrollable.py @@ -1,7 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa +from gi.repository import Gtk class NoOverlayScrolledWindow(Gtk.ScrolledWindow): diff --git a/dzgui/views/dialogs/boot.py b/dzgui/views/dialogs/boot.py index bfc0b1e..5a8a718 100644 --- a/dzgui/views/dialogs/boot.py +++ b/dzgui/views/dialogs/boot.py @@ -1,13 +1,9 @@ +import gi import sys + +from enum import Enum from typing import Any, Literal, Self, TYPE_CHECKING -# import time -from enum import Enum - - -from dzgui.views.mixins.colorscheme import ColorAwareApp - -# TODO: import dialog titles from dzgui.api.mods import remove_stale_signatures as remove_stale from dzgui.config.ipdb import get_ipdb from dzgui.const.constants import HEX_GREEN, HEX_RED @@ -20,12 +16,10 @@ from dzgui.util.format import format_exception from dzgui.util.strings import dialog_header from dzgui.util.symlink import rebuild_symlinks from dzgui.views.components.buttons import ClipboardButton - - -import gi +from dzgui.views.mixins.colorscheme import ColorAwareApp gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk # noqa +from gi.repository import Gtk, GLib, Gdk if TYPE_CHECKING: from dzgui.config.xdg import Xdg diff --git a/dzgui/views/dialogs/servers.py b/dzgui/views/dialogs/servers.py index b58d352..643d132 100644 --- a/dzgui/views/dialogs/servers.py +++ b/dzgui/views/dialogs/servers.py @@ -15,7 +15,7 @@ from dzgui.views.dialogs.generic import GenericDialog from dzgui.views.trees.tree_base import TreeView gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, Pango # noqa +from gi.repository import Gtk, Gdk, Pango if TYPE_CHECKING: from dzgui.api.servers import Details diff --git a/dzgui/views/mixins/colorscheme.py b/dzgui/views/mixins/colorscheme.py index 2e0be9c..f70a1bd 100644 --- a/dzgui/views/mixins/colorscheme.py +++ b/dzgui/views/mixins/colorscheme.py @@ -1,3 +1,5 @@ +import gi + from typing import Any from dzgui.const.constants import ( @@ -7,10 +9,8 @@ from dzgui.const.constants import ( GIO_SETTINGS_VAL, ) -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gio # noqa +from gi.repository import Gtk, Gio class ColorAwareApp: diff --git a/dzgui/views/mixins/help_menu_mixin.py b/dzgui/views/mixins/help_menu_mixin.py index d287bb7..5ef6fda 100644 --- a/dzgui/views/mixins/help_menu_mixin.py +++ b/dzgui/views/mixins/help_menu_mixin.py @@ -1,7 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa +from gi.repository import Gtk, Gdk class HelpMenuMixin: diff --git a/dzgui/views/mixins/scrollable_mixin.py b/dzgui/views/mixins/scrollable_mixin.py index 79d83b8..db99c81 100644 --- a/dzgui/views/mixins/scrollable_mixin.py +++ b/dzgui/views/mixins/scrollable_mixin.py @@ -1,10 +1,10 @@ +import gi + from dzgui.const.enum import VAdjustment from dzgui.const.constants import SCROLL_INCREMENT -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa +from gi.repository import Gtk, Gdk class ScrollableMixin: diff --git a/dzgui/views/pages/mods.py b/dzgui/views/pages/mods.py index 05696a7..5903091 100644 --- a/dzgui/views/pages/mods.py +++ b/dzgui/views/pages/mods.py @@ -1,3 +1,4 @@ +import gi from pathlib import Path from typing import Self, TYPE_CHECKING @@ -8,10 +9,8 @@ from dzgui.views.components.buttons import SteamWorkshopButton from dzgui.views.components.scrollable import NoOverlayScrolledWindow from dzgui.views.trees.tree_mods import ModTreeView -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/offline.py b/dzgui/views/pages/offline.py index ceb5686..141c722 100644 --- a/dzgui/views/pages/offline.py +++ b/dzgui/views/pages/offline.py @@ -1,9 +1,10 @@ from __future__ import annotations + +import gi + from enum import Enum from typing import Self, TYPE_CHECKING, Union -from dzgui.util import css -from dzgui.const.icons import ICON_EDIT_DELETE, ICON_FOLDER, ICON_WARNING from dzgui.const.constants import ( APPID_DAYZ, APPID_DAYZ_EXP, @@ -11,8 +12,10 @@ from dzgui.const.constants import ( APPNAME_DAYZ_EXP_HUMAN, ) from dzgui.const.enum import ContextMenuGroup, NotebookPage +from dzgui.const.icons import ICON_EDIT_DELETE, ICON_FOLDER, ICON_WARNING from dzgui.managers.offline import OfflineManager from dzgui.strings import generic, offline +from dzgui.util import css from dzgui.views.components.box import HBox, VBox from dzgui.views.components.buttons import Icon, IconTextButton from dzgui.views.components.eventbox import InfoEventBox @@ -21,11 +24,8 @@ from dzgui.views.components.scrollable import NoOverlayScrolledWindow from dzgui.views.components.misc import ErrorPopover from dzgui.views.trees.tree_mods import OfflineModTreeView - -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GObject # noqa +from gi.repository import Gtk, Gdk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 1fa3fbb..533fa67 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -1,9 +1,10 @@ +import gi + from pathlib import Path from typing import Any, Callable, TYPE_CHECKING from dzgui.api import pefile as PeFile from dzgui.api.steam import get_last_updated - from dzgui.config import query from dzgui.const.constants import ( APPID_DAYZ, @@ -14,12 +15,11 @@ from dzgui.const.constants import ( FLATPAK_SANDBOX, FLATPAK_STEAM_PATH, ) -from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.const.endpoints import STEAM_API_SETUP from dzgui.const.enum import Preferences, ServerTab +from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.strings import options from dzgui.util import strings, css, open_links - from dzgui.views.components.box import ShortHBox, VBox from dzgui.views.components.eventbox import InfoEventBox from dzgui.views.components.labels import LeftLabel @@ -29,11 +29,8 @@ from dzgui.views.components.misc import ErrorPopover from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.mixins.scrollable_mixin import ScrollableMixin - -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa +from gi.repository import Gtk, Gdk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index 0919b08..a8d134e 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -1,3 +1,4 @@ +import gi import logging from typing import Any, Optional, TYPE_CHECKING @@ -6,10 +7,8 @@ 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 +from gi.repository import Gtk, Gdk, GObject logger = logging.getLogger(APP_NAME) diff --git a/dzgui/views/trees/tree_menu.py b/dzgui/views/trees/tree_menu.py index a0964bc..c64b371 100644 --- a/dzgui/views/trees/tree_menu.py +++ b/dzgui/views/trees/tree_menu.py @@ -10,7 +10,7 @@ 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 +from gi.repository import Gtk logger = logging.getLogger(APP_NAME) diff --git a/dzgui/views/trees/tree_mods.py b/dzgui/views/trees/tree_mods.py index 64dd55c..aa48c38 100644 --- a/dzgui/views/trees/tree_mods.py +++ b/dzgui/views/trees/tree_mods.py @@ -1,4 +1,6 @@ +import gi import logging + from typing import Any, TYPE_CHECKING from dzgui.const.constants import APP_NAME, HEX_RED @@ -9,10 +11,8 @@ 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 +from gi.repository import Gtk, Gdk if TYPE_CHECKING: diff --git a/dzgui/views/trees/tree_server_mods.py b/dzgui/views/trees/tree_server_mods.py index fe1169c..6b6ca07 100644 --- a/dzgui/views/trees/tree_server_mods.py +++ b/dzgui/views/trees/tree_server_mods.py @@ -1,15 +1,15 @@ +import gi + +from typing import TYPE_CHECKING + from dzgui.const.enum import ContextMenuGroup from dzgui.model.model_factory import ModelFactory from dzgui.strings import server_mods from dzgui.views.mixins.context_mixin import ContextMixin from dzgui.views.trees.tree_base import TreeView -from typing import TYPE_CHECKING - -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, Pango # noqa +from gi.repository import Gtk, Pango if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 37210cb..349c19b 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -1,8 +1,9 @@ +import gi import logging import threading from queue import Queue -from typing import Any, Self, Union +from typing import Any, Literal, Self, TYPE_CHECKING, Union from warnings import deprecated from dzgui.api.servers import ping, Record @@ -14,17 +15,11 @@ from dzgui.util import strings from dzgui.util.dist import CalcDist from dzgui.util.keys import is_ctrl_mask from dzgui.views.mixins.context_mixin import ContextMixin -from typing import Literal, TYPE_CHECKING - - from dzgui.views.trees.tree_base import TreeView import dzgui.util._json as JSON # noqa -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa - +from gi.repository import Gtk, GLib, Gdk, GObject logger = logging.getLogger(APP_NAME) @@ -415,6 +410,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore real_model = self.proxy_man.get_control() from dataclasses import fields from dzgui.model.proxy_model import ServerRow + key = fields(ServerRow)[col_index].name value = getattr(real_model[row_index], key) diff --git a/dzgui/views/trees/tree_simple.py b/dzgui/views/trees/tree_simple.py index be96668..8bd9f48 100644 --- a/dzgui/views/trees/tree_simple.py +++ b/dzgui/views/trees/tree_simple.py @@ -1,13 +1,13 @@ +import gi + from typing import TYPE_CHECKING, Union +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + if TYPE_CHECKING: from dzgui.model.model_factory import FastInsertListStore -import gi - -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa - class SimpleTree(Gtk.ScrolledWindow): """Simple scrollable 1-column tree""" diff --git a/tests/test_colorscheme.py b/tests/test_colorscheme.py index a8818dc..3462231 100644 --- a/tests/test_colorscheme.py +++ b/tests/test_colorscheme.py @@ -1,13 +1,12 @@ +import gi import pytest import subprocess from dzgui.const.constants import GIO_SETTINGS_KEY from dzgui.views.mixins.colorscheme import ColorAwareApp -import gi - gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gio, GLib # noqa +from gi.repository import Gtk, GLib class DummyWidget(ColorAwareApp, Gtk.Button): From 88c740105a8ad32f4bd1984ba60c13bab105e8ba Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:02:23 +0900 Subject: [PATCH 03/23] chore: drop unused dataclasses --- dzgui/views/pages/preconnect.py | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/dzgui/views/pages/preconnect.py b/dzgui/views/pages/preconnect.py index 3f54b31..1ec2e17 100644 --- a/dzgui/views/pages/preconnect.py +++ b/dzgui/views/pages/preconnect.py @@ -1,11 +1,12 @@ -from dataclasses import dataclass +import gi + from typing import Self, Sequence, TYPE_CHECKING +from dzgui.const.enum import NotebookPage from dzgui.const.icons import ( ICON_ERROR, ICON_WARNING, ) -from dzgui.const.enum import NotebookPage from dzgui.util.css import add_class from dzgui.util.keys import is_ctrl_mask from dzgui.util.localize import number @@ -15,33 +16,15 @@ from dzgui.views.dialogs.generic import DebugDialog from dzgui.views.components.frame import HeadingFrame from dzgui.views.trees.tree_server_mods import ServerModTreeView -import gi - gi.require_version("Gtk", "3.0") from gi.repository import Gdk, Gtk - if TYPE_CHECKING: from dzgui.managers.connection import Prerequisites from dzgui.controllers.mc import Controller from dzgui.controllers.emitter import Emitter -@dataclass -class Warnings: - passworded: bool - dayz_running: bool - no_steam: bool - wrong_version: bool - - -@dataclass -class Errors: - no_space: bool - no_dayz_exp: bool - no_dayz: bool - - class Placeholder(Gtk.Label): def __init__(self, text: str) -> None: super().__init__( From e6ebeaeb5ede9288fc2cabec925316011c5dff79 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:04:25 +0900 Subject: [PATCH 04/23] chore: immutable dataclass --- dzgui/model/servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index 5e217db..115655b 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -34,7 +34,7 @@ LAN_TIMEOUT = 0.5 API_TIMEOUT = 3 -@dataclass +@dataclass(slots=True, frozen=True) class NewPlayerCount: treeiter: Gtk.TreeIter players: int From aef48e515b97f8bce861f2ee7349e32210858cb4 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:15:28 +0900 Subject: [PATCH 05/23] fix: failing test --- tests/test_mod_signatures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_mod_signatures.py b/tests/test_mod_signatures.py index 8aa5dd6..49b9ef2 100644 --- a/tests/test_mod_signatures.py +++ b/tests/test_mod_signatures.py @@ -48,5 +48,5 @@ def test_signatures_with_no_ids(monkeypatch, tmp: str, versions: str) -> None: monkeypatch.setattr("dzgui.api.mods.lookup", mock_lookup) dzgui.api.mods.remove_stale_signatures(path, path) with open(tmp, "r") as f: - lines = f.readlines() - assert lines == ["3410710885,1752864732\n", "3739934289,1780855136\n"] + lines = [line.rstrip() for line in f.readlines()] + assert lines == ["3410710885,1752864732", "3739934289,1780855136"] From bfa83c3f9431aa5dd58e5f6dc8a2655da35f134e Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:15:53 +0900 Subject: [PATCH 06/23] change: import sort order --- dzgui/util/ip.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dzgui/util/ip.py b/dzgui/util/ip.py index 168e036..f13f16b 100644 --- a/dzgui/util/ip.py +++ b/dzgui/util/ip.py @@ -1,10 +1,10 @@ import a2s -from ipaddress import ip_address import requests import shutil import subprocess from dataclasses import dataclass +from ipaddress import ip_address from typing import TYPE_CHECKING from dzgui.api.servers import Record @@ -12,12 +12,11 @@ from dzgui.config.ipdb import read_from_table from dzgui.const.constants import REQUEST_TIMEOUT from dzgui.const.endpoints import IP_ECHO - if TYPE_CHECKING: from pathlib import Path -@dataclass +@dataclass(slots=True, frozen=True) class Coords: lat: float lon: float From 0907f5a4748adf854af337e2aa26a832889ed9c8 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:50:12 +0900 Subject: [PATCH 07/23] change: immutable dataclass --- dzgui/config/xdg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui/config/xdg.py b/dzgui/config/xdg.py index 532c73f..eac3dcf 100644 --- a/dzgui/config/xdg.py +++ b/dzgui/config/xdg.py @@ -12,7 +12,7 @@ from dzgui.const.constants import ( from dzgui.init.proc import is_sandboxed -@dataclass +@dataclass(slots=True, frozen=True) class Xdg: config: Path columns: Path From 65e04c2fc494497a49021a3d06bc8a80eb0f8257 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:50:38 +0900 Subject: [PATCH 08/23] fix: multiple signals being stacked --- dzgui/views/pages/options.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 533fa67..92c7e1c 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -230,10 +230,19 @@ class ToggleField(Gtk.Box): self.pack_start(self.radio1, expand=False, fill=False, padding=0) self.pack_start(self.radio2, expand=False, fill=False, padding=0) + self.signal_id: int | None = None + + def disconnect_signal(self) -> None: + if self.signal_id is not None: + self.radio1.disconnect(self.signal_id) + def set_suboption_active(self, state: bool) -> None: # NOTE: defer connection of signal until after state is set self.radio2.set_active(state) - self.radio1.connect("toggled", self._on_radio_toggled, self.context) + self.disconnect_signal() + self.signal_id = self.radio1.connect( + "toggled", self._on_radio_toggled, self.context + ) def _on_radio_toggled(self, button: Gtk.RadioButton, context: Preferences) -> None: self.controller.toggle_config(context) From ba92d15085a80fa958987265505ad1cbb498d6bb Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:50:54 +0900 Subject: [PATCH 09/23] drop: unused signal logic --- dzgui/views/pages/options.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 92c7e1c..8c681f1 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -492,14 +492,5 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore start_tab = self.controller.query_config(Preferences.START_TAB) self.start_tab_combo.set_active(start_tab) - def _suppress_toggles(self, state: bool) -> None: - for toggle in [ - self.fullscreen_toggle, - self.distance_toggle, - ]: - self.controller.suppress_signal( - self, toggle.get_children()[0], "_on_radio_toggled", state - ) - def grab_content_area(self) -> None: self.grab_focus() From 7a6f4a2bb9e13e4ce92deca0fb76c9e7703dcb20 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:52:05 +0900 Subject: [PATCH 10/23] feat: immutable decorator --- dzgui/util/immutable.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 dzgui/util/immutable.py diff --git a/dzgui/util/immutable.py b/dzgui/util/immutable.py new file mode 100644 index 0000000..98c0ce4 --- /dev/null +++ b/dzgui/util/immutable.py @@ -0,0 +1,9 @@ +from dataclasses import dataclass +from typing import Callable + +def immutable_dataclass(cls: type | None = None, **kwargs: bool) -> type | Callable[[type], type]: + kwargs["slots"] = True + kwargs["frozen"] = True + if cls is None: + return lambda c: dataclass(c, **kwargs) + return dataclass(cls, **kwargs) From d5693b07fbb9b323d58201419c276fcc4271266f Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:03:31 +0900 Subject: [PATCH 11/23] chore: update comments --- tests/test_pefile.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_pefile.py b/tests/test_pefile.py index ebcfb0e..02892ab 100644 --- a/tests/test_pefile.py +++ b/tests/test_pefile.py @@ -7,7 +7,7 @@ from dzgui.api.steam import ( VDFLoadError, AppNotInstalledError, AppMovedError, - get_app_path + get_app_path, ) from dzgui.config.query import get_config @@ -26,9 +26,8 @@ def default_steam_path(): conf = get_config(xdg.config) return conf["default_steam_path"] +# TODO: additional parsing tests -# TODO: split into separate test file -# FIXME: use fixtures def test_pefile_length(default_steam_path): try: pe_file_path = PeFile.get_pefile_path(Path(default_steam_path), APPID_DAYZ) @@ -47,6 +46,7 @@ def test_invalid_pefile_path(): raise e +# TODO: split into separate test file @pytest.mark.parametrize( "fixture, exception", [ @@ -57,6 +57,7 @@ def test_invalid_pefile_path(): ) def test_not_in_library(monkeypatch, fixture, exception): import dzgui.api.steam as steam + monkeypatch.setattr(steam, "LIBRARYFOLDERS_PATH", fixture) folder_path = Path(fixture_path("api")) @@ -74,6 +75,7 @@ def second_drive(): def test_on_second_drive(monkeypatch, second_drive): import dzgui.api.steam as steam + monkeypatch.setattr(steam, "LIBRARYFOLDERS_PATH", second_drive) folder_path = Path(fixture_path("api")) path = get_app_path(folder_path, APPID_DAYZ) From 1b9448735dbb60bd05b88a6ab00de15376f81f85 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:03:59 +0900 Subject: [PATCH 12/23] chore: drop old comments --- dzgui/controllers/mc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 151e6ed..169c72a 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -366,7 +366,6 @@ class Controller(GObject.GObject): filter_man = self.get_filter_man() return filter_man.get_filters() - # FIXME: wipe maps store when changing tabs if model is none def has_server_model(self) -> bool: treeview = self.get_active_treeview() proxy_man = treeview.get_proxy_man() From f2375feeec221bb57eb08bddc4653b71bc9af093 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:04:55 +0900 Subject: [PATCH 13/23] feat: add get_index() method to ServerRow --- dzgui/model/proxy_model.py | 5 ++++ dzgui/views/trees/tree_servers.py | 46 ++++++++++++++----------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/dzgui/model/proxy_model.py b/dzgui/model/proxy_model.py index 2cd9b24..1f0028e 100644 --- a/dzgui/model/proxy_model.py +++ b/dzgui/model/proxy_model.py @@ -58,6 +58,11 @@ class ServerRow: getter = cls._to_tuple return [getter(row) for row in rows] + @classmethod + def get_index(cls, field: str) -> int: + _fields = [f.name for f in fields(cls)] + return _fields.index(field) + class FiltrationManager: def __init__(self) -> None: diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 349c19b..5d52694 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -10,7 +10,7 @@ from dzgui.api.servers import ping, Record from dzgui.const.constants import APP_NAME from dzgui.const.enum import ContextMenuItem, ContextMenuGroup, ServerTab from dzgui.managers.filter import FilterManager -from dzgui.model.proxy_model import ProxyModelManager +from dzgui.model.proxy_model import ProxyModelManager, ServerRow from dzgui.util import strings from dzgui.util.dist import CalcDist from dzgui.util.keys import is_ctrl_mask @@ -29,8 +29,14 @@ if TYPE_CHECKING: from dzgui.model.model_factory import FastInsertListStore from dzgui.util.dist import Haversine +# TODO: consts QUEUE_CHECK_DELAY = 200 +IND_NAME = ServerRow.get_index("name") +IND_ADDR = ServerRow.get_index("ip") +IND_QPORT = ServerRow.get_index("qport") +IND_PING = ServerRow.get_index("ping") +IND_MODDED = ServerRow.get_index("modded") class ServerTreeView(ContextMixin, TreeView): # type: ignore def __init__( @@ -140,8 +146,8 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore if model is None: return False tree_iter = model.get_iter(path[0]) - ip = model.get_value(tree_iter, 7) - qport = model.get_value(tree_iter, 8) + ip = model.get_value(tree_iter, IND_ADDR) + qport = model.get_value(tree_iter, IND_QPORT) addr = ip + ":" + str(qport) note = self.controller.get_note_by_record(addr) @@ -164,14 +170,12 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore return self.enum def _on_map(self, widget: Self) -> None: - # TODO: disable filter panel if current model is None state = self.get_enum() is ServerTab.LAN self.emitter.emit("lan_tab_toggled", state) store = self.filter_man.get_map_store() - # FIXME: if model is none, wipe maps - # distinguish this signal from changing map combo in-situ + # TODO: distinguish this signal from changing map combo in-situ self.emitter.emit("load_maps", store) self.handler_id = self.emitter.connect("statusbar_loaded", self.start_distcalc) self.start_queue_checker() @@ -216,7 +220,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore def _check_result_queue(self) -> Literal[True]: latest_result = None - # FIXME: empty results cause statusbar to be emptied + # TODO: Nonetype results cause statusbar to be blank while not self.queue.empty(): latest_result = self.queue.get() @@ -262,15 +266,9 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore (model, pathlist) = sels path = pathlist[0] tree_iter = model.get_iter(path) - has_mods = model.get_value(tree_iter, 11) + has_mods = model.get_value(tree_iter, IND_MODDED) return bool(has_mods) - # def get_selected_row(self) -> Gtk.TreeModelRow: - # sel = self.get_selection() - # sels = sel.get_selected_rows() - # print(type(sels[0])) - # return sels[0] - def is_in_favs(self) -> bool: record = self.get_record_string() if self.controller.get_config_man().is_in_favs(record): @@ -299,17 +297,17 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore self.start_distcalc() def get_name(self) -> str: - return str(self.get_value_at_index(0)) + return str(self.get_value_at_index(IND_NAME)) def get_simplified_ip(self) -> str: - addr = self.get_value_at_index(7) - qport = self.get_value_at_index(8) + addr = self.get_value_at_index(IND_ADDR) + qport = self.get_value_at_index(IND_QPORT) ip = addr.split(":")[0] return f"{ip}:{qport}" def get_record_string(self) -> str: - addr = self.get_value_at_index(7) - qport = self.get_value_at_index(8) + addr = self.get_value_at_index(IND_ADDR) + qport = self.get_value_at_index(IND_QPORT) return f"{addr}:{qport}" def get_record(self) -> Record | None: @@ -348,8 +346,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore def _redraw( self, model: "FastInsertListStore", _iter: Gtk.TreeIter, _ping: int ) -> None: - ping_column = 9 - model.set(_iter, ping_column, _ping) + model.set(_iter, IND_PING, _ping) self.queue_draw() def wipe_cache(self) -> None: @@ -364,13 +361,10 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore data: Any, ) -> None: - addr_column = 7 - qport_column = 8 - - addr = model.get_value(_iter, addr_column).split(":") + addr = model.get_value(_iter, IND_ADDR).split(":") ip = addr[0] gameport = int(addr[1]) - qport = model.get_value(_iter, qport_column) + qport = model.get_value(_iter, IND_QPORT) record = Record(ip, gameport, qport) if record in self.seen_cache: From 535bc505f76e46c9765a5c3b333a40be18b9599e Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:06:20 +0900 Subject: [PATCH 14/23] chore: update comments --- dzgui/model/servers.py | 4 ++-- dzgui/views/components/right_panel.py | 5 +++-- dzgui/views/components/statusbar.py | 2 +- dzgui/views/dialogs/filepicker.py | 1 + dzgui/views/pages/offline.py | 1 - 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index 115655b..c1e5200 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -341,8 +341,8 @@ class ServerModelManager: return config_man.add_saved_server(fqip) - # FIXME: this is valid if saved servers tab is already open, - # but not if app was just booted; causes single row to appear prematurely + # TODO: this is valid if saved servers tab is already open, + # but not if tab is unloaded; causes single row to appear prematurely if proxy_man.has_control_model() is False: proxy_man.push(records) else: diff --git a/dzgui/views/components/right_panel.py b/dzgui/views/components/right_panel.py index c04bba7..078bb49 100644 --- a/dzgui/views/components/right_panel.py +++ b/dzgui/views/components/right_panel.py @@ -106,14 +106,15 @@ class RightPanel(Gtk.Box): if page.loaded is True: return self.filters_vbox.set_sensitive(False) - # TODO: unless it is lan page - # self.refresh_button.set_sensitive(False) + self.refresh_button.set_sensitive(False) def _on_lan_page_init(self, emitter: "Emitter") -> None: self.filters_vbox.set_sensitive(False) def _on_servers_loaded(self, emitter: "Emitter", context: "ServerTab") -> None: # TODO: similar logic on notebook page change + # TODO: wipe maps store when changing tabs if model is None + state = self.controller.has_server_model() self.filters_vbox.set_sensitive(state) diff --git a/dzgui/views/components/statusbar.py b/dzgui/views/components/statusbar.py index 43e5ff7..fd1ad81 100644 --- a/dzgui/views/components/statusbar.py +++ b/dzgui/views/components/statusbar.py @@ -101,7 +101,7 @@ class Statusbar(Gtk.Grid): if type(context) is NotebookPage: self.prior_enum = context self.prior_status = "" - # FIXME: CalcDist is being called when table is not loaded + if dist is None: self.set_by_context(context, "") return diff --git a/dzgui/views/dialogs/filepicker.py b/dzgui/views/dialogs/filepicker.py index 7951ae7..7fd1359 100644 --- a/dzgui/views/dialogs/filepicker.py +++ b/dzgui/views/dialogs/filepicker.py @@ -54,6 +54,7 @@ class FolderPicker(Gtk.FileChooserDialog): return None if res == Gtk.ResponseType.OK: folder = self.get_current_folder() + # TODO: this should never be possible if folder is None: try: uri = self.get_uri() diff --git a/dzgui/views/pages/offline.py b/dzgui/views/pages/offline.py index 141c722..6398e4a 100644 --- a/dzgui/views/pages/offline.py +++ b/dzgui/views/pages/offline.py @@ -136,7 +136,6 @@ class FolderHBox(HBox): self.folder = "" self.label.set_label("") self.unset_button.hide() - # FIXME: rename signal self.emitter.emit("custom_mods_unloaded", self) def get_button(self) -> Gtk.Button: From d0b3a723c634d2ac42646b4fc0ec8bb03281f65d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:06:36 +0900 Subject: [PATCH 15/23] drop: unused comment --- dzgui/managers/connection.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index a57a421..f3ac7e9 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -330,7 +330,6 @@ class ConnectionManager: self.thread_man.update_dialog(waiting_for_launch) while True: - # FIXME: cancel should not be visible here per setting above if self.controller.is_cancel_pending(): # TODO: some facility to also close spawned steam process return From 439109d11d6a7bc14a746304b9918d5f4f135961 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:07:49 +0900 Subject: [PATCH 16/23] docs: update to DZGUI 7 spec --- docs/source/bugs.rst | 17 +++++++------- docs/source/conf.py | 4 ++-- docs/source/development.rst | 15 +++++-------- docs/source/flags.rst | 12 ++++++++++ docs/source/index.rst | 6 ++--- docs/source/installation.rst | 41 +++++++++++++++++++++------------- docs/source/kb.rst | 17 ++++++++++++-- docs/source/setup.rst | 19 +++++++++++----- docs/source/uninstallation.rst | 10 +++------ docs/source/usage.rst | 20 ++++++++++------- 10 files changed, 99 insertions(+), 62 deletions(-) create mode 100644 docs/source/flags.rst diff --git a/docs/source/bugs.rst b/docs/source/bugs.rst index dcb4a75..faa8175 100644 --- a/docs/source/bugs.rst +++ b/docs/source/bugs.rst @@ -1,11 +1,11 @@ Submitting a ticket ========================== -Tickets are tracked at the `DZGUI issue tracker `_. +Tickets are tracked at the `DZGUI issue tracker `_. You will need to `register for a GitHub account `_ in order to submit one. -If have checked the :doc:`kb` and `closed issues `_ area and did not find a solution, three ticket types are provided for your +If have checked the :doc:`kb` and `closed issues `_ area and did not find a solution, three ticket types are provided for your convenience: - **Bug report**: for unexpected, breaking behavior in the application @@ -20,18 +20,17 @@ Below are some examples of how to format a constructive report that will ensure A non-actionable report ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Subject: add button + Subject: BUG: add button hi, you must add a button to show how long I have to wait to join a full server, the app is useless without this...do your job, guys!!! ;-) This report exhibits a number of problems: -- Vague title and summary: in addition to being unclear, this will slow down filing the incoming report. -- Problem space is poorly defined: it is not clear where the issue lies, where the feature is supposed to be implemented, nor why. -- Lack of context: the feature may already exist, but there is not enough information to go on. Alternatively, the feature may be technically impossible to implement, but there is not enough - information to go on. - Incorrect report type: this is a feature request filed as a bug report. +- Vague title and summary: this will slow down filing the incoming report. +- Problem space is poorly defined: it is not clear where the issue lies, where the feature is supposed to be implemented, nor why. +- Lack of context: the feature may already exist, but there is not enough information to go on. Alternatively, the feature may be technically impossible to implement. - Unprofessional tone: the message is disrespectful towards project members and inserts the user's subjective opinion. An actionable report @@ -42,7 +41,7 @@ An actionable report This occurs specifically on version 5.5.0-beta.2 if the setting ALLOW_MULTI is set to ON. I was able to reproduce it using the following steps: Distribution: Fedora - + - Ensure that ALLOW_MULTI is set to ON - Open the application and immediately navigate to the Server Browser - Uses the Ctrl-click binding to select multiple rows in the table @@ -56,5 +55,5 @@ This report is actionable because it is objective, specific, and detailed: - The subject is clearly defined: specific details ensure it will be filed in a timely manner. - Scope is explicit: the specific version, settings, and conditions under which the problem occur were given. - Ample context: the user gave steps to reproduce the problem and clarified each one. -- Courteous tone: the user interacted with project members in a professional manner. - Supporting information: the user provided a crash dump to expedite resolution of the issue. +- Courteous tone: the user interacted with project members in a professional manner. diff --git a/docs/source/conf.py b/docs/source/conf.py index b1f4fae..4c746e2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -36,5 +36,5 @@ html_show_copyright = False html_show_sourcelink = False today_fmt = "%Y-%m-%d" -release = "6.x.x - 7.x.x" -version = "6.x.x - 7.x.x" +release = "7.x.x" +version = "7.x.x" diff --git a/docs/source/development.rst b/docs/source/development.rst index 5c6868c..c92c64b 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -1,19 +1,14 @@ Developers =========== - This project is open source under the GPLv3 license. You can find the source code on -`GitHub `_. If you wish to contribute to +`GitHub `_. If you wish to contribute to development, you will find further help in the -`CONTRIBUTING.md `_ +`CONTRIBUTING.md `_ file. All contributors are expected to act in accordance with the project's -`code of conduct `_, +`code of conduct `_, and follow the project's standards and guidelines. -To install DZGUI and related dependencies for linting, testing, and version control, -invoke the command ``uv pip install .[dev]``. - -After this process, install the applicable pre-commit hooks by invoking the command ``pre-commit install``. - -These pre-commit hooks enforce code checks that prevent making commits unless the relevant tests pass. +Detailed instructions on setting up a build environment and installing DZGUI from source code +can be found in the `DEVELOPERS.md `_ file. diff --git a/docs/source/flags.rst b/docs/source/flags.rst new file mode 100644 index 0000000..a74e451 --- /dev/null +++ b/docs/source/flags.rst @@ -0,0 +1,12 @@ +Command line launch flags +========================== +When run from the terminal, DZGUI provides several flags: + +``-d, --debug``: enable developer debugging features. This does not add hidden or extra functionality; it merely enables developers to track deprecation warnings and see values stored in memory. +End-users will gain no benefit from using this flag. + +``-m, --map``: check and update system map count value. Unnecessary on most modern systems. If your system does not meet the threshold, the DZGUI setup wizard will prompt you to use this flag. + +``-u, --uninstall``: uninstall: granular selection of which state/configuration files to remove. + +``-v, --version``: displays the DZGUI version. diff --git a/docs/source/index.rst b/docs/source/index.rst index 185ca2b..a071366 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,8 +15,8 @@ A DayZ server browser/mod manager for Linux. Used to list official and community Source code: -- `GitHub `_ -- `Codeberg (mirror) `_ +- `GitHub `_ +- `Codeberg (mirror) `_ Installation ------------- @@ -56,8 +56,8 @@ See: :doc:`kb` or :ref:`Submitting a ticket`. :maxdepth: 3 :hidden: - steam locale + flags .. toctree:: :caption: Help diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 5ed1960..9ed1aa4 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -1,28 +1,37 @@ Installation ================== -As of this writing, you have a choice of two DZGUI versions: +.. note:: + Version 6 of DZGUI 6 has been fully replaced with DZGUI 7. + Users on existing DZGUI 6 installations should migrate to the DZGUI 7 build. -- DZGUI 6: Legacy stable version, more complicated to install -- DZGUI 7: Unstable beta version, much easier to install +In order to make the first-time setup experience easier for end-users, DZGUI 7 no longer requires +the tool to be installed from source code into a working Python environment. All necessary dependencies and the +runtime environment are built-in. -DZGUI 6 --------------------- -This version is no longer receiving feature updates, but will receive security updates until it is replaced by DZGUI 7. +Turnkey installer +------------------------ -DZGUI 6 must be installed from the source code and has many more package dependencies and prerequisites for it to function correctly. -If you are looking for a one-click, self-contained installer, use :ref:`DZGUI 7` instead. +- Visit the project's `Releases page `_. +- Download the DZGUI archive from the top of the **Assets** list. This file will be labeled ``dzgui--x86_64-unknown-linux-musl.tar.gz``. +- Extract the archive's contents. +- From a terminal, run the command ``./dzgui`` or double click on the extracted file in a file explorer. +- Once the setup wizard opens, follow the steps at the bottom of this page. -To install **DZGUI 6**, visit :doc:`dzgui6`. +UI dependencies (Python and PyGObject) +--------------------------------------- +On most major distributions, GObject introspection libraries should be available by default. +If you receive an error about a missing ``libgirepository-2.0`` dependency, install it via your system's package manager. -DZGUI 7 --------------------- -This version is currently in beta testing and has all of the features found in DZGUI 6, but may be unstable. +On Debian-based distributions (Ubuntu, etc.), this package is not explicitly installed on the system. +You can install it via the following set of commands: -DZGUI 7 has an all-in-one installer and setup wizard, and many new features not found in DZGUI 6. -However, this codebase is newer and is provided as a pre-release beta candidate. +.. code:: console -If you want the simplest installer and don't mind experiencing the occasional bug, use this version. + sudo apt update + sudo apt install libgirepository-2.0-0 -To install **DZGUI 7**, visit :doc:`dzgui7`. +Next steps +--------------- +Proceed to the :doc:`setup` section for setup instructions. diff --git a/docs/source/kb.rst b/docs/source/kb.rst index 7ab8bb2..26d4475 100644 --- a/docs/source/kb.rst +++ b/docs/source/kb.rst @@ -98,15 +98,28 @@ tend to have less headroom for simultaneous connections than their wired counter DZG-009: Floating dialogs appear maximized on tiling window managers ------------------------------------------------------------------- - The main DZGUI window and its child dialogs are expected to be rendered as floating by your window manager. DZGUI sends window manager hints to this effect, but tiling window managers designed to bisect the screen into quadrants (e.g., i3 window manager) may try to always launch applications in fullscreen. To resolve this, set specific exclusions or window hints in your WM's configuration file. -For example, for i3, add the following to your `XDG_CONFIG_HOME/i3/config` file (defaults to `$HOME/.config/i3/config`): +For example, for i3, add the following to your ``XDG_CONFIG_HOME/i3/config`` file (defaults to ``$HOME/.config/i3/config``): .. code:: console for_window [instance="DZGUI"] floating enable, move position center for_window [instance="DZGUI - Dialog"] floating enable, move position center + +DZG-010: Maps combobox extends to full height of window when there are many maps to choose from +--------------------------------------------------------------------------------------------------- +This is a limitation of GTK 3. If and when DZGUI is refactored to support the GTK 4 API, this visual glitch is expected to be resolved. + +DZG-011: GTK reports "Failed to load module 'xapp-gtk3-module' when starting DZGUI +--------------------------------------------------------------------------------------------------- +This is a purely cosmetic message that appears when Cinnamon (Xapp) desktop integations are not present. +While you can suppress this message by installing the package ``xapp``, if you are not actually using Cinnamon as +part of your desktop environment, it will pull in a large number of unnecessary dependencies. + +DZG-012: After adding the DZGUI Steam shortcut via the installer, shortcut icons do not appear in the small library list +------------------------------------------------------------------------------------------------------------------------- +It can take 1-2 restarts of the Steam client for these icons to synchronize. diff --git a/docs/source/setup.rst b/docs/source/setup.rst index ec1fa07..88614cd 100644 --- a/docs/source/setup.rst +++ b/docs/source/setup.rst @@ -19,14 +19,14 @@ You will need at a minimum a :ref:`Steam Web API key` in order to bro Steam Web API key ^^^^^^^^^^^^^^^^^^ - **This step is required**. -Register for a `Steam Web API key `_ (free) using your Steam account. You will be asked for a unique URL for your app when registering. +Register for a `Steam Web API key `_ (free) using your Steam account. -Since this key is for a personal use application and does not actually call back anywhere, set a generic local identifier here like "127.0.0.1" or some other name that is meaningful to you. +You will be asked for a unique URL for your app when registering. Typically, an API would send logs back to your URL in the form of callbacks. +However, since these API queries will be used for local consumption by a single user only, you can set a generic local identifier here like ``127.0.0.1`` to have the server discard them. -Once configured, you can insert this key in the app when launching it for the first time. +Once configured, you can insert this API key in the app when launching it for the first time. .. note:: If you are confused about this requirement, please refer to DZGUI Knowledge Base article :ref:`DZG-007` for additional information. @@ -36,7 +36,16 @@ Battlemetrics API key .. warning:: This feature is no longer supported in DZGUI. Battlemetrics has switched to a paid service. - Battlemetrics queries are expected to fail in DZGUI 6. In DZGUI 7, this feature has been removed entirely. + +Choosing a Steam client +^^^^^^^^^^^^^^^^^^^^^^^^^ +If multiple Steam clients are available (native Steam client/Flatpak Steam client), you will be +asked to choose which you want to use. Due to the way Steam's inter-process communication and internal URIs work, +if you choose one or the other, you should not run both clients simultaneously. This can lead DZGUI to send requests to the wrong one. + +.. note:: + If you decide to switch to using a different Steam client with DZGUI, please uninstall fully (``dzgui -u``) and re-run the first time setup. + Next steps -------------- diff --git a/docs/source/uninstallation.rst b/docs/source/uninstallation.rst index 7d8c2ff..699f198 100644 --- a/docs/source/uninstallation.rst +++ b/docs/source/uninstallation.rst @@ -1,12 +1,8 @@ Uninstallation ================== +To uninstall DZGUI and its associated files, invoke ``./dzgui`` from the terminal with the ``-u`` or ``--uninstall`` flag. -To uninstall DZGUI and its associated files, invoke ``./dzgui.sh`` with the ``-u`` or ``--uninstall`` flag. - -Follow the prompts to choose from: - -- **Full uninstall** -- removes the application and all user-defined configuration files -- **Partial uninstall** -- removes the application, but keeps user-defined configuration files +You will be prompted to select atomic files you wish to remove. .. tip:: - If you intend to reinstall DZGUI again, keeping your configuration files is recommended. + If you intend to reinstall DZGUI again, keeping your configuration files at a minimum is recommended. diff --git a/docs/source/usage.rst b/docs/source/usage.rst index ddeab0e..9e27e0c 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -1,25 +1,29 @@ Usage ========= - It is always advised to have Steam running in the background. DZGUI is meant to run "on top of" Steam. DZGUI can be launched in one of three ways. From a terminal ------------------ - -Invoke the command ``./dzgui.sh`` from wherever you downloaded the DZGUI script to. +Invoke the command ``./dzgui`` from wherever you downloaded DZGUI to. Launching from a terminal may give more verbose information in the event of a crash, and can be a good way of troubleshooting problems. From the shortcut shipped with the application -------------------------------------------------- +When completing the first-time setup, you will be asked if you want to create additional system shortcuts. +If applicable for yourDesktop Environment, these shortcuts can be created. -On most distributions, if you are using a desktop environment based on the Freedesktop specification, shortcuts will be installed for you. - -- One shortcut is located under the ``Games`` category of your system’s applications list/start menu. -- The other is accessed via the ``DZGUI`` desktop icon (Steam Deck only) +- One shortcut will be located under the ``Games`` category of your system’s applications list/start menu. +- The other is accessed via the ``DZGUI`` shortcut on the desktop From Steam -------------- -See :doc:`steam`. +DZGUI will also ask you if you want to add a "non-Steam game" shortcut to Steam. +This shortcut will launch DZGUI directly and comes with integrated grid and cover artwork. + +You must restart Steam for this shortcut to take effect in your library. + +.. note:: + You can also pass DZGUI launch parameter's to the Steam shortcut via Steam's right-click menu. See :doc:`flags`. From c267b1bbc74754247a4e0edab476ca4f76925cb1 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 02:12:40 +0900 Subject: [PATCH 17/23] docs: update changelog --- CHANGELOG.md | 10 +++------- dzgui/data/CHANGELOG.md | 17 ++++++++++------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7916e9c..d65c8c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ - List timestamp of last DayZ client update - Validate mods via Mod page to pull in updates - Support for Nasdara (Badlands) DLC +- Load offline mods ### Changed - Conform to PEP 440 versioning for beta versions @@ -99,16 +100,11 @@ - Current keyword filter not being applied when refreshing table - Steam Flatpak cannot run DZGUI as a non-Steam game - Collisions between native Steam and Steam Flatpak clients - -### Unreleased -- Load offline mods -- Local documentation -- Raw debug command in context menu +- Sticky toggle signal on radio buttons when reloading Options ### Developer-facing -- Add pyproject.toml file -- Show deprecation warnings - Options -> Dev page +- Raw debug command in preconnect menu ## [6.0.5] 2026-05-17 ### Changed diff --git a/dzgui/data/CHANGELOG.md b/dzgui/data/CHANGELOG.md index 4e0eea2..d65c8c8 100644 --- a/dzgui/data/CHANGELOG.md +++ b/dzgui/data/CHANGELOG.md @@ -53,6 +53,11 @@ - Expand/collapse changelog versions - Support local light/dark mode changes on system theme - Server time calculator +- Add "Unmodded" filter to servers +- List timestamp of last DayZ client update +- Validate mods via Mod page to pull in updates +- Support for Nasdara (Badlands) DLC +- Load offline mods ### Changed - Conform to PEP 440 versioning for beta versions @@ -74,6 +79,7 @@ - Enable LAN page Empty/Full filters on first run of app - Propagate subscribed mods to Steam client - Make j/k keys in context menus follow same wraparound logic as down arrow/up arrow +- Use SQLite DB for geolocation records ### Dropped - Battlemetrics API support @@ -92,16 +98,13 @@ - Moved dialogs out of threads - History table not being in lock-step with state file - Current keyword filter not being applied when refreshing table - -### Unreleased -- Load offline mods -- Local documentation -- Raw debug command in context menu +- Steam Flatpak cannot run DZGUI as a non-Steam game +- Collisions between native Steam and Steam Flatpak clients +- Sticky toggle signal on radio buttons when reloading Options ### Developer-facing -- Add pyproject.toml file -- Show deprecation warnings - Options -> Dev page +- Raw debug command in preconnect menu ## [6.0.5] 2026-05-17 ### Changed From 1dbbd5977d828fe4e5773085eae38b1a1ae8574b Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 05:05:59 +0900 Subject: [PATCH 18/23] chore: drop Optional annotation --- dzgui/api/servers.py | 6 +++--- dzgui/views/trees/tree_base.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dzgui/api/servers.py b/dzgui/api/servers.py index 546ec15..5fa219c 100644 --- a/dzgui/api/servers.py +++ b/dzgui/api/servers.py @@ -9,7 +9,7 @@ import subprocess import threading from dataclasses import dataclass -from typing import Any, Optional, TYPE_CHECKING, Union +from typing import Any, TYPE_CHECKING, Union from dzgui.const.constants import APP_NAME, REQUEST_TIMEOUT from dzgui.const.endpoints import STEAM_SERVERS @@ -491,7 +491,7 @@ def query_by_record(record: Record, update_gameport: bool = False) -> A2SInfo: return A2SInfo(record, None) -def short_ip_to_record(addr: str) -> Optional[Record]: +def short_ip_to_record(addr: str) -> Record | None: r = addr.split(":") # TODO: raise exceptions instead of Nonetype if len(r) != 2: @@ -499,7 +499,7 @@ def short_ip_to_record(addr: str) -> Optional[Record]: return Record(r[0], 0, int(r[1])) -def fqip_to_record(addr: str) -> Optional[Record]: +def fqip_to_record(addr: str) -> Record | None: r = addr.split(":") if len(r) != 3: return None diff --git a/dzgui/views/trees/tree_base.py b/dzgui/views/trees/tree_base.py index a8d134e..2d16df7 100644 --- a/dzgui/views/trees/tree_base.py +++ b/dzgui/views/trees/tree_base.py @@ -1,7 +1,7 @@ import gi import logging -from typing import Any, Optional, TYPE_CHECKING +from typing import Any, TYPE_CHECKING from dzgui.const.constants import APP_NAME, SEPARATOR from dzgui.util.keys import is_ctrl_mask, is_navkey @@ -19,7 +19,7 @@ if TYPE_CHECKING: class TreeView(CursorMixin, Gtk.TreeView): # type: ignore def __init__( - self, controller: "Controller", menu: Optional["ContextMenuGroup"] + self, controller: "Controller", menu: "ContextMenuGroup | None" ) -> None: super().__init__( enable_search=False, @@ -58,7 +58,7 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore return True return False - def get_current_iter(self) -> Optional[Gtk.TreeIter]: + def get_current_iter(self) -> Gtk.TreeIter | None: it = self.get_selection().get_selected()[1] return it From 170990ee1d31f7ce6ae0f8ca84e24ed972c7cdae Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 05:06:51 +0900 Subject: [PATCH 19/23] chore: downgrade FIXME tags --- dzgui/views/base.py | 8 +++++--- dzgui/views/dialogs/filepicker.py | 2 +- dzgui/views/trees/tree_servers.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 756dae2..4c69bdc 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -1,3 +1,4 @@ +import gi import logging import signal @@ -34,8 +35,6 @@ from dzgui.views.pages.preconnect import PreConnectionAssistant from dzgui.views.pages.servers import ServerNotebook from dzgui.views.pages.thanks import Thanks -import gi - gi.require_version("Gtk", "3.0") gi.require_version("GLibUnix", "2.0") from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore @@ -49,7 +48,10 @@ logger = logging.getLogger(APP_NAME) class OuterWindow(Gtk.ApplicationWindow): def __init__(self, app: "App") -> None: super().__init__( - application=app, title=APP_NAME, border_width=10, icon_name=APP_NAME_LOWER + application=app, + title=APP_NAME, + border_width=10, + icon_name=APP_NAME_LOWER, ) self.hb = AppHeaderBar() diff --git a/dzgui/views/dialogs/filepicker.py b/dzgui/views/dialogs/filepicker.py index 7fd1359..2c0e3cc 100644 --- a/dzgui/views/dialogs/filepicker.py +++ b/dzgui/views/dialogs/filepicker.py @@ -62,7 +62,7 @@ class FolderPicker(Gtk.FileChooserDialog): return None return Path.from_uri(uri) except Exception: - # FIXME: edge cases + # TODO: edge cases return Path("/") self.destroy() return Path(folder) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 5d52694..9c1c671 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -224,7 +224,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore while not self.queue.empty(): latest_result = self.queue.get() - # FIXME: cache is being checked in two passes + # TODO: cache is being checked in two passes cache = self.controller.get_dist_cache() if latest_result: From b9cb7ec973d7acbf6b9779128a3e923906f5a9ac Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 06:03:40 +0900 Subject: [PATCH 20/23] chore: update repo URL --- CONTRIBUTING.md | 5 ++--- dzgui/const/endpoints.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77d627a..1e5fe05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ If you are a developer, you can skip to the end. # Requesting help If you encounter a problem with DZGUI, you can submit tickets on the GitHub -[issue tracker](https://github.com/aclist/dztui/issues) under the +[issue tracker](https://github.com/aclist/dzgui/issues) under the `troubleshooting` tag. # How can I help the project? @@ -24,7 +24,7 @@ accordingly. ## Submitting a ticket -Navigate to the GitHub [issue tracker](https://github.com/aclist/dztui/issues). +Navigate to the GitHub [issue tracker](https://github.com/aclist/dzgui/issues). From there, follow the onscreen prompts. You will be asked questions such as: - What version are you using? @@ -55,7 +55,6 @@ The following naming conventions apply for PRs: - fix/ - patch/hotfix branches - feat/ - feature branches - doc/ - documentation branches -- infra/ - infrastructure branches Implement your changes and test them locally. If they work, you may open a merge request, and then we review your changes. If everything is OK, it diff --git a/dzgui/const/endpoints.py b/dzgui/const/endpoints.py index ed6239d..547cb5d 100644 --- a/dzgui/const/endpoints.py +++ b/dzgui/const/endpoints.py @@ -8,9 +8,9 @@ STEAM_UNSUB = "https://api.steampowered.com/IPublishedFileService/Unsubscribe/v1 STEAM_APP_DETAILS = "https://store.steampowered.com/api/appdetails?" GITHUB = "https://github.com/aclist" -GITHUB_RELEASES = "https://api.github.com/repos/aclist/dztui/releases/latest" +GITHUB_RELEASES = "https://api.github.com/repos/aclist/dzgui/releases/latest" CODEBERG_RELEASES = "https://codeberg.org/api/v1/repos/aclist/dzgui/releases/latest" -GITHUB_USER_RELEASES = "https://github.com/aclist/dztui/releases" +GITHUB_USER_RELEASES = "https://github.com/aclist/dzgui/releases" DB_IP = "https://db-ip.com/db/download/ip-to-city-lite" IP_ECHO = "https://ipecho.net/plain" COORDS_API = "http://ip-api.com/json" From 35623b645696f8899dec5187a14f24037dace8e8 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 06:06:27 +0900 Subject: [PATCH 21/23] change: use ServerRow classmethod --- dzgui/views/trees/tree_servers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 9c1c671..f4f871a 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -38,6 +38,7 @@ IND_QPORT = ServerRow.get_index("qport") IND_PING = ServerRow.get_index("ping") IND_MODDED = ServerRow.get_index("modded") + class ServerTreeView(ContextMixin, TreeView): # type: ignore def __init__( self, @@ -107,7 +108,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore if column_title in width_map: w = width_map[column_title] column.set_fixed_width(w) - if column_title == "Ping": + if i == IND_PING: column.set_cell_data_func(renderer, self._get_ping) column.connect("notify::fixed-width", self._on_col_width_changed) From e4dc5450389068d96683b8e613926439f1690b07 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 06:10:00 +0900 Subject: [PATCH 22/23] fix: URLs --- docs/source/development.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/development.rst b/docs/source/development.rst index c92c64b..167f05b 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -3,12 +3,12 @@ Developers This project is open source under the GPLv3 license. You can find the source code on `GitHub `_. If you wish to contribute to development, you will find further help in the -`CONTRIBUTING.md `_ +`CONTRIBUTING.md `_ file. All contributors are expected to act in accordance with the project's -`code of conduct `_, +`code of conduct `_, and follow the project's standards and guidelines. Detailed instructions on setting up a build environment and installing DZGUI from source code -can be found in the `DEVELOPERS.md `_ file. +can be found in the `DEVELOPERS.md `_ file. From 8aaa806cd3442560a849c5eeb51feaa6ec561d18 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 12 Nov 2026 06:11:48 +0900 Subject: [PATCH 23/23] chore: drop unused docs pages --- docs/source/dzgui6.rst | 110 ----------------------------------------- docs/source/dzgui7.rst | 33 ------------- docs/source/steam.rst | 94 ----------------------------------- 3 files changed, 237 deletions(-) delete mode 100644 docs/source/dzgui6.rst delete mode 100644 docs/source/dzgui7.rst delete mode 100644 docs/source/steam.rst diff --git a/docs/source/dzgui6.rst b/docs/source/dzgui6.rst deleted file mode 100644 index 1869fa5..0000000 --- a/docs/source/dzgui6.rst +++ /dev/null @@ -1,110 +0,0 @@ -Installation (DZGUI 6 legacy) -================== - -Basic runtime dependencies ---------------------------------- - -If not already installed, the below can be found in your system’s package manager. - -If any dependencies are missing when the application starts, it will warn you, so you need not take any preemptive measures here. - -- curl -- jq -- steam -- wmctrl or xdotool -- zenity - -.. note:: - All dependencies are installed out of the box on Steam Deck. - -UI dependencies (Python and PyGObject) ---------------------------------------- -.. important:: - As of version 6.0.0, you must have a valid Python 3.13 and matching PyGObject environment. - Depending on your distribution, this may require additional manual intervention. - -Arch Linux (vanilla variants) -^^^^^^^^^^^^^^^^^^^^^^ -You will need the ``python3.13`` package, if it is not already installed. - -Install the following build dependencies: - -.. code:: console - - sudo pacman -S cmake gcc pkgconf python-cairo - -.. include:: venv.rst - -CachyOS (Arch) -^^^^^^^^^^^^^^^^^^^^^^^ -Refer to the build instructions for Arch Linux first. -The ``python3.13`` package is not available on CachyOS, so it is recommended to -use ``uv`` to manage Python versions. - -.. code:: console - - sudo pacman -S uv - -.. include:: venv.rst - -Manjaro 26 (Arch) -^^^^^^^^^^^^^^^^^^^^^^^ -If Python 3.13 is not already available out of the box, refer to the build instructions for :ref:`Arch Linux (vanilla variants)`. - -Debian 13 variants -^^^^^^^^^^^^^^^^^^^^^^^ -Python 3.13 and PyGObject are available out of the box. No additional steps are necessary. -You can proceed to the :ref:`Installscript`. - -Fedora 43 variants -^^^^^^^^^^^^^^^^^^^^^^^ -Fedora 43 ships with a newer version of Python (3.14), so you must set up Python 3.13 in its own -virtual environment (venv) to prevent it from conflicting with the system package. - -Install the following build dependencies: - -.. code:: console - - sudo dnf install cairo cairo-devel cairo-gobject-devel gcc python3.13 python3.13-devel - -.. include:: venv.rst - -Ubuntu 24 variants -^^^^^^^^^^^^^^^^^^^^^^ -Ubuntu ships with an older version of Python (3.12). You must install additional dependencies. -Add the PPA below to add Python 3.13 to your sources: - -.. code:: console - - sudo add-apt-repository ppa:deadsnakes/ppa - -Install the following build dependencies: - -.. code:: console - - sudo apt install python3.13 python3.13-venv python3.13-dev build-essential python3-gi-cairo pkg-config libgirepository-2.0-dev libcairo2-dev - -.. include:: venv.rst - -Installscript ------------------------ - -Invoke the command below from a terminal. This script fetches the main DZGUI script from the repository, -makes it executable, and launches DZGUI's first-time setup. After running this installscript, you will -have the file ``dzgui.sh`` wherever you invoked the command. - -.. code:: console - - curl -s "https://codeberg.org/aclist/dztui/raw/branch/dzgui/install.sh" | bash - -nixOS installation ----------------------- -Two packages are independently maintained by other contributors. Each takes a slightly different approach. -nixOS packages are standalone and do not require cloning the git repository. - -- https://github.com/lelgenio/dzgui-nix -- https://github.com/jiriks74/dzgui.flake - -Next steps ---------------- -Proceed to the :doc:`setup` section for setup instructions. diff --git a/docs/source/dzgui7.rst b/docs/source/dzgui7.rst deleted file mode 100644 index b6a0e30..0000000 --- a/docs/source/dzgui7.rst +++ /dev/null @@ -1,33 +0,0 @@ -Installation (DZGUI 7 beta) -================== - -In order to make the first-time setup experience easier for end-users, DZGUI 7 no longer requires -the tool to be installed from source code into a working Python environment. All necessary dependencies and the -runtime environment are built-in. - -Turnkey installer ------------------------- - -- Visit the project's `Releases page `_. -- Extract the DZGUI tarball from the top of the **Assets** list. -- From a terminal, run the command ``./dzgui`` or double click on the extracted file in - a file explorer. -- Once the setup wizard opens, follow the steps at the bottom of this page. - -UI dependencies (Python and PyGObject) ---------------------------------------- -On most major distributions, GObject introspection libraries should be available by default. - -If you receive an error about a missing ``libgirepository-2.0`` dependency, install it via your system's package manager. - -On Debian-based distributions (Ubuntu, etc.), this package is not explicitly installed on the system. -You can install it via the following set of commands: - -.. code:: console - - sudo apt update - sudo apt install libgirepository-2.0-0 - -Next steps ---------------- -Proceed to the :doc:`setup` section for setup instructions. diff --git a/docs/source/steam.rst b/docs/source/steam.rst deleted file mode 100644 index 687c75d..0000000 --- a/docs/source/steam.rst +++ /dev/null @@ -1,94 +0,0 @@ -Steam integration -==================== - -.. note:: - - In :doc:`DZGUI 7 `, Steam shortcut creation and cover art setup are handled automatically during setup. You can skip this step unless you are using DZGUI 6. - -DZGUI can be added to Steam as a "non-Steam game" in order to facilitate integration with Steam Deck or desktop environments. - -First, launch Steam in the **Large** (default) view. - -.. attention:: - Steam Deck users: Gaming Mode has limited support for configuration of custom games. You will need to switch to **Desktop Mode** in order to add a non-Steam game. - -.. figure:: images/01.png - :scale: 70% - :alt: Adding a non-Steam game - -Select **Add a Game** > **Add a Non-Steam Game** from the bottom left corner of the Steam client. - -Navigate to ``$HOME/.local/share/applications`` and select ``dzgui.desktop``. - -Select **Add Selected Programs** to add a shortcut to DZGUI. - -Artwork -^^^^^^^^^^ - -DZGUI ships with custom artwork that provides various cover/splash images to allow it to integrate with the rest of your games library. - -.. figure:: images/02.png - :scale: 70% - :alt: Adding a non-Steam game - -From the main library view, navigate to the app’s details page and right-click the blank image header at the top. - -.. figure:: images/03.png - :scale: 70% - :alt: Adding a non-Steam game - - -Select **Set Custom Background** - -Select to display **All Files** from the **File type** dropdown - -Navigate to ``$HOME/.local/share/dzgui`` and select ``hero.png``. - -.. figure:: images/04.png - :scale: 70% - :alt: Adding a non-Steam game - -Next, right-click the image background and select **Set Custom Logo**. - -Navigate to ``$HOME/.local/share/dzgui`` and select ``logo.png``. - -.. figure:: images/05.png - :scale: 70% - :alt: Adding a non-Steam game - -Notice that this removes the redundant app name that occluded the image, as seen above. - -.. figure:: images/06.png - :scale: 70% - :alt: Adding a non-Steam game - -Next, navigate to your Library index (looks like a bookshelf of cover art) and find the DZGUI app. - -Right-click its cover and select **Manage** > **Set custom artwork**. - -Navigate to ``$HOME/.local/share/dzgui`` and select ``grid.png``. - -.. figure:: images/07.png - :scale: 70% - :alt: Adding a non-Steam game - -The final result will create box art looking like the above. - -.. figure:: images/08.png - :scale: 100% - :alt: Adding a non-Steam game - -Next, right-click the DZGUI entry in your Library and select **Properties** to open the properties dialog. Next to the **Shortcut** field, you will see a small square box which represents the game’s -icon. Click this to open a file explorer, navigate to ``$HOME/.local/share/dzgui``, and select ``icon.png``. This will add a small icon to the list view. - -Finally, after you launch DZGUI for the first time, you should quit the application and return to the Library view. Select the **Recent Games** dropdown on the right-hand side. - -Steam shows a collection of box art based on categories like "Play Next", "Recent Games", etc. Look for a **downward-pointing caret icon** and click it, then select the **Recent Games** category. - -.. figure:: images/09.png - :scale: 100% - :alt: Adding a non-Steam game - -If DZGUI was the last item played, it will be shown with a landscape, rather than portrait, orientation cover, which is initially blank. - -To customize this cover, right click it and select **Manage** > **Set custom artwork**, navigate to ``$HOME/.local/share/dzgui``, then select ``hero.png``.