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

+15 -22
View File
@@ -4595,9 +4595,8 @@ void on_panel_switch_toggled(GObject* obj, GParamSpec*, gpointer user) {
sync_panel_switches(*app);
}
/// Both panes' modes, applied together: the trigger's body against its summary line, the two [edit]
/// buttons against what they would do, and the signal list rebuilt because the lock decides what a row
/// carries. Idempotent, so a caller only flips a flag and calls this.
/// The trigger pane's mode: its body against its summary line and its [edit] button against what it would
/// do. Idempotent, so a caller only flips the flag and calls this.
void apply_pane_lock(App& app) {
if (app.trigger_body != nullptr) gtk_widget_set_visible(app.trigger_body, !app.trigger_locked);
if (app.trigger_summary != nullptr) {
@@ -4614,23 +4613,16 @@ void apply_pane_lock(App& app) {
gtk_widget_set_tooltip_text(button, tip.c_str());
};
edit_button(app.trigger_edit, app.trigger_locked, "the trigger");
edit_button(app.signals_edit, app.signals_locked, "the signals");
// The lock decides whether the compact line's arm control is the one on screen: with the body shown the
// body's own button is there, and two arm buttons at once would be two controls for one state.
sync_arm_buttons(app);
sync_trigger_summary(app);
// The list, because the lock is what decides whether a row carries a tick, a menu and the `+`.
if (app.signal_list != nullptr) rebuild_signal_panels(app);
}
/// Either pane's [edit] button: one handler, because the two differ only in which flag they flip.
/// The trigger pane's [edit] button.
void on_pane_edit_clicked(GtkButton* button, gpointer user) {
App* app = static_cast<App*>(user);
if (GTK_WIDGET(button) == app->trigger_edit) {
app->trigger_locked = !app->trigger_locked;
} else if (GTK_WIDGET(button) == app->signals_edit) {
app->signals_locked = !app->signals_locked;
}
if (GTK_WIDGET(button) == app->trigger_edit) app->trigger_locked = !app->trigger_locked;
apply_pane_lock(*app);
}
@@ -6150,12 +6142,12 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
static_cast<unsigned long long>(app.dbg_latches_at_disarm));
std::printf("[udpscope] window control: '%s'\n", app.dbg_window_text.c_str());
{
// The signals panel's frame, read from the window rather than from the `.ui`: the two labels and the
// list the file gives it. A `.ui` that lost one of them reads here -- `labels=1` or `list=0` -- rather
// The signals panel's frame, read from the window rather than from the `.ui`: the three labels (heading,
// hint, and the "every signal is acquired" one, hidden or not) and the list the file gives it. A `.ui` that lost one of them reads here -- `labels=1` or `list=0` -- rather
// than showing as a panel quietly missing its hint.
GtkWidget* panel = app.signal_list != nullptr ? gtk_widget_get_parent(app.signal_list) : nullptr;
// Counted over the panel's *subtree*, not its direct children: the heading lives in a heading row
// beside the pane's [edit] button, and a count of children would read 1 whatever the file lost.
// and the hint in a box of its own, and a count of children would read 1 whatever the file lost.
int labels = 0;
int lists = 0;
const std::function<void(GtkWidget*)> count = [&](GtkWidget* w) {
@@ -6175,13 +6167,15 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
// 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 drag_sources=%d\n",
labels, lists, app.dbg_signal_rows, app.dbg_signal_plain, app.math.size(),
"divider=%d drag_sources=%d addable=%zu addable_ok=%d empty_label=%d\n",
labels, lists, app.dbg_signal_rows, app.dbg_signal_plain, app.dbg_signal_math_rows,
app.dbg_signal_rows ==
static_cast<int>(app.dbg_signal_plain + 1 + app.math.size())
static_cast<int>(app.dbg_signal_plain + 1 + app.dbg_signal_math_rows)
? 1
: 0,
app.dbg_signal_drag_sources);
app.dbg_signal_drag_sources, app.dbg_signal_addable,
app.dbg_signal_plain + app.dbg_signal_math_rows == app.dbg_signal_addable ? 1 : 0,
app.dbg_signal_empty_label);
}
{
// The events pane's frame, read from the window: the four widgets the `.ui` gives it, and the list
@@ -6218,9 +6212,8 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
app.dbg_pane_view_icon.c_str(),
gtk_icon_theme_has_icon(theme, app.dbg_pane_view_icon.c_str()) ? "ok" : "MISSING");
}
std::printf("[udpscope] panes: trigger=%s signals=%s body_visible=%d summary='%s'\n",
app.dbg_trigger_locked ? "locked" : "config",
app.dbg_signals_locked ? "locked" : "config", app.dbg_trigger_body_visible,
std::printf("[udpscope] panes: trigger=%s body_visible=%d summary='%s'\n",
app.dbg_trigger_locked ? "locked" : "config", app.dbg_trigger_body_visible,
app.dbg_trigger_summary.c_str());
std::printf("[udpscope] panes: the same line as the probe found it: '%s'\n",
app.dbg_trigger_summary_early.c_str());