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.
This commit is contained in:
@@ -272,6 +272,7 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin, AnalysisMixin):
|
|||||||
self.player.setAudioOutput(self.audio_output)
|
self.player.setAudioOutput(self.audio_output)
|
||||||
|
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
|
self._load_window_state()
|
||||||
|
|
||||||
# Defer heavy start-up tasks to ensure UI renders immediately
|
# Defer heavy start-up tasks to ensure UI renders immediately
|
||||||
QTimer.singleShot(100, self._perform_startup_checks)
|
QTimer.singleShot(100, self._perform_startup_checks)
|
||||||
@@ -290,6 +291,22 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin, AnalysisMixin):
|
|||||||
# Initialize UI state based on current mode
|
# Initialize UI state based on current mode
|
||||||
self.handle_mode_change()
|
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):
|
def _perform_startup_checks(self):
|
||||||
"""Perform potentially blocking startup checks after UI is shown."""
|
"""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.terminate()
|
||||||
self.current_download.wait(1000) # Wait for termination
|
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...")
|
logger.info("Application closing...")
|
||||||
event.accept()
|
event.accept()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ class ConfigManager:
|
|||||||
"preferred_audio_format": "best",
|
"preferred_audio_format": "best",
|
||||||
"audio_normalization": False,
|
"audio_normalization": False,
|
||||||
"filename_format": "%(title)s_%(resolution)s_[%(id)s].%(ext)s",
|
"filename_format": "%(title)s_%(resolution)s_[%(id)s].%(ext)s",
|
||||||
|
"window_geometry": None,
|
||||||
|
"window_state": None,
|
||||||
"cached_versions": {
|
"cached_versions": {
|
||||||
"ytdlp": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
|
"ytdlp": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
|
||||||
"ffmpeg": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
|
"ffmpeg": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
|
||||||
|
|||||||
Reference in New Issue
Block a user