Move ratings, flags and keywording onto the library's Slint global

The keywording sheet's rows and its open/assign/unassign callbacks, the
star and flag callbacks a cell click or a judgement key fires, the burst
toggle and representative-chosen callbacks, the trash-selection shortcut,
and the rating/unjudged/flag filter chips with their rating-counts model
move from AppWindow onto the `Library` global started in the previous
commit. Rust reaches them through window.global::<Library>() rather than
window.set_/get_/on_ on the root.
This commit is contained in:
2026-09-20 21:57:40 +02:00
parent 402dcdc24c
commit 00e2fe6aaf
8 changed files with 309 additions and 272 deletions
+17 -63
View File
@@ -506,48 +506,10 @@ export component AppWindow inherits Window {
/// Ask about a collection's local copies: the tray on a row, or a long
/// press anywhere on it.
callback collection-offline-menu(int);
/// TRACES: FR-CAT-5 | FR-CAT-6
/// Keywording the grid's selection. The catalog has been searchable by
/// keyword since it existed and there was nowhere to type one; this is it.
///
/// The vocabulary arrives already answered against the selection — each row
/// says how many of the selected photographs carry that word — because only
/// Rust knows what is selected, and a `.slint` file counting it would need
/// the selection as a second model that could disagree with the first.
in property <[KeywordRow]> library-keywords;
/// The sheet is opening: recompute the rows against the selection as it
/// stands now. Pulled rather than pushed, because the selection changes on
/// every arrow key and the sheet is shut for almost all of them.
callback library-keywords-opened();
/// Put a keyword on the selection, creating it if it is new. By name, so a
/// word typed into the field and a word tapped in the list are one path.
callback library-assign-keyword(string);
/// Take a keyword off the selection. Never deletes the keyword itself —
/// it stays in the vocabulary and on every other photograph that carries it.
callback library-unassign-keyword(string);
// --- ratings and flags (FR-CAT-5, FR-CULL-4) ---
//
// Stars and pick/reject, set from the grid and persisted to the catalog
// and the sidecar. Every image enters unrated, which is a state of its
// own rather than a zero score.
/// A star was clicked on a cell: row, then the rating 0..5.
callback library-cell-rated(int, int);
/// The trash target was clicked on one cell, by row.
callback library-cell-trashed(int);
/// The burst mark was clicked on one cell, by row (FR-CULL-5).
callback library-burst-toggled(int);
/// One frame of an open burst was named as the one the group folds to, by
/// row (FR-CULL-5).
callback library-burst-representative-chosen(int);
/// Move the grid selection to the trash — the `Delete` key.
callback library-trash-selection();
/// A judgement key was pressed, applying to the whole selection. One of
/// the two arguments is -1, saying which axis was *not* meant.
callback library-judged(int, int);
/// Whose photographs the grid is narrowed to, one entry each.
in property <[PersonChip]> library-filter-people;
@@ -566,15 +528,7 @@ export component AppWindow inherits Window {
in property <[PersonChip]> library-people;
callback library-people-listed();
callback library-filter-person-toggled(int);
in property <int> library-filter-min-rating: 0;
in property <bool> library-filter-unjudged: false;
in property <int> library-filter-flag: 0;
/// Images per star count, index 0 unrated, for the filter chips.
in-out property <[int]> library-rating-counts;
callback library-filter-min-rating-changed(int);
callback library-filter-unjudged-changed(bool);
callback library-filter-flag-changed(int);
callback next-image();
callback prev-image();
@@ -1618,10 +1572,10 @@ in property <bool> panel-visible: true;
file-in-collection(id, moves) => {
Library.library-file-in-collection(id, moves);
}
keywords: root.library-keywords;
keywords-opened() => { root.library-keywords-opened(); }
assign-keyword(word) => { root.library-assign-keyword(word); }
unassign-keyword(word) => { root.library-unassign-keyword(word); }
keywords: Library.library-keywords;
keywords-opened() => { Library.library-keywords-opened(); }
assign-keyword(word) => { Library.library-assign-keyword(word); }
unassign-keyword(word) => { Library.library-unassign-keyword(word); }
cursor: Library.library-cursor;
move-cursor(delta, extend) => {
Library.library-move-cursor(delta, extend);
@@ -1641,24 +1595,24 @@ in property <bool> panel-visible: true;
filter-eyes-open: root.library-filter-eyes-open;
people: root.library-people;
gestures: root.library-gestures;
filter-min-rating: root.library-filter-min-rating;
filter-unjudged: root.library-filter-unjudged;
filter-flag: root.library-filter-flag;
rating-counts: root.library-rating-counts;
filter-min-rating: Library.library-filter-min-rating;
filter-unjudged: Library.library-filter-unjudged;
filter-flag: Library.library-filter-flag;
rating-counts: Library.library-rating-counts;
cell-rated(i, n) => { root.library-cell-rated(i, n); }
cell-trashed(i) => { root.library-cell-trashed(i); }
burst-toggled(i) => { root.library-burst-toggled(i); }
cell-rated(i, n) => { Library.library-cell-rated(i, n); }
cell-trashed(i) => { Library.library-cell-trashed(i); }
burst-toggled(i) => { Library.library-burst-toggled(i); }
burst-representative-chosen(i) => {
root.library-burst-representative-chosen(i);
Library.library-burst-representative-chosen(i);
}
trash-selection() => { root.library-trash-selection(); }
trash-selection() => { Library.library-trash-selection(); }
// Derived from the sidebar's own selection rather than
// mirrored in a second property: `-1` is already the sentinel
// for the trash row (see collections.slint), and two sources
// for one fact is how they come to disagree.
viewing-trash: root.collection-selected == -1;
judged(rating, flag) => { root.library-judged(rating, flag); }
judged(rating, flag) => { Library.library-judged(rating, flag); }
// `F2` renames whatever the grid is scoped to. Answered from
// the sidebar's selection rather than a second property, for
// the same reason `viewing-trash` above is: one fact, one
@@ -1669,12 +1623,12 @@ in property <bool> panel-visible: true;
Collections.collection-rename-start(root.collection-selected);
}
filter-min-rating-changed(n) => {
root.library-filter-min-rating-changed(n);
Library.library-filter-min-rating-changed(n);
}
filter-unjudged-toggled(on) => {
root.library-filter-unjudged-changed(on);
Library.library-filter-unjudged-changed(on);
}
filter-flag-changed(f) => { root.library-filter-flag-changed(f); }
filter-flag-changed(f) => { Library.library-filter-flag-changed(f); }
filter-person-cleared(id) => { root.library-filter-person-cleared(id); }
filter-people-mode-toggled() => { root.library-filter-people-mode-toggled(); }
filter-eyes-open-toggled() => { root.library-filter-eyes-open-toggled(); }
+46
View File
@@ -600,6 +600,52 @@ export global Library {
in property <int> library-cursor: -1;
callback library-move-cursor(int, bool);
callback library-open-cursor();
/// TRACES: FR-CAT-5 | FR-CAT-6
/// Keywording the grid's selection. The catalog has been searchable by
/// keyword since it existed and there was nowhere to type one; this is it.
///
/// The vocabulary arrives already answered against the selection — each row
/// says how many of the selected photographs carry that word — because only
/// Rust knows what is selected, and a `.slint` file counting it would need
/// the selection as a second model that could disagree with the first.
in property <[KeywordRow]> library-keywords;
/// The sheet is opening: recompute the rows against the selection as it
/// stands now. Pulled rather than pushed, because the selection changes on
/// every arrow key and the sheet is shut for almost all of them.
callback library-keywords-opened();
/// Put a keyword on the selection, creating it if it is new. By name, so a
/// word typed into the field and a word tapped in the list are one path.
callback library-assign-keyword(string);
/// Take a keyword off the selection. Never deletes the keyword itself —
/// it stays in the vocabulary and on every other photograph that carries it.
callback library-unassign-keyword(string);
// --- ratings and flags (FR-CAT-5, FR-CULL-4) ---
//
// Stars and pick/reject, set from the grid and persisted to the catalog
// and the sidecar. Every image enters unrated, which is a state of its
// own rather than a zero score.
/// A star was clicked on a cell: row, then the rating 0..5.
callback library-cell-rated(int, int);
/// The trash target was clicked on one cell, by row.
callback library-cell-trashed(int);
/// The burst mark was clicked on one cell, by row (FR-CULL-5).
callback library-burst-toggled(int);
/// One frame of an open burst was named as the one the group folds to, by
/// row (FR-CULL-5).
callback library-burst-representative-chosen(int);
/// Move the grid selection to the trash — the `Delete` key.
callback library-trash-selection();
/// A judgement key was pressed, applying to the whole selection. One of
/// the two arguments is -1, saying which axis was *not* meant.
callback library-judged(int, int);
in property <int> library-filter-min-rating: 0;
in property <bool> library-filter-unjudged: false;
in property <int> library-filter-flag: 0;
/// Images per star count, index 0 unrated, for the filter chips.
in-out property <[int]> library-rating-counts;
callback library-filter-min-rating-changed(int);
callback library-filter-unjudged-changed(bool);
callback library-filter-flag-changed(int);
}
// The photo roll: the grid's loaded window along the foot of the develop view.