badges: source badge shows the name only; drop the signals lock; the signals page proposes what can be added

The link state is the status bar's, so the Source badge loses its state text. The signals have no lock
(the badges and signal pages are direct manipulation), and the signals page lists only unacquired
signals and uncomputed math channels (plus the acquired ones while the badge bar has overflowed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-03 02:14:37 +01:00
1 parent dad424f1de
commit b98a3478ff
10 files changed
+164 -148

No files matched your search

+21 -19
View File
@@ -102,7 +102,7 @@ gboolean exit_probe_step3b(gpointer user) {
a->dbg_signal_w = gtk_widget_get_width(a->signal_panel);
a->dbg_signal_h = gtk_widget_get_height(a->signal_panel);
// How many rows of the signal list carry a drag source: none. Dragging a signal onto a plot is the signal
// badge's job (and survives the pane lock, since the badges do not follow it); the list's rows only open
// badge's job (the signals have no lock to survive); the list's rows only open
// the signal's page. The reading says the list did not grow a second, competing handle.
if (a->signal_list != nullptr) {
int sources = 0;
@@ -3836,32 +3836,35 @@ gboolean enable_all_probe(gpointer user) {
std::fprintf(stderr, "[enable-all-probe] %zu channel(s) enabled and assigned to plots, notice='%s'\n",
a->model->channel_count(), a->notice.c_str());
std::fflush(stderr);
// Then switch one off through its own switch in the signal list: a disabled signal must leave the plots,
// not sit there drawing nothing in a slot a live one could take. Late enough that a math probe armed behind
// this one has had its graphs installed -- the dependants are the point of the second line.
// Then switch one off through its own switch on the signal's page -- the user's path now that an acquired
// signal is not in the list: a disabled signal must leave the plots, not sit there drawing nothing in a slot
// a live one could take. Late enough that a math probe armed behind this one has had its graphs installed --
// the dependants are the point of the second line.
g_timeout_add(2000, +[](gpointer u) -> gboolean {
App* app = static_cast<App*>(u);
if (app->model->channels().empty() || app->signal_list == nullptr) return G_SOURCE_REMOVE;
const std::size_t signal = app->model->channels().front().signal;
const std::string name = app->model->channels().front().name;
GtkWidget* tick = nullptr;
for (GtkWidget* row_widget = gtk_widget_get_first_child(app->signal_list);
row_widget != nullptr && tick == nullptr;
row_widget = gtk_widget_get_next_sibling(row_widget)) {
// The tick sits a box inside the row, which is the shape `signal_tick_visible()` walks too.
for (GtkWidget* box = gtk_widget_get_first_child(row_widget); box != nullptr && tick == nullptr;
box = gtk_widget_get_next_sibling(box)) {
for (GtkWidget* w = gtk_widget_get_first_child(box); w != nullptr;
w = gtk_widget_get_next_sibling(w)) {
if (!GTK_IS_CHECK_BUTTON(w)) continue;
if (GPOINTER_TO_SIZE(g_object_get_data(G_OBJECT(w), "udpscope-signal")) != signal) continue;
tick = w;
break;
std::string signal_name;
{
std::lock_guard<std::mutex> lock(app->model->mutex());
const std::vector<SignalInfo>& sigs = app->model->signals();
if (signal < sigs.size()) signal_name = sigs[signal].name;
}
if (!signal_name.empty() && signal_page_ensure(*app, signal_name)) {
// The page's "Acquire this signal" check is the first check button in it.
const std::function<GtkWidget*(GtkWidget*)> first_check = [&](GtkWidget* root) -> GtkWidget* {
for (GtkWidget* c = gtk_widget_get_first_child(root); c != nullptr; c = gtk_widget_get_next_sibling(c)) {
if (GTK_IS_CHECK_BUTTON(c)) return c;
if (GtkWidget* deeper = first_check(c)) return deeper;
}
}
return nullptr;
};
tick = first_check(app->signal_pages[signal_name]);
}
if (tick == nullptr) {
std::fprintf(stderr, "[enable-all-probe] no acquire tick found for signal %zu\n", signal);
std::fprintf(stderr, "[enable-all-probe] no acquire tick found on the page of signal %zu\n", signal);
std::fflush(stderr);
return G_SOURCE_REMOVE;
}
@@ -4314,7 +4317,6 @@ gboolean exit_probe_step1(gpointer user) {
g_signal_emit_by_name(a->trigger_edit, "clicked"); // and back to the view
}
a->dbg_trigger_locked = a->trigger_locked ? 1 : 0;
a->dbg_signals_locked = a->signals_locked ? 1 : 0;
a->dbg_trigger_body_visible =
a->trigger_body != nullptr && gtk_widget_get_visible(a->trigger_body) ? 1 : 0;
// The summary's text comes from the sync that wrote it: the container is a grid of key/value rows,