mirror of
https://github.com/aclist/dztui.git
synced 2026-11-11 04:20:39 +01:00
Merge pull request #534 from aclist/chore/strict-typehinting
chore: clear strict typehinting errors
This commit is contained in:
39 files changed
+131
-155
No files matched your search
+2
-1
@@ -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
-5
@@ -106,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"))
|
||||||
@@ -144,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 []
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
+2
-2
@@ -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"]
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -274,7 +274,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 +308,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,17 +355,17 @@ 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()
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -291,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}"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class ContextMenuManager:
|
|||||||
# UNTHREADED
|
# UNTHREADED
|
||||||
case ContextMenu.ADD_NOTE:
|
case ContextMenu.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 ContextMenu.COPY_SERVER_IP:
|
||||||
self.copy_server_ip()
|
self.copy_server_ip()
|
||||||
case ContextMenu.COPY_SERVER_NAME:
|
case ContextMenu.COPY_SERVER_NAME:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ 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)
|
||||||
|
|||||||
@@ -55,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]
|
||||||
@@ -11,7 +11,7 @@ from gi.repository.Gtk import ListStore, TreeIter
|
|||||||
from gi.repository import GObject
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
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
|
||||||
@@ -17,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
|
||||||
@@ -31,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]],
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
@@ -52,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:
|
||||||
@@ -68,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],
|
||||||
@@ -248,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))
|
||||||
@@ -259,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:
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -54,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:
|
||||||
@@ -67,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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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(".")]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
from typing import Callable, Literal, Self, TYPE_CHECKING, Union
|
from typing import Callable, Literal, Self, TYPE_CHECKING
|
||||||
|
|
||||||
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 (
|
||||||
@@ -64,7 +62,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:
|
||||||
@@ -108,7 +106,7 @@ class ClipboardButton(IconTextButton):
|
|||||||
|
|
||||||
self.set_tooltip_text(buttons.clipboard_button)
|
self.set_tooltip_text(buttons.clipboard_button)
|
||||||
|
|
||||||
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
|
||||||
@@ -119,10 +117,9 @@ 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)
|
||||||
|
|
||||||
self.set_tooltip_text(buttons.clipboard_ip_button)
|
self.set_tooltip_text(buttons.clipboard_ip_button)
|
||||||
|
|
||||||
@@ -249,30 +246,6 @@ class AddButton(IconTextButton):
|
|||||||
self.set_tooltip_text(connect_panel.add_tooltip)
|
self.set_tooltip_text(connect_panel.add_tooltip)
|
||||||
|
|
||||||
|
|
||||||
# TODO: drop
|
|
||||||
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__()
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ 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)
|
||||||
|
|
||||||
self.unset_button = CloseButton(unset_button_label)
|
self.unset_button = CloseButton(unset_button_label)
|
||||||
self.unset_button.connect("clicked", self._on_unset_clicked)
|
self.unset_button.connect("clicked", self._on_unset_clicked)
|
||||||
|
|||||||
@@ -39,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:
|
||||||
@@ -47,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
|
||||||
|
|
||||||
@@ -73,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:
|
||||||
@@ -142,7 +141,7 @@ 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
|
||||||
|
|
||||||
self.entry = Gtk.Entry(
|
self.entry = Gtk.Entry(
|
||||||
width_chars=60, hexpand=True, placeholder_text=api_placeholder
|
width_chars=60, hexpand=True, placeholder_text=api_placeholder
|
||||||
@@ -221,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:
|
||||||
|
|||||||
@@ -31,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__(
|
||||||
@@ -97,7 +97,7 @@ 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
|
||||||
|
|
||||||
|
|
||||||
@@ -306,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
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ 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
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -185,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)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ 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():
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ logger = logging.getLogger(APP_NAME)
|
|||||||
|
|
||||||
|
|
||||||
class ContextMixin(TreeView):
|
class ContextMixin(TreeView):
|
||||||
def present_menu(
|
def present_menu(self, widget: Gtk.Widget, event: Gdk.Event) -> bool:
|
||||||
self, widget: Gtk.Widget, event: Gdk.Event
|
|
||||||
) -> bool:
|
|
||||||
|
|
||||||
if self.menu is None:
|
if self.menu is None:
|
||||||
return False
|
return False
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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,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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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] = []
|
||||||
|
|
||||||
@@ -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]:
|
||||||
|
|||||||
+1
-1
@@ -105,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 = [
|
||||||
|
|||||||
Reference in new issue
Block a user