A 4:1 composite drawn in one square cell is a strip a few pixels high. A photograph about twice as wide as it is tall (1.9 and up) now spans two columns, three from 2.9, with a thumbnail class of its own whose long edge is sized for that width; on the tablet, or where the columns are too few to put it beside anything, it takes the whole row. Rows are computed in one place, library_ui::layout. The grid is a lattice of slots: each cell is drawn at the slot Rust gives it, and a wide cell that would not fit in what is left of a row starts the next one, leaving the gap empty so the grid still reads in capture order. The scrollbar spans the slots, a scroll reports a slot that the layout turns back into an ordinal, and scrubs, restores and the cursor go through the same conversion. Up and down step by rows through the layout rather than by a row's worth of ordinals; left and right, a shift-click's run, burst folding and the timeline are ordinal-based and unchanged. The window's own read carries each photograph's w and h, so the cells know their shape with no query per cell. Where the wide ones sit in the whole list is one query, run when what the grid lists changes or when a window finds the layout out of date, and a library with no panorama answers it from a partial index created on first use (images_wide), not a schema bump. The merge makes the wide thumbnail for a wide composite along with the others.
58 lines
2.6 KiB
Rust
58 lines
2.6 KiB
Rust
//! TRACES: FR-CAT-4 | FR-NC-3 | NFR-P9
|
|
//! Drives the library grid from scan and thumbnail workers.
|
|
//!
|
|
//! Owns the bridge between three background activities and one single-threaded
|
|
//! event loop:
|
|
//!
|
|
//! - a **scan** worker walking the remote tree into the catalog
|
|
//! - a **thumbnail** worker range-fetching previews for visible cells
|
|
//! - the **grid model** Slint renders
|
|
//!
|
|
//! Nothing here blocks. Workers post through mpsc channels drained by Slint
|
|
//! timers, which is the same shape [`crate::launch_ui`] uses for login.
|
|
//!
|
|
//! # Why thumbnails are fetched, not derived from the scan
|
|
//!
|
|
//! A scan yields paths and sizes, nothing visual. Each thumbnail costs its own
|
|
//! range request, so they are fetched **only for cells the grid actually
|
|
//! wants** — never for the whole library up front. On the reference library
|
|
//! that is the difference between a few MB and ~370 GB (ARCH §6.7).
|
|
//!
|
|
//! Split into one module per area of behaviour (docs/dev/code-health.md CH-1):
|
|
//! `controller` holds the running state every other module reads and writes
|
|
//! through `pub(super)` fields; `open` is the launch-to-scan cycle and the
|
|
//! worker that checks the catalog file before either touches it; `offline`
|
|
//! is what of a collection is on this device and the prompt that offers to
|
|
//! change it; `window` fills the grid model from the catalog and drains the
|
|
//! thumbnail fetch; `sync` is the background passes that reach beyond the
|
|
//! loaded window — the metadata sweep, the whole-library thumbnail pass, and
|
|
//! the exchange with the server; `ratings_keywords` applies a judgement or a
|
|
//! keyword to a selection and queues the sidecar and XMP writes behind it;
|
|
//! `timeline` is the capture-time sidebar and the photographer's place,
|
|
//! which move together closely enough to live in one file; `grid` wires the
|
|
//! grid's own callbacks — the keyboard cursor, cell-size zoom, the routes
|
|
//! into and out of develop; `filter_bar` wires the rating, people, date and
|
|
//! offline-scope filters. `mod.rs` re-exports what the rest of the crate
|
|
//! calls by `library_ui::` path, so nothing outside this module needs to
|
|
//! change.
|
|
|
|
mod controller;
|
|
mod filter_bar;
|
|
mod grid;
|
|
pub(crate) mod layout;
|
|
mod offline;
|
|
mod open;
|
|
mod ratings_keywords;
|
|
mod sync;
|
|
mod timeline;
|
|
mod window;
|
|
|
|
pub use controller::LibraryController;
|
|
pub use grid::wire;
|
|
pub use open::{catalogue_composite, open, reload};
|
|
pub(crate) use open::{forget_catalog, show_catalog_now, start_rescan};
|
|
pub use ratings_keywords::paste_settings_to_selection;
|
|
pub(crate) use ratings_keywords::{save_judgements, start_sidecar_writes};
|
|
pub use timeline::format_date;
|
|
pub use window::refresh_thumbnail;
|