Compare commits

..
Author SHA1 Message Date
aclist c94e4e73db chore: add strings file 2026-11-10 04:34:38 +09:00
aclist 8da264686a chore: clear typehinting errors 2026-11-10 04:33:54 +09:00
aclist 598973104c change: reference dataclass values in enum 2026-11-10 04:30:40 +09:00
aclist 15d4b71350 Merge pull request #533 from aclist/docs/more-attribution
Mirror to Codeberg / mirror-to-codeberg (push) Waiting to run
chore: add remarks to README
2026-11-10 03:08:12 +09:00
aclist 16d3df618a chore: add remarks to README 2026-11-10 03:07:30 +09:00
aclist 22dd8fc67f Merge pull request #525 from aclist/change/get-git-root
change: get git root
2026-11-10 02:44:51 +09:00
aclist 03fa707305 chore: remove unused imports 2026-11-09 11:04:56 +09:00
aclist 2479cbd41b change: parse repository root 2026-11-09 11:03:50 +09:00
36 changed files with 410 additions and 352 deletions

No files matched your search

+2
View File
@@ -37,6 +37,8 @@ Users wishing to review the licenses to these components can inspect the `LICENS
Steam and the Steam logo are trademarks and/or registered trademarks of Valve Corporation in the U.S. and/or other countries. Steam and the Steam logo are trademarks and/or registered trademarks of Valve Corporation in the U.S. and/or other countries.
DayZ is a trademark and brand of Bohemia Interactive a.s.
## Disclaimer ## Disclaimer
DZGUI is beta-quality software and is provided as-is. DZGUI is beta-quality software and is provided as-is.
+2 -1
View File
@@ -5,6 +5,7 @@ from dzgui.util._json import read_json
from dzgui.const.enum import Preferences from dzgui.const.enum import Preferences
class ConfigFileError(Exception): class ConfigFileError(Exception):
pass pass
@@ -39,4 +40,4 @@ def get_favorites(path: Path) -> list[str]:
def enum_to_key(enum: Preferences) -> str: def enum_to_key(enum: Preferences) -> str:
return str(enum.dict["key"]) return str(enum.key)
+22
View File
@@ -37,6 +37,28 @@ HEX_GREEN = "#32CD32"
HEX_RED = "#FF0000" HEX_RED = "#FF0000"
HEX_ORANGE = "#FFAC1C" HEX_ORANGE = "#FFAC1C"
# TODO: normalize icon names
CALCULATOR = "accessories-calculator-symbolic"
CARET_DOWN = "go-down-symbolic"
CARET_UP = "go-up-symbolic"
CLIPBOARD = "edit-copy-symbolic"
CLOSE = "window-close-symbolic"
FOLDER = "folder-symbolic"
EDIT_DELETE = "edit-delete-symbolic"
ERROR = "dialog-error-symbolic"
HELP_BUBBLE = "help-about-symbolic"
INPUT_KEYBOARD = "input-keyboard-symbolic"
LIST_ADD = "list-add-symbolic"
REFRESH_ICON = "view-refresh-symbolic"
SEARCH_ICON = "system-search-symbolic"
STEAM_ICON = "steam-tray-symbolic"
VIEW_CONCEAL = "view-conceal-symbolic"
VIEW_REVEAL = "view-reveal-symbolic"
WARNING = "dialog-warning-symbolic"
WEB_BROWSER = "web-browser-symbolic"
DAY_ICON = "weather-clear-symbolic"
NIGHT_ICON = "weather-clear-night-symbolic"
SEPARATOR = "SEPARATOR" SEPARATOR = "SEPARATOR"
# TODO: drop # TODO: drop
+224 -206
View File
@@ -1,7 +1,9 @@
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Any, Self
from dzgui.util import strings from dzgui.util import strings
from dzgui.strings import rows
class Port(Enum): class Port(Enum):
@@ -46,125 +48,61 @@ class FilterMode(Enum):
TOGGLE_ON = 3 TOGGLE_ON = 3
class EnumWithAttrs(Enum): @dataclass(slots=True, frozen=True)
def __new__(cls, *args: Any, **kwargs: Any) -> Self: class ModButtonMeta:
value = len(cls.__members__) + 1 label: str
obj = object.__new__(cls) tooltip: str
obj._value_ = value
return obj
def __init__(self, d: dict):
self.dict = d
class Preferences(EnumWithAttrs): @dataclass(slots=True, frozen=True)
STEAM = { class ButtonTypeMeta:
"key": "steam_api", label: str
} tooltip: str
CLIENT = { opens: NotebookPage | None
"key": "client",
}
WINDOW = {
"key": "fullscreen",
}
DIST = {
"key": "use_miles",
}
NAME = {
"key": "name",
}
DEFAULT = {
"key": "default_steam_path",
}
FAV_LBL = {
"key": "fav_label",
}
FAV_SRV = {
"key": "fav_server",
}
IP_LIST = {
"key": "ip_list",
}
START_TAB = {
"key": "start_tab",
}
class NotebookPage(EnumWithAttrs): @dataclass(slots=True, frozen=True)
OFFLINE = {"crumbs": strings.crumbs.offline, "statusbar": True} class ConfigKey:
CHANGELOG = {"crumbs": strings.crumbs.changelog, "statusbar": True} key: str
DEVELOPERS = {"crumbs": strings.crumbs.developers, "statusbar": False}
HELP = {"crumbs": strings.crumbs._help, "statusbar": True}
KEYS = {"crumbs": strings.crumbs.keys, "statusbar": True}
LOG = {"crumbs": strings.crumbs.log, "statusbar": True}
MODS = {"crumbs": strings.crumbs.mods, "statusbar": True}
OPTIONS = {"crumbs": strings.crumbs.options, "statusbar": False}
SERVERS = {"crumbs": strings.crumbs.servers, "statusbar": True}
THANKS = {"crumbs": strings.crumbs.thanks, "statusbar": True}
CONNECTION = {"crumbs": "Connect", "statusbar": True}
class RowType(EnumWithAttrs): @dataclass(slots=True, frozen=True)
# TODO: strings class NotebookMeta:
CHANGELOG = { crumbs: str
"label": "View changelog", has_statusbar: bool
"tooltip": "Opens the DZGUI changelog",
}
SHOW_LOG = {
"label": "Show debug log",
"tooltip": "Read the DZGUI log generated since startup",
}
SEPARATOR = {
"label": "SEPARATOR",
"tooltip": "",
}
DUMP_LOG = {
"label": "Output system info to log file",
"tooltip": "Dump diagnostic data for troubleshooting",
}
DOCS = {
"label": "Documentation/help files (GitHub) ⧉",
"tooltip": "Open the DZGUI documentation in a browser",
}
DOCS_FALLBACK = {
"label": "Documentation/help files (Codeberg mirror) ⧉",
"tooltip": "Open the DZGUI documentation in a browser",
}
BUGS = {
"label": "Report a bug (GitHub) ⧉",
"tooltip": "Open the DZGUI issue tracker in a browser",
}
FORUM = {
"label": "DZGUI Subreddit ⧉",
"tooltip": "Open the DZGUI discussion forum in a browser",
}
SPONSOR = {
"label": "Sponsor (GitHub) ⧉",
"tooltip": "Sponsor development of the DZGUI project",
}
THANKS = {
"label": "Special thanks",
"tooltip": "A list of contributors, testers, and sponsors",
}
# TODO: rename to ContextMenuItem @dataclass(slots=True, frozen=True)
class ContextMenu(EnumWithAttrs): class RowMeta:
ADD_NOTE = {"label": strings.add_note} label: str
ADD_SERVER = {"label": strings.add} tooltip: str
CONNECT = {"label": strings.connect}
COPY_LOG_CLIPBOARD = {"label": strings.copy_log}
COPY_SERVER_IP = {"label": strings.copy_ip} @dataclass(slots=True, frozen=True)
COPY_SERVER_NAME = {"label": strings.copy_name} class ContextMenuMeta:
UNSUB_MOD = {"label": strings.unsub_mod} label: str
VALIDATE_MOD = {"label": strings.validate_mod}
OPEN_WORKSHOP = {"label": strings.open_workshop}
REFRESH_PLAYERS = {"label": strings.refresh_players} class ContextMenuItem(Enum):
REMOVE_HISTORY = {"label": strings.remove_history} ADD_NOTE = ContextMenuMeta(strings.add_note)
REMOVE_SERVER = {"label": strings.remove} ADD_SERVER = ContextMenuMeta(strings.add)
SET_FAV = {"label": strings.add_fav} CONNECT = ContextMenuMeta(strings.connect)
SHOW_DETAILS = {"label": strings.show_details} COPY_LOG_CLIPBOARD = ContextMenuMeta(strings.copy_log)
SHOW_MODS = {"label": strings.show_mods} COPY_SERVER_IP = ContextMenuMeta(strings.copy_ip)
COPY_SERVER_NAME = ContextMenuMeta(strings.copy_name)
UNSUB_MOD = ContextMenuMeta(strings.unsub_mod)
VALIDATE_MOD = ContextMenuMeta(strings.validate_mod)
OPEN_WORKSHOP = ContextMenuMeta(strings.open_workshop)
REFRESH_PLAYERS = ContextMenuMeta(strings.refresh_players)
REMOVE_HISTORY = ContextMenuMeta(strings.remove_history)
REMOVE_SERVER = ContextMenuMeta(strings.remove)
SET_FAV = ContextMenuMeta(strings.add_fav)
SHOW_DETAILS = ContextMenuMeta(strings.show_details)
SHOW_MODS = ContextMenuMeta(strings.show_mods)
@property
def label(self) -> str:
return self.value.label
class ContextMenuGroup(Enum): class ContextMenuGroup(Enum):
@@ -172,113 +110,193 @@ class ContextMenuGroup(Enum):
Groupings of context menu items Groupings of context menu items
""" """
SERVER_MOD = (ContextMenu.OPEN_WORKSHOP,) SERVER_MOD = (ContextMenuItem.OPEN_WORKSHOP,)
MOD = (ContextMenu.OPEN_WORKSHOP, ContextMenu.UNSUB_MOD, ContextMenu.VALIDATE_MOD) MOD = (
ContextMenuItem.OPEN_WORKSHOP,
ContextMenuItem.UNSUB_MOD,
ContextMenuItem.VALIDATE_MOD,
)
MOD_OFFLINE = (None,) MOD_OFFLINE = (None,)
LOG = (ContextMenu.COPY_LOG_CLIPBOARD,) LOG = (ContextMenuItem.COPY_LOG_CLIPBOARD,)
SERVER_BROWSER = ( SERVER_BROWSER = (
ContextMenu.CONNECT, ContextMenuItem.CONNECT,
ContextMenu.ADD_SERVER, ContextMenuItem.ADD_SERVER,
ContextMenu.SET_FAV, ContextMenuItem.SET_FAV,
ContextMenu.COPY_SERVER_NAME, ContextMenuItem.COPY_SERVER_NAME,
ContextMenu.COPY_SERVER_IP, ContextMenuItem.COPY_SERVER_IP,
ContextMenu.ADD_NOTE, ContextMenuItem.ADD_NOTE,
ContextMenu.SHOW_MODS, ContextMenuItem.SHOW_MODS,
ContextMenu.SHOW_DETAILS, ContextMenuItem.SHOW_DETAILS,
ContextMenu.REFRESH_PLAYERS, ContextMenuItem.REFRESH_PLAYERS,
) )
SCAN_LAN = ( SCAN_LAN = (
ContextMenu.CONNECT, ContextMenuItem.CONNECT,
ContextMenu.SET_FAV, ContextMenuItem.SET_FAV,
ContextMenu.COPY_SERVER_NAME, ContextMenuItem.COPY_SERVER_NAME,
ContextMenu.COPY_SERVER_IP, ContextMenuItem.COPY_SERVER_IP,
ContextMenu.ADD_NOTE, ContextMenuItem.ADD_NOTE,
ContextMenu.SHOW_MODS, ContextMenuItem.SHOW_MODS,
ContextMenu.SHOW_DETAILS, ContextMenuItem.SHOW_DETAILS,
ContextMenu.REFRESH_PLAYERS, ContextMenuItem.REFRESH_PLAYERS,
) )
SAVED = ( SAVED = (
ContextMenu.CONNECT, ContextMenuItem.CONNECT,
ContextMenu.SET_FAV, ContextMenuItem.SET_FAV,
ContextMenu.REMOVE_SERVER, ContextMenuItem.REMOVE_SERVER,
ContextMenu.COPY_SERVER_NAME, ContextMenuItem.COPY_SERVER_NAME,
ContextMenu.COPY_SERVER_IP, ContextMenuItem.COPY_SERVER_IP,
ContextMenu.ADD_NOTE, ContextMenuItem.ADD_NOTE,
ContextMenu.SHOW_MODS, ContextMenuItem.SHOW_MODS,
ContextMenu.SHOW_DETAILS, ContextMenuItem.SHOW_DETAILS,
ContextMenu.REFRESH_PLAYERS, ContextMenuItem.REFRESH_PLAYERS,
) )
RECENT = ( RECENT = (
ContextMenu.CONNECT, ContextMenuItem.CONNECT,
ContextMenu.ADD_SERVER, ContextMenuItem.ADD_SERVER,
ContextMenu.SET_FAV, ContextMenuItem.SET_FAV,
ContextMenu.REMOVE_HISTORY, ContextMenuItem.REMOVE_HISTORY,
ContextMenu.COPY_SERVER_NAME, ContextMenuItem.COPY_SERVER_NAME,
ContextMenu.COPY_SERVER_IP, ContextMenuItem.COPY_SERVER_IP,
ContextMenu.ADD_NOTE, ContextMenuItem.ADD_NOTE,
ContextMenu.SHOW_MODS, ContextMenuItem.SHOW_MODS,
ContextMenu.SHOW_DETAILS, ContextMenuItem.SHOW_DETAILS,
ContextMenu.REFRESH_PLAYERS, ContextMenuItem.REFRESH_PLAYERS,
) )
class ModButton(EnumWithAttrs): class Preferences(Enum):
SELECT_ALL = { STEAM = ConfigKey("steam_api")
"label": strings.mod_panel.select_all, CLIENT = ConfigKey("client")
"tooltip": strings.mod_panel.select_all_tooltip, WINDOW = ConfigKey("fullscreen")
} DIST = ConfigKey("use_miles")
UNSELECT_ALL = { NAME = ConfigKey("name")
"label": strings.mod_panel.unselect_all, DEFAULT = ConfigKey("default_steam_path")
"tooltip": strings.mod_panel.unselect_all_tooltip, FAV_LBL = ConfigKey("fav_label")
} FAV_SRV = ConfigKey("fav_server")
HIGHLIGHT_STALE = { IP_LIST = ConfigKey("ip_list")
"label": strings.mod_panel.highlight_stale, START_TAB = ConfigKey("start_tab")
"tooltip": strings.mod_panel.highlight_stale_tooltip,
} @property
UNHIGHLIGHT_STALE = { def key(self) -> str:
"label": strings.mod_panel.unhighlight_stale, return self.value.key
"tooltip": strings.mod_panel.unhighlight_stale_tooltip,
}
UNSUB_SELECTED = {
"label": strings.mod_panel.unsub_selected,
"tooltip": strings.mod_panel.unsub_selected_tooltip,
}
SELECT_STALE = {
"label": strings.mod_panel.select_stale,
"tooltip": strings.mod_panel.select_stale_tooltip,
}
VALIDATE = {
"label": strings.mod_panel.validate,
"tooltip": strings.mod_panel.validate_tooltip,
}
class ButtonType(EnumWithAttrs): class NotebookPage(Enum):
SERVERS = { OFFLINE = NotebookMeta(strings.crumbs.offline, True)
"label": strings.buttons.servers_label, CHANGELOG = NotebookMeta(strings.crumbs.changelog, True)
"tooltip": strings.buttons.servers_tooltip, DEVELOPERS = NotebookMeta(strings.crumbs.developers, False)
"opens": NotebookPage.SERVERS, HELP = NotebookMeta(strings.crumbs._help, True)
} KEYS = NotebookMeta(strings.crumbs.keys, True)
MODS = { LOG = NotebookMeta(strings.crumbs.log, True)
"label": strings.buttons.mods_label, MODS = NotebookMeta(strings.crumbs.mods, True)
"tooltip": strings.buttons.mods_tooltip, OPTIONS = NotebookMeta(strings.crumbs.options, False)
"opens": NotebookPage.MODS, SERVERS = NotebookMeta(strings.crumbs.servers, True)
} THANKS = NotebookMeta(strings.crumbs.thanks, True)
OPTIONS = { CONNECTION = NotebookMeta(strings.crumbs.connect, True)
"label": strings.buttons.options_label,
"tooltip": strings.buttons.options_tooltip, @property
"opens": NotebookPage.OPTIONS, def crumbs(self) -> str:
} return self.value.crumbs
HELP = {
"label": strings.buttons.help_label, @property
"tooltip": strings.buttons.help_tooltip, def has_statusbar(self) -> bool:
"opens": NotebookPage.HELP, return self.value.has_statusbar
}
EXIT = {
"label": strings.buttons.exit_label, class RowType(Enum):
"tooltip": strings.buttons.exit_tooltip, CHANGELOG = RowMeta(rows.changelog_label, rows.changelog_status)
"opens": None, SHOW_LOG = RowMeta(rows.log_label, rows.log_status)
} SEPARATOR = RowMeta(rows.separator_label, rows.separator_status)
DUMP_LOG = RowMeta(rows.system_log_label, rows.system_log_status)
DOCS = RowMeta(rows.docs_label, rows.docs_status)
DOCS_FALLBACK = RowMeta(rows.docs_fallback_label, rows.docs_fallback_status)
BUGS = RowMeta(rows.bugs_label, rows.bugs_status)
FORUM = RowMeta(rows.forum_label, rows.forum_status)
SPONSOR = RowMeta(rows.sponsor_label, rows.sponsor_status)
THANKS = RowMeta(rows.thanks_label, rows.thanks_status)
@property
def label(self) -> str:
return self.value.label
@property
def tooltip(self) -> str:
return self.value.tooltip
class ModButton(Enum):
SELECT_ALL = ModButtonMeta(
strings.mod_panel.select_all, strings.mod_panel.select_all_tooltip
)
UNSELECT_ALL = ModButtonMeta(
strings.mod_panel.unselect_all, strings.mod_panel.unselect_all_tooltip
)
HIGHLIGHT_STALE = ModButtonMeta(
strings.mod_panel.highlight_stale, strings.mod_panel.highlight_stale_tooltip
)
UNHIGHLIGHT_STALE = ModButtonMeta(
strings.mod_panel.unhighlight_stale, strings.mod_panel.unhighlight_stale_tooltip
)
UNSUB_SELECTED = ModButtonMeta(
strings.mod_panel.unsub_selected,
strings.mod_panel.unsub_selected_tooltip,
)
SELECT_STALE = ModButtonMeta(
strings.mod_panel.select_stale,
strings.mod_panel.select_stale_tooltip,
)
VALIDATE = ModButtonMeta(
strings.mod_panel.validate,
strings.mod_panel.validate_tooltip,
)
@property
def label(self) -> str:
return self.value.label
@property
def tooltip(self) -> str:
return self.value.tooltip
class ButtonType(Enum):
SERVERS = ButtonTypeMeta(
strings.buttons.servers_label,
strings.buttons.servers_tooltip,
NotebookPage.SERVERS,
)
MODS = ButtonTypeMeta(
strings.buttons.mods_label,
strings.buttons.mods_tooltip,
NotebookPage.MODS,
)
OPTIONS = ButtonTypeMeta(
strings.buttons.options_label,
strings.buttons.options_tooltip,
NotebookPage.OPTIONS,
)
HELP = ButtonTypeMeta(
strings.buttons.help_label,
strings.buttons.help_tooltip,
NotebookPage.HELP,
)
EXIT = ButtonTypeMeta(
strings.buttons.exit_label,
strings.buttons.exit_tooltip,
None,
)
@property
def label(self) -> str:
return self.value.label
@property
def tooltip(self) -> str:
return self.value.tooltip
@property
def opens(self) -> NotebookPage | None:
return self.value.opens
HELP_MENU_ROWS = ( HELP_MENU_ROWS = (
-20
View File
@@ -1,20 +0,0 @@
ICON_CALCULATOR = "accessories-calculator-symbolic"
ICON_CARET_DOWN = "go-down-symbolic"
ICON_CARET_UP = "go-up-symbolic"
ICON_CLIPBOARD = "edit-copy-symbolic"
ICON_CLOSE = "window-close-symbolic"
ICON_DAY = "weather-clear-symbolic"
ICON_EDIT_DELETE = "edit-delete-symbolic"
ICON_ERROR = "dialog-error-symbolic"
ICON_FOLDER = "folder-symbolic"
ICON_HELP_BUBBLE = "help-about-symbolic"
ICON_INPUT_KEYBOARD = "input-keyboard-symbolic"
ICON_LIST_ADD = "list-add-symbolic"
ICON_NIGHT = "weather-clear-night-symbolic"
ICON_REFRESH = "view-refresh-symbolic"
ICON_SEARCH = "system-search-symbolic"
ICON_STEAM = "steam-tray-symbolic"
ICON_VIEW_CONCEAL = "view-conceal-symbolic"
ICON_VIEW_REVEAL = "view-reveal-symbolic"
ICON_WARNING = "dialog-warning-symbolic"
ICON_WEB_BROWSER = "web-browser-symbolic"
+8 -7
View File
@@ -8,7 +8,7 @@ import dzgui.util._json as JSON # noqa
from dzgui.const.enum import ( from dzgui.const.enum import (
ButtonType, ButtonType,
ContextMenu, ContextMenuItem,
FilterMode, FilterMode,
NotebookPage, NotebookPage,
Preferences, Preferences,
@@ -196,7 +196,9 @@ class Controller(GObject.GObject):
def show_developers_page(self) -> None: def show_developers_page(self) -> None:
self.open_page(NotebookPage.DEVELOPERS) self.open_page(NotebookPage.DEVELOPERS)
def open_page(self, page: NotebookPage) -> None: def open_page(self, page: NotebookPage | None) -> None:
if page is None:
return
self.mediator.grid.notebook.set_page_by_enum(page) self.mediator.grid.notebook.set_page_by_enum(page)
def open_page_by_button(self, button: "ContextualButton") -> None: def open_page_by_button(self, button: "ContextualButton") -> None:
@@ -262,7 +264,7 @@ class Controller(GObject.GObject):
logger.critical(e) logger.critical(e)
return return
def menu_action(self, action: ContextMenu, tree: "ServerTreeView") -> None: def menu_action(self, action: ContextMenuItem, tree: "ServerTreeView") -> None:
context_man = ContextMenuManager(tree, self) context_man = ContextMenuManager(tree, self)
context_man.process(action) context_man.process(action)
@@ -274,7 +276,7 @@ class Controller(GObject.GObject):
except Exception as e: except Exception as e:
dialog = ExceptionDialog(self, str(e)) dialog = ExceptionDialog(self, str(e))
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def select_colorized(self) -> None: def select_colorized(self) -> None:
mod_man = self.mediator.modtreeview.get_mod_man() mod_man = self.mediator.modtreeview.get_mod_man()
@@ -308,7 +310,7 @@ class Controller(GObject.GObject):
except Exception as e: except Exception as e:
dialog = ExceptionDialog(self, str(e)) dialog = ExceptionDialog(self, str(e))
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def update_steam_api_key(self, text: str) -> None: def update_steam_api_key(self, text: str) -> None:
self.config_man.update_steam_api_key(text) self.config_man.update_steam_api_key(text)
@@ -365,12 +367,11 @@ class Controller(GObject.GObject):
filter_man = self.get_filter_man() filter_man = self.get_filter_man()
return filter_man.get_map_store() return filter_man.get_map_store()
def get_enabled_filters(self) -> dict: def get_enabled_filters(self) -> dict[str, bool]:
filter_man = self.get_filter_man() filter_man = self.get_filter_man()
return filter_man.get_filters() return filter_man.get_filters()
# FIXME: wipe maps store when changing tabs if model is none # FIXME: wipe maps store when changing tabs if model is none
def has_server_model(self) -> bool: def has_server_model(self) -> bool:
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
proxy_man = treeview.get_proxy_man() proxy_man = treeview.get_proxy_man()
+1 -1
View File
@@ -124,7 +124,7 @@ class ConfigManager:
return False return False
def enum_to_key(self, enum: Preferences) -> str: def enum_to_key(self, enum: Preferences) -> str:
return str(enum.dict["key"]) return str(enum.key)
def toggle_config(self, key: Preferences) -> None: def toggle_config(self, key: Preferences) -> None:
try: try:
+19 -19
View File
@@ -2,7 +2,7 @@ import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from dzgui.const.constants import APP_NAME from dzgui.const.constants import APP_NAME
from dzgui.const.enum import ContextMenu, Preferences from dzgui.const.enum import ContextMenuItem, Preferences
from dzgui.util.clip import copy_clipboard from dzgui.util.clip import copy_clipboard
from dzgui.util.open_links import open_workshop_page from dzgui.util.open_links import open_workshop_page
@@ -34,7 +34,7 @@ class ContextMenuManager:
self.controller = controller self.controller = controller
self.treeview = treeview self.treeview = treeview
def process(self, action: ContextMenu) -> None: def process(self, action: ContextMenuItem) -> None:
if isinstance(self.treeview, ServerTreeView): if isinstance(self.treeview, ServerTreeView):
record = self.treeview.get_record() record = self.treeview.get_record()
if record is None: if record is None:
@@ -42,14 +42,14 @@ class ContextMenuManager:
match action: match action:
# UNTHREADED # UNTHREADED
case ContextMenu.ADD_NOTE: case ContextMenuItem.ADD_NOTE:
dialog = NoteDialog(self.controller) dialog = NoteDialog(self.controller)
dialog.run() dialog.run() # type: ignore[no-untyped-call]
case ContextMenu.COPY_SERVER_IP: case ContextMenuItem.COPY_SERVER_IP:
self.copy_server_ip() self.copy_server_ip()
case ContextMenu.COPY_SERVER_NAME: case ContextMenuItem.COPY_SERVER_NAME:
self.copy_server_name() self.copy_server_name()
case ContextMenu.SET_FAV: case ContextMenuItem.SET_FAV:
name = self.treeview.get_value_at_index(0) name = self.treeview.get_value_at_index(0)
# NOTE: fully qualified ip # NOTE: fully qualified ip
fqip = self.treeview.get_record_string() fqip = self.treeview.get_record_string()
@@ -58,40 +58,40 @@ class ContextMenuManager:
self.controller.set_fav(name, fqip, simple) self.controller.set_fav(name, fqip, simple)
# THREADED # THREADED
case ContextMenu.ADD_SERVER: case ContextMenuItem.ADD_SERVER:
self.controller.add_by_record(record) self.controller.add_by_record(record)
case ContextMenu.CONNECT: case ContextMenuItem.CONNECT:
self.controller.connect_by_record(record) self.controller.connect_by_record(record)
case ContextMenu.REFRESH_PLAYERS: case ContextMenuItem.REFRESH_PLAYERS:
self.controller.refresh_players(record) self.controller.refresh_players(record)
case ContextMenu.REMOVE_HISTORY: case ContextMenuItem.REMOVE_HISTORY:
self.controller.remove_from_history(record) self.controller.remove_from_history(record)
case ContextMenu.REMOVE_SERVER: case ContextMenuItem.REMOVE_SERVER:
self.controller.remove_by_record(record) self.controller.remove_by_record(record)
case ContextMenu.SHOW_DETAILS: case ContextMenuItem.SHOW_DETAILS:
self.controller.get_details(record) self.controller.get_details(record)
case ContextMenu.SHOW_MODS: case ContextMenuItem.SHOW_MODS:
self.controller.get_modlist(record) self.controller.get_modlist(record)
if isinstance(self.treeview, (ModTreeView, OfflineModTreeView)): if isinstance(self.treeview, (ModTreeView, OfflineModTreeView)):
match action: match action:
case ContextMenu.OPEN_WORKSHOP: case ContextMenuItem.OPEN_WORKSHOP:
self.open_mod_page() self.open_mod_page()
case ContextMenu.UNSUB_MOD: case ContextMenuItem.UNSUB_MOD:
self.controller.unsub_mods(self.treeview) self.controller.unsub_mods(self.treeview)
case ContextMenu.VALIDATE_MOD: case ContextMenuItem.VALIDATE_MOD:
self.controller.validate_mods(self.treeview) self.controller.validate_mods(self.treeview)
case _: case _:
pass pass
if isinstance(self.treeview, LogTreeView): if isinstance(self.treeview, LogTreeView):
match action: match action:
case ContextMenu.COPY_LOG_CLIPBOARD: case ContextMenuItem.COPY_LOG_CLIPBOARD:
self.copy_log() self.copy_log()
if isinstance(self.treeview, ServerModTreeView): if isinstance(self.treeview, ServerModTreeView):
match action: match action:
case ContextMenu.OPEN_WORKSHOP: case ContextMenuItem.OPEN_WORKSHOP:
self.open_mod_page() self.open_mod_page()
def copy_server_ip(self) -> None: def copy_server_ip(self) -> None:
+1 -1
View File
@@ -147,7 +147,7 @@ class ModelFactory:
def make_help_store(self) -> FastInsertListStore: def make_help_store(self) -> FastInsertListStore:
store = self.new_model_from_class(MenuCols) store = self.new_model_from_class(MenuCols)
rows = [[row.dict["label"], row] for row in HELP_MENU_ROWS] rows = [[row.label, row] for row in HELP_MENU_ROWS]
store.extend(rows) store.extend(rows)
return store return store
+29
View File
@@ -0,0 +1,29 @@
changelog_label = "View changelog"
changelog_status = "Opens the DZGUI changelog"
log_label = "Show debug log"
log_status = "Read the DZGUI log generated since startup"
separator_label = "SEPARATOR"
separator_status = ""
system_log_label = "Output system info to log file"
system_log_status = "Dump diagnostic data for troubleshooting"
docs_label = "Documentation/help files (GitHub) ⧉"
docs_status = "Open the DZGUI documentation in a browser"
docs_fallback_label = "Documentation/help files (Codeberg mirror) ⧉"
docs_fallback_status = "Open the DZGUI documentation in a browser"
bugs_label = "Report a bug (GitHub) ⧉"
bugs_status = "Open the DZGUI issue tracker in a browser"
forum_label = "DZGUI Subreddit ⧉"
forum_status = "Open the DZGUI discussion forum in a browser"
sponsor_label = "Sponsor (GitHub) ⧉"
sponsor_status = "Sponsor development of the DZGUI project"
thanks_label = "Special thanks"
thanks_status = "A list of contributors, testers, and sponsors"
+2
View File
@@ -252,6 +252,7 @@ class Crumbs:
developers: str developers: str
default: str default: str
offline: str offline: str
connect: str
@dataclass(slots=True, frozen=True) @dataclass(slots=True, frozen=True)
@@ -439,6 +440,7 @@ crumbs = Crumbs(
developers="Options > Developers", developers="Options > Developers",
default="Servers > ", default="Servers > ",
offline="Mods > Play offline", offline="Mods > Play offline",
connect="Connect",
) )
no_mods = "No local mods found." no_mods = "No local mods found."
+4 -4
View File
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
class ContextualButton(Gtk.Button): class ContextualButton(Gtk.Button):
def __init__( def __init__(
self, label: str, opens: "NotebookPage", tooltip: str, context: ButtonType self, label: str, opens: "NotebookPage" | None, tooltip: str, context: ButtonType
) -> None: ) -> None:
super().__init__( super().__init__(
label=label, label=label,
@@ -51,9 +51,9 @@ class ButtonBox(Gtk.Box):
for side_button in ButtonType: for side_button in ButtonType:
button = ContextualButton( button = ContextualButton(
label=side_button.dict["label"], label=side_button.label,
opens=side_button.dict["opens"], opens=side_button.opens,
tooltip=side_button.dict["tooltip"], tooltip=side_button.tooltip,
context=side_button, context=side_button,
) )
+17 -17
View File
@@ -7,15 +7,15 @@ from dzgui.util.strings import (
alert_button_tooltip, alert_button_tooltip,
atomic_buttons, atomic_buttons,
) )
from dzgui.const.icons import ( from dzgui.const.constants import (
ICON_CLIPBOARD, CLIPBOARD,
ICON_CLOSE, CLOSE,
ICON_INPUT_KEYBOARD, INPUT_KEYBOARD,
ICON_LIST_ADD, LIST_ADD,
ICON_REFRESH, REFRESH_ICON,
ICON_STEAM, STEAM_ICON,
ICON_WARNING, WARNING,
ICON_WEB_BROWSER, WEB_BROWSER,
) )
from dzgui.strings import connect_panel from dzgui.strings import connect_panel
@@ -102,7 +102,7 @@ class LargeIconTextButton(IconButton):
class ClipboardButton(IconTextButton): class ClipboardButton(IconTextButton):
def __init__(self, controller: Union["Controller", None], func: Callable) -> None: def __init__(self, controller: Union["Controller", None], func: Callable) -> None:
super().__init__(ICON_CLIPBOARD, atomic_buttons.copy) super().__init__(CLIPBOARD, atomic_buttons.copy)
self.controller = controller self.controller = controller
self.connect("clicked", self._on_button_clicked, func) self.connect("clicked", self._on_button_clicked, func)
@@ -131,7 +131,7 @@ class CopyIpButton(ClipboardButton):
class CloseButton(IconTextButton): class CloseButton(IconTextButton):
def __init__(self, label: str) -> None: def __init__(self, label: str) -> None:
super().__init__(icon=ICON_CLOSE, label=label) super().__init__(icon=CLOSE, label=label)
# TODO: strings # TODO: strings
self.set_tooltip_text("Unset this server as favorite") self.set_tooltip_text("Unset this server as favorite")
@@ -139,14 +139,14 @@ class CloseButton(IconTextButton):
class WebButton(IconTextButton): class WebButton(IconTextButton):
def __init__(self, label: str) -> None: def __init__(self, label: str) -> None:
super().__init__(icon=ICON_WEB_BROWSER, label=label) super().__init__(icon=WEB_BROWSER, label=label)
pass pass
class RefreshButton(IconTextButton): class RefreshButton(IconTextButton):
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
super().__init__( super().__init__(
icon=ICON_REFRESH, icon=REFRESH_ICON,
label=atomic_buttons.refresh, label=atomic_buttons.refresh,
) )
@@ -211,7 +211,7 @@ class RefreshButton(IconTextButton):
class KeysButton(IconTextButton): class KeysButton(IconTextButton):
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
super().__init__(icon=ICON_INPUT_KEYBOARD, label=atomic_buttons.keys) super().__init__(icon=INPUT_KEYBOARD, label=atomic_buttons.keys)
self.controller = controller self.controller = controller
self.set_margin_top(10) self.set_margin_top(10)
@@ -228,7 +228,7 @@ class KeysButton(IconTextButton):
class SteamConnectButton(LargeIconTextButton): class SteamConnectButton(LargeIconTextButton):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__(icon=ICON_STEAM, label=connect_panel.connect_button) super().__init__(icon=STEAM_ICON, label=connect_panel.connect_button)
self.set_tooltip_text(connect_panel.connect_tooltip) self.set_tooltip_text(connect_panel.connect_tooltip)
@@ -248,7 +248,7 @@ class SteamWorkshopButton(SteamTextButton):
class AddButton(IconTextButton): class AddButton(IconTextButton):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__(icon=ICON_LIST_ADD, label=connect_panel.add_button) super().__init__(icon=LIST_ADD, label=connect_panel.add_button)
self.set_tooltip_text(connect_panel.add_tooltip) self.set_tooltip_text(connect_panel.add_tooltip)
@@ -267,7 +267,7 @@ class LoggerAlertsButton(IconTextButton):
separator = "," separator = ","
concat = warnings_text + separator + errors_text concat = warnings_text + separator + errors_text
super().__init__( super().__init__(
icon=ICON_WARNING, icon=WARNING,
label=f"Loaded with{concat}", label=f"Loaded with{concat}",
) )
self.set_halign(Gtk.Align.END) self.set_halign(Gtk.Align.END)
+4 -5
View File
@@ -1,7 +1,6 @@
from typing import Self, TYPE_CHECKING from typing import Self, TYPE_CHECKING
from dzgui.const.icons import ICON_CARET_DOWN, ICON_CARET_UP from dzgui.const.constants import CARET_DOWN, CARET_UP, UDP_PORT
from dzgui.const.constants import UDP_PORT
from dzgui.model.servers import ServerModelManager from dzgui.model.servers import ServerModelManager
from dzgui.strings import connect_panel from dzgui.strings import connect_panel
from dzgui.util.keys import is_ctrl_mask from dzgui.util.keys import is_ctrl_mask
@@ -31,7 +30,7 @@ ROWS = 1
class DockButton(IconButton): class DockButton(IconButton):
def __init__(self, child: Gtk.Widget) -> None: def __init__(self, child: Gtk.Widget) -> None:
super().__init__(ICON_CARET_DOWN) super().__init__(CARET_DOWN)
self.expanded = True self.expanded = True
self.child = child self.child = child
@@ -44,12 +43,12 @@ class DockButton(IconButton):
self.set_tooltip_text(self.collapse_text) self.set_tooltip_text(self.collapse_text)
def collapse(self) -> None: def collapse(self) -> None:
self.set_image(Icon(ICON_CARET_UP)) self.set_image(Icon(CARET_UP))
self.child.hide() self.child.hide()
self.set_tooltip_text(self.expand_text) self.set_tooltip_text(self.expand_text)
def expand(self) -> None: def expand(self) -> None:
self.set_image(Icon(ICON_CARET_DOWN)) self.set_image(Icon(CARET_DOWN))
self.child.show() self.child.show()
self.set_tooltip_text(self.collapse_text) self.set_tooltip_text(self.collapse_text)
+1 -1
View File
@@ -43,7 +43,7 @@ class Breadcrumbs(Gtk.Label):
label = page.get_current_tab_text() label = page.get_current_tab_text()
self.set_server_crumbs(label) self.set_server_crumbs(label)
else: else:
crumbs = enum.dict["crumbs"] crumbs = enum.crumbs
self.set_crumbs(crumbs) self.set_crumbs(crumbs)
def set_server_crumbs(self, suffix: str) -> None: def set_server_crumbs(self, suffix: str) -> None:
+4 -4
View File
@@ -1,7 +1,7 @@
from typing import Any, Callable, TYPE_CHECKING from typing import Any, Callable, TYPE_CHECKING
from dzgui.api.servers import validate_ip from dzgui.api.servers import validate_ip
from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.const.constants import VIEW_CONCEAL, VIEW_REVEAL
from dzgui.util.css import add_class, remove_class from dzgui.util.css import add_class, remove_class
from dzgui.strings import connect_panel from dzgui.strings import connect_panel
from dzgui.strings.errors import api_popover from dzgui.strings.errors import api_popover
@@ -147,7 +147,7 @@ class APIEntry(Gtk.Box):
self.entry = Gtk.Entry( self.entry = Gtk.Entry(
width_chars=60, hexpand=True, placeholder_text="Enter API key" width_chars=60, hexpand=True, placeholder_text="Enter API key"
) )
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL) self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, VIEW_REVEAL)
self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True)
self.entry.set_visibility(False) self.entry.set_visibility(False)
self.entry.connect("changed", self._on_text_changed) self.entry.connect("changed", self._on_text_changed)
@@ -206,9 +206,9 @@ class APIEntry(Gtk.Box):
) -> None: ) -> None:
visible = widget.get_visibility() visible = widget.get_visibility()
if visible: if visible:
icon, state = ICON_VIEW_REVEAL, False icon, state = VIEW_REVEAL, False
else: else:
icon, state = ICON_VIEW_CONCEAL, True icon, state = VIEW_CONCEAL, True
widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon) widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon)
widget.set_visibility(state) widget.set_visibility(state)
+2 -2
View File
@@ -1,7 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from dzgui.const.enum import NotebookPage from dzgui.const.enum import NotebookPage
from dzgui.const.icons import ICON_HELP_BUBBLE from dzgui.const.constants import HELP_BUBBLE
import gi import gi
@@ -20,7 +20,7 @@ class InfoEventBox(Gtk.EventBox):
self.text = text self.text = text
self.icon = Gtk.Image.new_from_icon_name( self.icon = Gtk.Image.new_from_icon_name(
ICON_HELP_BUBBLE, Gtk.IconSize.LARGE_TOOLBAR HELP_BUBBLE, Gtk.IconSize.LARGE_TOOLBAR
) )
self.icon.set_opacity(0.8) self.icon.set_opacity(0.8)
box = Gtk.Box() box = Gtk.Box()
+2 -2
View File
@@ -7,8 +7,8 @@ from dzgui.const.constants import (
NO_EXPAND, NO_EXPAND,
NO_FILL, NO_FILL,
NO_PADDING, NO_PADDING,
SEARCH_ICON,
) )
from dzgui.const.icons import ICON_SEARCH
from dzgui.util.format import format_exception from dzgui.util.format import format_exception
from dzgui.util.strings import all_maps from dzgui.util.strings import all_maps
from dzgui.views.components.maps_combo import MapsCombo from dzgui.views.components.maps_combo import MapsCombo
@@ -109,7 +109,7 @@ class KeywordEntry(Gtk.Entry):
self.connect("key-press-event", self._on_keypress) self.connect("key-press-event", self._on_keypress)
self.connect("icon-release", lambda *args: self.activate()) self.connect("icon-release", lambda *args: self.activate())
self.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_SEARCH) self.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, SEARCH_ICON)
self.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True)
self.emitter.connect("load_maps", self._on_maps_loaded) self.emitter.connect("load_maps", self._on_maps_loaded)
+2 -3
View File
@@ -1,8 +1,7 @@
from typing import Self from typing import Self
from warnings import deprecated from warnings import deprecated
from dzgui.const.constants import FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD from dzgui.const.constants import ERROR, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD
from dzgui.const.icons import ICON_ERROR
from dzgui.init.prereqs import has_steam_client, has_flatpak_client from dzgui.init.prereqs import has_steam_client, has_flatpak_client
from dzgui.strings import options from dzgui.strings import options
from dzgui.views.components.box import HBox from dzgui.views.components.box import HBox
@@ -74,7 +73,7 @@ class ErrorPopover(Gtk.Popover):
self.hbox = HBox() self.hbox = HBox()
self.label = Gtk.Label(label="", margin_start=10, margin_end=10) self.label = Gtk.Label(label="", margin_start=10, margin_end=10)
error_icon = Icon(ICON_ERROR, margin_start=10) error_icon = Icon(ERROR, margin_start=10)
self.hbox.extend([error_icon, self.label]) self.hbox.extend([error_icon, self.label])
self.add(self.hbox) self.add(self.hbox)
self.show_all() self.show_all()
+2 -2
View File
@@ -20,8 +20,8 @@ class EnumeratedModButton(Gtk.Button):
super().__init__(margin_start=10, margin_end=10, focus_on_click=False) super().__init__(margin_start=10, margin_end=10, focus_on_click=False)
self.enum = enum self.enum = enum
self.set_label(enum.dict["label"]) self.set_label(enum.label)
self.set_tooltip_text(enum.dict["tooltip"]) self.set_tooltip_text(enum.tooltip)
class ModPanelButton(EnumeratedModButton): class ModPanelButton(EnumeratedModButton):
+2 -2
View File
@@ -60,7 +60,7 @@ class Statusbar(Gtk.Grid):
return return
enum = notebook.get_page_by_enum() enum = notebook.get_page_by_enum()
show_statusbar = enum.dict["statusbar"] show_statusbar = enum.has_statusbar
if show_statusbar is False: if show_statusbar is False:
self.set_by_context(enum, "") self.set_by_context(enum, "")
@@ -152,5 +152,5 @@ class Statusbar(Gtk.Grid):
row = tree.get_value_at_index(1) row = tree.get_value_at_index(1)
if self.controller.loaded is False: if self.controller.loaded is False:
return return
tooltip = row.dict["tooltip"] tooltip = row.tooltip
self.set_by_context(NotebookPage.HELP, tooltip) self.set_by_context(NotebookPage.HELP, tooltip)
+3 -3
View File
@@ -3,7 +3,7 @@ from dataclasses import dataclass
from datetime import datetime, time, timedelta from datetime import datetime, time, timedelta
from typing import Literal from typing import Literal
from dzgui.const.icons import ICON_DAY, ICON_NIGHT from dzgui.const.constants import DAY_ICON, NIGHT_ICON
from dzgui.strings import calc from dzgui.strings import calc
from dzgui.views.components.icon import Icon from dzgui.views.components.icon import Icon
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
@@ -385,7 +385,7 @@ class TimePickerFrame(Gtk.Frame):
h1 = BoldLabel(calc.heading_server_time) h1 = BoldLabel(calc.heading_server_time)
h2 = BoldLabel(calc.heading_target_time) h2 = BoldLabel(calc.heading_target_time)
self.icon_indicator = Icon(ICON_DAY) self.icon_indicator = Icon(DAY_ICON)
self.update_server_icon() self.update_server_icon()
server_time_box = HBox(10) server_time_box = HBox(10)
@@ -411,7 +411,7 @@ class TimePickerFrame(Gtk.Frame):
self.add(flowbox) self.add(flowbox)
def update_server_icon(self) -> None: def update_server_icon(self) -> None:
icon = ICON_DAY if self.server_time.is_day() else ICON_NIGHT icon = DAY_ICON if self.server_time.is_day() else NIGHT_ICON
self.icon_indicator.set_icon_name(icon) self.icon_indicator.set_icon_name(icon)
def _on_server_clock_increment(self, emitter: Emitter, time_now: datetime) -> None: def _on_server_clock_increment(self, emitter: Emitter, time_now: datetime) -> None:
+2 -2
View File
@@ -2,7 +2,7 @@ import gi
import html import html
from typing import Self, TYPE_CHECKING from typing import Self, TYPE_CHECKING
from dzgui.const.icons import ICON_CALCULATOR from dzgui.const.constants import CALCULATOR
from dzgui.const.enum import ContextMenuGroup from dzgui.const.enum import ContextMenuGroup
from dzgui.model.model_factory import ModelFactory from dzgui.model.model_factory import ModelFactory
from dzgui.util import css from dzgui.util import css
@@ -110,7 +110,7 @@ class ServerDetailsDialog(ServerDialog):
text = format_hyperlinks(text) text = format_hyperlinks(text)
self.description.set_markup(html.escape(text)) self.description.set_markup(html.escape(text))
calc_button = IconTextButton(ICON_CALCULATOR, dialogs.toggle_calc) calc_button = IconTextButton(CALCULATOR, dialogs.toggle_calc)
calc_button.connect("clicked", self._on_calc_pressed) calc_button.connect("clicked", self._on_calc_pressed)
calc_button.set_halign(Gtk.Align.END) calc_button.set_halign(Gtk.Align.END)
calc_button.set_valign(Gtk.Align.START) calc_button.set_valign(Gtk.Align.START)
+9 -11
View File
@@ -1,7 +1,7 @@
import logging import logging
from dzgui.const.constants import APP_NAME from dzgui.const.constants import APP_NAME
from dzgui.const.enum import ContextMenu from dzgui.const.enum import ContextMenuItem
from dzgui.util.keys import is_ctrl_mask, is_navkey from dzgui.util.keys import is_ctrl_mask, is_navkey
from dzgui.util.strings import edit_note from dzgui.util.strings import edit_note
from dzgui.views.trees.tree_base import TreeView from dzgui.views.trees.tree_base import TreeView
@@ -15,9 +15,7 @@ logger = logging.getLogger(APP_NAME)
class ContextMixin(TreeView): class ContextMixin(TreeView):
def present_menu( def present_menu(self, widget: Gtk.Widget, event: Gdk.Event) -> bool:
self, widget: Gtk.Widget, event: Gdk.Event
) -> bool:
if self.menu is None: if self.menu is None:
return False return False
@@ -60,17 +58,17 @@ class ContextMixin(TreeView):
self.context_menu.select_first(False) self.context_menu.select_first(False)
return True return True
def _process_dynamic_row(self, row: ContextMenu) -> Gtk.MenuItem: def _process_dynamic_row(self, row: ContextMenuItem) -> Gtk.MenuItem:
if row == ContextMenu.ADD_SERVER and self.is_in_favs(): # type: ignore if row == ContextMenuItem.ADD_SERVER and self.is_in_favs(): # type: ignore
row = ContextMenu.REMOVE_SERVER row = ContextMenuItem.REMOVE_SERVER
item = Gtk.MenuItem(label=row.dict["label"]) item = Gtk.MenuItem(label=row.label)
item.connect("activate", self._on_menu_click, row) item.connect("activate", self._on_menu_click, row)
if row == ContextMenu.SHOW_MODS: if row == ContextMenuItem.SHOW_MODS:
item.set_sensitive(self.is_modded()) # type: ignore item.set_sensitive(self.is_modded()) # type: ignore
if row == ContextMenu.ADD_NOTE: if row == ContextMenuItem.ADD_NOTE:
if self.controller.has_note(): if self.controller.has_note():
item.set_label(edit_note) item.set_label(edit_note)
@@ -94,7 +92,7 @@ class ContextMixin(TreeView):
except AttributeError: except AttributeError:
return False return False
def _on_menu_click(self, widget: Gtk.MenuItem, enum: ContextMenu) -> None: def _on_menu_click(self, widget: Gtk.MenuItem, enum: ContextMenuItem) -> None:
self.controller.menu_action(enum, self) # type: ignore self.controller.menu_action(enum, self) # type: ignore
def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None: def _on_key(self, menu: Gtk.Menu, event: Gdk.EventKey) -> bool | None:
+6 -4
View File
@@ -3,12 +3,14 @@ from enum import Enum
from typing import Self, TYPE_CHECKING, Union from typing import Self, TYPE_CHECKING, Union
from dzgui.util import css from dzgui.util import css
from dzgui.const.icons import ICON_EDIT_DELETE, ICON_FOLDER, ICON_WARNING
from dzgui.const.constants import ( from dzgui.const.constants import (
APPID_DAYZ, APPID_DAYZ,
APPID_DAYZ_EXP, APPID_DAYZ_EXP,
APPNAME_DAYZ, APPNAME_DAYZ,
APPNAME_DAYZ_EXP_HUMAN, APPNAME_DAYZ_EXP_HUMAN,
EDIT_DELETE,
FOLDER,
WARNING,
) )
from dzgui.const.enum import ContextMenuGroup, NotebookPage from dzgui.const.enum import ContextMenuGroup, NotebookPage
from dzgui.managers.offline import OfflineManager from dzgui.managers.offline import OfflineManager
@@ -85,7 +87,7 @@ class FolderHBox(HBox):
self.emitter = controller.get_emitter() self.emitter = controller.get_emitter()
self.eb = InfoEventBox(eb_text, controller) self.eb = InfoEventBox(eb_text, controller)
self.button = IconTextButton(ICON_FOLDER, btn_label, Gtk.PositionType.LEFT) self.button = IconTextButton(FOLDER, btn_label, Gtk.PositionType.LEFT)
self.button.set_halign(Gtk.Align.START) self.button.set_halign(Gtk.Align.START)
self.button.set_image_position(Gtk.PositionType.LEFT) self.button.set_image_position(Gtk.PositionType.LEFT)
@@ -97,7 +99,7 @@ class FolderHBox(HBox):
self.label = Gtk.Label() self.label = Gtk.Label()
self.scrolled_label.add(self.label) self.scrolled_label.add(self.label)
self.unset_button = IconTextButton(ICON_EDIT_DELETE, offline.unset_button) self.unset_button = IconTextButton(EDIT_DELETE, offline.unset_button)
self.unset_button.connect("clicked", self._on_unset_clicked) self.unset_button.connect("clicked", self._on_unset_clicked)
self.spinner = Gtk.Spinner() self.spinner = Gtk.Spinner()
@@ -193,7 +195,7 @@ class ModFrame(HeadingFrame):
self.tree_vbox.extend([self.scrolled, self.status]) self.tree_vbox.extend([self.scrolled, self.status])
self.no_mods = HBox(spacing=10) self.no_mods = HBox(spacing=10)
no_mods_icon = Icon(ICON_WARNING, margin_start=10) no_mods_icon = Icon(WARNING, margin_start=10)
no_mods_label = Gtk.Label(label=offline.no_local_mods, halign=Gtk.Align.START) no_mods_label = Gtk.Label(label=offline.no_local_mods, halign=Gtk.Align.START)
self.no_mods.extend([no_mods_icon, no_mods_label]) self.no_mods.extend([no_mods_icon, no_mods_label])
+5 -4
View File
@@ -16,8 +16,9 @@ from dzgui.const.constants import (
NO_EXPAND, NO_EXPAND,
NO_FILL, NO_FILL,
NO_PADDING, NO_PADDING,
VIEW_CONCEAL,
VIEW_REVEAL,
) )
from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL
from dzgui.const.endpoints import STEAM_API_SETUP from dzgui.const.endpoints import STEAM_API_SETUP
from dzgui.const.enum import Preferences, ServerTab from dzgui.const.enum import Preferences, ServerTab
from dzgui.strings import options from dzgui.strings import options
@@ -66,7 +67,7 @@ class SubmitField(Gtk.Box):
# TODO: audit for all applicable callbacks # TODO: audit for all applicable callbacks
if private: if private:
self.entry.set_icon_from_icon_name( self.entry.set_icon_from_icon_name(
Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL Gtk.EntryIconPosition.SECONDARY, VIEW_REVEAL
) )
self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True)
self.entry.connect("icon-release", self._on_icon_release) self.entry.connect("icon-release", self._on_icon_release)
@@ -130,9 +131,9 @@ class SubmitField(Gtk.Box):
) -> None: ) -> None:
visible = widget.get_visibility() visible = widget.get_visibility()
if visible: if visible:
icon, state = ICON_VIEW_REVEAL, False icon, state = VIEW_REVEAL, False
else: else:
icon, state = ICON_VIEW_CONCEAL, True icon, state = VIEW_CONCEAL, True
widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon) widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon)
widget.set_visibility(state) widget.set_visibility(state)
+5 -5
View File
@@ -1,9 +1,9 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Self, Sequence, TYPE_CHECKING from typing import Self, Sequence, TYPE_CHECKING
from dzgui.const.icons import ( from dzgui.const.constants import (
ICON_ERROR, ERROR,
ICON_WARNING, WARNING,
) )
from dzgui.const.enum import NotebookPage from dzgui.const.enum import NotebookPage
from dzgui.util.css import add_class from dzgui.util.css import add_class
@@ -166,7 +166,7 @@ class PreConnectionAssistant(Gtk.Box):
# TODO: abstract into components # TODO: abstract into components
self.warning_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.warning_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.warning_tree = MaskedTree(ICON_WARNING) self.warning_tree = MaskedTree(WARNING)
self.warning_placeholder = Placeholder(preconnect.placeholder_no_warnings) self.warning_placeholder = Placeholder(preconnect.placeholder_no_warnings)
self.warning_box.add(self.warning_tree) self.warning_box.add(self.warning_tree)
self.warning_box.add(self.warning_placeholder) self.warning_box.add(self.warning_placeholder)
@@ -175,7 +175,7 @@ class PreConnectionAssistant(Gtk.Box):
) )
self.error_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.error_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.error_tree = MaskedTree(ICON_ERROR) self.error_tree = MaskedTree(ERROR)
self.error_placeholder = Placeholder(preconnect.no_errors) self.error_placeholder = Placeholder(preconnect.no_errors)
self.error_box.add(self.error_tree) self.error_box.add(self.error_tree)
self.error_box.add(self.error_placeholder) self.error_box.add(self.error_placeholder)
+1 -1
View File
@@ -77,4 +77,4 @@ class MenuTreeView(TreeView):
raise ValueError("Trying to call a method on non-existent model") raise ValueError("Trying to call a method on non-existent model")
_iter = self.get_focused_row_iter() _iter = self.get_focused_row_iter()
rowtype = model.get_value(_iter, 1) rowtype = model.get_value(_iter, 1)
return str(rowtype.dict["tooltip"]) return str(rowtype.tooltip)
+3 -3
View File
@@ -7,7 +7,7 @@ from warnings import deprecated
from dzgui.api.servers import ping, Record from dzgui.api.servers import ping, Record
from dzgui.const.constants import APP_NAME from dzgui.const.constants import APP_NAME
from dzgui.const.enum import ContextMenu, ContextMenuGroup, ServerTab from dzgui.const.enum import ContextMenuItem, ContextMenuGroup, ServerTab
from dzgui.managers.filter import FilterManager from dzgui.managers.filter import FilterManager
from dzgui.model.proxy_model import ProxyModelManager from dzgui.model.proxy_model import ProxyModelManager
from dzgui.util import strings from dzgui.util import strings
@@ -250,9 +250,9 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore
if self.enum is ServerTab.LAN: if self.enum is ServerTab.LAN:
self.emitter.emit("request_custom_port_focus") self.emitter.emit("request_custom_port_focus")
case Gdk.KEY_c: case Gdk.KEY_c:
self.controller.menu_action(ContextMenu.COPY_SERVER_IP, self) self.controller.menu_action(ContextMenuItem.COPY_SERVER_IP, self)
case Gdk.KEY_r: case Gdk.KEY_r:
self.controller.menu_action(ContextMenu.REFRESH_PLAYERS, self) self.controller.menu_action(ContextMenuItem.REFRESH_PLAYERS, self)
else: else:
match event.keyval: match event.keyval:
case Gdk.KEY_l | Gdk.KEY_Right: case Gdk.KEY_l | Gdk.KEY_Right:
+2 -2
View File
@@ -1,4 +1,4 @@
from pathlib import Path from shared import get_git_root
BOILERPLATE = """ BOILERPLATE = """
This file includes the combined licenses to the following components: This file includes the combined licenses to the following components:
@@ -40,7 +40,7 @@ class CombinedLicense:
def concat_license() -> str: def concat_license() -> str:
combined = CombinedLicense() combined = CombinedLicense()
root = Path(__file__).resolve().parents[1] root = get_git_root()
licenses = root.joinpath("docs/licenses") licenses = root.joinpath("docs/licenses")
main_license = root.joinpath(LICENSE_FILE) main_license = root.joinpath(LICENSE_FILE)
+5 -4
View File
@@ -1,10 +1,11 @@
import shutil import shutil
import subprocess import subprocess
from pathlib import Path
par = Path(__file__).parent.parent from shared import get_git_root
clog = par / "CHANGELOG.md"
target = par / "dzgui/data/CHANGELOG.md" root = get_git_root()
clog = root.joinpath("CHANGELOG.md")
target = root.joinpath("dzgui/data/CHANGELOG.md")
shutil.copy(clog, target) shutil.copy(clog, target)
+2 -3
View File
@@ -1,10 +1,9 @@
import tomllib import tomllib
from pathlib import Path from shared import get_git_root
root = Path(__file__).resolve().parents[1]
def get_entrypoint() -> None: def get_entrypoint() -> None:
root = get_git_root()
p = root.joinpath("pyproject.toml") p = root.joinpath("pyproject.toml")
with open(p, "rb") as f: with open(p, "rb") as f:
t = tomllib.load(f) t = tomllib.load(f)
+3 -2
View File
@@ -3,14 +3,15 @@ import requests
import subprocess import subprocess
import tarfile import tarfile
from pathlib import Path
from urllib.parse import unquote from urllib.parse import unquote
from shared import get_git_root
BUILD = "3.13.9" BUILD = "3.13.9"
DATE = "20251014" DATE = "20251014"
CPYTHON_BUILD = f"cpython-{BUILD}" CPYTHON_BUILD = f"cpython-{BUILD}"
root = Path(__file__).resolve().parents[1] root = get_git_root()
build_dir = root.joinpath("build") build_dir = root.joinpath("build")
cpython_dir = build_dir.joinpath(CPYTHON_BUILD) cpython_dir = build_dir.joinpath(CPYTHON_BUILD)
+2 -1
View File
@@ -9,6 +9,7 @@ from pathlib import Path
from concat_licenses import concat_license from concat_licenses import concat_license
from parse_toml import get_entrypoint from parse_toml import get_entrypoint
from prebuild import get_pyapp, rebuild_cpython from prebuild import get_pyapp, rebuild_cpython
from shared import get_git_root
def update_uname(info: tarfile.TarInfo) -> tarfile.TarInfo: def update_uname(info: tarfile.TarInfo) -> tarfile.TarInfo:
@@ -17,7 +18,7 @@ def update_uname(info: tarfile.TarInfo) -> tarfile.TarInfo:
return info return info
root = Path(__file__).resolve().parents[1] root = get_git_root()
dist_dir = root.joinpath("dist") dist_dir = root.joinpath("dist")
build_dir = root.joinpath("build") build_dir = root.joinpath("build")
+1 -10
View File
@@ -1,16 +1,7 @@
import subprocess
from pathlib import Path from pathlib import Path
from dzgui.app_init import build_gui from dzgui.app_init import build_gui
from shared import get_git_root
def get_git_root() -> Path:
proc = subprocess.run(
["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True
)
if proc.returncode != 0:
raise OSError("Failed to parse git root")
return Path(proc.stdout.rstrip())
def get_image_path() -> Path: def get_image_path() -> Path:
+11
View File
@@ -0,0 +1,11 @@
import subprocess
from pathlib import Path
def get_git_root() -> Path:
proc = subprocess.run(
["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True
)
if proc.returncode != 0:
raise OSError("Failed to parse git root")
return Path(proc.stdout.rstrip())