diff options
Diffstat (limited to 'ui/main_window.py')
| -rw-r--r-- | ui/main_window.py | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/ui/main_window.py b/ui/main_window.py index ba93121..6dae1be 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -12,9 +12,10 @@ from PyQt6.QtWidgets import ( QToolBar, QSizePolicy, QApplication, QFrame, QAbstractSpinBox, QComboBox, QMenu, ) -from PyQt6.QtCore import Qt, QTimer, QObject, QEvent, QRect, pyqtSignal, pyqtSlot +from PyQt6.QtCore import Qt, QTimer, QObject, QEvent, QRect, QByteArray, pyqtSignal, pyqtSlot from PyQt6.QtGui import QPainter, QColor, QFont, QAction import logging +import base64 import os @@ -116,6 +117,12 @@ _LIGHT_QSS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "style_lig class MainWindow(QMainWindow): + # Bump when dock/toolbar structure changes in a way that would make an + # old saved dock_state blob meaningless (e.g. a dock renamed/removed) — + # restoreState() rejects a mismatched version and just no-ops instead + # of applying garbage. + _DOCK_STATE_VERSION = 1 + def __init__(self): super().__init__() self.setWindowTitle("LabUI") @@ -622,6 +629,7 @@ class MainWindow(QMainWindow): def _profile_capture(self, name: str = "Profile") -> Profile: """Serialise current state into a Profile object.""" + self._capture_dock_state() return ProfileManager.capture( registry=self.registry, processor=self.processor, @@ -702,6 +710,7 @@ class MainWindow(QMainWindow): self._win_config.refresh_devices() self._win_config.refresh_derived() self._win_config.refresh_plot(self._chart._cfg) + QTimer.singleShot(0, self._apply_dock_state) self._status.setText(f"Profile loaded: {profile.name}") # ── Device / signal events ──────────────────────────────────────────── @@ -819,6 +828,31 @@ class MainWindow(QMainWindow): self._apply_theme(self._settings.get("theme", "dark")) self.engine._interval = self._settings.get("poll_ms", 100) / 1000.0 self._apply_developer_mode(self._settings.get("developer_mode", False)) + QTimer.singleShot(0, self._apply_dock_state) + + def _capture_dock_state(self): + """Snapshot Control Panel / Namespace dock area, floating geometry, + visibility, size and order via Qt's own QMainWindow.saveState() — + one call covers everything a QDockWidget can have moved, instead of + hand-tracking each attribute. Stored as base64 in self._settings, + which both app_settings.json (save_settings()) and .labui profiles + (Profile.settings — see ProfileManager.capture()) already round-trip + verbatim, so this needs no schema changes on either side, just + needs to run before whichever save happens.""" + raw = bytes(self.saveState(self._DOCK_STATE_VERSION)) + self._settings["dock_state"] = base64.b64encode(raw).decode("ascii") + + def _apply_dock_state(self): + """Restore saved dock state — deferred one event-loop tick (via + QTimer.singleShot(0, ...) at call sites) since restoreState() before + the main window's initial layout has settled doesn't stick, the + same reason splitter sizing elsewhere in this codebase (e.g. + plot_window.py's _init_split) defers similarly.""" + encoded = self._settings.get("dock_state") + if not encoded: + return + raw = QByteArray(base64.b64decode(encoded)) + self.restoreState(raw, self._DOCK_STATE_VERSION) def _apply_developer_mode(self, enabled: bool): level = logging.DEBUG if enabled else logging.WARNING |
