diff --git a/dzgui/init/migrate.py b/dzgui/init/migrate.py index 9414b4c..97c5587 100644 --- a/dzgui/init/migrate.py +++ b/dzgui/init/migrate.py @@ -1,6 +1,7 @@ import shutil from pathlib import Path +from typing import Any from dzgui.const.constants import LEGACY_CONFIG_PATH, LEGACY_COLS_PATH, LEGACY_IPS_PATH from dzgui.config.convert import rc2json from dzgui.util._json import read_json, write_json @@ -17,7 +18,7 @@ def has_new_config(config: Path) -> bool: return config.exists() -def convert_cols_file(res: Path) -> dict[str, int] | None: +def convert_cols_file(res: Path) -> Any | None: j = read_json(res) cols = j["cols"] # NOTE: implies prior conversion diff --git a/dzgui/main.py b/dzgui/main.py index 9ca1018..c5d74d4 100644 --- a/dzgui/main.py +++ b/dzgui/main.py @@ -121,8 +121,6 @@ def main() -> None: with open(XDG.debug, "w") as f: f.truncate(0) - latest_release = check_updates(version) - if _is_steam_deck is False: # TODO: sudo escalation dialog # count = get_map_count() @@ -130,16 +128,22 @@ def main() -> None: if has_steam_client() is False: EarlyAlertDialog(init.requires_steam) + is_dayz_installed(XDG.config) + + # TODO: slow running procs here--needs dialog # NOTE: clears versions file of unlinked mods rebuild_symlinks(XDG.config) remove_stale_signatures(XDG.config, XDG.version) - is_dayz_installed(XDG.config) # TODO: handle IP DB failure and use coords fallback + # TODO: drop this after dialog is complete + print("Fetching geolocation data, may take some time...") get_ipdb(XDG.ips) local_coords = get_local_coords(XDG.ips) use_miles = lookup(XDG.config, Preferences.DIST) + latest_release = check_updates(version) + prefs = UserPrefs( is_steam_deck=_is_steam_deck, is_game_mode=_is_game_mode, diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 43e2293..a03992d 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -161,7 +161,7 @@ class ConnectionManager: if len(self.missing_mods) > 0: required_size = sum(row[2] for row in self.missing_mods) required_mib = format_mib(required_size) - free_mib = format_mib(required_size) + free_mib = format_mib(free) dayz_running = is_dayz_running() @@ -222,7 +222,8 @@ class ConnectionManager: def query_modlist_and_present(self, record: Servers.Record) -> None: try: mods = self._query_modlist(record) - except Exception: + except Exception as e: + print(f"{type(e).__name__}: {e}") self.thread_man.set_cleanup_func( StoredFunc(self._server_timeout), destroy_first=True ) @@ -279,8 +280,13 @@ class ConnectionManager: for title, mod, stamp, size in self.missing_mods: # TODO: check cancel and exit events + if self.controller.get_exit_event().is_set(): + return + if self.controller.get_cancel_event().is_set(): + self.controller.clear_cancel_event() + return enqueue_mod(mod, self.appid) - time.sleep(2) + time.sleep(3) if raise_window is True: logger.info("Bringing window to foreground") diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index db9cac7..ad75b15 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -324,6 +324,7 @@ class ServerModelManager: self.thread_man.set_cleanup_func(func) return config_man.add_saved_server(fqip) + # FIXME: this is valid if saved servers tab is already open, # but not if app was just booted; causes single row to appear prematurely if proxy_man.has_control_model() is False: @@ -374,7 +375,8 @@ class ServerModelManager: proxy = self._get_proxy_man().get_proxy_model() self.tv.set_model(proxy) - self.emitter.emit("servers_loaded", self.enum) + if self.controller.get_active_treeview().get_enum == ServerTab.SAVED: + self.emitter.emit("servers_loaded", self.enum) filter_man = self.tv.get_filter_man() # NOTE: maps are set outside of thread because it triggers map changed signals diff --git a/dzgui/util/_json.py b/dzgui/util/_json.py index 58faa93..cad0263 100644 --- a/dzgui/util/_json.py +++ b/dzgui/util/_json.py @@ -12,7 +12,7 @@ def read_json(path: Path) -> Any: raise e -def write_json(data: dict, path: Path) -> None: +def write_json(data: dict[str, Any], path: Path) -> None: try: j = json.dumps(data, indent=2) path.write_text(j) diff --git a/dzgui/util/symlink.py b/dzgui/util/symlink.py index ad96e0a..50253b8 100644 --- a/dzgui/util/symlink.py +++ b/dzgui/util/symlink.py @@ -43,11 +43,14 @@ def clone_symlinks(steam_path: Path) -> None: # TODO: test these two operations # use less time intensive logic like the above - for file in exp_path.iterdir(): - if file.is_symlink(): - file.unlink() + try: + for file in exp_path.iterdir(): + if file.is_symlink(): + file.unlink() - for file in dayz_path.iterdir(): - if file.is_symlink(): - uid = file.name - Path(exp_path / uid).symlink_to(dayz_path / uid) + for file in dayz_path.iterdir(): + if file.is_symlink(): + uid = file.name + Path(exp_path / uid).symlink_to(dayz_path / uid) + except Exception as e: + logger.critical(e) diff --git a/dzgui/views/components/scrollable.py b/dzgui/views/components/scrollable.py new file mode 100644 index 0000000..294ca53 --- /dev/null +++ b/dzgui/views/components/scrollable.py @@ -0,0 +1,9 @@ +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk # noqa + + +class NoOverlayScrolledWindow(Gtk.ScrolledWindow): + def __init__(self) -> None: + super().__init__(overlay_scrolling=False) diff --git a/dzgui/views/dialogs/early_alert.py b/dzgui/views/dialogs/early_alert.py index a404a32..1f911c7 100644 --- a/dzgui/views/dialogs/early_alert.py +++ b/dzgui/views/dialogs/early_alert.py @@ -53,3 +53,5 @@ class EarlyIgnoreDialog(EarlyAlertDialog): # TODO: reverse order self.add_button("Ignore", Gtk.ResponseType.CANCEL) + + # TODO: if exit, sys.exit(1), else pass diff --git a/dzgui/views/pages/log.py b/dzgui/views/pages/log.py index b9fbc3b..a9e1bd5 100644 --- a/dzgui/views/pages/log.py +++ b/dzgui/views/pages/log.py @@ -1,5 +1,6 @@ from typing import TYPE_CHECKING from dzgui.const.constants import LOG_FILTERS +from dzgui.views.components.scrollable import NoOverlayScrolledWindow from dzgui.views.mixins.cursor_mixin import CursorMixin from dzgui.views.mixins.help_menu_mixin import HelpMenuMixin from dzgui.views.trees.tree_log import LogTreeView @@ -21,7 +22,7 @@ class Log(CursorMixin, HelpMenuMixin, Gtk.Box): # type: ignore NOTE: LogTreeView is kept in a separate ScrolledWindow so that checkboxes will be flush on bottom """ - self.scrolled = Gtk.ScrolledWindow() + self.scrolled = NoOverlayScrolledWindow() self.treeview = LogTreeView(controller) self.scrolled.add(self.treeview) diff --git a/dzgui/views/pages/mods.py b/dzgui/views/pages/mods.py index 89509d6..f87d993 100644 --- a/dzgui/views/pages/mods.py +++ b/dzgui/views/pages/mods.py @@ -1,4 +1,5 @@ from typing import Self, TYPE_CHECKING +from dzgui.views.components.scrollable import NoOverlayScrolledWindow from dzgui.views.trees.tree_mods import ModTreeView import gi @@ -10,7 +11,8 @@ if TYPE_CHECKING: from dzgui.controllers.mc import Controller -class Mods(Gtk.ScrolledWindow): + +class Mods(NoOverlayScrolledWindow): def __init__(self, controller: "Controller") -> None: super().__init__() diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index 2d12413..651dfe5 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -162,19 +162,6 @@ class ServerNotebook(Gtk.ScrolledWindow): return tv raise ValueError("No treeview set") - def add_notification(self) -> None: - saved = self.notebook.get_nth_page(1) - if saved is None: - return - text = self.notebook.get_tab_label_text(saved) - if text is None: - return - # TODO: strings - if "*" in text: - return - text += "*" - self.notebook.set_tab_label_text(saved, text) - def update_tab_widths(self, col: Gtk.TreeViewColumn) -> None: # TODO: may cause pixel offsets when application is maximized width = col.get_width() diff --git a/pyproject.toml b/pyproject.toml index 5f81c07..63badb5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux" authors = [ {name = "aclist"} ] -version = "7.0.0b5" +version = "7.0.0b6" license = "GPL-3.0-or-later" license-files = ["LICENSE"] readme = "README.md"