feat: the host form, and the help window, are UI files
src/ui/source-form.ui is the form a source is added or edited with: an AdwDialog of AdwPreferencesGroup rows (AdwEntryRow, AdwSpinRow, AdwSwitchRow) with its action in the header bar, where the label says which mode the form is in -- Connect for a new host, Save for an existing configuration. The grid of labels and bare entries it replaces had its hints in placeholders, which vanish as soon as there is a value; they are the groups' descriptions now. src/ui/help.ui is the help window's chrome: an AdwWindow with a header bar and an AdwNavigationSplitView whose sidebar is the page list. The rows stay in C++ because the fourteen pages are data, not template. Four UI files now, 653 lines of template that used to be widget construction. Two libadwaita traps cost a run each and are in docs/claude/invariants-gtk-and-chrome.md: an AdwDialog has no content property (its child is a plain <child>, unlike an AdwToolbarView), and AdwEntryRow has no subtitle (it is an AdwPreferencesRow, not an AdwActionRow). The unused form_field() helper went with them. Every probe reading is unchanged -- [sources] form:, [sources] edit form:, [help] -- which is what refactoring a shape rather than a behaviour should look like.
This commit is contained in:
1 parent
4c56172005
commit
68743a7d7f
8 files changed
+388
-184
No files matched your search
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
<!-- SPDX-FileCopyrightText: 2026 Martino Ferrari -->
|
||||
<!--
|
||||
The help window's chrome: a window, its own header bar, and a two-pane split whose sidebar is the
|
||||
list of pages and whose content is one page at a time.
|
||||
|
||||
The split is AdwNavigationSplitView rather than a GtkBox with a separator in it, so the sidebar
|
||||
collapses on a narrow window and comes back behind the header bar's button instead of squeezing the
|
||||
text. On a wide one it is the same two panes it always was.
|
||||
|
||||
The page list itself is *not* here: its rows are the fourteen pages in `help_window.cpp`, each with
|
||||
section headings between the groups, and a template cannot know them. What is here is the shape they
|
||||
are put into: an id to find the list by, the scroller around the page, and the label that holds one
|
||||
page's markup with the screenshot column above it.
|
||||
-->
|
||||
<interface>
|
||||
<object class="AdwWindow" id="help_window">
|
||||
<property name="title" translatable="yes">udpscope help</property>
|
||||
<property name="default-width">860</property>
|
||||
<property name="default-height">640</property>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="show-title">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwNavigationSplitView">
|
||||
<property name="sidebar">
|
||||
<object class="AdwNavigationPage">
|
||||
<property name="title" translatable="yes">Pages</property>
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="width-request">220</property>
|
||||
<property name="child">
|
||||
<object class="GtkListBox" id="page_list">
|
||||
<property name="selection-mode">single</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="content">
|
||||
<object class="AdwNavigationPage">
|
||||
<property name="title" translatable="yes">Page</property>
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="page_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="shot_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">8</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="margin-top">14</property>
|
||||
<property name="visible">0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="body">
|
||||
<property name="use-markup">1</property>
|
||||
<property name="wrap">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="selectable">1</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="margin-top">14</property>
|
||||
<property name="margin-bottom">14</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
<!-- SPDX-FileCopyrightText: 2026 Martino Ferrari -->
|
||||
<!--
|
||||
The form a source is added or edited with: one dialog, two groups, eight rows.
|
||||
|
||||
A grid of labels and bare entries is what this was, and a grid is the wrong shape for it. Each row
|
||||
here is a whole row — a title, a subtitle under it where the hint used to be a placeholder, and the
|
||||
editing widget on the right — so the form reads the way every GNOME application's does, and the hints
|
||||
survive being typed over (a placeholder does not: it disappears the moment there is a value, which is
|
||||
exactly when a user may want to know what empty meant).
|
||||
|
||||
The action is in the header bar rather than a button row at the foot: it is what the dialog is *for*,
|
||||
it is what the keyboard's Enter reaches, and its label says which mode the form is in — `Connect` for
|
||||
a new host, `Save` for an existing configuration, which `source_dialog.cpp` sets.
|
||||
|
||||
Nothing here carries a value. The dialog is filled from the source being edited, or from the command
|
||||
line for a new one, by the code that opens it.
|
||||
-->
|
||||
<interface>
|
||||
<object class="AdwDialog" id="source_form">
|
||||
<property name="content-width">420</property>
|
||||
<property name="content-height">560</property>
|
||||
<child>
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="title-widget">
|
||||
<object class="AdwWindowTitle" id="form_title">
|
||||
<property name="title" translatable="yes">New host</property>
|
||||
</object>
|
||||
</property>
|
||||
<child type="end">
|
||||
<object class="GtkButton" id="form_cancel">
|
||||
<property name="label" translatable="yes">_Cancel</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkButton" id="form_apply">
|
||||
<property name="label" translatable="yes">_Connect</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="css-classes">suggested-action</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="child">
|
||||
<object class="AdwPreferencesPage">
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Connection</property>
|
||||
<property name="description" translatable="yes">Leave the multicast group and the interface empty for unicast on the default route</property>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="server_row">
|
||||
<property name="title" translatable="yes">_Server</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSpinRow" id="port_row">
|
||||
<property name="title" translatable="yes">_Port</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">65535</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="value">8000</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="group_row">
|
||||
<property name="title" translatable="yes">Multicast _group</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="iface_row">
|
||||
<property name="title" translatable="yes">_Interface</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Configuration</property>
|
||||
<property name="description" translatable="yes">The name is what this source's session is called. The buffer and the clock are decided before the first socket is opened.</property>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="name_row">
|
||||
<property name="title" translatable="yes">_Name</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwEntryRow" id="note_row">
|
||||
<property name="title" translatable="yes">N_ote</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSpinRow" id="buffer_row">
|
||||
<property name="title" translatable="yes">_Buffer MB</property>
|
||||
<property name="subtitle" translatable="yes">sample buffer per source, applied when this source is opened</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">65536</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="value">64</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSwitchRow" id="form_relative_row">
|
||||
<property name="title" translatable="yes">_Relative time</property>
|
||||
<property name="subtitle" translatable="yes">plot time from the packet counter and the declared rate, instead of the stream's own time signal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -11,5 +11,7 @@
|
||||
<gresource prefix="/org/udpscope/ui">
|
||||
<file preprocess="xml-stripblanks">shortcuts.ui</file>
|
||||
<file preprocess="xml-stripblanks">preferences.ui</file>
|
||||
<file preprocess="xml-stripblanks">help.ui</file>
|
||||
<file preprocess="xml-stripblanks">source-form.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
Reference in new issue
Block a user