source: capability panels as side-stack pages, with a probe for the path

This commit is contained in:
Martino Ferrari committed 2026-10-31 20:18:28 +01:00
1 parent 79c33b25c5
commit 5cee00aaee
6 files changed
+209 -3

No files matched your search

+17 -3
View File
@@ -2978,9 +2978,14 @@ std::string icon_report(GtkIconTheme* theme, const char* name, const char* resou
/// The words the pills do not draw. The pages' `title` is empty on purpose (see the `.ui`), so the
/// human name of a tab lives here and is put on the pill — its tooltip and its accessible name — by
/// `name_side_tabs()`. That keeps an icon-only pill a *named* control for a screen reader.
static const char* side_tab_title(const char* name) {
static const char* side_tab_title(const App& app, const char* name) {
if (name != nullptr && std::strcmp(name, "measure") == 0) return "Measure";
if (name != nullptr && std::strcmp(name, "signals") == 0) return "Signals";
if (name != nullptr) {
for (const SourcePanelPage& p : app.source_panels) {
if (p.name == name) return p.title.c_str();
}
}
return "";
}
@@ -3000,7 +3005,7 @@ void name_side_tabs(App& app) {
for (guint i = 0; pages != nullptr && pill != nullptr && i < g_list_model_get_n_items(pages);
pill = gtk_widget_get_next_sibling(pill), ++i) {
AdwViewStackPage* page = ADW_VIEW_STACK_PAGE(g_list_model_get_item(pages, i));
const char* title = side_tab_title(adw_view_stack_page_get_name(page));
const char* title = side_tab_title(app, adw_view_stack_page_get_name(page));
g_object_unref(page);
if (title[0] == '\0') continue;
gtk_widget_set_tooltip_text(pill, title);
@@ -3457,6 +3462,7 @@ gboolean tick(gpointer user) {
// no text and no name either.
name_side_tabs(*app);
note_panel_controls(*app);
sync_source_panels(*app);
// The tour, re-measured every frame: the target's allocation is 0 on the frame it is first shown
// (see the allocation bullets in `docs/claude/invariants-trigger-and-pinning.md`) and the widget
// moves under the spotlight on a window resize, so a one-shot measurement is wrong both ways.
@@ -4551,7 +4557,8 @@ gboolean tick(gpointer user) {
}
if (app->capture_button != nullptr) {
// Insensitive until connected: the capture's path is keyed on the source.
gtk_widget_set_sensitive(app->capture_button, snap.connected ? TRUE : FALSE);
gtk_widget_set_sensitive(app->capture_button,
snap.connected && app->source_has_datagrams ? TRUE : FALSE);
if (app->capture_want_ui && !app->acq->capture_want()) {
// The producer refused the open (a full disk, a read-only directory) and cleared
// the flag; the button follows the flag rather than lying about the state. Going
@@ -5282,6 +5289,9 @@ void on_activate(GtkApplication* application, gpointer user) {
g_signal_connect(app->side_stack, "notify::visible-child-name",
G_CALLBACK(on_side_tab_changed), app);
}
// The source kind's own tabs (a generator, digital I/O). Before the first tick: that is when
// `name_side_tabs()` puts the words on the pills, and it must see these pages too.
build_source_panels(*app);
// The left side is the events pane *and* the plot, in one row: the pane is a column of its own
// (the item's "collapsable pane on the left"), revealed by trigger mode.
@@ -5926,6 +5936,7 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
} else {
app.source_title = app.source_host + ":" + std::to_string(app.source_port);
}
if (SourceKind* k = find_kind(cfg.source_kind)) app.source_has_datagrams = k->has_datagrams();
// The event cache is keyed on the source, like the packet capture. A waveform has no source, so a
// file-mode run has no cache either -- there are no latches in a file.
if (!app.source_host.empty() && app.source_port != 0) {
@@ -6098,6 +6109,9 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
if (const char* env = g_getenv("UDPSCOPE_PROBE_DENSITY_MS")) {
g_timeout_add(static_cast<guint>(std::atoi(env)), density_probe, &app);
}
if (const char* env = g_getenv("UDPSCOPE_PROBE_SOURCE_KINDS")) {
g_timeout_add(static_cast<guint>(std::atoi(env)), source_kinds_probe, &app);
}
// Our own options were consumed by parse_args(); GTK would reject them, so only
// the program name is handed to g_application_run().