docs: correct the sidebar spec, and plan its implementation

The spec claimed the math pane and the signal list were two lists of the same
channels; they are one. `append_math_signals_locked()` already puts every math
channel into `signals()` and nothing filters `sig.math`, so the merge is mostly
a deletion -- the list gains a `MATH` divider and a second menu, and the pane
goes. §2, §3 and §6 say so now.

The plan is seven tasks, each ending in a build, `make test-ui` and one short
headless probe read.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-14 10:48:21 +02:00
1 parent a519e13b67
commit e10a92fc52
2 files changed
+1470 -13

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -78,6 +78,10 @@ that they are appended to a page's box instead of to a revealer.
The two deleted toggles leave `src/ui/header-bar.ui` with their handlers, so the bar is The two deleted toggles leave `src/ui/header-bar.ui` with their handlers, so the bar is
declared with five controls and no id resolves to a button nothing listens to. declared with five controls and no id resolves to a button nothing listens to.
`update_side_visibility()` (`ui.cpp:2830-2850`) keeps its job — the whole sidebar is still the
split view's to show, still gated on a CONFIG having named a signal — minus the line that showed
`signal_toggle`, which no longer exists.
Everything else those handlers do is untouched: `tc.armed`, the epoch rule and the Everything else those handlers do is untouched: `tc.armed`, the epoch rule and the
`set_time_window()` call in `on_trigger_toggled()`, `sync_events_availability()`, the `set_time_window()` call in `on_trigger_toggled()`, `sync_events_availability()`, the
Arm/Disarm label, and `rows->set_cursors_visible()` with its `reset_cursors()`. Arm/Disarm label, and `rows->set_cursors_visible()` with its `reset_cursors()`.
@@ -88,28 +92,48 @@ quotes.
## 3. One channel list ## 3. One channel list
`rebuild_signal_list()` (`ui_signals.cpp:139-301`) gains a tail: a `MATH` divider row carrying **The duplication is literal, and the merge is mostly a deletion.**
the `+`, then one row per math channel, built with the same widgets as a signal row — tick, `rebuild_signal_list()` is handed `model.signals()`, and `append_math_signals_locked()`
colour chip, name, unit, menu. (`model.cpp:252-269`) has already appended one synthetic entry per math channel — *"they go
through the ordinary signal path on purpose: a derived channel is a channel"*, says its own
comment. Nothing in the list filters `sig.math`, so **every math channel is already a row in
the signal list**, with its tick, chip, name, unit and menu. The math pane listed the same
channels a second time.
What the list gains:
- a non-selectable `MATH` divider row before the first math row, carrying the `+` that opens
the node editor on a new channel;
- two items in a math row's menu.
| | signal row | math row | | | signal row | math row |
| --- | --- | --- | | --- | --- | --- |
| tick | acquire (hidden in a file view) | enabled | | tick | acquire (hidden in a file view) | enabled |
| colour chip | clickable while plotted | clickable while plotted | | colour chip | clickable while plotted | unchanged |
| unit | from CONFIG | the channel's own | | unit | from CONFIG | the channel's own |
| menu | Information, Calibration | Edit graph…, Delete | | menu | Information, Default colour, Calibrate… | **Edit graph…**, Default colour, **Delete** |
No rename item: the node editor owns a math channel's name and unit already Information and Calibrate… are a *streamed* signal's — calibration is applied at ingest — so a
(`src/ui/math-editor.ui:37-43`), so *Edit graph…* is where both are changed, and a second place math row carries neither. No rename item either: the node editor owns a math channel's name and
to change them would be a second answer to the same question. unit (`src/ui/math-editor.ui:37-43`), so *Edit graph…* is where both are changed, and a second
place to change them would be a second answer to the same question.
The colour chip and the tick need no special case: `ScopeModel::set_math_channels()` already Two things already work and must not be rebuilt: the tick is already the right switch —
appends a synthetic `SignalInfo` with `math=true`, which is why measurements, export and the `enable_locked()` (`model.cpp:626-639`) mirrors it into the `MathChannel`'s own `enabled` flag —
plots never knew the difference. and the row's `GtkDragSource` already lets a math channel be dropped onto a plot row, which is
how `math1` reached row 0 in the session this work started from.
One defect to fix while merging: `App::math` is the copy the session file is written from, so a
tick on a math row must mirror `enabled` into it before `schedule_layout_save()`. Today the pane's
checkbox did that (`ui.cpp:2276`) and the list's tick did not, so the two controls disagreed
about what gets saved.
Deleted: `build_math_panel()` (`ui_math.cpp:1044`), `rebuild_math_pane()` (`ui.cpp:2251-2319`), Deleted: `build_math_panel()` (`ui_math.cpp:1044`), `rebuild_math_pane()` (`ui.cpp:2251-2319`),
`src/ui/math-panel.ui` and its GResource entry, `App::math_revealer`, `App::math_toggle`. The `src/ui/math-panel.ui` and its entry in `src/ui/udpscope-ui.gresource.xml`, `App::math_revealer`,
node editor dialog itself is untouched — only the button that opens it moves. `App::math_list`, `App::math_toggle`, `App::measures_toggle`, `App::signal_revealer`, and
`App::signal_toggle` with `on_signals_toggled()` (`ui_signals.cpp:303-307`) and its overflow-menu
row (`ui.cpp:4452-4455`) — the list is a page now, so "show or hide the signal list" has nothing
to hide. The node editor dialog itself is untouched; only the button that opens it moves.
## 4. Persistence ## 4. Persistence
@@ -148,6 +172,7 @@ Readings that change, and what each must say instead:
| `dbg_signal_revealed` (`ui_probe.cpp:90`) | the signal revealer's child is revealed | the `signals` page is current **and** its list is non-empty | | `dbg_signal_revealed` (`ui_probe.cpp:90`) | the signal revealer's child is revealed | the `signals` page is current **and** its list is non-empty |
| `dbg_trigger_revealed` (`ui_probe.cpp:92`, `:2190`) | the trigger revealer's child is revealed | the `signals` page is current **and** the trigger body is sensitive | | `dbg_trigger_revealed` (`ui_probe.cpp:92`, `:2190`) | the trigger revealer's child is revealed | the `signals` page is current **and** the trigger body is sensitive |
| `dbg_measures_pane_w/h` | the pane's size while revealed | the pane's size while its page is current; 0 otherwise, and read as such | | `dbg_measures_pane_w/h` | the pane's size while revealed | the pane's size while its page is current; 0 otherwise, and read as such |
| the panel-toggle reading (`ui_probe.cpp:104`) | both menu toggles are visible | the switcher is visible, which is the one control those two became |
One new probe, `UDPSCOPE_PROBE_SIDE_TAB_MS`: select the page that is not current, then dump the One new probe, `UDPSCOPE_PROBE_SIDE_TAB_MS`: select the page that is not current, then dump the
page name, the measurement row count and the accumulator's sample count. The count must have page name, the measurement row count and the accumulator's sample count. The count must have