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:
1 parent
132041f79e
commit
a493737ca1
6 files changed
+186
-190
No files matched your search
+13
-93
@@ -2248,76 +2248,6 @@ void open_math_dialog(App& app, int edit) {
|
||||
}
|
||||
|
||||
|
||||
void rebuild_math_pane(App& app) {
|
||||
if (app.math_list == nullptr) return;
|
||||
while (GtkWidget* child = gtk_widget_get_first_child(app.math_list)) {
|
||||
gtk_box_remove(GTK_BOX(app.math_list), child);
|
||||
}
|
||||
if (app.math.empty()) {
|
||||
GtkWidget* none = gtk_label_new("— none —");
|
||||
gtk_widget_add_css_class(none, "dim-label");
|
||||
gtk_widget_set_halign(none, GTK_ALIGN_START);
|
||||
gtk_box_append(GTK_BOX(app.math_list), none);
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < app.math.size(); ++i) {
|
||||
const MathChannel& m = app.math[i];
|
||||
GtkWidget* row = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
GtkWidget* on = gtk_check_button_new();
|
||||
gtk_check_button_set_active(GTK_CHECK_BUTTON(on), m.enabled);
|
||||
gtk_widget_set_tooltip_text(on, "enable this math channel: off means it is not acquired, not\n"
|
||||
"plotted and not measured, exactly like a signal's switch");
|
||||
const std::size_t index = i;
|
||||
g_signal_connect(on, "toggled", G_CALLBACK(+[](GtkToggleButton* b, gpointer user) {
|
||||
App* a = static_cast<App*>(user);
|
||||
const std::size_t k = GPOINTER_TO_SIZE(
|
||||
g_object_get_data(G_OBJECT(b), "udpscope-math-index"));
|
||||
if (k >= a->math.size()) return;
|
||||
a->math[k].enabled = gtk_toggle_button_get_active(b);
|
||||
apply_math_channels(*a);
|
||||
}),
|
||||
&app);
|
||||
g_object_set_data(G_OBJECT(on), "udpscope-math-index", GSIZE_TO_POINTER(index));
|
||||
gtk_box_append(GTK_BOX(row), on);
|
||||
|
||||
std::string text = m.name;
|
||||
if (!m.unit.empty()) text += " [" + m.unit + "]";
|
||||
GtkWidget* label = gtk_label_new(text.c_str());
|
||||
gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
|
||||
gtk_widget_set_hexpand(label, true);
|
||||
gtk_widget_set_halign(label, GTK_ALIGN_START);
|
||||
gtk_box_append(GTK_BOX(row), label);
|
||||
|
||||
GtkWidget* edit = gtk_button_new_from_icon_name("document-edit-symbolic");
|
||||
gtk_widget_add_css_class(edit, "flat");
|
||||
gtk_widget_set_tooltip_text(edit, "edit this math channel's graph");
|
||||
g_object_set_data(G_OBJECT(edit), "udpscope-math-index", GSIZE_TO_POINTER(index));
|
||||
g_signal_connect(edit, "clicked", G_CALLBACK(+[](GtkButton* b, gpointer user) {
|
||||
App* a = static_cast<App*>(user);
|
||||
const std::size_t k = GPOINTER_TO_SIZE(
|
||||
g_object_get_data(G_OBJECT(b), "udpscope-math-index"));
|
||||
open_math_dialog(*a, static_cast<int>(k));
|
||||
}),
|
||||
&app);
|
||||
gtk_box_append(GTK_BOX(row), edit);
|
||||
|
||||
GtkWidget* del = gtk_button_new_from_icon_name("window-close-symbolic");
|
||||
gtk_widget_add_css_class(del, "flat");
|
||||
gtk_widget_set_tooltip_text(del, "delete this math channel");
|
||||
g_object_set_data(G_OBJECT(del), "udpscope-math-index", GSIZE_TO_POINTER(index));
|
||||
g_signal_connect(del, "clicked", G_CALLBACK(+[](GtkButton* b, gpointer user) {
|
||||
App* a = static_cast<App*>(user);
|
||||
const std::size_t k = GPOINTER_TO_SIZE(
|
||||
g_object_get_data(G_OBJECT(b), "udpscope-math-index"));
|
||||
if (k < a->math.size()) a->math.erase(a->math.begin() + k);
|
||||
apply_math_channels(*a);
|
||||
}),
|
||||
&app);
|
||||
gtk_box_append(GTK_BOX(row), del);
|
||||
gtk_box_append(GTK_BOX(app.math_list), row);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* build_measures_panel(App& app) {
|
||||
// The panel's frame is a UI file; the readings are not, because each row is one measurement and they are
|
||||
// rebuilt whenever the set or the mode changes. `make test-ui` checks the file's types against the GIR;
|
||||
@@ -4724,10 +4654,6 @@ void on_activate(GtkApplication* application, gpointer user) {
|
||||
app->trigger_panel = build_trigger_panel(*app);
|
||||
gtk_box_append(GTK_BOX(signals_page), app->trigger_panel);
|
||||
gtk_box_append(GTK_BOX(signals_page), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
|
||||
// Still on the signals page until the list grows the `+` and the per-row menu that replace it.
|
||||
gtk_box_append(GTK_BOX(signals_page), build_math_panel(*app));
|
||||
gtk_box_append(GTK_BOX(signals_page), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
|
||||
rebuild_math_pane(*app);
|
||||
app->signal_panel = build_signal_panel(*app);
|
||||
gtk_box_append(GTK_BOX(signals_page), app->signal_panel);
|
||||
|
||||
@@ -5376,6 +5302,9 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
if (const char* env = g_getenv("UDPSCOPE_PROBE_STATS_MS")) {
|
||||
g_timeout_add(static_cast<guint>(std::atoi(env)), stats_probe, &app);
|
||||
}
|
||||
if (const char* env = g_getenv("UDPSCOPE_PROBE_SIDE_TAB_MS")) {
|
||||
g_timeout_add(static_cast<guint>(std::atoi(env)), side_tab_probe, &app);
|
||||
}
|
||||
if (const char* env = g_getenv("UDPSCOPE_PROBE_SEARCH_MS")) {
|
||||
g_timeout_add(static_cast<guint>(std::atoi(env)), search_probe, &app);
|
||||
}
|
||||
@@ -5606,25 +5535,16 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
if (GTK_IS_LABEL(c)) ++labels;
|
||||
if (GTK_IS_LIST_BOX(c)) ++lists;
|
||||
}
|
||||
std::printf("[udpscope] signals panel: labels=%d list=%d\n", labels, lists);
|
||||
}
|
||||
{
|
||||
// The math panel's frame, read from the window: the head row with the title and the add button, and the
|
||||
// list. `buttons=0` is a `.ui` that lost the `+` -- otherwise a panel that cannot add anything, with
|
||||
// nothing else complaining -- and the title is read out to show the file's own text arrived.
|
||||
GtkWidget* panel = app.math_list != nullptr ? gtk_widget_get_parent(app.math_list) : nullptr;
|
||||
GtkWidget* head = panel != nullptr ? gtk_widget_get_first_child(panel) : nullptr;
|
||||
GtkWidget* title = head != nullptr ? gtk_widget_get_first_child(head) : nullptr;
|
||||
int head_children = 0;
|
||||
int buttons = 0;
|
||||
for (GtkWidget* c = head != nullptr ? gtk_widget_get_first_child(head) : nullptr; c != nullptr;
|
||||
c = gtk_widget_get_next_sibling(c)) {
|
||||
++head_children;
|
||||
if (GTK_IS_BUTTON(c)) ++buttons;
|
||||
}
|
||||
std::printf("[udpscope] math panel: head=%d buttons=%d list=%d title='%s'\n", head_children,
|
||||
buttons, app.math_list != nullptr ? 1 : 0,
|
||||
GTK_IS_LABEL(title) ? gtk_label_get_text(GTK_LABEL(title)) : "-");
|
||||
// The list's shape, beside the frame: `rows` is what the list holds, `signals` the streamed
|
||||
// ones, and the `MATH` divider plus the math channels account for the rest -- so
|
||||
// `rows == signals + 1 + math` is the invariant, and `divider=0` is a list that lost its `+`.
|
||||
std::printf("[udpscope] signals panel: labels=%d list=%d rows=%d signals=%zu math=%zu "
|
||||
"divider=%d\n",
|
||||
labels, lists, app.dbg_signal_rows, app.dbg_signal_plain, app.math.size(),
|
||||
app.dbg_signal_rows ==
|
||||
static_cast<int>(app.dbg_signal_plain + 1 + app.math.size())
|
||||
? 1
|
||||
: 0);
|
||||
}
|
||||
{
|
||||
// The events pane's frame, read from the window: the four widgets the `.ui` gives it, and the list
|
||||
|
||||
Reference in new issue
Block a user