Problem
PR #82 introduced user_config.py, which dumps a .dashpva_data.json file into the repository root to persist dock layout and window geometry. This has several problems:
- Dirties the git working tree
- Breaks with multiple users sharing one install
- Reimplements what PyQt's native
QSettings already provides
Scope — Tier 2: Machine-Local Layout Only
This issue covers physical/machine-specific UI state that should NOT travel in TOML exports. Semantic viewer preferences (colormap, autoscale, etc.) are handled by #77 via ConfigSource.
Decision rule
"Would I want this setting to travel with my TOML config to another machine?"
What to persist (Tier 2)
| Key |
QSettings path |
Current location |
| Window geometry |
geometry |
user_config.py → JSON |
| Dock layout (saveState) |
dock_state |
user_config.py → JSON |
| Dock state version |
dock_state_version |
Hard-coded constant |
| Last-typed PV prefix |
last_prefix |
user_config.py → JSON |
| Splitter positions |
splitter_sizes |
Not persisted |
| Last file browser dirs |
last_poni_dir, last_cif_dir |
settings.py globals (reset on restart) |
Why these do NOT belong in ConfigSource/TOML:
- Window geometry saved on a 32" 4K monitor would spawn off-screen on a 13" laptop
- Dock layout depends on monitor arrangement and window size
- Last-typed prefix is convenience state for one user on one machine
Implementation
Add to BaseWindow (so all viewers get it for free)
# base_window.py
from PyQt5.QtCore import QSettings
def _qsettings(self) -> QSettings:
"""Return a QSettings scoped to this viewer type."""
viewer_key = type(self).__name__
return QSettings("DashPVA", viewer_key)
def save_layout(self) -> None:
s = self._qsettings()
s.setValue("geometry", self.saveGeometry())
s.setValue("dock_state", self.saveState())
def restore_layout(self) -> None:
s = self._qsettings()
geom = s.value("geometry")
if geom:
self.restoreGeometry(geom)
state = s.value("dock_state")
if state:
self.restoreState(state)
Wire into BaseWindow.closeEvent()
def closeEvent(self, event):
self.save_layout()
event.accept()
Area detector viewer changes
- Replace
from dashpva.utils.user_config import load_last, save_last with self._qsettings()
- Call
self.restore_layout() in __init__ after docks are created
- Call
self.save_layout() in closeEvent
- Last-typed prefix:
self._qsettings().setValue("last_prefix", prefix)
Storage locations (automatic, no custom code)
- macOS:
~/Library/Preferences/com.dashpva.DiffractionImageWindow.plist
- Linux:
~/.config/DashPVA/DiffractionImageWindow.conf
Delete
Acceptance criteria
Related
Problem
PR #82 introduced
user_config.py, which dumps a.dashpva_data.jsonfile into the repository root to persist dock layout and window geometry. This has several problems:QSettingsalready providesScope — Tier 2: Machine-Local Layout Only
Decision rule
What to persist (Tier 2)
QSettingspathgeometryuser_config.py→ JSONdock_stateuser_config.py→ JSONdock_state_versionlast_prefixuser_config.py→ JSONsplitter_sizeslast_poni_dir,last_cif_dirsettings.pyglobals (reset on restart)Why these do NOT belong in ConfigSource/TOML:
Implementation
Add to
BaseWindow(so all viewers get it for free)Wire into
BaseWindow.closeEvent()Area detector viewer changes
from dashpva.utils.user_config import load_last, save_lastwithself._qsettings()self.restore_layout()in__init__after docks are createdself.save_layout()incloseEventself._qsettings().setValue("last_prefix", prefix)Storage locations (automatic, no custom code)
~/Library/Preferences/com.dashpva.DiffractionImageWindow.plist~/.config/DashPVA/DiffractionImageWindow.confDelete
src/dashpva/utils/user_config.py— replaced entirely byQSettings.dashpva_data.json— no longer generated; add to.gitignoreas safety netAcceptance criteria
save_layout()andrestore_layout()added toBaseWindowQSettingsinstead ofuser_config.pyuser_config.pyand.dashpva_data.jsonare deletedRelated
ConfigSourceuser_config.py(to be replaced by this issue)