Add global time window control to Plot tab (1–24 h)
A spinbox above the plot grid sets the visible x range for all 8 plots. Data outside the window is excluded from each redraw; x axis is fixed to [now - window, now]. Setting is persisted in plot_settings.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+38
-7
@@ -15,6 +15,7 @@ import json
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from collections import deque
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
@@ -348,6 +349,22 @@ class PlotTab(QWidget):
|
||||
main_layout.setContentsMargins(4, 4, 4, 4)
|
||||
main_layout.setSpacing(4)
|
||||
|
||||
# ── toolbar ───────────────────────────────────────────────────────────
|
||||
tb = QWidget()
|
||||
tb.setMaximumHeight(32)
|
||||
tb_row = QHBoxLayout(tb)
|
||||
tb_row.setContentsMargins(0, 0, 0, 0)
|
||||
tb_row.setSpacing(6)
|
||||
tb_row.addWidget(QLabel("Time window:"))
|
||||
self._tw_spin = QSpinBox()
|
||||
self._tw_spin.setRange(1, 24)
|
||||
self._tw_spin.setSuffix(" h")
|
||||
self._tw_spin.setFixedWidth(72)
|
||||
self._tw_spin.valueChanged.connect(self._on_time_window_changed)
|
||||
tb_row.addWidget(self._tw_spin)
|
||||
tb_row.addStretch()
|
||||
main_layout.addWidget(tb)
|
||||
|
||||
# ── data ──────────────────────────────────────────────────────────────
|
||||
self._traces: list[list[str]] = [[] for _ in range(self.NUM_PLOTS)]
|
||||
self._saved_traces: list[list[str]] = self._load_settings()
|
||||
@@ -540,25 +557,37 @@ class PlotTab(QWidget):
|
||||
def _save_settings(self):
|
||||
try:
|
||||
_SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
_SETTINGS_PATH.write_text(
|
||||
json.dumps({"traces": [list(t) for t in self._traces]}, indent=2)
|
||||
)
|
||||
_SETTINGS_PATH.write_text(json.dumps({
|
||||
"traces": [list(t) for t in self._traces],
|
||||
"time_window": self._tw_spin.value(),
|
||||
}, indent=2))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _load_settings(self) -> list[list[str]]:
|
||||
try:
|
||||
data = json.loads(_SETTINGS_PATH.read_text())
|
||||
saved = data.get("traces", [])
|
||||
data = json.loads(_SETTINGS_PATH.read_text())
|
||||
saved = data.get("traces", [])
|
||||
while len(saved) < self.NUM_PLOTS:
|
||||
saved.append([])
|
||||
tw = int(data.get("time_window", 1))
|
||||
self._tw_spin.blockSignals(True)
|
||||
self._tw_spin.setValue(max(1, min(24, tw)))
|
||||
self._tw_spin.blockSignals(False)
|
||||
return [list(t) for t in saved[: self.NUM_PLOTS]]
|
||||
except (OSError, json.JSONDecodeError, KeyError):
|
||||
except (OSError, json.JSONDecodeError, KeyError, AttributeError):
|
||||
return [[] for _ in range(self.NUM_PLOTS)]
|
||||
|
||||
# ── drawing ───────────────────────────────────────────────────────────────
|
||||
|
||||
def _on_time_window_changed(self):
|
||||
self._save_settings()
|
||||
self._redraw()
|
||||
|
||||
def _redraw(self):
|
||||
now = time.time()
|
||||
cutoff = now - self._tw_spin.value() * 3600
|
||||
|
||||
for i, pw in enumerate(self._plot_widgets):
|
||||
pi = pw.getPlotItem()
|
||||
pi.clear()
|
||||
@@ -569,7 +598,7 @@ class PlotTab(QWidget):
|
||||
for j, key in enumerate(self._traces[i]):
|
||||
if key not in self._series:
|
||||
continue
|
||||
series = self._series[key]
|
||||
series = [(t, v) for t, v in self._series[key] if t >= cutoff]
|
||||
if not series:
|
||||
continue
|
||||
times, values = zip(*series)
|
||||
@@ -580,6 +609,8 @@ class PlotTab(QWidget):
|
||||
name=label,
|
||||
)
|
||||
|
||||
pw.setXRange(cutoff, now, padding=0.02)
|
||||
|
||||
# ── cursor tracing ────────────────────────────────────────────────────────
|
||||
|
||||
def _on_mouse_move(self, evt, plot_idx: int):
|
||||
|
||||
Reference in New Issue
Block a user