plot tab remembers now value, satellite, points

This commit is contained in:
2026-05-24 12:07:41 +02:00
parent 45ef58ea8d
commit d492e32a8b
2 changed files with 62 additions and 6 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ class PlotTab(QWidget):
frame.setFrameShadow(QFrame.Raised) frame.setFrameShadow(QFrame.Raised)
fl = QVBoxLayout(frame) fl = QVBoxLayout(frame)
fl.setContentsMargins(2, 2, 2, 2) fl.setContentsMargins(2, 2, 2, 2)
pw = SinglePlotWidget(model) pw = SinglePlotWidget(model, plot_index=i)
pw.setMinimumHeight(230) pw.setMinimumHeight(230)
fl.addWidget(pw) fl.addWidget(pw)
grid.addWidget(frame, i // 2, i % 2) grid.addWidget(frame, i // 2, i % 2)
+61 -5
View File
@@ -1,8 +1,24 @@
import sys, os, math, time import sys, os, math, time, json
from datetime import datetime from datetime import datetime
from queue import Queue, Empty from queue import Queue, Empty
from collections import deque from collections import deque
_SETTINGS_PATH = os.path.expanduser('~/.nmea_client_plots.json')
def _load_plot_settings() -> list:
try:
with open(_SETTINGS_PATH) as f:
return json.load(f).get('plots', [])
except Exception:
return []
def _save_plot_settings(settings: list):
try:
with open(_SETTINGS_PATH, 'w') as f:
json.dump({'plots': settings}, f, indent=2)
except Exception:
pass
_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) _root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_gui = os.path.dirname(os.path.abspath(__file__)) _gui = os.path.dirname(os.path.abspath(__file__))
for _p in [_root, _gui]: for _p in [_root, _gui]:
@@ -256,13 +272,16 @@ class _Canvas(QWidget):
# ── Single configurable plot ────────────────────────────────────────────────── # ── Single configurable plot ──────────────────────────────────────────────────
class SinglePlotWidget(QWidget): class SinglePlotWidget(QWidget):
def __init__(self, model: ReceiverManager): def __init__(self, model: ReceiverManager, plot_index: int = 0):
super().__init__() super().__init__()
self._model = model self._model = model
self._plot_index = plot_index
self._data: dict = {} # rid → [deque(ts), deque(val)] self._data: dict = {} # rid → [deque(ts), deque(val)]
self._known_sats: dict = {} # rid → set[sat_label] (selected only) self._known_sats: dict = {} # rid → set[sat_label] (selected only)
self._restore_sat = '' # persisted satellite, applied on first combo fill
self._build_ui() self._build_ui()
self._load_settings()
self._thread = PlotRenderThread() self._thread = PlotRenderThread()
self._thread.frame_ready.connect(self._canvas.set_image) self._thread.frame_ready.connect(self._canvas.set_image)
@@ -296,7 +315,7 @@ class SinglePlotWidget(QWidget):
bar.addWidget(QLabel("Satellit:")) bar.addWidget(QLabel("Satellit:"))
self._val_cb = QComboBox() self._val_cb = QComboBox()
self._val_cb.setMinimumWidth(90); self._val_cb.setMaximumWidth(120) self._val_cb.setMinimumWidth(90); self._val_cb.setMaximumWidth(120)
self._val_cb.currentTextChanged.connect(self._submit_render) self._val_cb.currentTextChanged.connect(self._on_sat_changed)
bar.addWidget(self._val_cb) bar.addWidget(self._val_cb)
bar.addWidget(QLabel("Quelle:")) bar.addWidget(QLabel("Quelle:"))
@@ -332,9 +351,39 @@ class SinglePlotWidget(QWidget):
result.append(it.data(Qt.UserRole)) result.append(it.data(Qt.UserRole))
return result return result
# ── Persistence ───────────────────────────────────────────────────────────
def _load_settings(self):
all_s = _load_plot_settings()
s = all_s[self._plot_index] if self._plot_index < len(all_s) else {}
if 'y_axis' in s:
self._y_cb.blockSignals(True)
self._y_cb.setCurrentText(s['y_axis'])
self._y_cb.blockSignals(False)
self._val_cb.setEnabled(s['y_axis'] != 'pDOP')
if 'history' in s:
self._hist_spin.blockSignals(True)
self._hist_spin.setValue(s['history'])
self._hist_spin.blockSignals(False)
if 'satellite' in s:
self._restore_sat = s['satellite']
def _save_settings(self):
all_s = _load_plot_settings()
while len(all_s) <= self._plot_index:
all_s.append({})
all_s[self._plot_index] = {
'y_axis': self._y_cb.currentText(),
'satellite': self._val_cb.currentText(),
'history': self._hist_spin.value(),
}
_save_plot_settings(all_s)
# ── Source helpers ────────────────────────────────────────────────────────
def _rebuild_val_combo(self): def _rebuild_val_combo(self):
selected = set(self._selected_rids()) selected = set(self._selected_rids())
current = self._val_cb.currentText() current = self._val_cb.currentText() or self._restore_sat
self._val_cb.blockSignals(True) self._val_cb.blockSignals(True)
self._val_cb.clear() self._val_cb.clear()
sats = set() sats = set()
@@ -344,6 +393,7 @@ class SinglePlotWidget(QWidget):
self._val_cb.addItem(s) self._val_cb.addItem(s)
if current in sats: if current in sats:
self._val_cb.setCurrentText(current) self._val_cb.setCurrentText(current)
self._restore_sat = ''
self._val_cb.blockSignals(False) self._val_cb.blockSignals(False)
# ── Render submission ───────────────────────────────────────────────────── # ── Render submission ─────────────────────────────────────────────────────
@@ -369,12 +419,17 @@ class SinglePlotWidget(QWidget):
# ── Config change handlers ──────────────────────────────────────────────── # ── Config change handlers ────────────────────────────────────────────────
def _on_sat_changed(self, _text: str):
self._save_settings()
self._submit_render()
def _on_y_changed(self, _text: str): def _on_y_changed(self, _text: str):
is_pdop = (_text == 'pDOP') is_pdop = (_text == 'pDOP')
self._val_cb.setEnabled(not is_pdop) self._val_cb.setEnabled(not is_pdop)
for rid in list(self._data): for rid in list(self._data):
n = self._hist_spin.value() n = self._hist_spin.value()
self._data[rid] = [deque(maxlen=n), deque(maxlen=n)] self._data[rid] = [deque(maxlen=n), deque(maxlen=n)]
self._save_settings()
self._submit_render() self._submit_render()
def _on_source_changed(self): def _on_source_changed(self):
@@ -385,6 +440,7 @@ class SinglePlotWidget(QWidget):
for rid in list(self._data): for rid in list(self._data):
old_ts, old_v = self._data[rid] old_ts, old_v = self._data[rid]
self._data[rid] = [deque(old_ts, maxlen=n), deque(old_v, maxlen=n)] self._data[rid] = [deque(old_ts, maxlen=n), deque(old_v, maxlen=n)]
self._save_settings()
self._submit_render() self._submit_render()
# ── Model signals ───────────────────────────────────────────────────────── # ── Model signals ─────────────────────────────────────────────────────────