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:
+36
-5
@@ -15,6 +15,7 @@ import json
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -348,6 +349,22 @@ class PlotTab(QWidget):
|
|||||||
main_layout.setContentsMargins(4, 4, 4, 4)
|
main_layout.setContentsMargins(4, 4, 4, 4)
|
||||||
main_layout.setSpacing(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 ──────────────────────────────────────────────────────────────
|
# ── data ──────────────────────────────────────────────────────────────
|
||||||
self._traces: list[list[str]] = [[] for _ in range(self.NUM_PLOTS)]
|
self._traces: list[list[str]] = [[] for _ in range(self.NUM_PLOTS)]
|
||||||
self._saved_traces: list[list[str]] = self._load_settings()
|
self._saved_traces: list[list[str]] = self._load_settings()
|
||||||
@@ -540,9 +557,10 @@ class PlotTab(QWidget):
|
|||||||
def _save_settings(self):
|
def _save_settings(self):
|
||||||
try:
|
try:
|
||||||
_SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
_SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||||
_SETTINGS_PATH.write_text(
|
_SETTINGS_PATH.write_text(json.dumps({
|
||||||
json.dumps({"traces": [list(t) for t in self._traces]}, indent=2)
|
"traces": [list(t) for t in self._traces],
|
||||||
)
|
"time_window": self._tw_spin.value(),
|
||||||
|
}, indent=2))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -552,13 +570,24 @@ class PlotTab(QWidget):
|
|||||||
saved = data.get("traces", [])
|
saved = data.get("traces", [])
|
||||||
while len(saved) < self.NUM_PLOTS:
|
while len(saved) < self.NUM_PLOTS:
|
||||||
saved.append([])
|
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]]
|
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)]
|
return [[] for _ in range(self.NUM_PLOTS)]
|
||||||
|
|
||||||
# ── drawing ───────────────────────────────────────────────────────────────
|
# ── drawing ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def _on_time_window_changed(self):
|
||||||
|
self._save_settings()
|
||||||
|
self._redraw()
|
||||||
|
|
||||||
def _redraw(self):
|
def _redraw(self):
|
||||||
|
now = time.time()
|
||||||
|
cutoff = now - self._tw_spin.value() * 3600
|
||||||
|
|
||||||
for i, pw in enumerate(self._plot_widgets):
|
for i, pw in enumerate(self._plot_widgets):
|
||||||
pi = pw.getPlotItem()
|
pi = pw.getPlotItem()
|
||||||
pi.clear()
|
pi.clear()
|
||||||
@@ -569,7 +598,7 @@ class PlotTab(QWidget):
|
|||||||
for j, key in enumerate(self._traces[i]):
|
for j, key in enumerate(self._traces[i]):
|
||||||
if key not in self._series:
|
if key not in self._series:
|
||||||
continue
|
continue
|
||||||
series = self._series[key]
|
series = [(t, v) for t, v in self._series[key] if t >= cutoff]
|
||||||
if not series:
|
if not series:
|
||||||
continue
|
continue
|
||||||
times, values = zip(*series)
|
times, values = zip(*series)
|
||||||
@@ -580,6 +609,8 @@ class PlotTab(QWidget):
|
|||||||
name=label,
|
name=label,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pw.setXRange(cutoff, now, padding=0.02)
|
||||||
|
|
||||||
# ── cursor tracing ────────────────────────────────────────────────────────
|
# ── cursor tracing ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def _on_mouse_move(self, evt, plot_idx: int):
|
def _on_mouse_move(self, evt, plot_idx: int):
|
||||||
|
|||||||
Reference in New Issue
Block a user