ui: one channel list, and the math pane is gone

`rebuild_signal_list()` is handed `model.signals()`, and `append_math_signals_locked()` already
appends one synthetic entry per math channel -- "they go through the ordinary signal path on
purpose: a derived channel is a channel" -- so **every math channel was already a row of the
signal list**, with its tick, chip, name, unit and menu. The math pane listed the same channels a
second time, so this is mostly a deletion: `build_math_panel()`, `rebuild_math_pane()`,
`src/ui/math-panel.ui` and its resource entry, `App::math_list`, and the `math panel:` dump line.

What the one list gains:

- a non-selectable `MATH` divider before the first math row, carrying the `+` that creates a
  channel -- appended even when there are no math channels at all, because a `+` conditional on
  one existing could never create the first one;
- a math row's own menu: *Edit graph…*, *Default colour*, *Delete*. No Information and no
  Calibrate (calibration is applied at ingest, and a derived channel has no stream to describe),
  and no rename, because the node editor owns a channel's name and unit -- a second place to
  change them would be a second answer to the same question. An item dismisses the row's popover
  before opening or destroying anything from it;
- `App::math` mirrored from a math row's tick: `enable_locked()` mirrors it into the model, but
  `App::math` is the copy the session file is written from. The mirror sits *before* the
  `apply_math_channels()` in the `!on` path, which would otherwise push a stale `enabled = true`
  straight back into the model;
- a tick visible in a file view too: a derived channel is computed, and a file view has no
  acquisition to start, which is the other tick's question.

`rebuild_signal_list()` also publishes the list's own shape -- `rows`, `signals`, `math` -- and
the dump prints `divider=1` when `rows == signals + 1 + math`: the reading for a list that lost
its `+`.

Verified: `make test-ui` 14 files (was 15); `signals panel: labels=2 list=1 rows=9 signals=4
math=4 divider=1`; `[math-probe] 3 math channels`, every other line unchanged; no `math panel:`
line, and zero `Gtk-CRITICAL`.
This commit is contained in:
Martino Ferrari committed 2026-10-14 12:56:31 +02:00
1 parent 132041f79e
commit a493737ca1
6 files changed
+186 -190

No files matched your search

-21
View File
@@ -22,7 +22,6 @@ void apply_math_channels(App& app) {
// refills that; a file's nothing does, so the view is re-read -- and with the math set now in place
// the reload computes the derived channels over the file as it goes.
reload_file_view(app);
rebuild_math_pane(app);
// The math channels are rows of the signal list too -- `append_math_signals_locked()` puts them
// in `signals()` -- so the list is stale until it is rebuilt.
rebuild_signal_panels(app);
@@ -1044,25 +1043,5 @@ GtkWidget* math_row(const char* label, GtkWidget* widget, GtkWidget** row_out) {
return row;
}
GtkWidget* build_math_panel(App& app) {
// The panel's frame -- the heading row with its add button, and the list -- is a UI file; the rows are
// not, because each one is a channel and the whole list is rebuilt whenever the set changes. `make test-ui`
// checks the file's types against the GIR; the ids below are what keeps the code and the file agreeing.
GtkBuilder* ui = ui_load(app, "/org/udpscope/ui/math-panel.ui");
GtkWidget* box = GTK_WIDGET(gtk_builder_get_object(ui, "math_panel"));
GtkWidget* add = GTK_WIDGET(gtk_builder_get_object(ui, "math_add"));
app.math_list = GTK_WIDGET(gtk_builder_get_object(ui, "math_list"));
if (box == nullptr || add == nullptr || app.math_list == nullptr) {
// A missing id is a mistake in the `.ui`: the panel comes up empty rather than taking the window with
// it, and `[udpscope] math panel:` reads the difference.
return box != nullptr ? box : gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
}
g_signal_connect(add, "clicked", G_CALLBACK(+[](GtkButton*, gpointer user) {
add_math_channel(*static_cast<App*>(user));
}),
&app);
return box;
}
} // namespace ui_impl
} // namespace udpscope