Say what the grid is showing in one line, not four

The header carried four readouts beside the title: the image count,
the selection count, the scan's status and where in the library the
visible window sits. Each had `horizontal-stretch: 1`, which is what
actually lets a Text shrink in Slint — so between them they claimed
about a third of a 768px header and left the buttons to scroll off the
end of it.

The selection count goes to the bar at the foot of the grid, beside
the buttons that act on it. The other three are one subject and are
now one sentence with separators, sharing one stretch.

Two of them were also saying the same words while a sweep ran:
"indexing 300 / 12 480" appeared both as the status and, redundantly,
in place of the window position.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-30 13:16:20 +02:00
co-authored by Claude Opus 5
parent 18063152f9
commit f4fbabf18b
3 changed files with 69 additions and 72 deletions
+49 -52
View File
@@ -1078,6 +1078,42 @@ export component LibraryGrid inherits Rectangle {
in property <bool> syncing: false;
property <bool> sweeping: root.sweep-total > 0 && root.sweep-done < root.sweep-total;
// --- the header's one status line -------------------------------------
//
// Four readouts used to sit in the header beside the title: the image
// count, the selection count, the scan's status and where in the library
// the visible window sits. Each carried `horizontal-stretch: 1` — which is
// what actually lets a `Text` shrink in Slint — so between them they took
// about a third of a 768px header and left the buttons to scroll off the
// end of it.
//
// The selection count is gone from here entirely: it belongs beside the
// buttons that act on it, which is the bar at the foot of the grid.
//
// The other three are one subject — what this grid is showing and what is
// being done to it — so they are one sentence with separators, and one
// stretch between them. Two of them even said the same words while a sweep
// ran: "indexing 300 / 12 480" appeared as the status *and* as the window
// position.
//
// Assembled in two steps rather than one so the separators can be dropped
// along with the parts they follow. A library with nothing scanned and
// nothing loaded should read as empty, not as " · · ".
property <string> status-phrase:
root.scanning ? root.scan-status
: (root.sweeping
? "indexing " + root.sweep-done + " / " + root.sweep-total
: root.scan-status);
property <string> status-line:
(root.total > 0 ? root.total + " images" : "")
+ (root.status-phrase != ""
? (root.total > 0 ? " · " : "") + root.status-phrase
: "")
+ (root.window-label != ""
? ((root.total > 0 || root.status-phrase != "") ? " · " : "")
+ root.window-label
: "");
callback cell-clicked(int);
/// A star was clicked on a cell: row, and the rating 0..5.
callback cell-rated(int, int);
@@ -1710,63 +1746,24 @@ export component LibraryGrid inherits Rectangle {
overflow: elide;
}
// `elide` + `horizontal-stretch: 1`, like `window-label` below:
// stretch is what actually lets a `Text` shrink under pressure
// in Slint, not `elide` alone (see the comment on the header
// row's Flickable) — without it these three readouts kept
// their full natural width and were what pushed the sidebar
// toggle and the "More" button past the right edge on a
// narrow window, reachable only by knowing to flick-scroll.
// Everything the grid has to say about itself, in one line:
// how many images, what is running over them, and where in the
// library the visible window sits. See `status-line` for why
// the four readouts that used to be here are one.
//
// `elide` + `horizontal-stretch: 1`: stretch is what actually
// lets a `Text` shrink under pressure in Slint, not `elide`
// alone (see the comment on the header row's Flickable) —
// without it this readout keeps its full natural width and is
// what pushes the sidebar toggle and the "More" button past
// the right edge on a narrow window, reachable only by knowing
// to flick-scroll.
Caption {
text: root.total > 0 ? root.total + " images" : "";
text: root.status-line;
overflow: elide;
horizontal-stretch: 1;
}
// The selection count, and how to act on it. Both appear only
// when something is selected — an empty selection has nothing
// to say and the buttons would be permanently greyed chrome.
// A live selection is state, not a label — it is the thing the
// buttons beside it act on — so it keeps `active` rather than
// dropping to ink with the counts around it.
Value {
text: root.selected-count > 0
? root.selected-count + " selected" : "";
modified: true;
compact: true;
font-weight: 600;
overflow: elide;
horizontal-stretch: 1;
}
Label {
// The scan's own status while it runs; once it is done,
// thumbnail progress takes the line over — that is the
// work the user is actually waiting on by then.
// No per-window preview count: it counted an arbitrary
// batch, so "48 / 120" described the window's size rather
// than anything the user cares about. Whole-library
// indexing is the number worth showing, and the bar below
// already says that the window itself is still filling.
text: root.scanning ? root.scan-status
: (root.sweeping
? "indexing " + root.sweep-done + " / " + root.sweep-total
: root.scan-status);
overflow: elide;
horizontal-stretch: 1;
}
// Where in the library the visible window sits. A scrubbable
// grid is disorienting without it.
Caption {
text: root.sweeping
? "indexing " + root.sweep-done + " / " + root.sweep-total
: root.window-label;
horizontal-alignment: right;
horizontal-stretch: 1;
overflow: elide;
}
// Expanded: the actions sit in the header as one row. There
// is room, and a disclosure would be a click in front of a
// button that was already visible.