From 72f9098a7095b97e1ed40593e1358fa589538110 Mon Sep 17 00:00:00 2001 From: oop7 <110548351+oop7@users.noreply.github.com> Date: Sun, 14 Jun 2026 20:19:40 +0300 Subject: [PATCH] Persist and restore main window state Restore window geometry/state on startup and save them on exit. Adds YTSageApp._load_window_state() and calls it during UI init; saves Base64-encoded geometry/state via ConfigManager when closing. Adds default config keys "window_geometry" and "window_state". Includes error handling and debug logging to avoid failures if stored values are invalid. --- ytsage/gui/ytsage_gui_main.py | 24 ++++++++++++++++++++++++ ytsage/utils/ytsage_config_manager.py | 2 ++ 2 files changed, 26 insertions(+) diff --git a/ytsage/gui/ytsage_gui_main.py b/ytsage/gui/ytsage_gui_main.py index 2263e6f..d25273b 100644 --- a/ytsage/gui/ytsage_gui_main.py +++ b/ytsage/gui/ytsage_gui_main.py @@ -272,6 +272,7 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin, AnalysisMixin): self.player.setAudioOutput(self.audio_output) self.init_ui() + self._load_window_state() # Defer heavy start-up tasks to ensure UI renders immediately QTimer.singleShot(100, self._perform_startup_checks) @@ -290,6 +291,22 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin, AnalysisMixin): # Initialize UI state based on current mode self.handle_mode_change() + def _load_window_state(self): + """Restore previous window geometry and state from config.""" + from PySide6.QtCore import QByteArray + geo_b64 = ConfigManager.get("window_geometry") + if geo_b64: + try: + self.restoreGeometry(QByteArray.fromBase64(geo_b64.encode("ascii"))) + except Exception as e: + logger.debug(f"Failed to restore geometry: {e}") + + state_b64 = ConfigManager.get("window_state") + if state_b64: + try: + self.restoreState(QByteArray.fromBase64(state_b64.encode("ascii"))) + except Exception as e: + logger.debug(f"Failed to restore state: {e}") def _perform_startup_checks(self): """Perform potentially blocking startup checks after UI is shown.""" @@ -1194,6 +1211,13 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin, AnalysisMixin): self.current_download.terminate() self.current_download.wait(1000) # Wait for termination + # Save the window size and state + try: + ConfigManager.set("window_geometry", self.saveGeometry().toBase64().data().decode("ascii")) + ConfigManager.set("window_state", self.saveState().toBase64().data().decode("ascii")) + except Exception as w_e: + logger.debug(f"Failed to save window state: {w_e}") + logger.info("Application closing...") event.accept() except Exception as e: diff --git a/ytsage/utils/ytsage_config_manager.py b/ytsage/utils/ytsage_config_manager.py index 3f73532..05e61d2 100644 --- a/ytsage/utils/ytsage_config_manager.py +++ b/ytsage/utils/ytsage_config_manager.py @@ -96,6 +96,8 @@ class ConfigManager: "preferred_audio_format": "best", "audio_normalization": False, "filename_format": "%(title)s_%(resolution)s_[%(id)s].%(ext)s", + "window_geometry": None, + "window_state": None, "cached_versions": { "ytdlp": {"version": None, "path": None, "last_check": 0, "path_mtime": 0}, "ffmpeg": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},