feat: switching a signal off takes its traces off every plot

The switch in the signal list means "do not acquire this", and until now a trace of it
stayed on its plot drawing nothing: a slot that holds one of the four a plot has, reads
`--`, and blocks the drop that would fill it with something live.

`on_signal_switch()` now clears every slot that holds that signal, by the **signal name**
the slot remembers -- never the channel index, which is what the enable change renumbers --
and says what it did: `'sine' is off: 1 trace left the plots`. The follow-ups (a relayout,
the panels' chips, the layout save) happen once rather than per slot.

Re-enabling deliberately does not put the traces back: the arrangement is the user's, and
guessing where they were is worse than leaving them off. Say the word if you want that
direction too.

[enable-all-probe] reads it end to end -- it enables every signal, assigns the channels
across the rows, then switches one off *through its own acquire tick*:

    [enable-all-probe] switched 'sine' off: traces_left=0 (want 0) notice=''sine' is off: 1 trace left the plots'

which is also why the notice shares the status line's warning styling from the previous
commit: the trace leaving the plots is something the user should see happen.
This commit is contained in:
Martino Ferrari committed 2026-10-12 22:12:24 +02:00
1 parent aaf544be1e
commit 8b3240cacb
6 files changed
+102 -1

No files matched your search

+19 -1
View File
@@ -17,7 +17,25 @@ void on_signal_switch(GObject* obj, GParamSpec*, gpointer user) {
if (app->updating_panels) return;
const std::size_t index = static_cast<std::size_t>(
GPOINTER_TO_SIZE(g_object_get_data(obj, "udpscope-signal")));
app->model->set_signal_enabled(index, gtk_check_button_get_active(GTK_CHECK_BUTTON(obj)));
const bool on = gtk_check_button_get_active(GTK_CHECK_BUTTON(obj)) != FALSE;
// The name first: the switch may be the last reference to a signal the model is about to drop.
std::string name;
{
const std::vector<SignalInfo>& signals = app->model->signals();
if (index < signals.size()) name = signals[index].name;
}
app->model->set_signal_enabled(index, on);
if (!on) {
// A trace of a signal nobody acquires draws nothing, and holds the slot a live one could take.
const int gone = remove_signal_from_plots(*app, name);
if (gone > 0) {
app->relayout_pending = true;
rebuild_signal_panels(*app); // the chips of the signals that are still plotted
set_notice(*app, "'" + name + "' is off: " + std::to_string(gone) +
(gone == 1 ? " trace left the plots" : " traces left the plots"),
4);
}
}
// The enable state is part of the session (a signal can be on only as a math channel's source).
schedule_layout_save(*app);
}