|
16 | 16 | import os |
17 | 17 | from typing import TypeVar, cast |
18 | 18 |
|
19 | | -from PySide6.QtCore import QDir, QFile, QModelIndex, Qt |
| 19 | +from PySide6.QtCore import QDir, QFile, QModelIndex, QSettings, Qt |
20 | 20 | from PySide6.QtGui import QAction, QKeySequence, QShortcut |
21 | 21 | from PySide6.QtUiTools import QUiLoader |
22 | 22 | from PySide6.QtWidgets import ( |
|
30 | 30 | QMessageBox, |
31 | 31 | QPlainTextEdit, |
32 | 32 | QPushButton, |
| 33 | + QSplitter, |
33 | 34 | QTabWidget, |
34 | 35 | QTreeView, |
35 | 36 | ) |
@@ -76,6 +77,10 @@ def __init__(self, viewmodel: MainViewModel) -> None: |
76 | 77 | self._load_ui() |
77 | 78 | self._setup_file_tree() |
78 | 79 | self._connect_signals() |
| 80 | + self._load_settings() |
| 81 | + app = QApplication.instance() |
| 82 | + if app is not None: |
| 83 | + app.aboutToQuit.connect(self._save_settings) |
79 | 84 |
|
80 | 85 | def show(self) -> None: |
81 | 86 | """Show the main application window.""" |
@@ -181,6 +186,13 @@ def _load_ui(self) -> None: |
181 | 186 | self._cursor_label = QLabel("Ln 1, Col 1 | 0 chars") |
182 | 187 | self.ui.statusBar().addPermanentWidget(self._cursor_label) |
183 | 188 |
|
| 189 | + self._main_splitter = _require( |
| 190 | + self.ui.findChild(QSplitter, "mainSplitter"), "mainSplitter" |
| 191 | + ) |
| 192 | + self._left_splitter = _require( |
| 193 | + self.ui.findChild(QSplitter, "leftPanelSplitter"), "leftPanelSplitter" |
| 194 | + ) |
| 195 | + |
184 | 196 | def _setup_file_tree(self) -> None: |
185 | 197 | """Configure QFileSystemModel rooted at the user's home directory.""" |
186 | 198 | self._fs_model = QFileSystemModel(self.ui) |
@@ -411,6 +423,29 @@ def _update_cursor_label(self) -> None: |
411 | 423 | chars = self._plain_text_edit.document().characterCount() - 1 |
412 | 424 | self._cursor_label.setText(f"Ln {line}, Col {col} | {chars:,} chars") |
413 | 425 |
|
| 426 | + def _load_settings(self) -> None: |
| 427 | + """Restore window geometry and splitter positions from QSettings. |
| 428 | +
|
| 429 | + Silent no-op when no settings exist yet (first launch or cleared). |
| 430 | + """ |
| 431 | + settings = QSettings("TextTools", "TextTools") |
| 432 | + if geometry := settings.value("window/geometry"): |
| 433 | + self.ui.restoreGeometry(geometry) |
| 434 | + if main_state := settings.value("splitter/main"): |
| 435 | + self._main_splitter.restoreState(main_state) |
| 436 | + if left_state := settings.value("splitter/left"): |
| 437 | + self._left_splitter.restoreState(left_state) |
| 438 | + |
| 439 | + def _save_settings(self) -> None: |
| 440 | + """Save window geometry and splitter positions to QSettings. |
| 441 | +
|
| 442 | + Connected to QApplication.aboutToQuit in __init__. |
| 443 | + """ |
| 444 | + settings = QSettings("TextTools", "TextTools") |
| 445 | + settings.setValue("window/geometry", self.ui.saveGeometry()) |
| 446 | + settings.setValue("splitter/main", self._main_splitter.saveState()) |
| 447 | + settings.setValue("splitter/left", self._left_splitter.saveState()) |
| 448 | + |
414 | 449 | # ------------------------------------------ ViewModel signal handlers |
415 | 450 |
|
416 | 451 | def _on_document_loaded(self, content: str) -> None: |
|
0 commit comments