Compare commits

...
Author SHA1 Message Date
aclist 7ae5880890 chore: update union
Mirror to Codeberg / mirror-to-codeberg (push) Waiting to run
2026-11-11 03:36:14 +09:00
aclist afbced228d Merge branch 'dzgui7' into change/enum-dataclasses 2026-11-11 03:33:44 +09:00
aclist f5d7bf713d Merge pull request #538 from aclist/fix/clipboard-button-controller
fix: clipboard button controller
2026-11-11 03:32:27 +09:00
aclist c1630adee1 chore: update return value 2026-11-11 03:31:17 +09:00
aclist 88f6b84bea fix: restore dropped typehint 2026-11-11 03:29:23 +09:00
aclist 134dcb6f0b fix: unused param blocking boot 2026-11-11 03:27:12 +09:00
aclist cc0354c881 chore: drop unused imports 2026-11-11 03:21:31 +09:00
aclist f2d21be347 Merge pull request #534 from aclist/chore/strict-typehinting
chore: clear strict typehinting errors
2026-11-11 03:19:29 +09:00
aclist f65fa153cc Merge branch 'chore/strict-typehinting' of github.com:aclist/dzgui into chore/strict-typehinting
Mirror to Codeberg / mirror-to-codeberg (push) Waiting to run
2026-11-11 03:18:50 +09:00
aclist 8aa7328d8f chore: drop unused import 2026-11-11 03:18:40 +09:00
aclist bb04854cd7 chore: add keybinding to strings 2026-11-11 03:17:29 +09:00
aclist 5014b2a467 Merge branch 'dzgui7' into chore/strict-typehinting 2026-11-11 03:15:26 +09:00
aclist d020295aa3 Merge pull request #537 from aclist/fix/cannot-acquire-lock
fix: cannot acquire lock
2026-11-11 03:12:31 +09:00
aclist 1879347831 chore: add typehints 2026-11-11 03:09:39 +09:00
aclist 5a1c098af7 fix: acquire lock prior to calling build_gui() 2026-11-11 03:09:14 +09:00
aclist 3d346dfb07 Merge pull request #531 from aclist/chore/update-strings-pass-1
chore: update strings pass 1
2026-11-11 03:06:43 +09:00
aclist cb03db6032 Merge branch 'dzgui7' into chore/strict-typehinting 2026-11-11 02:47:40 +09:00
aclist c69022f74c Merge pull request #532 from aclist/drop/no-e402
chore: drop unused Gtk imports
2026-11-11 02:44:40 +09:00
aclist 7f0bccad64 Merge pull request #528 from aclist/drop/abstract-constructor-params
drop: abstracted constructor params
2026-11-11 02:43:30 +09:00
aclist 0c4026daf8 chore: clear typehinting errors 2026-11-10 10:02:41 +09:00
aclist e03c6905c6 chore: clear typehinting errors 2026-11-10 06:30:12 +09:00
aclist 8fb3462f35 chore: add placeholder for row struct 2026-11-10 05:58:22 +09:00
aclist bfe9b9d147 chore: clear typehinting errors 2026-11-10 05:58:02 +09:00
aclist 9f36569fd4 drop: LoggerAlertsButton 2026-11-10 05:10:56 +09:00
aclist da18b41136 chore: drop Soup2 stubs 2026-11-10 05:09:02 +09:00
aclist f092207c61 chore: clear strict typehinting errors 2026-11-10 04:37:51 +09:00
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 4e5fadf928 chore: drop old comments 2026-11-10 03:04:44 +09:00
aclist 3dc37561be chore: update pyproject.toml 2026-11-10 03:02:35 +09:00
aclist 13786591b3 chore: restore exclusion for GLibUnix 2026-11-10 03:02:06 +09:00
aclist 9eb1342877 drop: unused imports script 2026-11-10 03:00:35 +09:00
aclist 3f29484895 chore: drop unused Gtk imports 2026-11-10 02:59:22 +09:00
aclist fa2f86b03e chore: abstract string literals 2026-11-10 02:41:24 +09:00
aclist c8fe6ec056 chore: update strings files 2026-11-10 02:37:22 +09:00
aclist 6901e5456e drop: unused dataclass 2026-11-10 02:36:18 +09:00
83 changed files with 582 additions and 603 deletions

No files matched your search

+2 -1
View File
@@ -111,7 +111,8 @@ class WorkshopACF(ACF):
def __init__(self, file: Path) -> None: def __init__(self, file: Path) -> None:
super().__init__(file) super().__init__(file)
def unpack(self, d: dict, lines: list[Any] = []) -> str: def unpack(self, d: dict[str, Any], lines: list[Any] = []) -> str:
self.indent: int
t1 = "AppWorkshop" t1 = "AppWorkshop"
t2 = ("WorkshopItemsInstalled", "WorkshopItemDetails") t2 = ("WorkshopItemsInstalled", "WorkshopItemDetails")
for k, v in d.items(): for k, v in d.items():
+1 -13
View File
@@ -24,14 +24,6 @@ from typing import Any
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
@dataclass
class ModMeta:
protocol: str
published_id: str
name: str
timestamp: str
def get_local_mod_ids(steam_path: Path) -> list[int]: def get_local_mod_ids(steam_path: Path) -> list[int]:
workshop_path = get_local_mod_path(steam_path) workshop_path = get_local_mod_path(steam_path)
mods = get_local_mods(workshop_path) mods = get_local_mods(workshop_path)
@@ -114,10 +106,6 @@ def get_delimited_mods(steam_path: Path) -> list[Any]:
return parse_mods(mods) return parse_mods(mods)
def get_missing_mods(local: list, remote: list) -> list:
return [mod for mod in remote if mod not in local]
def _hash(uid: str, use_custom: bool = False) -> str: def _hash(uid: str, use_custom: bool = False) -> str:
md5 = hashlib.md5() md5 = hashlib.md5()
md5.update(uid.encode("ascii")) md5.update(uid.encode("ascii"))
@@ -152,7 +140,7 @@ def remove_stale_signatures(
def find_stale_mods(config: Path) -> list[int]: def find_stale_mods(config: Path) -> list[int]:
def push_record(rec: str) -> list: def push_record(rec: str) -> list[int]:
record = fqip_to_record(rec) record = fqip_to_record(rec)
if record is None: if record is None:
return [] return []
+6 -4
View File
@@ -111,7 +111,7 @@ def get_netmask() -> str:
# TODO: rename # TODO: rename
def test_ip(suffix: int, port: int, event: threading.Event) -> dict | None: def test_ip(suffix: int, port: int, event: threading.Event) -> dict[str, Any] | None:
if event.is_set(): if event.is_set():
return None return None
netmask = get_netmask() netmask = get_netmask()
@@ -139,7 +139,9 @@ def sanitize(name: str) -> str:
return name return name
def parse_json(json: list) -> list: def parse_json(
json: list[dict[str, Any]],
) -> list[tuple[str, str, str, str, int, int, int, str, int, int, str, bool]]:
""" """
Server metadata is underspecified and server operators Server metadata is underspecified and server operators
tend to insert random garbage in the headers. In case tend to insert random garbage in the headers. In case
@@ -507,14 +509,14 @@ def record_to_fqip(record: Record) -> str:
return f"{record.ip}:{record.gameport}:{record.qport}" return f"{record.ip}:{record.gameport}:{record.qport}"
def response_to_fqip(res: dict) -> str: def response_to_fqip(res: dict[str, Any]) -> str:
ip = res["addr"].split(":")[0] ip = res["addr"].split(":")[0]
gameport = res["gameport"] gameport = res["gameport"]
qport = res["addr"].split(":")[1] qport = res["addr"].split(":")[1]
return f"{ip}:{gameport}:{qport}" return f"{ip}:{gameport}:{qport}"
def response_to_record(res: dict) -> Record: def response_to_record(res: dict[str, Any]) -> Record:
ip = res["addr"].split(":")[0] ip = res["addr"].split(":")[0]
gameport = res["gameport"] gameport = res["gameport"]
qport = res["addr"].split(":")[1] qport = res["addr"].split(":")[1]
-6
View File
@@ -22,7 +22,6 @@ from dzgui.init.migrate import (
copy_state_files, copy_state_files,
migrate_cols_file, migrate_cols_file,
) )
from dzgui.init.flock import lock_acquire
from dzgui.init.prereqs import has_flatpak_client, has_steam_client from dzgui.init.prereqs import has_flatpak_client, has_steam_client
from dzgui.strings import boot from dzgui.strings import boot
@@ -122,8 +121,6 @@ def load_steam_icon() -> None:
def build_gui(version: str, is_debug: bool) -> App | None: def build_gui(version: str, is_debug: bool) -> App | None:
lock = lock_acquire() # noqa
set_locale() set_locale()
# NOTE: consider aborting this check if steam deck # NOTE: consider aborting this check if steam deck
xdg_paths = get_xdg_paths() xdg_paths = get_xdg_paths()
@@ -158,9 +155,6 @@ def build_gui(version: str, is_debug: bool) -> App | None:
f.truncate(0) f.truncate(0)
if _is_steam_deck is False: if _is_steam_deck is False:
# TODO: sudo escalation dialog
# count = get_map_count()
# TODO: move into module
if FLATPAK_ROOT_PATH in lookup(XDG.config, Preferences.DEFAULT): if FLATPAK_ROOT_PATH in lookup(XDG.config, Preferences.DEFAULT):
has_client = has_flatpak_client() has_client = has_flatpak_client()
else: else:
+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)
+2 -2
View File
@@ -51,7 +51,7 @@ def is_writeable(path_str: str) -> bool:
return True return True
def get_xdg_paths() -> dict: def get_xdg_paths() -> dict[str, Path]:
home = Path.home() home = Path.home()
xdg_paths = { xdg_paths = {
"XDG_CONFIG_HOME": home / ".config", "XDG_CONFIG_HOME": home / ".config",
@@ -73,7 +73,7 @@ def get_xdg_paths() -> dict:
return resolved_paths return resolved_paths
def parse_filepaths(xdg: dict) -> Xdg: def parse_filepaths(xdg: dict[str, Path]) -> Xdg:
config = xdg["XDG_CONFIG_HOME"] config = xdg["XDG_CONFIG_HOME"]
state = xdg["XDG_STATE_HOME"] state = xdg["XDG_STATE_HOME"]
share = xdg["XDG_DATA_HOME"] share = xdg["XDG_DATA_HOME"]
+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 = (
+2 -2
View File
@@ -3,8 +3,8 @@ from typing import TYPE_CHECKING
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository.Gtk import ListStore # noqa E402 from gi.repository.Gtk import ListStore
from gi.repository import Gdk, GObject # noqa E402 from gi.repository import GObject
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.const.enum import NotebookPage, ServerTab from dzgui.const.enum import NotebookPage, ServerTab
+12 -11
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,
@@ -32,7 +32,7 @@ from dzgui.views.dialogs.generic import ExceptionDialog
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402 from gi.repository import Gtk, Gdk, GLib, GObject
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
@@ -77,7 +77,7 @@ class AppNavigation:
class Controller(GObject.GObject): class Controller(GObject.GObject):
def __init__(self) -> None: def __init__(self) -> None:
self.dist_cache: dict[str, "Haversine"] = {} self.dist_cache: dict[str, "Haversine" | None] = {}
self.mediator = AppNavigation() self.mediator = AppNavigation()
self.prefs: UserPrefs self.prefs: UserPrefs
@@ -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)
@@ -355,22 +357,21 @@ class Controller(GObject.GObject):
filter_man.set_filter(filt, state) filter_man.set_filter(filt, state)
self.mediator.filters.set_filters(filters) self.mediator.filters.set_filters(filters)
def get_dist_cache(self) -> dict[str, "Haversine"]: def get_dist_cache(self) -> dict[str, Union["Haversine", None]]:
return self.dist_cache return self.dist_cache
def set_dist_cache(self, addr: str, haversine: "Haversine") -> None: def set_dist_cache(self, addr: str, haversine: Union["Haversine", None]) -> None:
self.dist_cache[addr] = haversine self.dist_cache[addr] = haversine
def get_map_store(self) -> Gtk.ListStore: def get_map_store(self) -> Gtk.ListStore:
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()
+3
View File
@@ -43,6 +43,9 @@ def main() -> None:
# NOTE: only import ligbirepository modules after the above check # NOTE: only import ligbirepository modules after the above check
from dzgui.app_init import build_gui from dzgui.app_init import build_gui
from dzgui.init.flock import lock_acquire
lock = lock_acquire() # noqa
app = build_gui(version, args.debug) app = build_gui(version, args.debug)
if app is None: if app is None:
+2 -2
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:
@@ -162,7 +162,7 @@ class ConfigManager:
trace = traceback.format_exc() trace = traceback.format_exc()
dialog = ExceptionDialog(self.controller, trace) dialog = ExceptionDialog(self.controller, trace)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def save_res_and_quit(self, tv: "ServerTreeView", window: "OuterWindow") -> None: def save_res_and_quit(self, tv: "ServerTreeView", window: "OuterWindow") -> None:
columns = tv.get_columns() columns = tv.get_columns()
+7 -14
View File
@@ -48,18 +48,13 @@ from dzgui.strings.dialogs import (
waiting_for_directories, waiting_for_directories,
) )
from dzgui.strings import kb from dzgui.strings import kb
from dzgui.strings.server_mods import checkmark, resync from dzgui.strings.server_mods import checkmark, resync, invalid_mod
from dzgui.util.format import format_exception, format_mib from dzgui.util.format import format_exception, format_mib
from dzgui.util.strings import dialog, server_timeout from dzgui.util.strings import dialog, server_timeout
from dzgui.util.symlink import rebuild_symlinks from dzgui.util.symlink import rebuild_symlinks
from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.dialogs.generic import ExceptionDialog
from dzgui.views.dialogs.servers import ServerDetailsDialog, ServerModDialog from dzgui.views.dialogs.servers import ServerDetailsDialog, ServerModDialog
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.api.servers import A2SInfo, Record from dzgui.api.servers import A2SInfo, Record
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -197,9 +192,8 @@ class ConnectionManager:
is_last = self.is_last_server() is_last = self.is_last_server()
# TODO: strings
invalid_mods = [ invalid_mods = [
(mod[0], mod[1]) for mod in remote_mods if mod[2] == "Invalid mod" (mod[0], mod[1]) for mod in remote_mods if mod[2] == invalid_mod
] ]
prereqs = Prerequisites( prereqs = Prerequisites(
@@ -277,8 +271,7 @@ class ConnectionManager:
for mod in alpha_mods: for mod in alpha_mods:
# NOTE: if the mod is neither synched or out of date, it is a malformed mod # NOTE: if the mod is neither synched or out of date, it is a malformed mod
if mod[2] == "": if mod[2] == "":
# TODO: strings mod[2] = invalid_mod
mod[2] = "Invalid mod"
return alpha_mods, missing_mods return alpha_mods, missing_mods
@@ -298,22 +291,22 @@ class ConnectionManager:
def _present_modlist_dialog(self, mods: list[list[str]]) -> None: def _present_modlist_dialog(self, mods: list[list[str]]) -> None:
dialog = ServerModDialog(self.controller, mods) dialog = ServerModDialog(self.controller, mods)
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _present_details_dialog(self, details: Servers.Details) -> None: def _present_details_dialog(self, details: Servers.Details) -> None:
dialog = ServerDetailsDialog(self.controller, details) dialog = ServerDetailsDialog(self.controller, details)
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _workshop_timeout(self, msg: str) -> None: def _workshop_timeout(self, msg: str) -> None:
dialog = ExceptionDialog(self.controller, msg) dialog = ExceptionDialog(self.controller, msg)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _server_timeout(self) -> None: def _server_timeout(self) -> None:
dialog = ExceptionDialog(self.controller, server_timeout) dialog = ExceptionDialog(self.controller, server_timeout)
dialog.set_details_buffer(kb.DZG_006) dialog.set_details_buffer(kb.DZG_006)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def get_debug_args(self) -> str: def get_debug_args(self) -> str:
addr = f"{self.record.ip}:{self.record.gameport}" addr = f"{self.record.ip}:{self.record.gameport}"
+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:
+6 -13
View File
@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING
from dzgui.model.model_factory import ModelFactory from dzgui.model.model_factory import ModelFactory
from dzgui.util import strings from dzgui.util import strings
from dzgui.util.strings import all_maps from dzgui.strings.filters import all_maps
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.model.model_factory import FastInsertListStore from dzgui.model.model_factory import FastInsertListStore
@@ -51,7 +51,6 @@ class FilterManager:
self.active_map = (0, all_maps) self.active_map = (0, all_maps)
self.prior_map = all_maps self.prior_map = all_maps
self.filters: list
self.enabled_filters = dict(self.default_filters) self.enabled_filters = dict(self.default_filters)
def get_tooltips(self) -> dict[str, str]: def get_tooltips(self) -> dict[str, str]:
@@ -75,11 +74,11 @@ class FilterManager:
def set_active_keyword(self, word: str) -> None: def set_active_keyword(self, word: str) -> None:
self.active_keyword = word self.active_keyword = word
def get_default_filters(self) -> dict: def get_default_filters(self) -> dict[str, bool]:
"""Deep copy of defaults""" """Deep copy of defaults"""
return dict(self.default_filters) return dict(self.default_filters)
def get_filters(self) -> dict: def get_filters(self) -> dict[str, bool]:
return self.enabled_filters return self.enabled_filters
def set_filter(self, label: str, state: bool) -> None: def set_filter(self, label: str, state: bool) -> None:
@@ -106,17 +105,11 @@ class FilterManager:
self.reinit_map_store() self.reinit_map_store()
maps.sort() maps.sort()
for m in maps: clean = [m for m in maps if m != all_maps]
# TODO: strings for m in clean:
if m == "All maps":
continue
self.append_map([m]) self.append_map([m])
# TODO: currently unused def get_all_filters(self) -> tuple[str, ...]:
def get_unique_maps(self) -> list[str]:
return [row[0] for row in self.map_store if row[0] != "All maps"]
def get_all_filters(self) -> tuple:
map_name = self.get_active_map_name() map_name = self.get_active_map_name()
enabled = self.get_filters() enabled = self.get_filters()
kw = self.get_active_keyword() kw = self.get_active_keyword()
+2 -2
View File
@@ -30,7 +30,7 @@ import dzgui.api.pefile as PeFile
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -221,7 +221,7 @@ class ModManager:
total_size += mod[3] total_size += mod[3]
return total_mods, total_size return total_mods, total_size
def _on_stale_mods_found(self, stale_mods: list) -> None: def _on_stale_mods_found(self, stale_mods: list[int]) -> None:
"""Manipulates attached ListStore in the main event loop""" """Manipulates attached ListStore in the main event loop"""
model = self.treeview.get_model() model = self.treeview.get_model()
if model is None: if model is None:
+1 -1
View File
@@ -52,7 +52,7 @@ class OfflineManager:
is_valid = is_mission(folder) is_valid = is_mission(folder)
self.emitter.emit("custom_mission_loaded", str(folder), is_valid) self.emitter.emit("custom_mission_loaded", str(folder), is_valid)
def find_custom_mods(self, callback: Callable) -> None: def find_custom_mods(self, callback: Callable[[], None]) -> None:
folder = self.open_folderpicker(dialogs.custom_mod_dialog) folder = self.open_folderpicker(dialogs.custom_mod_dialog)
window = self.controller.get_window() window = self.controller.get_window()
window.set_sensitive(False) window.set_sensitive(False)
+4 -4
View File
@@ -15,15 +15,15 @@ if TYPE_CHECKING:
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402 from gi.repository import GLib
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
def call_on_thread( def call_on_thread(
dialog_str: str, show_dialog: bool = True, show_cancel: bool = False dialog_str: str, show_dialog: bool = True, show_cancel: bool = False
) -> Callable: ) -> Callable[..., Any]:
def decorator(func: Callable) -> Callable: def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
@wraps(func) @wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> None: def wrapper(*args: Any, **kwargs: Any) -> None:
self = args[0] self = args[0]
@@ -42,7 +42,7 @@ def call_on_thread(
class StoredFunc: class StoredFunc:
def __init__(self, func: Callable, *args: Any, **kwargs: Any) -> None: def __init__(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> None:
sig = inspect.signature(func) sig = inspect.signature(func)
self.func = func self.func = func
self.bindings = sig.bind(*args, **kwargs) self.bindings = sig.bind(*args, **kwargs)
+2 -7
View File
@@ -15,11 +15,6 @@ from dzgui.strings import dialogs
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
from dzgui.views.dialogs.generic import ExceptionDialog, QuitDialog from dzgui.views.dialogs.generic import ExceptionDialog, QuitDialog
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -60,9 +55,9 @@ class UpdateManager:
def _on_update_success(self) -> None: def _on_update_success(self) -> None:
msg = dialogs.update_success msg = dialogs.update_success
dialog = QuitDialog(self.controller, msg) dialog = QuitDialog(self.controller, msg)
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _on_update_failure(self, msg: str) -> None: def _on_update_failure(self, msg: str) -> None:
dialog = ExceptionDialog(self.controller, msg) dialog = ExceptionDialog(self.controller, msg)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
+4 -4
View File
@@ -7,11 +7,11 @@ from dzgui.util.strings import delimiter
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository.Gtk import ListStore, TreeIter # noqa E402 from gi.repository.Gtk import ListStore, TreeIter
from gi.repository import GObject # noqa E402 from gi.repository import GObject
GTYPE_TO_PYTHON = { GTYPE_TO_PYTHON = {
GObject.type_from_name(GObject.type_name(ptype)): ptype GObject.type_from_name(GObject.type_name(ptype)): ptype # type: ignore[no-untyped-call]
for ptype in (int, float, str, bool, object) for ptype in (int, float, str, bool, object)
} }
@@ -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
+22 -8
View File
@@ -1,10 +1,12 @@
import re import re
from dataclasses import dataclass
from typing import Any, TYPE_CHECKING, Union from typing import Any, TYPE_CHECKING, Union
from dzgui.const.enum import FilterMode from dzgui.const.enum import FilterMode
from dzgui.model.model_factory import ModelFactory from dzgui.model.model_factory import ModelFactory
from dzgui.util import strings from dzgui.util import strings
from dzgui.strings import filters as str_filters
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.managers.filter import FilterManager from dzgui.managers.filter import FilterManager
@@ -16,6 +18,22 @@ DAY_REG = r"([0][6-9]|[1][0-7])"
NIGHT_REG = r"([0][0-5]|[1][8-9]|[2][0-3])" NIGHT_REG = r"([0][0-5]|[1][8-9]|[2][0-3])"
@dataclass(slots=True, frozen=True)
class ServerRow:
name: str
mapname: str
view: str
time: str
players: int
max_players: int
queue: int
ip: str
qport: int
ping: str
provider: str
modded: bool
class ProxyModelManager: class ProxyModelManager:
""" """
Manages access to cached FastInsertListStore resources and Manages access to cached FastInsertListStore resources and
@@ -30,7 +48,7 @@ class ProxyModelManager:
def __init__(self, filter_man: "FilterManager") -> None: def __init__(self, filter_man: "FilterManager") -> None:
self.filter_cache: dict[ self.filter_cache: dict[
tuple[str], tuple[str, ...],
list[tuple[str, str, str, str, int, int, int, str, int, int, str, bool]], list[tuple[str, str, str, str, int, int, int, str, int, int, str, bool]],
] = {} ] = {}
@@ -51,9 +69,6 @@ class ProxyModelManager:
return False return False
return True return True
def append_row(self, row: list) -> None:
self.proxy_model.append(row)
def append_row_to_control( def append_row_to_control(
self, row: tuple[str, str, str, str, int, int, int, str, int, int, str, bool] self, row: tuple[str, str, str, str, int, int, int, str, int, int, str, bool]
) -> None: ) -> None:
@@ -67,7 +82,6 @@ class ProxyModelManager:
self.proxy_model[treeiter][4] = playercount.players self.proxy_model[treeiter][4] = playercount.players
self.proxy_model[treeiter][6] = playercount.queue self.proxy_model[treeiter][6] = playercount.queue
# TODO: use dataclass for record rows
def append_row_to_history( def append_row_to_history(
self, self,
history: tuple[str, str, str, str, int, int, int, str, int, int, str, bool], history: tuple[str, str, str, str, int, int, int, str, int, int, str, bool],
@@ -175,7 +189,7 @@ class ProxyModelManager:
rows = self.filtered rows = self.filtered
sel_map = self.filter_man.get_active_map_name() sel_map = self.filter_man.get_active_map_name()
if sel_map == strings.all_maps: if sel_map == str_filters.all_maps:
return rows return rows
rows = [row for row in rows if row[1] == sel_map] rows = [row for row in rows if row[1] == sel_map]
@@ -247,7 +261,7 @@ class ProxyModelManager:
rows = [row for row in rows if row[11]] rows = [row for row in rows if row[11]]
return rows return rows
def filter_toggle_on(self, filters: tuple[str]) -> list: def filter_toggle_on(self, filters: tuple[str, ...]) -> list:
"""Effectively applies all filters""" """Effectively applies all filters"""
self.set_filtered(self.control_model) self.set_filtered(self.control_model)
self.set_filtered(self.filter_map(filters)) self.set_filtered(self.filter_map(filters))
@@ -258,7 +272,7 @@ class ProxyModelManager:
self.set_filtered(self.filter_toggle_off(filters, f)) self.set_filtered(self.filter_toggle_off(filters, f))
return self.filtered return self.filtered
def set_cache(self, filters: tuple[str], filtered_rows: list[tuple]) -> None: def set_cache(self, filters: tuple[str, ...], filtered_rows: list[tuple]) -> None:
self.filter_cache[filters] = filtered_rows self.filter_cache[filters] = filtered_rows
def set_filtered(self, rows: list | None) -> None: def set_filtered(self, rows: list | None) -> None:
+4 -4
View File
@@ -21,7 +21,7 @@ from dzgui.views.dialogs.generic import ExceptionDialog
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402 from gi.repository import Gtk, GLib
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.api.servers import A2SInfo, Record from dzgui.api.servers import A2SInfo, Record
@@ -432,7 +432,7 @@ class ServerModelManager:
if show_dialog: if show_dialog:
dialog = ExceptionDialog(self.controller, dialogs.load_error_lan) dialog = ExceptionDialog(self.controller, dialogs.load_error_lan)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _cleanup_on_failure(self, show_dialog: bool = True) -> None: def _cleanup_on_failure(self, show_dialog: bool = True) -> None:
# TODO: disable map, keyword, and filter widgets if model is None # TODO: disable map, keyword, and filter widgets if model is None
@@ -451,14 +451,14 @@ class ServerModelManager:
dialog = ExceptionDialog(self.controller, server_timeout) dialog = ExceptionDialog(self.controller, server_timeout)
dialog.set_details_buffer(kb.DZG_006) dialog.set_details_buffer(kb.DZG_006)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
def _push_data(self, data: list[Any]) -> None: def _push_data(self, data: list[Any]) -> None:
self._get_proxy_man().push(data) self._get_proxy_man().push(data)
self._sort_unique_maps(data) self._sort_unique_maps(data)
self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_on_success)) self.thread_man.set_cleanup_func(StoredFunc(self._cleanup_on_success))
def _sort_unique_maps(self, data: list) -> None: def _sort_unique_maps(self, data: list[Any]) -> None:
u_maps = set([row[1] for row in data]) u_maps = set([row[1] for row in data])
self._set_new_maps(sorted(u_maps)) self._set_new_maps(sorted(u_maps))
+14
View File
@@ -1,2 +1,16 @@
clipboard_button = "Copy to clipboard"
clipboard_ip_button = "Copy IP to clipboard"
dock_button_collapse = "Collapse the connection panel"
dock_button_expand = "Expand the connection panel"
workshop = "Steam Workshop" workshop = "Steam Workshop"
workshop_tooltip = "Open your Workshop subscriptions" workshop_tooltip = "Open your Workshop subscriptions"
version_notifier = "Copied!"
version_tooltip = "Click to copy to clipboard"
update_button = "Updates available"
unset_button_label = "Unset"
unset_button_tooltip = "Unset this server as favorite"
+2
View File
@@ -29,3 +29,5 @@ toggle_calc = "Toggle calculator"
server_details = "Server details" server_details = "Server details"
server_message = "Server message" server_message = "Server message"
caught_cancel_signal = "Caught cancel signal, cleaning up"
+4
View File
@@ -0,0 +1,4 @@
all_maps = "All maps"
filters_heading = "Filters"
keyword_placeholder = "Filter by keyword"
map_placeholder = "Filter by map"
+1
View File
@@ -1 +1,2 @@
tab_changed_label = "*"
selectable_tree = "Ctrl-click to select multiple; Shift-click to select a range." selectable_tree = "Ctrl-click to select multiple; Shift-click to select a range."
+5
View File
@@ -0,0 +1,5 @@
dialog_title = "Add a short note/reminder"
dialog_subtitle = "Limit 30 chars"
delete_button = "Delete note"
ok_button = "Update note"
current_note = "Current note: '{0}'"
+2
View File
@@ -16,7 +16,9 @@ lan_combo = "LAN"
fullscreen_eventbox = "This option is not available on Steam Deck." fullscreen_eventbox = "This option is not available on Steam Deck."
save_button = "Save" save_button = "Save"
api_placeholder = "Enter API key"
api_failed = "API validation failed" api_failed = "API validation failed"
api_validate = "Validate"
flatpak_label = "Flatpak client" flatpak_label = "Flatpak client"
flatpak_standard = "Standard" flatpak_standard = "Standard"
+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 -1
View File
@@ -3,4 +3,5 @@ mod_id = "ID"
up_to_date = "Up to date" up_to_date = "Up to date"
modlist = "Modlist" modlist = "Modlist"
checkmark = "✓" checkmark = "✓"
resync="⟳" resync = "⟳"
invalid_mod = "Invalid mod"
+1 -2
View File
@@ -1,8 +1,7 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0") from gi.repository import Gtk, Gdk
from gi.repository import Gtk, Gdk # noqa E402
def copy_clipboard(text: str) -> None: def copy_clipboard(text: str) -> None:
+1 -1
View File
@@ -5,7 +5,7 @@ from dzgui.const.constants import APP_NAME_LOWER, CSS_PATH
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa E402 from gi.repository import Gtk, Gdk
def add_class(widget: Gtk.Widget, label: str) -> None: def add_class(widget: Gtk.Widget, label: str) -> None:
+2 -7
View File
@@ -7,11 +7,6 @@ from dzgui.const.constants import APP_NAME
from dzgui.util.ip import get_coords from dzgui.util.ip import get_coords
from dzgui.util.localize import number from dzgui.util.localize import number
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402
if TYPE_CHECKING: if TYPE_CHECKING:
from queue import Queue from queue import Queue
from dzgui.const.enum import ServerTab from dzgui.const.enum import ServerTab
@@ -59,7 +54,7 @@ class CalcDist:
self, self,
addr: str, addr: str,
enum: "ServerTab", enum: "ServerTab",
result_queue: "Queue", result_queue: "Queue[tuple[str, Haversine | None, ServerTab]]",
controller: "Controller", controller: "Controller",
cache: dict[str, Haversine], cache: dict[str, Haversine],
) -> None: ) -> None:
@@ -72,7 +67,7 @@ class CalcDist:
self.ip = self.addr self.ip = self.addr
dist = self.compare(self.ip) dist = self.compare(self.ip)
self.result_queue.put([self.addr, dist, self.enum]) self.result_queue.put((self.addr, dist, self.enum))
def compare(self, remote_ip: str) -> Haversine | None: def compare(self, remote_ip: str) -> Haversine | None:
prefs = self.controller.get_prefs() prefs = self.controller.get_prefs()
+6 -2
View File
@@ -1,12 +1,16 @@
import logging import logging
import subprocess import subprocess
from typing import TYPE_CHECKING
from dzgui.const.constants import APP_NAME, FLATPAK_APPID, GTK_APP_ID, TMP_PATH from dzgui.const.constants import APP_NAME, FLATPAK_APPID, GTK_APP_ID, TMP_PATH
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
if TYPE_CHECKING:
from pathlib import Path
def apply_overrides(xdg: dict[str, str]) -> None:
def apply_overrides(xdg: dict[str, "Path"]) -> None:
try: try:
# NOTE: D-Bus registration required for sandbox # NOTE: D-Bus registration required for sandbox
args = [ args = [
@@ -19,7 +23,7 @@ def apply_overrides(xdg: dict[str, str]) -> None:
subprocess.run([*args], capture_output=True) subprocess.run([*args], capture_output=True)
paths: list[str] = [] paths: list[str] = []
paths.extend([*xdg.values()]) paths.extend([str(path) for path in xdg.values()])
paths.append(TMP_PATH) paths.append(TMP_PATH)
for path in paths: for path in paths:
+3 -2
View File
@@ -1,4 +1,5 @@
import re import re
from typing import Any
from dzgui.util.localize import number from dzgui.util.localize import number
from dzgui.strings.generic import selectable_tree from dzgui.strings.generic import selectable_tree
@@ -7,7 +8,7 @@ from dzgui.util.strings import no_mods, no_servers, workshop
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
def format_pango(text: str) -> str: def format_pango(text: str) -> str:
@@ -60,7 +61,7 @@ def format_server_mods(mods: int) -> str:
return f"Found {mods:n} {plural}. {workshop}" return f"Found {mods:n} {plural}. {workshop}"
def format_player_count(model: Gtk.TreeModel | None, control: list) -> str: def format_player_count(model: Gtk.TreeModel | None, control: list[Any]) -> str:
players = 0 players = 0
hits: int hits: int
status: str status: str
+1 -1
View File
@@ -31,7 +31,7 @@ class ReservedIPError(Exception):
pass pass
def ip2list(ip: str) -> list: def ip2list(ip: str) -> list[int]:
return [int(digit) for digit in ip.split(".")] return [int(digit) for digit in ip.split(".")]
+4 -1
View File
@@ -1,6 +1,8 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gdk # noqa E402 from gi.repository import Gdk
def is_navkey(key: int) -> bool: def is_navkey(key: int) -> bool:
nav_keys = [ nav_keys = [
@@ -18,6 +20,7 @@ def is_navkey(key: int) -> bool:
return True return True
return False return False
def is_ctrl_mask(event: Gdk.EventKey) -> bool: def is_ctrl_mask(event: Gdk.EventKey) -> bool:
if event.state is Gdk.ModifierType.CONTROL_MASK: if event.state is Gdk.ModifierType.CONTROL_MASK:
return True return True
+3 -1
View File
@@ -1,6 +1,8 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
def set_surrounding_margins(widget: Gtk.Widget, margin: int) -> None: def set_surrounding_margins(widget: Gtk.Widget, margin: int) -> None:
""" """
+1 -1
View File
@@ -4,7 +4,7 @@ from typing import cast, TYPE_CHECKING
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib # noqa E402 from gi.repository import Gdk, GLib
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
+3 -3
View File
@@ -118,6 +118,7 @@ servers = {
"0": "toggle filter 10", "0": "toggle filter 10",
"Minus": "toggle filter 11", "Minus": "toggle filter 11",
"Backslash": "toggle filter 12", "Backslash": "toggle filter 12",
"Apostrophe": "toggle filter 13",
} }
vim = { vim = {
"j": "Move down a row/scroll up", "j": "Move down a row/scroll up",
@@ -159,9 +160,6 @@ filter_unofficial = "Unofficial"
filter_modded = "Modded" filter_modded = "Modded"
filter_unmodded = "Unmodded" filter_unmodded = "Unmodded"
# maps
all_maps = "All maps"
# state # state
unknown = "Unknown" unknown = "Unknown"
none_provided = "None provided" none_provided = "None provided"
@@ -252,6 +250,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 +438,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."
+1 -1
View File
@@ -38,7 +38,7 @@ import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
gi.require_version("GLibUnix", "2.0") gi.require_version("GLibUnix", "2.0")
from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore # noqa E402 from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.config.userprefs import UserPrefs from dzgui.config.userprefs import UserPrefs
+9 -5
View File
@@ -7,7 +7,7 @@ from dzgui.const.enum import ButtonType
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa E402 from gi.repository import Gtk, Gdk
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
@@ -19,7 +19,11 @@ 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 +55,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,
) )
+9 -40
View File
@@ -1,10 +1,8 @@
from typing import Callable, Literal, Self, TYPE_CHECKING, Union from typing import Callable, Literal, Self, TYPE_CHECKING, Union
from dzgui.util.clip import copy_clipboard from dzgui.util.clip import copy_clipboard
from dzgui.util.format import pluralize
from dzgui.strings import buttons from dzgui.strings import buttons
from dzgui.util.strings import ( from dzgui.util.strings import (
alert_button_tooltip,
atomic_buttons, atomic_buttons,
) )
from dzgui.const.icons import ( from dzgui.const.icons import (
@@ -14,7 +12,6 @@ from dzgui.const.icons import (
ICON_LIST_ADD, ICON_LIST_ADD,
ICON_REFRESH, ICON_REFRESH,
ICON_STEAM, ICON_STEAM,
ICON_WARNING,
ICON_WEB_BROWSER, ICON_WEB_BROWSER,
) )
from dzgui.strings import connect_panel from dzgui.strings import connect_panel
@@ -22,7 +19,7 @@ from dzgui.strings import connect_panel
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib # noqa E402 from gi.repository import Gtk, GLib
if TYPE_CHECKING: if TYPE_CHECKING:
from gi.repository import GLib from gi.repository import GLib
@@ -64,7 +61,7 @@ class IconButton(Gtk.Button):
self.icon = Icon(icon, margin_start=margin_start, margin_end=margin_end) self.icon = Icon(icon, margin_start=margin_start, margin_end=margin_end)
self.set_image(self.icon) self.set_image(self.icon)
self.set_image_position(position) self.set_image_position(position)
self.set_focus_on_click(False) self.set_focus_on_click(False) # type: ignore[no-untyped-call]
self.set_always_show_image(True) self.set_always_show_image(True)
def swap_icon(self, icon: str) -> None: def swap_icon(self, icon: str) -> None:
@@ -101,15 +98,13 @@ class LargeIconTextButton(IconButton):
class ClipboardButton(IconTextButton): class ClipboardButton(IconTextButton):
def __init__(self, controller: Union["Controller", None], func: Callable) -> None: def __init__(self, func: Callable[[], str]) -> None:
super().__init__(ICON_CLIPBOARD, atomic_buttons.copy) super().__init__(ICON_CLIPBOARD, atomic_buttons.copy)
self.controller = controller
self.connect("clicked", self._on_button_clicked, func) self.connect("clicked", self._on_button_clicked, func)
# TODO: strings self.set_tooltip_text(buttons.clipboard_button)
self.set_tooltip_text("Copy to clipboard")
def _on_button_clicked(self, button: Self, func: Callable) -> None: def _on_button_clicked(self, button: Self, func: Callable[[], str]) -> None:
def revert() -> Literal[False]: def revert() -> Literal[False]:
self.revert_icon() self.revert_icon()
return False return False
@@ -120,21 +115,18 @@ class ClipboardButton(IconTextButton):
GLib.timeout_add(600, revert) GLib.timeout_add(600, revert)
# TODO: determine when controller would be passed to this button or drop
class CopyIpButton(ClipboardButton): class CopyIpButton(ClipboardButton):
def __init__(self, controller: Union["Controller", None], func: Callable) -> None: def __init__(self, func: Callable[[], str]) -> None:
super().__init__(controller, func) super().__init__(func)
# TODO: strings self.set_tooltip_text(buttons.clipboard_ip_button)
self.set_tooltip_text("Copy IP to clipboard")
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=ICON_CLOSE, label=label)
# TODO: strings self.set_tooltip_text(buttons.unset_button_tooltip)
self.set_tooltip_text("Unset this server as favorite")
class WebButton(IconTextButton): class WebButton(IconTextButton):
@@ -252,29 +244,6 @@ class AddButton(IconTextButton):
self.set_tooltip_text(connect_panel.add_tooltip) self.set_tooltip_text(connect_panel.add_tooltip)
class LoggerAlertsButton(IconTextButton):
def __init__(self, warnings: int, errors: int) -> None:
warnings_text = ""
errors_text = ""
separator = ""
if warnings > 0:
warnings_plural = pluralize("warnings", warnings)
warnings_text = f"{warnings} {warnings_plural}"
if errors > 0:
errors_plural = pluralize("errors", errors)
errors_text = f" {errors} {errors_plural}"
if warnings + errors > 1:
separator = ","
concat = warnings_text + separator + errors_text
super().__init__(
icon=ICON_WARNING,
label=f"Loaded with{concat}",
)
self.set_halign(Gtk.Align.END)
self.set_hexpand(True)
self.set_tooltip_text(alert_button_tooltip)
class SpinnerButton(Gtk.Button): class SpinnerButton(Gtk.Button):
def __init__(self, label: str) -> None: def __init__(self, label: str) -> None:
super().__init__() super().__init__()
+11 -11
View File
@@ -4,6 +4,11 @@ from dzgui.const.icons import ICON_CARET_DOWN, ICON_CARET_UP
from dzgui.const.constants import 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.strings.buttons import (
dock_button_collapse,
dock_button_expand,
unset_button_label,
)
from dzgui.util.keys import is_ctrl_mask from dzgui.util.keys import is_ctrl_mask
from dzgui.views.components.buttons import ( from dzgui.views.components.buttons import (
AddButton, AddButton,
@@ -19,7 +24,7 @@ from dzgui.views.components.labels import BoldLabel
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa E402 from gi.repository import Gtk, Gdk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -37,21 +42,18 @@ class DockButton(IconButton):
self.child = child self.child = child
self.connect("clicked", self._on_click) self.connect("clicked", self._on_click)
self.collapse_text = "Collapse the connection panel"
self.expand_text = "Expand the connection panel"
self.set_margin_top(10) self.set_margin_top(10)
self.set_tooltip_text(self.collapse_text) self.set_tooltip_text(dock_button_collapse)
def collapse(self) -> None: def collapse(self) -> None:
self.set_image(Icon(ICON_CARET_UP)) self.set_image(Icon(ICON_CARET_UP))
self.child.hide() self.child.hide()
self.set_tooltip_text(self.expand_text) self.set_tooltip_text(dock_button_expand)
def expand(self) -> None: def expand(self) -> None:
self.set_image(Icon(ICON_CARET_DOWN)) self.set_image(Icon(ICON_CARET_DOWN))
self.child.show() self.child.show()
self.set_tooltip_text(self.collapse_text) self.set_tooltip_text(dock_button_collapse)
def _on_click(self, button: Self) -> None: def _on_click(self, button: Self) -> None:
if self.expanded: if self.expanded:
@@ -82,7 +84,6 @@ class LanPanel(Gtk.Frame):
self.scan = Gtk.Button(label=connect_panel.lan_scan_button) self.scan = Gtk.Button(label=connect_panel.lan_scan_button)
self.scan.connect("clicked", self._on_scan_clicked) self.scan.connect("clicked", self._on_scan_clicked)
# TODO: strings
self.early_abort = Gtk.CheckButton(label=connect_panel.lan_checkbox) self.early_abort = Gtk.CheckButton(label=connect_panel.lan_checkbox)
self.early_abort.set_active(True) self.early_abort.set_active(True)
self.early_abort.set_tooltip_text(connect_panel.lan_abort_tooltip) self.early_abort.set_tooltip_text(connect_panel.lan_abort_tooltip)
@@ -188,10 +189,9 @@ class FavPanel(Gtk.Frame):
self.fav_button = SteamConnectButton() self.fav_button = SteamConnectButton()
self.fav_button.connect("clicked", self._on_connect_clicked) self.fav_button.connect("clicked", self._on_connect_clicked)
self.copy_button = CopyIpButton(self.controller, self.get_fav_ip) self.copy_button = CopyIpButton(self.get_fav_ip)
# TODO: strings self.unset_button = CloseButton(unset_button_label)
self.unset_button = CloseButton("Unset")
self.unset_button.connect("clicked", self._on_unset_clicked) self.unset_button.connect("clicked", self._on_unset_clicked)
if favorite is None: if favorite is None:
+2 -2
View File
@@ -7,7 +7,7 @@ from dzgui.util.format import embolden
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -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:
+8 -10
View File
@@ -4,12 +4,13 @@ from dzgui.api.servers import validate_ip
from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_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.options import api_placeholder, api_validate
from dzgui.strings.errors import api_popover from dzgui.strings.errors import api_popover
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GObject # noqa E402 from gi.repository import Gtk, Gdk, GObject
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -38,7 +39,7 @@ class ValidatedEntry(Gtk.Entry):
def __init__( def __init__(
self, self,
controller: "Controller", controller: "Controller",
func: Callable, func: Callable[[str], bool],
placeholder_text: str = "", placeholder_text: str = "",
tooltip_text: str = "", tooltip_text: str = "",
) -> None: ) -> None:
@@ -46,7 +47,6 @@ class ValidatedEntry(Gtk.Entry):
hexpand=True, placeholder_text=placeholder_text, tooltip_text=tooltip_text hexpand=True, placeholder_text=placeholder_text, tooltip_text=tooltip_text
) )
self.func: Callable
self.set_validation_func(func) self.set_validation_func(func)
self.controller = controller self.controller = controller
@@ -72,7 +72,7 @@ class ValidatedEntry(Gtk.Entry):
self.emit("string_validated", False) self.emit("string_validated", False)
remove_class(self, self.classname) remove_class(self, self.classname)
def set_validation_func(self, func: Callable) -> None: def set_validation_func(self, func: Callable[[str], bool]) -> None:
self.func = func self.func = func
def insert_icon(self) -> None: def insert_icon(self) -> None:
@@ -141,11 +141,10 @@ class APIEntry(Gtk.Box):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
self.func: Callable | None = None self.func: Callable[[str], None] | None = None
# TODO: strings
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=api_placeholder
) )
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL) self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL)
self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True)
@@ -154,8 +153,7 @@ class APIEntry(Gtk.Box):
self.entry.connect("icon-release", self._on_icon_release) self.entry.connect("icon-release", self._on_icon_release)
self.entry.connect("activate", self._on_field_activated) self.entry.connect("activate", self._on_field_activated)
# TODO: strings self.submit = Gtk.Button(label=api_validate)
self.submit = Gtk.Button(label="Validate")
self.submit.set_sensitive(False) self.submit.set_sensitive(False)
self.submit.connect("clicked", self._on_submit) self.submit.connect("clicked", self._on_submit)
@@ -222,7 +220,7 @@ class APIEntry(Gtk.Box):
res = self.func(text) res = self.func(text)
return res return res
def set_validation_func(self, func: Callable | None) -> None: def set_validation_func(self, func: Callable[[str], None] | None) -> None:
self.func = func self.func = func
def disable_button(self) -> None: def disable_button(self) -> None:
+1 -1
View File
@@ -6,7 +6,7 @@ from dzgui.const.icons import ICON_HELP_BUBBLE
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa E402 from gi.repository import Gtk, Gdk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
+13 -10
View File
@@ -6,14 +6,19 @@ from dzgui.const.constants import (
) )
from dzgui.const.icons import ICON_SEARCH 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.strings.filters import (
all_maps,
filters_heading,
keyword_placeholder,
map_placeholder,
)
from dzgui.views.components.maps_combo import MapsCombo from dzgui.views.components.maps_combo import MapsCombo
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, Pango, GLib # noqa E402 from gi.repository import Gtk, Gdk, Pango, GLib
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
@@ -26,7 +31,7 @@ class ButtonGrid(Gtk.Grid):
def __init__( def __init__(
self, self,
controller: "Controller", controller: "Controller",
defaults: dict[str, str], defaults: dict[str, bool],
tooltips: dict[str, str], tooltips: dict[str, str],
) -> None: ) -> None:
super().__init__( super().__init__(
@@ -92,14 +97,13 @@ class ButtonGrid(Gtk.Grid):
logger.info(f"User toggled button '{label}' to {state}") logger.info(f"User toggled button '{label}' to {state}")
self.emitter.emit("check_toggled", label, state) self.emitter.emit("check_toggled", label, state)
def get_checkboxes(self) -> list: def get_checkboxes(self) -> list[Gtk.CheckButton]:
return self.checks return self.checks
class KeywordEntry(Gtk.Entry): class KeywordEntry(Gtk.Entry):
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
# TODO :strings super().__init__(placeholder_text=keyword_placeholder)
super().__init__(placeholder_text="Filter by keyword")
self.keyword = "" self.keyword = ""
self.controller = controller self.controller = controller
@@ -173,8 +177,7 @@ class FilterPanel(Gtk.Box):
self.keyword_entry = KeywordEntry(self.controller) self.keyword_entry = KeywordEntry(self.controller)
self.button_grid = ButtonGrid(self.controller, defaults, tooltips) self.button_grid = ButtonGrid(self.controller, defaults, tooltips)
# TODO: strings self.filters_label = BoldLabel(filters_heading)
self.filters_label = BoldLabel("Filters")
self.emitter.connect( self.emitter.connect(
"request_keyword_focus", lambda _: self.keyword_entry.grab_focus() "request_keyword_focus", lambda _: self.keyword_entry.grab_focus()
@@ -194,8 +197,7 @@ class FilterPanel(Gtk.Box):
self.maps_entry: Gtk.Entry = self.maps_combo.get_child() # type: ignore self.maps_entry: Gtk.Entry = self.maps_combo.get_child() # type: ignore
self.maps_entry.set_completion(completion) self.maps_entry.set_completion(completion)
# TODO: strings self.maps_entry.set_placeholder_text(map_placeholder)
self.maps_entry.set_placeholder_text("Filter by map")
self.maps_entry.connect("changed", self._on_map_completion, True) self.maps_entry.connect("changed", self._on_map_completion, True)
self.maps_entry.connect("key-press-event", self._on_map_entry_keypress) self.maps_entry.connect("key-press-event", self._on_map_entry_keypress)
self.maps_entry.connect("activate", self._on_maps_activated) self.maps_entry.connect("activate", self._on_maps_activated)
@@ -304,6 +306,7 @@ class FilterPanel(Gtk.Box):
Gdk.KEY_0: 9, Gdk.KEY_0: 9,
Gdk.KEY_minus: 10, Gdk.KEY_minus: 10,
Gdk.KEY_backslash: 11, Gdk.KEY_backslash: 11,
Gdk.KEY_apostrophe: 12,
} }
if keyval not in mappings: if keyval not in mappings:
return False return False
+1 -1
View File
@@ -1,7 +1,7 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
class Icon(Gtk.Image): class Icon(Gtk.Image):
+1 -1
View File
@@ -3,7 +3,7 @@ from dzgui.util.format import embolden
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
class BoldLabel(Gtk.Label): class BoldLabel(Gtk.Label):
+1 -1
View File
@@ -1,7 +1,7 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402 from gi.repository import Gtk
class MapsCombo(Gtk.EntryCompletion): class MapsCombo(Gtk.EntryCompletion):
+3 -3
View File
@@ -7,7 +7,7 @@ from dzgui.views.components.labels import BoldLabel
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -19,8 +19,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):
+5 -6
View File
@@ -9,6 +9,7 @@ from dzgui.const.constants import (
) )
from dzgui.const.enum import ServerTab from dzgui.const.enum import ServerTab
from dzgui.managers.update import UpdateManager from dzgui.managers.update import UpdateManager
from dzgui.strings.buttons import update_button, version_notifier, version_tooltip
from dzgui.util.clip import copy_clipboard from dzgui.util.clip import copy_clipboard
from dzgui.util.file import is_writeable from dzgui.util.file import is_writeable
from dzgui.views.components.buttonbox import ButtonBox from dzgui.views.components.buttonbox import ButtonBox
@@ -19,7 +20,7 @@ from dzgui.views.components.buttons import IconTextButton, RefreshButton, KeysBu
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib # noqa E402 from gi.repository import Gtk, Gdk, GLib
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -61,8 +62,7 @@ class RightPanel(Gtk.Box):
vexpand=True, vexpand=True,
halign=Gtk.Align.END, halign=Gtk.Align.END,
valign=Gtk.Align.END, valign=Gtk.Align.END,
# TODO: strings tooltip_text=version_tooltip,
tooltip_text="Click to copy to clipboard",
) )
eb = Gtk.EventBox(halign=Gtk.Align.END, valign=Gtk.Align.END) eb = Gtk.EventBox(halign=Gtk.Align.END, valign=Gtk.Align.END)
eb.add(self.version_label) eb.add(self.version_label)
@@ -74,7 +74,7 @@ class RightPanel(Gtk.Box):
self.pack_start(self.sel_panel, expand=False, fill=False, padding=0) self.pack_start(self.sel_panel, expand=False, fill=False, padding=0)
self.update_button = IconTextButton( self.update_button = IconTextButton(
"dialog-information-symbolic", label="Updates available" "dialog-information-symbolic", label=update_button
) )
self.gutter_box = Gtk.Box( self.gutter_box = Gtk.Box(
@@ -127,7 +127,6 @@ class RightPanel(Gtk.Box):
return return
self.copying = True self.copying = True
version = self.version_label.get_text() version = self.version_label.get_text()
# TODO: strings self.version_label.set_text(version_notifier)
self.version_label.set_text("Copied!")
copy_clipboard(version) copy_clipboard(version)
GLib.timeout_add_seconds(1, revert) GLib.timeout_add_seconds(1, revert)
+3 -7
View File
@@ -2,12 +2,11 @@ from typing import Self, Union, TYPE_CHECKING
from dzgui.const.enum import NotebookPage, ServerTab from dzgui.const.enum import NotebookPage, ServerTab
from dzgui.util.strings import esc_to_return, question_to_return from dzgui.util.strings import esc_to_return, question_to_return
from dzgui.views.components.buttons import LoggerAlertsButton
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.const.enum import ServerTab from dzgui.const.enum import ServerTab
@@ -47,9 +46,6 @@ class Statusbar(Gtk.Grid):
self.emitter.connect("servers_loaded", self._on_servers_loaded) self.emitter.connect("servers_loaded", self._on_servers_loaded)
self.emitter.connect("mods_updated", self._on_mods_updated) self.emitter.connect("mods_updated", self._on_mods_updated)
def _on_alerts_clicked(self, button: LoggerAlertsButton) -> None:
self.controller.populate_log()
def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None: def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None:
self.set_by_context(NotebookPage.MODS, msg) self.set_by_context(NotebookPage.MODS, msg)
@@ -60,7 +56,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 +148,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)
+2 -1
View File
@@ -2,8 +2,9 @@ from typing import Literal
from dzgui.util import css from dzgui.util import css
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402 from gi.repository import Gtk, GLib
class Toast(Gtk.EventBox): class Toast(Gtk.EventBox):
+1 -1
View File
@@ -104,7 +104,7 @@ class BootDialog(ColorAwareApp, Gtk.Dialog): # type: ignore
self.error_label = Gtk.Label(margin_start=15, margin_end=15) self.error_label = Gtk.Label(margin_start=15, margin_end=15)
# TODO: abstract class # TODO: abstract class
self.copy_button = ClipboardButton(None, lambda: self.error_label.get_text()) self.copy_button = ClipboardButton(self.error_label.get_text)
self.button_hbox = Gtk.Box( self.button_hbox = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL, halign=Gtk.Align.CENTER, spacing=10 orientation=Gtk.Orientation.HORIZONTAL, halign=Gtk.Align.CENTER, spacing=10
) )
+1 -1
View File
@@ -10,7 +10,7 @@ from dzgui.views.components.labels import BoldLabel
from dzgui.views.components.box import VBox, HBox from dzgui.views.components.box import VBox, HBox
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, GObject # type: ignore # noqa E402 from gi.repository import Gtk, GLib, GObject
DAY_START_TIME = time(hour=6, minute=0, second=0) DAY_START_TIME = time(hour=6, minute=0, second=0)
DAY_END_TIME = time(hour=18, minute=0, second=0) DAY_END_TIME = time(hour=18, minute=0, second=0)
+2 -2
View File
@@ -8,7 +8,7 @@ from dzgui.views.mixins.colorscheme import ColorAwareApp
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
class AbortDialog(ColorAwareApp, Gtk.MessageDialog): # type: ignore class AbortDialog(ColorAwareApp, Gtk.MessageDialog): # type: ignore
@@ -46,7 +46,7 @@ class AbortDialog(ColorAwareApp, Gtk.MessageDialog): # type: ignore
self.connect("response", self._on_response) self.connect("response", self._on_response)
self.run() self.run() # type: ignore[no-untyped-call]
self.destroy() self.destroy()
def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None: def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None:
+8 -8
View File
@@ -2,10 +2,10 @@ from pathlib import Path
from dzgui.util.strings import picker from dzgui.util.strings import picker
import gi # noqa E402 import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
class FilePicker(Gtk.FileChooserDialog): class FilePicker(Gtk.FileChooserDialog):
@@ -16,14 +16,14 @@ class FilePicker(Gtk.FileChooserDialog):
transient_for=parent, transient_for=parent,
resizable=True, resizable=True,
) )
self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL) self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL) # type: ignore[no-untyped-call]
self.add_buttons("_Save", Gtk.ResponseType.OK) self.add_buttons("_Save", Gtk.ResponseType.OK) # type: ignore[no-untyped-call]
self.set_default_response(Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK)
self.set_current_name(picker.placeholder) self.set_current_name(picker.placeholder)
def pick_file(self) -> Path | None: def pick_file(self) -> Path | None:
res = self.run() res = self.run() # type: ignore[no-untyped-call]
if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT): if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
self.destroy() self.destroy()
return None return None
@@ -43,12 +43,12 @@ class FolderPicker(Gtk.FileChooserDialog):
parent=parent, parent=parent,
resizable=True, resizable=True,
) )
self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL) self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL) # type: ignore[no-untyped-call]
self.add_buttons("_OK", Gtk.ResponseType.OK) self.add_buttons("_OK", Gtk.ResponseType.OK) # type: ignore[no-untyped-call]
self.set_default_response(Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK)
def pick_folder(self) -> Path | None: def pick_folder(self) -> Path | None:
res = self.run() res = self.run() # type: ignore[no-untyped-call]
if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT): if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
self.destroy() self.destroy()
return None return None
+3 -4
View File
@@ -7,7 +7,7 @@ from dzgui.views.components.buttons import ClipboardButton
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk, GLib
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -139,8 +139,7 @@ class WaitDialog(GenericDialog):
self.cur_job += 1 self.cur_job += 1
def _on_cancel_clicked(self, button: Gtk.Button) -> None: def _on_cancel_clicked(self, button: Gtk.Button) -> None:
# TODO: strings GLib.idle_add(self.update_text, dialogs.caught_cancel_signal)
GLib.idle_add(self.update_text, "Caught cancel signal, cleaning up")
self.controller.set_cancel_event() self.controller.set_cancel_event()
def show_cancel(self, state: bool) -> None: def show_cancel(self, state: bool) -> None:
@@ -186,7 +185,7 @@ class TextBufferDialog(GenericDialog):
secondary=secondary, secondary=secondary,
) )
self.text = text self.text = text
copy_button = ClipboardButton(controller, self.get_text) copy_button = ClipboardButton(self.get_text)
self.add_action_widget(copy_button, Gtk.ResponseType.NONE) self.add_action_widget(copy_button, Gtk.ResponseType.NONE)
self.add_button("OK", Gtk.ResponseType.OK) self.add_button("OK", Gtk.ResponseType.OK)
self.connect("response", self._on_response) self.connect("response", self._on_response)
+1 -1
View File
@@ -8,7 +8,7 @@ from dzgui.views.components.buttons import SteamTextButton
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
+11 -19
View File
@@ -1,12 +1,13 @@
from typing import Self, TYPE_CHECKING from typing import Self, TYPE_CHECKING
from dzgui.strings import notes
from dzgui.views.components.entry import ValidatedEntry from dzgui.views.components.entry import ValidatedEntry
from dzgui.views.dialogs.generic import GenericDialog from dzgui.views.dialogs.generic import GenericDialog
import gi # noqa E402 import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gdk, Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
@@ -14,23 +15,20 @@ if TYPE_CHECKING:
class NoteDialog(GenericDialog): class NoteDialog(GenericDialog):
def __init__(self, controller: "Controller"): def __init__(self, controller: "Controller"):
# TODO: add to strings
title = "Add a short note/reminder."
secondary = "Limit 30 chars"
super().__init__( super().__init__(
controller=controller, controller=controller,
text=title, text=notes.dialog_title,
buttons=Gtk.ButtonsType.NONE, buttons=Gtk.ButtonsType.NONE,
mtype=Gtk.MessageType.INFO, mtype=Gtk.MessageType.INFO,
secondary=secondary, secondary=notes.dialog_subtitle,
) )
self.controller = controller self.controller = controller
delete_button = Gtk.Button(label="Delete note") delete_button = Gtk.Button(label=notes.delete_button)
delete_button.set_sensitive(False) delete_button.set_sensitive(False)
self.add_action_widget(delete_button, Gtk.ResponseType.CANCEL) self.add_action_widget(delete_button, Gtk.ResponseType.CANCEL)
self.ok = self.add_button("Update note", Gtk.ResponseType.OK) self.ok = self.add_button(notes.ok_button, Gtk.ResponseType.OK)
self.ok.grab_default() self.ok.grab_default()
self.entry = ValidatedEntry(controller, self.validate) self.entry = ValidatedEntry(controller, self.validate)
@@ -42,7 +40,7 @@ class NoteDialog(GenericDialog):
self.entry.set_text(note) self.entry.set_text(note)
if len(note) > 0: if len(note) > 0:
delete_button.set_sensitive(True) delete_button.set_sensitive(True)
self.format_secondary_text(f"Current note: '{note}'") self.format_secondary_text(notes.current_note.format(note))
elif len(note) == 0: elif len(note) == 0:
self.ok.set_sensitive(False) self.ok.set_sensitive(False)
@@ -55,9 +53,6 @@ class NoteDialog(GenericDialog):
self.entry.connect("changed", self._on_text_changed) self.entry.connect("changed", self._on_text_changed)
def _on_text_changed(self, entry: Gtk.Entry) -> None: def _on_text_changed(self, entry: Gtk.Entry) -> None:
"""
Called in conjunction with signal callback in the parent class
"""
if len(entry.get_text()) == 0: if len(entry.get_text()) == 0:
self.ok.set_sensitive(False) self.ok.set_sensitive(False)
@@ -71,14 +66,11 @@ class NoteDialog(GenericDialog):
def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None: def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None:
match response: match response:
case Gtk.ResponseType.DELETE_EVENT:
self.destroy()
case Gtk.ResponseType.OK: case Gtk.ResponseType.OK:
note = self.entry.get_text() note = self.entry.get_text()
self.controller.add_note(note) self.controller.add_note(note)
self.destroy()
case Gtk.ResponseType.CANCEL: case Gtk.ResponseType.CANCEL:
self.controller.delete_note() self.controller.delete_note()
self.destroy() case _:
case Gtk.ResponseType.CANCEL | Gtk.ResponseType.CLOSE: pass
self.destroy() self.destroy()
+5 -5
View File
@@ -18,11 +18,11 @@ from dzgui.views.mixins.colorscheme import ColorAwareApp
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Pango # noqa E402 from gi.repository import Gtk, GLib, Pango
class Assistant(Gtk.Assistant): class Assistant(Gtk.Assistant):
def __init__(self, is_deck: bool, paths: dict[str, str]): def __init__(self, is_deck: bool, paths: dict[str, Path]):
super().__init__() super().__init__()
if is_deck: if is_deck:
# NOTE: deemed to be "safe" dimensions that exclude taskbar size # NOTE: deemed to be "safe" dimensions that exclude taskbar size
@@ -63,7 +63,7 @@ class Assistant(Gtk.Assistant):
class Window(Gtk.Window): class Window(Gtk.Window):
def __init__(self, is_deck: bool, paths: dict[str, str]) -> None: def __init__(self, is_deck: bool, paths: dict[str, Path]) -> None:
super().__init__(title=APP_NAME, icon_name=APP_NAME) super().__init__(title=APP_NAME, icon_name=APP_NAME)
self.assistant = Assistant(is_deck, paths) self.assistant = Assistant(is_deck, paths)
@@ -121,7 +121,7 @@ class CheckboxWithPath(CheckboxWithLabel):
class UninstallPage(ScrolledWizardPage): class UninstallPage(ScrolledWizardPage):
def __init__(self, paths: dict[str, str], pyapp: str | None): def __init__(self, paths: dict[str, Path], pyapp: str | None):
super().__init__(heading=uninstall.pg1_heading, description=uninstall.pg1_blurb) super().__init__(heading=uninstall.pg1_heading, description=uninstall.pg1_blurb)
self.pyapp = pyapp self.pyapp = pyapp
@@ -219,7 +219,7 @@ class UninstallPage(ScrolledWizardPage):
class UninstallWizard(ColorAwareApp, Gtk.Application): # type: ignore class UninstallWizard(ColorAwareApp, Gtk.Application): # type: ignore
def __init__(self, is_deck: bool, paths: dict[str, str]) -> None: def __init__(self, is_deck: bool, paths: dict[str, Path]) -> None:
super().__init__() super().__init__()
config = Path(paths["XDG_CONFIG_HOME"]) config = Path(paths["XDG_CONFIG_HOME"])
if not config.is_dir() or not config.joinpath("config.json").is_file(): if not config.is_dir() or not config.joinpath("config.json").is_file():
+12 -7
View File
@@ -14,7 +14,7 @@ from dzgui.const.constants import (
HERO_PATH, HERO_PATH,
FLATPAK_ROOT_PATH, FLATPAK_ROOT_PATH,
LEGACY_CONFIG_PATH, LEGACY_CONFIG_PATH,
TMP_PATH TMP_PATH,
) )
from dzgui.const.boilerplate import config_boilerplate from dzgui.const.boilerplate import config_boilerplate
from dzgui.const.endpoints import STEAM_API_SETUP from dzgui.const.endpoints import STEAM_API_SETUP
@@ -35,7 +35,7 @@ from dzgui.views.trees.tree_simple import SimpleTree
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gdk, Gtk, GLib, GObject, GdkPixbuf # noqa E402 from gi.repository import Gtk, GLib, GObject, GdkPixbuf
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.config.xdg import Xdg from dzgui.config.xdg import Xdg
@@ -168,7 +168,12 @@ class NotificationFrame(Gtk.Frame):
class APIValidationPage(EnumeratedWizardPage): class APIValidationPage(EnumeratedWizardPage):
def __init__( def __init__(
self, enum: PageNum, heading: str, description: str, link: str, func: Callable self,
enum: PageNum,
heading: str,
description: str,
link: str,
func: Callable[[str], None],
) -> None: ) -> None:
super().__init__( super().__init__(
enum=enum, enum=enum,
@@ -421,7 +426,7 @@ class PreferencesPage(EnumeratedWizardPage):
class FlatpakOverridePage(EnumeratedWizardPage): class FlatpakOverridePage(EnumeratedWizardPage):
def __init__(self, xdg_paths: dict[str, str]) -> None: def __init__(self, xdg_paths: dict[str, Path]) -> None:
super().__init__( super().__init__(
enum=PageNum.FLATPAK, enum=PageNum.FLATPAK,
heading=wizard.heading_flatpak, heading=wizard.heading_flatpak,
@@ -471,7 +476,7 @@ class CompletionPage(EnumeratedWizardPage):
class Assistant(Gtk.Assistant): class Assistant(Gtk.Assistant):
def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, str]): def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, Path]):
super().__init__() super().__init__()
if is_deck: if is_deck:
# NOTE: deemed to be "safe" dimensions that exclude taskbar size # NOTE: deemed to be "safe" dimensions that exclude taskbar size
@@ -776,7 +781,7 @@ class SteamPathPage(EnumeratedWizardPage):
class SetupWizard(ColorAwareApp, Gtk.Application): # type: ignore class SetupWizard(ColorAwareApp, Gtk.Application): # type: ignore
def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, str]) -> None: def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, Path]) -> None:
super().__init__() super().__init__()
GLib.set_prgname(APP_NAME) GLib.set_prgname(APP_NAME)
self.win = Window(is_deck, XDG, xdg_paths) self.win = Window(is_deck, XDG, xdg_paths)
@@ -787,7 +792,7 @@ class SetupWizard(ColorAwareApp, Gtk.Application): # type: ignore
class Window(Gtk.Window): class Window(Gtk.Window):
def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, str]) -> None: def __init__(self, is_deck: bool, XDG: "Xdg", xdg_paths: dict[str, Path]) -> None:
super().__init__(title=APP_NAME, icon_name=APP_NAME) super().__init__(title=APP_NAME, icon_name=APP_NAME)
self.assistant = Assistant(is_deck, XDG, xdg_paths) self.assistant = Assistant(is_deck, XDG, xdg_paths)
+11 -13
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
@@ -9,15 +9,13 @@ from dzgui.views.trees.tree_base import TreeView
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk, Gdk
logger = logging.getLogger(APP_NAME) 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
@@ -26,7 +24,7 @@ class ContextMixin(TreeView):
match event.type: match event.type:
case Gdk.EventType.BUTTON_PRESS: case Gdk.EventType.BUTTON_PRESS:
if event.button != 3: if event.button != Gdk.BUTTON_SECONDARY: # type: ignore[comparison-overlap]
return False return False
self._process_button_event(event) # type: ignore self._process_button_event(event) # type: ignore
case Gdk.EventType.KEY_PRESS: case Gdk.EventType.KEY_PRESS:
@@ -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:
+1 -1
View File
@@ -5,7 +5,7 @@ from dzgui.util.keys import is_ctrl_mask
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk, Gdk
class CursorMixin: class CursorMixin:
+1 -1
View File
@@ -3,7 +3,7 @@ from dzgui.views.trees.tree_base import TreeView
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk
class ModsMixin: class ModsMixin:
+1 -1
View File
@@ -15,7 +15,7 @@ from dzgui.views.mixins.scrollable_mixin import ScrollableMixin
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
+2 -2
View File
@@ -7,10 +7,10 @@ from dzgui.util.strings import developers
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
from dzgui.views.trees.tree_base import TreeView from dzgui.views.trees.tree_base import TreeView
import gi # noqa E402 import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
+1 -1
View File
@@ -4,7 +4,7 @@ from dzgui.views.trees.tree_menu import MenuTreeView
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
+5 -4
View File
@@ -7,12 +7,13 @@ from dzgui.util.css import add_class
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
# TODO: refactor into autopopulated ListStores
class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
""" """
Notebook page holding a prearranged grid Notebook page holding a prearranged grid
@@ -35,7 +36,7 @@ class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
self.connect("key-press-event", self._on_keypress) self.connect("key-press-event", self._on_keypress)
def build_keys(self, items: list) -> Gtk.Grid: def build_keys(self, items: list[dict[str, str]]) -> Gtk.Grid:
grid = Gtk.Grid(row_spacing=10, column_homogeneous=True) grid = Gtk.Grid(row_spacing=10, column_homogeneous=True)
grid.set_halign(Gtk.Align.START) grid.set_halign(Gtk.Align.START)
row, col = 1, 0 row, col = 1, 0
@@ -72,7 +73,7 @@ class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
row += 1 row += 1
return grid return grid
def build_sidebar(self, categories: list) -> Gtk.Grid: def build_sidebar(self, categories: list[str]) -> Gtk.Grid:
row, col = 0, 0 row, col = 0, 0
w, h = 1, 1 w, h = 1, 1
sidebar = Gtk.Grid(row_homogeneous=True, orientation=Gtk.Orientation.VERTICAL) sidebar = Gtk.Grid(row_homogeneous=True, orientation=Gtk.Orientation.VERTICAL)
@@ -83,7 +84,7 @@ class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
sidebar.attach(label, col, row, w, h) sidebar.attach(label, col, row, w, h)
return sidebar return sidebar
def build_grid(self, items: list) -> Gtk.Grid: def build_grid(self, items: list[dict[str, str]]) -> Gtk.Grid:
grid = Gtk.Grid( grid = Gtk.Grid(
row_spacing=20, row_spacing=20,
halign=Gtk.Align.CENTER, halign=Gtk.Align.CENTER,
+1 -1
View File
@@ -9,7 +9,7 @@ from dzgui.views.trees.tree_log import LogTreeView
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
+7 -6
View File
@@ -1,5 +1,5 @@
from pathlib import Path from pathlib import Path
from typing import Callable, TYPE_CHECKING from typing import Any, Callable, TYPE_CHECKING
from dzgui.api import pefile as PeFile from dzgui.api import pefile as PeFile
from dzgui.api.steam import get_last_updated from dzgui.api.steam import get_last_updated
@@ -51,7 +51,7 @@ class SubmitField(Gtk.Box):
) -> None: ) -> None:
super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
self.callback: Callable self.callback: Callable[[], None]
self.controller = controller self.controller = controller
self.context = context self.context = context
@@ -139,7 +139,7 @@ class SubmitField(Gtk.Box):
return return
self.save_option() self.save_option()
def set_callback(self, callback: Callable) -> None: def set_callback(self, callback: Callable[[], None]) -> None:
self.callback = callback self.callback = callback
def save_option(self) -> None: def save_option(self) -> None:
@@ -206,7 +206,7 @@ class NameSubmitField(SubmitField):
Preferences.NAME, Preferences.NAME,
private=False, private=False,
) )
self.entry.set_width_chars(30) # type: ignore self.entry.set_width_chars(30)
self.set_callback(self.save_player_name) self.set_callback(self.save_player_name)
def save_player_name(self) -> None: def save_player_name(self) -> None:
@@ -402,7 +402,8 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
def _on_link_button_clicked(self, button: Gtk.Button, url: str) -> None: def _on_link_button_clicked(self, button: Gtk.Button, url: str) -> None:
open_links.open_link_by_url(url) open_links.open_link_by_url(url)
def _make_grid(self, rows: list) -> Gtk.Grid: # TODO: use FlowBox
def _make_grid(self, rows: list[list[Any]]) -> Gtk.Grid:
grid = Gtk.Grid( grid = Gtk.Grid(
orientation=Gtk.Orientation.VERTICAL, orientation=Gtk.Orientation.VERTICAL,
column_spacing=10, column_spacing=10,
@@ -435,7 +436,7 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
if prefs.paths.config.is_file() is False: if prefs.paths.config.is_file() is False:
dialog = ExceptionDialog(self.controller, strings.config_not_found) dialog = ExceptionDialog(self.controller, strings.config_not_found)
dialog.show_all() dialog.show_all()
dialog.run() dialog.run() # type: ignore[no-untyped-call]
raise OSError(f"Config file '{prefs.paths.config}' not found") raise OSError(f"Config file '{prefs.paths.config}' not found")
config = query.get_config(prefs.paths.config) config = query.get_config(prefs.paths.config)
+2 -2
View File
@@ -18,7 +18,7 @@ from dzgui.views.trees.tree_server_mods import ServerModTreeView
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gdk, Gtk # noqa E402 from gi.repository import Gdk, Gtk
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -231,7 +231,7 @@ class PreConnectionAssistant(Gtk.Box):
args = self.controller.get_debug_args() args = self.controller.get_debug_args()
d = DebugDialog(self.controller, args) d = DebugDialog(self.controller, args)
d.show_all() d.show_all()
d.run() d.run() # type: ignore[no-untyped-call]
def _on_ok_clicked(self, button: Gtk.Button) -> None: def _on_ok_clicked(self, button: Gtk.Button) -> None:
self.controller.update_and_connect() self.controller.update_and_connect()
+3 -3
View File
@@ -5,12 +5,13 @@ from typing import Self, TYPE_CHECKING
from dzgui.const.constants import APP_NAME from dzgui.const.constants import APP_NAME
from dzgui.const.enum import ContextMenuGroup, ServerTab from dzgui.const.enum import ContextMenuGroup, ServerTab
from dzgui.views.trees.tree_servers import ServerTreeView from dzgui.views.trees.tree_servers import ServerTreeView
from dzgui.strings.generic import tab_changed_label
from dzgui.util.strings import server_labels from dzgui.util.strings import server_labels
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib # noqa E402 from gi.repository import Gtk, Gdk
logger = logging.getLogger(APP_NAME) logger = logging.getLogger(APP_NAME)
@@ -147,8 +148,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
label = self.notebook.get_tab_label_text(child) label = self.notebook.get_tab_label_text(child)
if label is not None: if label is not None:
# TODO: strings text = label.strip(tab_changed_label)
text = label.strip("*")
self.notebook.set_tab_label_text(child, text) self.notebook.set_tab_label_text(child, text)
tree = child.get_tree() tree = child.get_tree()
+1 -1
View File
@@ -8,7 +8,7 @@ from dzgui.views.mixins.scrollable_mixin import ScrollableMixin
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
# TODO: wrap and center long values # TODO: wrap and center long values
if TYPE_CHECKING: if TYPE_CHECKING:
+9 -25
View File
@@ -79,11 +79,6 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
index = path.get_indices()[0] index = path.get_indices()[0]
return index return index
def get_selected_records(self) -> list:
sel = self.get_selection()
model, rows = sel.get_selected_rows()
return [model[row] for row in rows]
def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> bool: def _on_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> bool:
from dzgui.views.trees.tree_servers import ServerTreeView from dzgui.views.trees.tree_servers import ServerTreeView
@@ -145,9 +140,11 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
self.set_cursor(path) self.set_cursor(path)
def get_value_at_index(self, index: int) -> Any: def get_value_at_index(self, index: int) -> Any:
(model, pathlist) = self.get_model_and_pathlist() model, pathlist = self.get_model_and_pathlist()
if len(pathlist) < 1: if len(pathlist) < 1:
return "" return ""
if model is None:
return ""
path = pathlist[0] path = pathlist[0]
tree_iter = model.get_iter(path) tree_iter = model.get_iter(path)
value = model.get_value(tree_iter, index) value = model.get_value(tree_iter, index)
@@ -161,20 +158,16 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
sel = self.get_selection() sel = self.get_selection()
self._on_tree_selection_changed(sel) self._on_tree_selection_changed(sel)
def get_model_and_pathlist(self) -> tuple: def get_model_and_pathlist(
self,
) -> tuple[Gtk.TreeModel | None, list[Gtk.TreePath]]:
select = self.get_selection() select = self.get_selection()
sels = select.get_selected_rows() sels = select.get_selected_rows()
(model, pathlist) = sels model: Gtk.TreeModel | None
pathlist: list[Gtk.TreePath]
model, pathlist = sels
return (model, pathlist) return (model, pathlist)
# @deprecated("Currently unused")
# def get_mpath(self) -> Optional[Gtk.TreePath]:
# (model, pathlist) = self.get_model_and_pathlist()
# if len(pathlist) < 1:
# return None
# path = pathlist[0]
# return path
def _on_row_activated( def _on_row_activated(
self, self,
treeview: Gtk.TreeView, treeview: Gtk.TreeView,
@@ -189,15 +182,6 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
return True return True
return False return False
# @deprecated("unused")
# def get_selected_row(self) -> Optional[Gtk.TreeModelRow]:
# ind = self.get_selected_row_index()
# model = self.get_model()
# if model is None:
# return None
# row = model[ind]
# return row
def get_col_value_by_path_index(self, path: Gtk.TreePath, index: int) -> Any: def get_col_value_by_path_index(self, path: Gtk.TreePath, index: int) -> Any:
model = self.get_model() model = self.get_model()
if model is None: if model is None:
+1 -1
View File
@@ -12,7 +12,7 @@ from dzgui.views.mixins.context_mixin import ContextMixin
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 from gi.repository import Gtk, Gdk
if TYPE_CHECKING: if TYPE_CHECKING:
from pathlib import Path from pathlib import Path
+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)
+6 -5
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
@@ -32,6 +32,7 @@ if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
from dzgui.controllers.emitter import Emitter from dzgui.controllers.emitter import Emitter
from dzgui.model.model_factory import FastInsertListStore from dzgui.model.model_factory import FastInsertListStore
from dzgui.util.dist import Haversine
QUEUE_CHECK_DELAY = 200 QUEUE_CHECK_DELAY = 200
@@ -64,7 +65,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore
self.queue_id: int self.queue_id: int
self.handler_id: int self.handler_id: int
self.queue: Queue = Queue() self.queue: Queue[tuple[str, "Haversine" | None, ServerTab]] = Queue()
self.seen_cache: list[Record] = [] self.seen_cache: list[Record] = []
@@ -250,9 +251,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:
@@ -406,7 +407,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore
path = model.get_path(it) path = model.get_path(it)
row_index = path.get_indices()[0] row_index = path.get_indices()[0]
try: try:
start, end = self.get_visible_range() start, end = self.get_visible_range() # type: ignore[no-untyped-call]
except Exception: except Exception:
return return
if row_index >= start[0] <= end[0]: if row_index >= start[0] <= end[0]:
+2 -1
View File
@@ -78,6 +78,7 @@ line-length = 88
indent-width = 4 indent-width = 4
extend-exclude = ["*lib/a2s"] extend-exclude = ["*lib/a2s"]
lint.unfixable = ["F401", "I001"] lint.unfixable = ["F401", "I001"]
lint.ignore = ["E402"]
[tool.ruff.format] [tool.ruff.format]
quote-style = "double" quote-style = "double"
@@ -104,7 +105,7 @@ python-a2s = { path = "./dzgui/lib/a2s", editable = true }
dayzquery = { path = "./dzgui/lib/dayzquery", editable = true } dayzquery = { path = "./dzgui/lib/dayzquery", editable = true }
[tool.uv] [tool.uv]
config-settings-package = { pygobject-stubs = { config = "Gtk3,Gdk3,Soup2" } } config-settings-package = { pygobject-stubs = { config = "Gtk3,Gdk3" } }
[tool.pytest.ini_options] [tool.pytest.ini_options]
markers = [ markers = [
-38
View File
@@ -1,38 +0,0 @@
from pathlib import Path
def iterate(search_str: str) -> None:
# TODO: exclude files from .gitignore
print()
print(f"Searching for '{search_str}'")
print()
files = Path(".").rglob("*")
ignore = [
"scripts/",
".git",
"egg",
"CHANGELOG",
".mypy",
"build/",
"test.py",
"bugs",
"pyproject.toml",
]
for file in files:
if file.is_dir():
continue
if any(s in str(file) for s in ignore):
continue
try:
text = file.read_text()
if search_str in text:
c = text.count(search_str)
if 0 < c < 2:
print(file, c)
except Exception:
continue
imports = ["Pango", "GObject", "GLib", "Gdk", "Gtk"]
for i in imports:
iterate(i)
+1 -1
View File
@@ -6,7 +6,7 @@ from dzgui.views.dialogs.servers import ServerDetailsDialog
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 from gi.repository import Gtk
class MockController: class MockController:
+1 -1
View File
@@ -16,7 +16,7 @@ from dzgui.api.steam import is_dayz_downloading
(["state_221100_1111"], False), (["state_221100_1111"], False),
], ],
) )
def test_dayz_patch_pending(monkeypatch, file_list, expect) -> None: def test_dayz_patch_pending(monkeypatch, file_list: list[str], expect: bool) -> None:
def mock_get_pending_downloads(steam_path: Path, appid: int) -> None: def mock_get_pending_downloads(steam_path: Path, appid: int) -> None:
files = [Path(file) for file in file_list] files = [Path(file) for file in file_list]
return files return files