Plot tab: auto-zoom Y axis on first draw after connect / trace change

Track a _needs_autozoom flag per plot. Set True at startup, on
reconnect (clear_data), and when a trace is added or removed. In
_redraw, when the flag is set and visible data exists, fit the Y range
to the data (with 10% margin) then clear the flag — subsequent live
updates leave the user's manual Y zoom undisturbed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 16:50:14 +02:00
co-authored by Claude Sonnet 4.6
parent 849473acc0
commit ad3cbf4859
+19 -7
View File
@@ -459,13 +459,14 @@ class PlotTab(QWidget):
for row in range(self.NUM_PLOTS // 2): for row in range(self.NUM_PLOTS // 2):
plot_grid.setRowMinimumHeight(row, 260) plot_grid.setRowMinimumHeight(row, 260)
self._plot_widgets: list[pg.PlotWidget] = [] self._plot_widgets: list[pg.PlotWidget] = []
self._vlines: list[pg.InfiniteLine] = [] self._vlines: list[pg.InfiniteLine] = []
self._proxies: list = [] self._proxies: list = []
self._add_combos: list[QComboBox] = [] self._add_combos: list[QComboBox] = []
self._chip_bars: list[QHBoxLayout] = [] self._chip_bars: list[QHBoxLayout] = []
self._date_labels: list[QLabel] = [] self._date_labels: list[QLabel] = []
self._tooltips: list[PlotTooltip] = [] self._tooltips: list[PlotTooltip] = []
self._needs_autozoom: list[bool] = [True] * self.NUM_PLOTS
for i in range(self.NUM_PLOTS): for i in range(self.NUM_PLOTS):
cell = QWidget() cell = QWidget()
@@ -563,6 +564,7 @@ class PlotTab(QWidget):
return return
traces.append(key) traces.append(key)
self._add_chip(plot_idx, key, len(traces) - 1) self._add_chip(plot_idx, key, len(traces) - 1)
self._needs_autozoom[plot_idx] = True
self._save_settings() self._save_settings()
self._redraw() self._redraw()
@@ -584,6 +586,7 @@ class PlotTab(QWidget):
return return
self._traces[plot_idx].remove(key) self._traces[plot_idx].remove(key)
self._rebuild_chips(plot_idx) self._rebuild_chips(plot_idx)
self._needs_autozoom[plot_idx] = True
self._save_settings() self._save_settings()
self._redraw() self._redraw()
@@ -604,6 +607,7 @@ class PlotTab(QWidget):
self._units.clear() self._units.clear()
for tt in self._tooltips: for tt in self._tooltips:
tt.hide() tt.hide()
self._needs_autozoom = [True] * self.NUM_PLOTS
self._redraw() self._redraw()
def update(self, snapshot: dict): def update(self, snapshot: dict):
@@ -702,6 +706,7 @@ class PlotTab(QWidget):
pi.legend.clear() pi.legend.clear()
x_min = None x_min = None
y_all: list[float] = []
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
@@ -710,6 +715,7 @@ class PlotTab(QWidget):
continue continue
times, values = zip(*series) times, values = zip(*series)
x_min = times[0] if x_min is None else min(x_min, times[0]) x_min = times[0] if x_min is None else min(x_min, times[0])
y_all.extend(values)
label = f"{_trace_label(key)} [{self._units.get(key, '')}]" label = f"{_trace_label(key)} [{self._units.get(key, '')}]"
pw.plot( pw.plot(
list(times), list(values), list(times), list(values),
@@ -720,6 +726,12 @@ class PlotTab(QWidget):
x_lo = x_min if x_min is not None else cutoff x_lo = x_min if x_min is not None else cutoff
pw.setXRange(x_lo, now, padding=0.02) pw.setXRange(x_lo, now, padding=0.02)
if y_all and self._needs_autozoom[i]:
y_min, y_max = min(y_all), max(y_all)
margin = max((y_max - y_min) * 0.1, 1.0)
pw.setYRange(y_min - margin, y_max + margin, padding=0)
self._needs_autozoom[i] = False
d_lo = datetime.fromtimestamp(x_lo).date() d_lo = datetime.fromtimestamp(x_lo).date()
d_hi = datetime.fromtimestamp(now).date() d_hi = datetime.fromtimestamp(now).date()
if d_lo == d_hi: if d_lo == d_hi: