Move the library grid's cells and selection onto their own Slint global
AppWindow carried the grid's loaded window of cells, the keyboard cursor, drag and drop, the held-row long-press state, columns and cell size, the scroll and viewport bookkeeping, the photo roll's pick and centre-request, and the local-only/reorder/collection-filing gestures that act on a selection, as properties and callbacks on the root component. That state now lives in the `Library` global declared in library.slint, next to the structs (LibraryCell, TimelineBar, KeywordRow, PersonChip) it and the grid's other components already share; Rust reaches it through window.global::<Library>() instead of window.set_/get_/on_/invoke_ on the root, the same change collections.slint's `Collections` global made for the sidebar. library-visible stays on AppWindow: it is computed from active-page and active-view, the shell's own routing state, which a global cannot read. Everything else still prefixed library- — the timeline, the filter bar, ratings and flags, keywording, and the routes and status lines — stays on the window for now and moves in the commits that follow.
This commit is contained in:
@@ -14,7 +14,7 @@ use std::sync::mpsc::Receiver;
|
||||
use slint::{ComponentHandle, Model as _};
|
||||
|
||||
use crate::library::{self, ThumbnailMessage};
|
||||
use crate::{AppWindow, LibraryCell};
|
||||
use crate::{AppWindow, Library, LibraryCell};
|
||||
|
||||
use super::controller::{stop, LibraryController, LibraryFacts};
|
||||
use super::filter_bar::period_headings;
|
||||
@@ -245,8 +245,8 @@ pub(super) fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
// Read before it is overwritten: the property still holds what the library
|
||||
// was last time this ran, and a library that has become shorter is the
|
||||
// signal that something was deleted out from under the view.
|
||||
let was = window.get_library_total().max(0) as usize;
|
||||
window.set_library_total(total as i32);
|
||||
let was = window.global::<Library>().get_library_total().max(0) as usize;
|
||||
window.global::<Library>().set_library_total(total as i32);
|
||||
let shrank = total < was;
|
||||
|
||||
// Clamp so a scrub to the very end still fills the window rather than
|
||||
@@ -278,7 +278,7 @@ pub(super) fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
//
|
||||
// The trash is never reorderable. It is a view of what was deleted, ordered
|
||||
// by when, and it is not a collection at all.
|
||||
window.set_library_reorderable(
|
||||
window.global::<Library>().set_library_reorderable(
|
||||
!trash
|
||||
&& scope.is_some_and(|c| {
|
||||
dr_catalog::collections::orders_manually(catalog.connection(), c).unwrap_or(false)
|
||||
@@ -321,7 +321,7 @@ pub(super) fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
// Month headings. The grid is ordered by capture time, so without these a
|
||||
// wall of thumbnails gives no sense of *when* you are looking — the
|
||||
// sidebar says it, but only if you consult it.
|
||||
let columns = window.get_library_columns().max(1) as usize;
|
||||
let columns = window.global::<Library>().get_library_columns().max(1) as usize;
|
||||
let headings = period_headings(
|
||||
cells.iter().map(|c| {
|
||||
c.captured_at.map(|t| {
|
||||
@@ -335,7 +335,7 @@ pub(super) fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
|
||||
// What the outgoing model is still holding — see [`hold_thumbnails`].
|
||||
let held = {
|
||||
let previous = window.get_library_cells();
|
||||
let previous = window.global::<Library>().get_library_cells();
|
||||
let ids = ctl.image_ids.borrow();
|
||||
let classes = ctl.thumb_class.borrow();
|
||||
hold_thumbnails(&previous, &ids, &classes)
|
||||
@@ -391,7 +391,9 @@ pub(super) fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
// those fetches would have filled are absent from `requested` above, so the
|
||||
// batch started below asks for them again.
|
||||
ctl.generation.set(ctl.generation.get().wrapping_add(1));
|
||||
window.set_library_cells(slint::ModelRc::new(slint::VecModel::from(rows)));
|
||||
window
|
||||
.global::<Library>()
|
||||
.set_library_cells(slint::ModelRc::new(slint::VecModel::from(rows)));
|
||||
|
||||
// The model is fresh, so the "in this many collections" badges are all zero
|
||||
// until refilled. One query for the whole window, not one per cell.
|
||||
@@ -481,7 +483,7 @@ fn request_thumbnails(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
// The drawn cell size decides which class to ask for. Chosen once for the
|
||||
// batch rather than per row, and carried through to the drain so a cell it
|
||||
// fills can record what it is now showing.
|
||||
let cell_pixels = window.get_library_cell_size().max(1.0) as u32;
|
||||
let cell_pixels = window.global::<Library>().get_library_cell_size().max(1.0) as u32;
|
||||
let class = dr_thumbs::ThumbSize::for_cell(cell_pixels);
|
||||
|
||||
let mut wanted: Vec<library::ThumbnailRequest> = {
|
||||
@@ -602,7 +604,9 @@ pub fn refresh_thumbnail(
|
||||
|
||||
// What the grid is drawing at, so the cell can be corrected on screen
|
||||
// rather than only on disk.
|
||||
let drawn = dr_thumbs::ThumbSize::for_cell(window.get_library_cell_size().max(1.0) as u32);
|
||||
let drawn = dr_thumbs::ThumbSize::for_cell(
|
||||
window.global::<Library>().get_library_cell_size().max(1.0) as u32,
|
||||
);
|
||||
|
||||
for class in [dr_thumbs::ThumbSize::Grid, dr_thumbs::ThumbSize::Large] {
|
||||
let (w, h, rgba) = match render(class.edge()) {
|
||||
@@ -634,7 +638,7 @@ pub fn refresh_thumbnail(
|
||||
// Straight into the model, so the edit is on the cell the moment
|
||||
// the grid comes back rather than after a scroll evicts and
|
||||
// refetches it.
|
||||
let model = window.get_library_cells();
|
||||
let model = window.global::<Library>().get_library_cells();
|
||||
if let Some(mut cell) = model.row_data(row) {
|
||||
cell.thumbnail = to_slint_image(w, h, &rgba);
|
||||
cell.has_thumb = true;
|
||||
@@ -707,7 +711,7 @@ fn drain_thumbnails(
|
||||
return;
|
||||
}
|
||||
|
||||
let model = w.get_library_cells();
|
||||
let model = w.global::<Library>().get_library_cells();
|
||||
|
||||
loop {
|
||||
let msg = match rx.try_recv() {
|
||||
|
||||
Reference in New Issue
Block a user