From f5edd49b6b79f025eb78c112975002d59aa72d03 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sat, 29 Aug 2026 20:04:17 +0200 Subject: [PATCH] Let a manual collection be put in the order it is meant to be seen in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `collection_members.position` and `Sort::CollectionPosition` have been in the catalog since collections were, and nothing above dr-catalog has ever written or read either: `collections::set_order` had no callers, and the grid ordered everything by capture time whatever it was scoped to — dr-ui does not construct a `Query` at all, it has its own `GRID_ORDER` constant. So a manual collection was a set with an order nobody could see or change. Three pieces, because it could not be fewer: `grid_order_for` decides the ordering from the scope, and both readers take it from there. That is the load-bearing part. An ordinal only names a photograph relative to an ordering, so the window read and the span read have to agree — a shift-click resolved through a different ORDER BY than the cells were drawn with selects a different run than the one on screen, and the user finds out when the export runs. `read_ids_span` already stated that invariant about `GRID_ORDER`; this widens it to an ordering that depends on the scope. Only a single manual collection has one. A set draws its descendants' images too, and two children's positions are unrelated integers that interleave arbitrarily; a smart collection has no member rows to carry a position at all. Both fall back to capture time and refuse the drop rather than pretending. The drop is on the cell, on whichever half of it the finger landed — the trailing edge is the only way to name the last place in a collection, since there is no cell beyond the last one to drop in front of. `reordered` is pure and the membership is rewritten whole. `set_order` sets the positions it is given and leaves the rest, so a partial write would interleave the moved run with rows nobody touched; and it is read unfiltered, so what the filter is hiding keeps its place relative to what the user can see. Co-Authored-By: Claude Opus 5 (1M context) --- core/dr-catalog/src/collections.rs | 17 ++ docs/traceability.md | 44 ++-- ui/dr-ui/src/collections_ui.rs | 118 ++++++++++ ui/dr-ui/src/library.rs | 336 ++++++++++++++++++++++++++++- ui/dr-ui/ui/app.slint | 10 + ui/dr-ui/ui/library.slint | 78 +++++++ 6 files changed, 575 insertions(+), 28 deletions(-) diff --git a/core/dr-catalog/src/collections.rs b/core/dr-catalog/src/collections.rs index 0f4a5e0..bdcbe69 100644 --- a/core/dr-catalog/src/collections.rs +++ b/core/dr-catalog/src/collections.rs @@ -477,6 +477,23 @@ pub fn collections_for_image( Ok(rows) } +/// What kind of collection `id` is, or `None` if there is no such collection. +/// +/// Cheaper than reading the whole [`Collection`] where the caller only needs to +/// know whether member rows exist — the grid asks this to decide whether manual +/// position is a thing it can order by, and a smart collection has no +/// `collection_members` rows to carry one. +pub fn kind(conn: &Connection, id: CollectionId) -> Result, CatalogError> { + let found = conn + .query_row( + "SELECT kind FROM collections WHERE id = ?1 AND deleted = 0", + [id.0 as i64], + |r| r.get::<_, i64>(0), + ) + .optional()?; + Ok(found.map(CollectionKind::from_i64)) +} + /// A collection and everything beneath it, including itself. /// /// Used for cycle checks and for scoping the grid to a parent: selecting a diff --git a/docs/traceability.md b/docs/traceability.md index 09dac0d..3a73637 100644 --- a/docs/traceability.md +++ b/docs/traceability.md @@ -10,7 +10,7 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n | Metric | Value | |---|---| | Source files scanned | 298 | -| TRACES tags found | 943 | +| TRACES tags found | 949 | | Requirements defined | 179 | | Requirements covered | 117 | | **Coverage** | **65.4%** (117/179) | @@ -38,53 +38,53 @@ _None._ | FR-CAT-11 | [`core/dr-catalog/src/dedup.rs:1`](../core/dr-catalog/src/dedup.rs#L1), [`core/dr-ingest/src/lib.rs:1`](../core/dr-ingest/src/lib.rs#L1), [`core/dr-ingest/src/lib.rs:392`](../core/dr-ingest/src/lib.rs#L392), [`core/dr-sync/src/upload.rs:40`](../core/dr-sync/src/upload.rs#L40), [`ui/dr-ui/src/import.rs:1`](../ui/dr-ui/src/import.rs#L1), [`ui/dr-ui/src/import_ui.rs:1`](../ui/dr-ui/src/import_ui.rs#L1), [`ui/dr-ui/src/lib.rs:1183`](../ui/dr-ui/src/lib.rs#L1183), [`ui/dr-ui/src/library.rs:162`](../ui/dr-ui/src/library.rs#L162), [`ui/dr-ui/src/library.rs:2375`](../ui/dr-ui/src/library.rs#L2375), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | | FR-CAT-12 | [`core/dr-pipeline/src/sidecar.rs:119`](../core/dr-pipeline/src/sidecar.rs#L119) | | FR-CAT-13 | [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1) | -| FR-CAT-15 | [`core/dr-catalog/src/schema.rs:641`](../core/dr-catalog/src/schema.rs#L641), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:457`](../core/dr-sync-nextcloud/src/lib.rs#L457), [`core/dr-sync/src/lib.rs:135`](../core/dr-sync/src/lib.rs#L135), [`core/dr-sync/src/scan.rs:429`](../core/dr-sync/src/scan.rs#L429), [`core/dr-sync/src/scan.rs:57`](../core/dr-sync/src/scan.rs#L57), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`ui/dr-ui/src/collections_ui.rs:1219`](../ui/dr-ui/src/collections_ui.rs#L1219), [`ui/dr-ui/src/collections_ui.rs:2042`](../ui/dr-ui/src/collections_ui.rs#L2042), [`ui/dr-ui/src/library.rs:162`](../ui/dr-ui/src/library.rs#L162), [`ui/dr-ui/src/library.rs:179`](../ui/dr-ui/src/library.rs#L179), [`ui/dr-ui/src/library.rs:208`](../ui/dr-ui/src/library.rs#L208), [`ui/dr-ui/src/library.rs:3869`](../ui/dr-ui/src/library.rs#L3869), [`ui/dr-ui/src/library.rs:3903`](../ui/dr-ui/src/library.rs#L3903), [`ui/dr-ui/src/library_ui.rs:190`](../ui/dr-ui/src/library_ui.rs#L190), [`ui/dr-ui/src/library_ui.rs:756`](../ui/dr-ui/src/library_ui.rs#L756), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1), [`ui/dr-ui/ui/collections.slint:572`](../ui/dr-ui/ui/collections.slint#L572) | +| FR-CAT-15 | [`core/dr-catalog/src/schema.rs:641`](../core/dr-catalog/src/schema.rs#L641), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:457`](../core/dr-sync-nextcloud/src/lib.rs#L457), [`core/dr-sync/src/lib.rs:135`](../core/dr-sync/src/lib.rs#L135), [`core/dr-sync/src/scan.rs:429`](../core/dr-sync/src/scan.rs#L429), [`core/dr-sync/src/scan.rs:57`](../core/dr-sync/src/scan.rs#L57), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`ui/dr-ui/src/collections_ui.rs:1249`](../ui/dr-ui/src/collections_ui.rs#L1249), [`ui/dr-ui/src/collections_ui.rs:2159`](../ui/dr-ui/src/collections_ui.rs#L2159), [`ui/dr-ui/src/library.rs:162`](../ui/dr-ui/src/library.rs#L162), [`ui/dr-ui/src/library.rs:179`](../ui/dr-ui/src/library.rs#L179), [`ui/dr-ui/src/library.rs:208`](../ui/dr-ui/src/library.rs#L208), [`ui/dr-ui/src/library.rs:3874`](../ui/dr-ui/src/library.rs#L3874), [`ui/dr-ui/src/library.rs:3908`](../ui/dr-ui/src/library.rs#L3908), [`ui/dr-ui/src/library_ui.rs:190`](../ui/dr-ui/src/library_ui.rs#L190), [`ui/dr-ui/src/library_ui.rs:756`](../ui/dr-ui/src/library_ui.rs#L756), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1), [`ui/dr-ui/ui/collections.slint:572`](../ui/dr-ui/ui/collections.slint#L572) | | FR-CAT-1a | [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`core/dr-types/src/lib.rs:54`](../core/dr-types/src/lib.rs#L54), [`platform/dr-plat/src/storage.rs:1`](../platform/dr-plat/src/storage.rs#L1), [`platform/dr-plat/src/storage.rs:216`](../platform/dr-plat/src/storage.rs#L216), [`platform/dr-plat/src/storage.rs:46`](../platform/dr-plat/src/storage.rs#L46) | | FR-CAT-2 | [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/schema.rs:1`](../core/dr-catalog/src/schema.rs#L1), [`tools/traceability/src/lib.rs:479`](../tools/traceability/src/lib.rs#L479) | -| FR-CAT-3 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`core/dr-catalog/src/walk.rs:66`](../core/dr-catalog/src/walk.rs#L66), [`core/dr-sync/src/scan.rs:69`](../core/dr-sync/src/scan.rs#L69), [`core/dr-thumbs/src/codec.rs:1`](../core/dr-thumbs/src/codec.rs#L1), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/import.rs:463`](../ui/dr-ui/src/import.rs#L463), [`ui/dr-ui/src/import.rs:488`](../ui/dr-ui/src/import.rs#L488), [`ui/dr-ui/src/library.rs:2848`](../ui/dr-ui/src/library.rs#L2848), [`ui/dr-ui/src/library.rs:3356`](../ui/dr-ui/src/library.rs#L3356), [`ui/dr-ui/src/library_ui.rs:172`](../ui/dr-ui/src/library_ui.rs#L172), [`ui/dr-ui/src/library_ui.rs:3627`](../ui/dr-ui/src/library_ui.rs#L3627), [`ui/dr-ui/src/library_ui.rs:4592`](../ui/dr-ui/src/library_ui.rs#L4592), [`ui/dr-ui/ui/app.slint:366`](../ui/dr-ui/ui/app.slint#L366), [`ui/dr-ui/ui/settings.slint:387`](../ui/dr-ui/ui/settings.slint#L387), [`ui/dr-ui/ui/settings.slint:73`](../ui/dr-ui/ui/settings.slint#L73) | +| FR-CAT-3 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`core/dr-catalog/src/walk.rs:66`](../core/dr-catalog/src/walk.rs#L66), [`core/dr-sync/src/scan.rs:69`](../core/dr-sync/src/scan.rs#L69), [`core/dr-thumbs/src/codec.rs:1`](../core/dr-thumbs/src/codec.rs#L1), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/import.rs:463`](../ui/dr-ui/src/import.rs#L463), [`ui/dr-ui/src/import.rs:488`](../ui/dr-ui/src/import.rs#L488), [`ui/dr-ui/src/library.rs:2848`](../ui/dr-ui/src/library.rs#L2848), [`ui/dr-ui/src/library.rs:3356`](../ui/dr-ui/src/library.rs#L3356), [`ui/dr-ui/src/library_ui.rs:172`](../ui/dr-ui/src/library_ui.rs#L172), [`ui/dr-ui/src/library_ui.rs:3627`](../ui/dr-ui/src/library_ui.rs#L3627), [`ui/dr-ui/src/library_ui.rs:4592`](../ui/dr-ui/src/library_ui.rs#L4592), [`ui/dr-ui/ui/app.slint:374`](../ui/dr-ui/ui/app.slint#L374), [`ui/dr-ui/ui/settings.slint:387`](../ui/dr-ui/ui/settings.slint#L387), [`ui/dr-ui/ui/settings.slint:73`](../ui/dr-ui/ui/settings.slint#L73) | | FR-CAT-4 | [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/query.rs:1`](../core/dr-catalog/src/query.rs#L1), [`core/dr-catalog/src/schema.rs:318`](../core/dr-catalog/src/schema.rs#L318), [`ui/dr-ui/src/library.rs:189`](../ui/dr-ui/src/library.rs#L189), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1) | -| FR-CAT-5 | [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/schema.rs:1059`](../core/dr-catalog/src/schema.rs#L1059), [`core/dr-catalog/src/schema.rs:556`](../core/dr-catalog/src/schema.rs#L556), [`core/dr-decode/src/lib.rs:285`](../core/dr-decode/src/lib.rs#L285), [`core/dr-decode/src/lib.rs:404`](../core/dr-decode/src/lib.rs#L404), [`core/dr-pipeline/src/sidecar.rs:136`](../core/dr-pipeline/src/sidecar.rs#L136), [`ui/dr-ui/src/collections_ui.rs:1558`](../ui/dr-ui/src/collections_ui.rs#L1558), [`ui/dr-ui/src/collections_ui.rs:1577`](../ui/dr-ui/src/collections_ui.rs#L1577), [`ui/dr-ui/src/collections_ui.rs:1626`](../ui/dr-ui/src/collections_ui.rs#L1626), [`ui/dr-ui/src/collections_ui.rs:243`](../ui/dr-ui/src/collections_ui.rs#L243), [`ui/dr-ui/src/collections_ui.rs:340`](../ui/dr-ui/src/collections_ui.rs#L340), [`ui/dr-ui/src/collections_ui.rs:89`](../ui/dr-ui/src/collections_ui.rs#L89), [`ui/dr-ui/src/library.rs:3917`](../ui/dr-ui/src/library.rs#L3917), [`ui/dr-ui/src/library_ui.rs:631`](../ui/dr-ui/src/library_ui.rs#L631), [`ui/dr-ui/src/library_ui.rs:6389`](../ui/dr-ui/src/library_ui.rs#L6389), [`ui/dr-ui/src/library_ui.rs:6400`](../ui/dr-ui/src/library_ui.rs#L6400), [`ui/dr-ui/src/library_ui.rs:6413`](../ui/dr-ui/src/library_ui.rs#L6413), [`ui/dr-ui/src/library_ui.rs:6428`](../ui/dr-ui/src/library_ui.rs#L6428), [`ui/dr-ui/src/library_ui.rs:6437`](../ui/dr-ui/src/library_ui.rs#L6437), [`ui/dr-ui/ui/app.slint:310`](../ui/dr-ui/ui/app.slint#L310), [`ui/dr-ui/ui/app.slint:492`](../ui/dr-ui/ui/app.slint#L492), [`ui/dr-ui/ui/library.slint:1242`](../ui/dr-ui/ui/library.slint#L1242), [`ui/dr-ui/ui/library.slint:1245`](../ui/dr-ui/ui/library.slint#L1245), [`ui/dr-ui/ui/library.slint:1287`](../ui/dr-ui/ui/library.slint#L1287), [`ui/dr-ui/ui/library.slint:18`](../ui/dr-ui/ui/library.slint#L18), [`ui/dr-ui/ui/library.slint:859`](../ui/dr-ui/ui/library.slint#L859), [`ui/dr-ui/ui/library.slint:911`](../ui/dr-ui/ui/library.slint#L911) | -| FR-CAT-6 | [`core/dr-catalog/src/collections.rs:1`](../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/query.rs:1`](../core/dr-catalog/src/query.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/schema.rs:556`](../core/dr-catalog/src/schema.rs#L556), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:63`](../core/dr-types/src/settings.rs#L63), [`core/dr-types/src/time.rs:67`](../core/dr-types/src/time.rs#L67), [`core/dr-types/src/time.rs:90`](../core/dr-types/src/time.rs#L90), [`ui/dr-ui/src/library.rs:213`](../ui/dr-ui/src/library.rs#L213), [`ui/dr-ui/src/library.rs:4163`](../ui/dr-ui/src/library.rs#L4163), [`ui/dr-ui/src/library_ui.rs:321`](../ui/dr-ui/src/library_ui.rs#L321), [`ui/dr-ui/src/library_ui.rs:393`](../ui/dr-ui/src/library_ui.rs#L393), [`ui/dr-ui/src/library_ui.rs:5203`](../ui/dr-ui/src/library_ui.rs#L5203), [`ui/dr-ui/src/library_ui.rs:5256`](../ui/dr-ui/src/library_ui.rs#L5256), [`ui/dr-ui/src/library_ui.rs:6529`](../ui/dr-ui/src/library_ui.rs#L6529), [`ui/dr-ui/ui/app.slint:314`](../ui/dr-ui/ui/app.slint#L314), [`ui/dr-ui/ui/app.slint:492`](../ui/dr-ui/ui/app.slint#L492), [`ui/dr-ui/ui/app.slint:780`](../ui/dr-ui/ui/app.slint#L780), [`ui/dr-ui/ui/library.slint:109`](../ui/dr-ui/ui/library.slint#L109), [`ui/dr-ui/ui/library.slint:1362`](../ui/dr-ui/ui/library.slint#L1362), [`ui/dr-ui/ui/library.slint:911`](../ui/dr-ui/ui/library.slint#L911), [`ui/dr-ui/ui/settings.slint:150`](../ui/dr-ui/ui/settings.slint#L150) | -| FR-CAT-7 | [`core/dr-catalog/src/collections.rs:1`](../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`ui/dr-ui/src/collections_ui.rs:1740`](../ui/dr-ui/src/collections_ui.rs#L1740), [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library_ui.rs:3489`](../ui/dr-ui/src/library_ui.rs#L3489), [`ui/dr-ui/src/library_ui.rs:4182`](../ui/dr-ui/src/library_ui.rs#L4182), [`ui/dr-ui/ui/app.slint:487`](../ui/dr-ui/ui/app.slint#L487), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/library.slint:2697`](../ui/dr-ui/ui/library.slint#L2697), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/library.slint:901`](../ui/dr-ui/ui/library.slint#L901) | +| FR-CAT-5 | [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/schema.rs:1059`](../core/dr-catalog/src/schema.rs#L1059), [`core/dr-catalog/src/schema.rs:556`](../core/dr-catalog/src/schema.rs#L556), [`core/dr-decode/src/lib.rs:285`](../core/dr-decode/src/lib.rs#L285), [`core/dr-decode/src/lib.rs:404`](../core/dr-decode/src/lib.rs#L404), [`core/dr-pipeline/src/sidecar.rs:136`](../core/dr-pipeline/src/sidecar.rs#L136), [`ui/dr-ui/src/collections_ui.rs:1588`](../ui/dr-ui/src/collections_ui.rs#L1588), [`ui/dr-ui/src/collections_ui.rs:1694`](../ui/dr-ui/src/collections_ui.rs#L1694), [`ui/dr-ui/src/collections_ui.rs:1743`](../ui/dr-ui/src/collections_ui.rs#L1743), [`ui/dr-ui/src/collections_ui.rs:244`](../ui/dr-ui/src/collections_ui.rs#L244), [`ui/dr-ui/src/collections_ui.rs:341`](../ui/dr-ui/src/collections_ui.rs#L341), [`ui/dr-ui/src/collections_ui.rs:90`](../ui/dr-ui/src/collections_ui.rs#L90), [`ui/dr-ui/src/library.rs:3922`](../ui/dr-ui/src/library.rs#L3922), [`ui/dr-ui/src/library_ui.rs:631`](../ui/dr-ui/src/library_ui.rs#L631), [`ui/dr-ui/src/library_ui.rs:6389`](../ui/dr-ui/src/library_ui.rs#L6389), [`ui/dr-ui/src/library_ui.rs:6400`](../ui/dr-ui/src/library_ui.rs#L6400), [`ui/dr-ui/src/library_ui.rs:6413`](../ui/dr-ui/src/library_ui.rs#L6413), [`ui/dr-ui/src/library_ui.rs:6428`](../ui/dr-ui/src/library_ui.rs#L6428), [`ui/dr-ui/src/library_ui.rs:6437`](../ui/dr-ui/src/library_ui.rs#L6437), [`ui/dr-ui/ui/app.slint:310`](../ui/dr-ui/ui/app.slint#L310), [`ui/dr-ui/ui/app.slint:500`](../ui/dr-ui/ui/app.slint#L500), [`ui/dr-ui/ui/library.slint:1242`](../ui/dr-ui/ui/library.slint#L1242), [`ui/dr-ui/ui/library.slint:1266`](../ui/dr-ui/ui/library.slint#L1266), [`ui/dr-ui/ui/library.slint:1308`](../ui/dr-ui/ui/library.slint#L1308), [`ui/dr-ui/ui/library.slint:18`](../ui/dr-ui/ui/library.slint#L18), [`ui/dr-ui/ui/library.slint:859`](../ui/dr-ui/ui/library.slint#L859), [`ui/dr-ui/ui/library.slint:911`](../ui/dr-ui/ui/library.slint#L911) | +| FR-CAT-6 | [`core/dr-catalog/src/collections.rs:1`](../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/query.rs:1`](../core/dr-catalog/src/query.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/schema.rs:556`](../core/dr-catalog/src/schema.rs#L556), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:63`](../core/dr-types/src/settings.rs#L63), [`core/dr-types/src/time.rs:67`](../core/dr-types/src/time.rs#L67), [`core/dr-types/src/time.rs:90`](../core/dr-types/src/time.rs#L90), [`ui/dr-ui/src/library.rs:213`](../ui/dr-ui/src/library.rs#L213), [`ui/dr-ui/src/library.rs:4313`](../ui/dr-ui/src/library.rs#L4313), [`ui/dr-ui/src/library_ui.rs:321`](../ui/dr-ui/src/library_ui.rs#L321), [`ui/dr-ui/src/library_ui.rs:393`](../ui/dr-ui/src/library_ui.rs#L393), [`ui/dr-ui/src/library_ui.rs:5203`](../ui/dr-ui/src/library_ui.rs#L5203), [`ui/dr-ui/src/library_ui.rs:5256`](../ui/dr-ui/src/library_ui.rs#L5256), [`ui/dr-ui/src/library_ui.rs:6529`](../ui/dr-ui/src/library_ui.rs#L6529), [`ui/dr-ui/ui/app.slint:322`](../ui/dr-ui/ui/app.slint#L322), [`ui/dr-ui/ui/app.slint:500`](../ui/dr-ui/ui/app.slint#L500), [`ui/dr-ui/ui/app.slint:788`](../ui/dr-ui/ui/app.slint#L788), [`ui/dr-ui/ui/library.slint:109`](../ui/dr-ui/ui/library.slint#L109), [`ui/dr-ui/ui/library.slint:1383`](../ui/dr-ui/ui/library.slint#L1383), [`ui/dr-ui/ui/library.slint:911`](../ui/dr-ui/ui/library.slint#L911), [`ui/dr-ui/ui/settings.slint:150`](../ui/dr-ui/ui/settings.slint#L150) | +| FR-CAT-7 | [`core/dr-catalog/src/collections.rs:1`](../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`ui/dr-ui/src/collections_ui.rs:1607`](../ui/dr-ui/src/collections_ui.rs#L1607), [`ui/dr-ui/src/collections_ui.rs:1857`](../ui/dr-ui/src/collections_ui.rs#L1857), [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/collections_ui.rs:945`](../ui/dr-ui/src/collections_ui.rs#L945), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library.rs:4118`](../ui/dr-ui/src/library.rs#L4118), [`ui/dr-ui/src/library.rs:4144`](../ui/dr-ui/src/library.rs#L4144), [`ui/dr-ui/src/library.rs:4199`](../ui/dr-ui/src/library.rs#L4199), [`ui/dr-ui/src/library_ui.rs:3489`](../ui/dr-ui/src/library_ui.rs#L3489), [`ui/dr-ui/src/library_ui.rs:4182`](../ui/dr-ui/src/library_ui.rs#L4182), [`ui/dr-ui/ui/app.slint:313`](../ui/dr-ui/ui/app.slint#L313), [`ui/dr-ui/ui/app.slint:495`](../ui/dr-ui/ui/app.slint#L495), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/library.slint:2718`](../ui/dr-ui/ui/library.slint#L2718), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/library.slint:901`](../ui/dr-ui/ui/library.slint#L901) | | FR-CAT-8 | [`core/dr-pipeline/src/graph.rs:346`](../core/dr-pipeline/src/graph.rs#L346), [`core/dr-pipeline/src/graph.rs:385`](../core/dr-pipeline/src/graph.rs#L385), [`core/dr-pipeline/src/ops/curve.rs:137`](../core/dr-pipeline/src/ops/curve.rs#L137), [`core/dr-pipeline/src/ops/curve.rs:656`](../core/dr-pipeline/src/ops/curve.rs#L656), [`core/dr-pipeline/src/sidecar.rs:1637`](../core/dr-pipeline/src/sidecar.rs#L1637), [`core/dr-pipeline/src/sidecar.rs:93`](../core/dr-pipeline/src/sidecar.rs#L93), [`core/dr-pipeline/src/state.rs:1`](../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../core/dr-pipeline/src/state.rs#L75), [`core/dr-pipeline/tests/tone_curve.rs:34`](../core/dr-pipeline/tests/tone_curve.rs#L34), [`ui/dr-ui/src/develop.rs:3693`](../ui/dr-ui/src/develop.rs#L3693), [`ui/dr-ui/src/develop.rs:3722`](../ui/dr-ui/src/develop.rs#L3722), [`ui/dr-ui/src/export.rs:750`](../ui/dr-ui/src/export.rs#L750), [`ui/dr-ui/src/lib.rs:1436`](../ui/dr-ui/src/lib.rs#L1436), [`ui/dr-ui/src/lib.rs:1893`](../ui/dr-ui/src/lib.rs#L1893), [`ui/dr-ui/src/lib.rs:2028`](../ui/dr-ui/src/lib.rs#L2028), [`ui/dr-ui/src/lib.rs:561`](../ui/dr-ui/src/lib.rs#L561), [`ui/dr-ui/src/lib.rs:986`](../ui/dr-ui/src/lib.rs#L986), [`ui/dr-ui/src/library.rs:1787`](../ui/dr-ui/src/library.rs#L1787), [`ui/dr-ui/src/library.rs:459`](../ui/dr-ui/src/library.rs#L459), [`ui/dr-ui/src/library.rs:506`](../ui/dr-ui/src/library.rs#L506), [`ui/dr-ui/src/library.rs:543`](../ui/dr-ui/src/library.rs#L543), [`ui/dr-ui/src/library.rs:790`](../ui/dr-ui/src/library.rs#L790), [`ui/dr-ui/src/library_ui.rs:4884`](../ui/dr-ui/src/library_ui.rs#L4884), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1) | -| FR-CAT-9 | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/schema.rs:613`](../core/dr-catalog/src/schema.rs#L613), [`core/dr-catalog/src/walk.rs:162`](../core/dr-catalog/src/walk.rs#L162), [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`core/dr-catalog/src/walk.rs:435`](../core/dr-catalog/src/walk.rs#L435), [`core/dr-catalog/src/walk.rs:704`](../core/dr-catalog/src/walk.rs#L704), [`core/dr-sync-nextcloud/src/desktop_client.rs:30`](../core/dr-sync-nextcloud/src/desktop_client.rs#L30), [`core/dr-sync/src/reachability.rs:1`](../core/dr-sync/src/reachability.rs#L1), [`core/dr-types/src/lib.rs:120`](../core/dr-types/src/lib.rs#L120), [`ui/dr-ui/src/develop.rs:3120`](../ui/dr-ui/src/develop.rs#L3120), [`ui/dr-ui/src/library.rs:148`](../ui/dr-ui/src/library.rs#L148), [`ui/dr-ui/src/library.rs:1747`](../ui/dr-ui/src/library.rs#L1747), [`ui/dr-ui/src/library.rs:1823`](../ui/dr-ui/src/library.rs#L1823), [`ui/dr-ui/src/library.rs:233`](../ui/dr-ui/src/library.rs#L233), [`ui/dr-ui/src/library.rs:4270`](../ui/dr-ui/src/library.rs#L4270), [`ui/dr-ui/src/library.rs:543`](../ui/dr-ui/src/library.rs#L543), [`ui/dr-ui/src/library.rs:774`](../ui/dr-ui/src/library.rs#L774), [`ui/dr-ui/src/library.rs:790`](../ui/dr-ui/src/library.rs#L790), [`ui/dr-ui/src/library.rs:844`](../ui/dr-ui/src/library.rs#L844), [`ui/dr-ui/src/library_ui.rs:1580`](../ui/dr-ui/src/library_ui.rs#L1580), [`ui/dr-ui/src/library_ui.rs:1606`](../ui/dr-ui/src/library_ui.rs#L1606), [`ui/dr-ui/src/library_ui.rs:1622`](../ui/dr-ui/src/library_ui.rs#L1622), [`ui/dr-ui/src/library_ui.rs:1716`](../ui/dr-ui/src/library_ui.rs#L1716), [`ui/dr-ui/src/library_ui.rs:232`](../ui/dr-ui/src/library_ui.rs#L232), [`ui/dr-ui/src/library_ui.rs:2332`](../ui/dr-ui/src/library_ui.rs#L2332), [`ui/dr-ui/src/library_ui.rs:265`](../ui/dr-ui/src/library_ui.rs#L265), [`ui/dr-ui/src/library_ui.rs:2770`](../ui/dr-ui/src/library_ui.rs#L2770), [`ui/dr-ui/src/library_ui.rs:2992`](../ui/dr-ui/src/library_ui.rs#L2992), [`ui/dr-ui/src/library_ui.rs:3270`](../ui/dr-ui/src/library_ui.rs#L3270), [`ui/dr-ui/src/library_ui.rs:3358`](../ui/dr-ui/src/library_ui.rs#L3358), [`ui/dr-ui/src/library_ui.rs:3540`](../ui/dr-ui/src/library_ui.rs#L3540), [`ui/dr-ui/src/library_ui.rs:3654`](../ui/dr-ui/src/library_ui.rs#L3654), [`ui/dr-ui/src/library_ui.rs:446`](../ui/dr-ui/src/library_ui.rs#L446), [`ui/dr-ui/src/library_ui.rs:504`](../ui/dr-ui/src/library_ui.rs#L504), [`ui/dr-ui/src/library_ui.rs:5301`](../ui/dr-ui/src/library_ui.rs#L5301), [`ui/dr-ui/src/library_ui.rs:5416`](../ui/dr-ui/src/library_ui.rs#L5416), [`ui/dr-ui/src/presets.rs:446`](../ui/dr-ui/src/presets.rs#L446), [`ui/dr-ui/src/presets.rs:458`](../ui/dr-ui/src/presets.rs#L458), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1) | +| FR-CAT-9 | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/schema.rs:613`](../core/dr-catalog/src/schema.rs#L613), [`core/dr-catalog/src/walk.rs:162`](../core/dr-catalog/src/walk.rs#L162), [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`core/dr-catalog/src/walk.rs:435`](../core/dr-catalog/src/walk.rs#L435), [`core/dr-catalog/src/walk.rs:704`](../core/dr-catalog/src/walk.rs#L704), [`core/dr-sync-nextcloud/src/desktop_client.rs:30`](../core/dr-sync-nextcloud/src/desktop_client.rs#L30), [`core/dr-sync/src/reachability.rs:1`](../core/dr-sync/src/reachability.rs#L1), [`core/dr-types/src/lib.rs:120`](../core/dr-types/src/lib.rs#L120), [`ui/dr-ui/src/develop.rs:3120`](../ui/dr-ui/src/develop.rs#L3120), [`ui/dr-ui/src/library.rs:148`](../ui/dr-ui/src/library.rs#L148), [`ui/dr-ui/src/library.rs:1747`](../ui/dr-ui/src/library.rs#L1747), [`ui/dr-ui/src/library.rs:1823`](../ui/dr-ui/src/library.rs#L1823), [`ui/dr-ui/src/library.rs:233`](../ui/dr-ui/src/library.rs#L233), [`ui/dr-ui/src/library.rs:4420`](../ui/dr-ui/src/library.rs#L4420), [`ui/dr-ui/src/library.rs:543`](../ui/dr-ui/src/library.rs#L543), [`ui/dr-ui/src/library.rs:774`](../ui/dr-ui/src/library.rs#L774), [`ui/dr-ui/src/library.rs:790`](../ui/dr-ui/src/library.rs#L790), [`ui/dr-ui/src/library.rs:844`](../ui/dr-ui/src/library.rs#L844), [`ui/dr-ui/src/library_ui.rs:1580`](../ui/dr-ui/src/library_ui.rs#L1580), [`ui/dr-ui/src/library_ui.rs:1606`](../ui/dr-ui/src/library_ui.rs#L1606), [`ui/dr-ui/src/library_ui.rs:1622`](../ui/dr-ui/src/library_ui.rs#L1622), [`ui/dr-ui/src/library_ui.rs:1716`](../ui/dr-ui/src/library_ui.rs#L1716), [`ui/dr-ui/src/library_ui.rs:232`](../ui/dr-ui/src/library_ui.rs#L232), [`ui/dr-ui/src/library_ui.rs:2332`](../ui/dr-ui/src/library_ui.rs#L2332), [`ui/dr-ui/src/library_ui.rs:265`](../ui/dr-ui/src/library_ui.rs#L265), [`ui/dr-ui/src/library_ui.rs:2770`](../ui/dr-ui/src/library_ui.rs#L2770), [`ui/dr-ui/src/library_ui.rs:2992`](../ui/dr-ui/src/library_ui.rs#L2992), [`ui/dr-ui/src/library_ui.rs:3270`](../ui/dr-ui/src/library_ui.rs#L3270), [`ui/dr-ui/src/library_ui.rs:3358`](../ui/dr-ui/src/library_ui.rs#L3358), [`ui/dr-ui/src/library_ui.rs:3540`](../ui/dr-ui/src/library_ui.rs#L3540), [`ui/dr-ui/src/library_ui.rs:3654`](../ui/dr-ui/src/library_ui.rs#L3654), [`ui/dr-ui/src/library_ui.rs:446`](../ui/dr-ui/src/library_ui.rs#L446), [`ui/dr-ui/src/library_ui.rs:504`](../ui/dr-ui/src/library_ui.rs#L504), [`ui/dr-ui/src/library_ui.rs:5301`](../ui/dr-ui/src/library_ui.rs#L5301), [`ui/dr-ui/src/library_ui.rs:5416`](../ui/dr-ui/src/library_ui.rs#L5416), [`ui/dr-ui/src/presets.rs:446`](../ui/dr-ui/src/presets.rs#L446), [`ui/dr-ui/src/presets.rs:458`](../ui/dr-ui/src/presets.rs#L458), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1) | | FR-CULL-1 | [`core/dr-decode/src/preview.rs:121`](../core/dr-decode/src/preview.rs#L121) | | FR-CULL-10 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:357`](../core/dr-catalog/src/schema.rs#L357), [`core/dr-catalog/src/schema.rs:442`](../core/dr-catalog/src/schema.rs#L442), [`core/dr-face/src/assign.rs:1`](../core/dr-face/src/assign.rs#L1), [`core/dr-face/src/neighbours.rs:1`](../core/dr-face/src/neighbours.rs#L1), [`ui/dr-ui/src/develop.rs:120`](../ui/dr-ui/src/develop.rs#L120), [`ui/dr-ui/src/develop.rs:129`](../ui/dr-ui/src/develop.rs#L129), [`ui/dr-ui/src/develop.rs:1944`](../ui/dr-ui/src/develop.rs#L1944), [`ui/dr-ui/src/develop.rs:195`](../ui/dr-ui/src/develop.rs#L195), [`ui/dr-ui/src/develop.rs:688`](../ui/dr-ui/src/develop.rs#L688), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/identity.rs:1`](../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1`](../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/lib.rs:2000`](../ui/dr-ui/src/lib.rs#L2000), [`ui/dr-ui/ui/identity.slint:1`](../ui/dr-ui/ui/identity.slint#L1) | | FR-CULL-11 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:442`](../core/dr-catalog/src/schema.rs#L442), [`ui/dr-ui/src/identity.rs:1`](../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1`](../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/library.rs:254`](../ui/dr-ui/src/library.rs#L254), [`ui/dr-ui/src/library.rs:284`](../ui/dr-ui/src/library.rs#L284), [`ui/dr-ui/ui/identity.slint:1`](../ui/dr-ui/ui/identity.slint#L1) | | FR-CULL-12 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:357`](../core/dr-catalog/src/schema.rs#L357), [`core/dr-catalog/src/schema.rs:442`](../core/dr-catalog/src/schema.rs#L442), [`ui/dr-ui/src/identity.rs:1`](../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/ui/identity.slint:1`](../ui/dr-ui/ui/identity.slint#L1) | | FR-CULL-2 | [`core/dr-decode/src/locate.rs:1`](../core/dr-decode/src/locate.rs#L1), [`core/dr-decode/src/preview.rs:148`](../core/dr-decode/src/preview.rs#L148), [`ui/dr-ui/src/import.rs:463`](../ui/dr-ui/src/import.rs#L463) | -| FR-CULL-3 | [`core/dr-gpu/src/focus.rs:154`](../core/dr-gpu/src/focus.rs#L154), [`core/dr-gpu/src/focus.rs:186`](../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`ui/dr-ui/src/develop.rs:2930`](../ui/dr-ui/src/develop.rs#L2930), [`ui/dr-ui/src/develop.rs:2941`](../ui/dr-ui/src/develop.rs#L2941), [`ui/dr-ui/src/develop.rs:2947`](../ui/dr-ui/src/develop.rs#L2947), [`ui/dr-ui/src/develop.rs:2964`](../ui/dr-ui/src/develop.rs#L2964), [`ui/dr-ui/src/develop.rs:726`](../ui/dr-ui/src/develop.rs#L726), [`ui/dr-ui/src/develop.rs:732`](../ui/dr-ui/src/develop.rs#L732), [`ui/dr-ui/src/lib.rs:1475`](../ui/dr-ui/src/lib.rs#L1475), [`ui/dr-ui/src/lib.rs:1553`](../ui/dr-ui/src/lib.rs#L1553), [`ui/dr-ui/src/lib.rs:1626`](../ui/dr-ui/src/lib.rs#L1626), [`ui/dr-ui/src/lib.rs:1660`](../ui/dr-ui/src/lib.rs#L1660), [`ui/dr-ui/src/lib.rs:2910`](../ui/dr-ui/src/lib.rs#L2910), [`ui/dr-ui/src/lib.rs:321`](../ui/dr-ui/src/lib.rs#L321), [`ui/dr-ui/src/peaking.rs:1`](../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:1693`](../ui/dr-ui/ui/app.slint#L1693), [`ui/dr-ui/ui/app.slint:2238`](../ui/dr-ui/ui/app.slint#L2238), [`ui/dr-ui/ui/app.slint:75`](../ui/dr-ui/ui/app.slint#L75), [`ui/dr-ui/ui/peaking.slint:1`](../ui/dr-ui/ui/peaking.slint#L1), [`ui/dr-ui/ui/peaking.slint:25`](../ui/dr-ui/ui/peaking.slint#L25), [`ui/dr-ui/ui/peaking.slint:56`](../ui/dr-ui/ui/peaking.slint#L56) | +| FR-CULL-3 | [`core/dr-gpu/src/focus.rs:154`](../core/dr-gpu/src/focus.rs#L154), [`core/dr-gpu/src/focus.rs:186`](../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`ui/dr-ui/src/develop.rs:2930`](../ui/dr-ui/src/develop.rs#L2930), [`ui/dr-ui/src/develop.rs:2941`](../ui/dr-ui/src/develop.rs#L2941), [`ui/dr-ui/src/develop.rs:2947`](../ui/dr-ui/src/develop.rs#L2947), [`ui/dr-ui/src/develop.rs:2964`](../ui/dr-ui/src/develop.rs#L2964), [`ui/dr-ui/src/develop.rs:726`](../ui/dr-ui/src/develop.rs#L726), [`ui/dr-ui/src/develop.rs:732`](../ui/dr-ui/src/develop.rs#L732), [`ui/dr-ui/src/lib.rs:1475`](../ui/dr-ui/src/lib.rs#L1475), [`ui/dr-ui/src/lib.rs:1553`](../ui/dr-ui/src/lib.rs#L1553), [`ui/dr-ui/src/lib.rs:1626`](../ui/dr-ui/src/lib.rs#L1626), [`ui/dr-ui/src/lib.rs:1660`](../ui/dr-ui/src/lib.rs#L1660), [`ui/dr-ui/src/lib.rs:2910`](../ui/dr-ui/src/lib.rs#L2910), [`ui/dr-ui/src/lib.rs:321`](../ui/dr-ui/src/lib.rs#L321), [`ui/dr-ui/src/peaking.rs:1`](../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:1703`](../ui/dr-ui/ui/app.slint#L1703), [`ui/dr-ui/ui/app.slint:2248`](../ui/dr-ui/ui/app.slint#L2248), [`ui/dr-ui/ui/app.slint:75`](../ui/dr-ui/ui/app.slint#L75), [`ui/dr-ui/ui/peaking.slint:1`](../ui/dr-ui/ui/peaking.slint#L1), [`ui/dr-ui/ui/peaking.slint:25`](../ui/dr-ui/ui/peaking.slint#L25), [`ui/dr-ui/ui/peaking.slint:56`](../ui/dr-ui/ui/peaking.slint#L56) | | FR-CULL-4 | [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-pipeline/src/sidecar.rs:136`](../core/dr-pipeline/src/sidecar.rs#L136), [`ui/dr-ui/src/library.rs:213`](../ui/dr-ui/src/library.rs#L213), [`ui/dr-ui/src/library.rs:459`](../ui/dr-ui/src/library.rs#L459) | | FR-CULL-8 | [`core/dr-catalog/src/face_shard.rs:1`](../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:401`](../core/dr-catalog/src/schema.rs#L401), [`core/dr-catalog/src/schema.rs:442`](../core/dr-catalog/src/schema.rs#L442), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/library.rs:2849`](../ui/dr-ui/src/library.rs#L2849), [`ui/dr-ui/src/library.rs:2953`](../ui/dr-ui/src/library.rs#L2953), [`ui/dr-ui/ui/settings.slint:419`](../ui/dr-ui/ui/settings.slint#L419), [`ui/dr-ui/ui/settings.slint:82`](../ui/dr-ui/ui/settings.slint#L82) | | FR-CULL-9 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:442`](../core/dr-catalog/src/schema.rs#L442), [`core/dr-face/src/assign.rs:1`](../core/dr-face/src/assign.rs#L1), [`core/dr-face/src/neighbours.rs:1`](../core/dr-face/src/neighbours.rs#L1), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1`](../ui/dr-ui/src/identity_ui.rs#L1) | | FR-DEV-1 | [`core/dr-pipeline/src/graph.rs:1`](../core/dr-pipeline/src/graph.rs#L1), [`core/dr-pipeline/src/sidecar.rs:1`](../core/dr-pipeline/src/sidecar.rs#L1) | | FR-DEV-2 | [`core/dr-pipeline/src/operation.rs:389`](../core/dr-pipeline/src/operation.rs#L389) | -| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:2165`](../core/dr-gpu/src/adjust.rs#L2165), [`core/dr-gpu/src/adjust.rs:651`](../core/dr-gpu/src/adjust.rs#L651), [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/adjust.rs:84`](../core/dr-gpu/src/adjust.rs#L84), [`core/dr-gpu/tests/tone_curve.rs:1`](../core/dr-gpu/tests/tone_curve.rs#L1), [`core/dr-pipeline/src/detail.rs:434`](../core/dr-pipeline/src/detail.rs#L434), [`core/dr-pipeline/src/detail.rs:524`](../core/dr-pipeline/src/detail.rs#L524), [`core/dr-pipeline/src/framing.rs:177`](../core/dr-pipeline/src/framing.rs#L177), [`core/dr-pipeline/src/framing.rs:234`](../core/dr-pipeline/src/framing.rs#L234), [`core/dr-pipeline/src/framing.rs:314`](../core/dr-pipeline/src/framing.rs#L314), [`core/dr-pipeline/src/framing.rs:488`](../core/dr-pipeline/src/framing.rs#L488), [`core/dr-pipeline/src/framing.rs:743`](../core/dr-pipeline/src/framing.rs#L743), [`core/dr-pipeline/src/graph.rs:170`](../core/dr-pipeline/src/graph.rs#L170), [`core/dr-pipeline/src/graph.rs:578`](../core/dr-pipeline/src/graph.rs#L578), [`core/dr-pipeline/src/mask.rs:121`](../core/dr-pipeline/src/mask.rs#L121), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:516`](../core/dr-pipeline/src/operation.rs#L516), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:210`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L210), [`core/dr-pipeline/src/ops/curve.rs:100`](../core/dr-pipeline/src/ops/curve.rs#L100), [`core/dr-pipeline/src/ops/curve.rs:1`](../core/dr-pipeline/src/ops/curve.rs#L1), [`core/dr-pipeline/src/ops/curve.rs:219`](../core/dr-pipeline/src/ops/curve.rs#L219), [`core/dr-pipeline/src/ops/curve.rs:635`](../core/dr-pipeline/src/ops/curve.rs#L635), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:1`](../core/dr-pipeline/src/ops/noise_reduction.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:273`](../core/dr-pipeline/src/ops/noise_reduction.rs#L273), [`core/dr-pipeline/src/sidecar.rs:157`](../core/dr-pipeline/src/sidecar.rs#L157), [`core/dr-pipeline/src/sidecar.rs:1637`](../core/dr-pipeline/src/sidecar.rs#L1637), [`core/dr-pipeline/src/sidecar.rs:1697`](../core/dr-pipeline/src/sidecar.rs#L1697), [`core/dr-pipeline/tests/tone_curve.rs:1`](../core/dr-pipeline/tests/tone_curve.rs#L1), [`ui/dr-ui/src/develop.rs:102`](../ui/dr-ui/src/develop.rs#L102), [`ui/dr-ui/src/develop.rs:1448`](../ui/dr-ui/src/develop.rs#L1448), [`ui/dr-ui/src/develop.rs:164`](../ui/dr-ui/src/develop.rs#L164), [`ui/dr-ui/src/develop.rs:1926`](../ui/dr-ui/src/develop.rs#L1926), [`ui/dr-ui/src/develop.rs:1944`](../ui/dr-ui/src/develop.rs#L1944), [`ui/dr-ui/src/develop.rs:1958`](../ui/dr-ui/src/develop.rs#L1958), [`ui/dr-ui/src/develop.rs:1980`](../ui/dr-ui/src/develop.rs#L1980), [`ui/dr-ui/src/develop.rs:2126`](../ui/dr-ui/src/develop.rs#L2126), [`ui/dr-ui/src/develop.rs:2224`](../ui/dr-ui/src/develop.rs#L2224), [`ui/dr-ui/src/develop.rs:327`](../ui/dr-ui/src/develop.rs#L327), [`ui/dr-ui/src/develop.rs:3391`](../ui/dr-ui/src/develop.rs#L3391), [`ui/dr-ui/src/develop.rs:3421`](../ui/dr-ui/src/develop.rs#L3421), [`ui/dr-ui/src/develop.rs:3487`](../ui/dr-ui/src/develop.rs#L3487), [`ui/dr-ui/src/develop.rs:3501`](../ui/dr-ui/src/develop.rs#L3501), [`ui/dr-ui/src/develop.rs:364`](../ui/dr-ui/src/develop.rs#L364), [`ui/dr-ui/src/develop.rs:3693`](../ui/dr-ui/src/develop.rs#L3693), [`ui/dr-ui/src/develop.rs:4353`](../ui/dr-ui/src/develop.rs#L4353), [`ui/dr-ui/src/develop.rs:4407`](../ui/dr-ui/src/develop.rs#L4407), [`ui/dr-ui/src/develop.rs:4451`](../ui/dr-ui/src/develop.rs#L4451), [`ui/dr-ui/src/develop.rs:4501`](../ui/dr-ui/src/develop.rs#L4501), [`ui/dr-ui/src/develop.rs:587`](../ui/dr-ui/src/develop.rs#L587), [`ui/dr-ui/src/develop.rs:648`](../ui/dr-ui/src/develop.rs#L648), [`ui/dr-ui/src/develop.rs:746`](../ui/dr-ui/src/develop.rs#L746), [`ui/dr-ui/src/develop.rs:793`](../ui/dr-ui/src/develop.rs#L793), [`ui/dr-ui/src/develop.rs:822`](../ui/dr-ui/src/develop.rs#L822), [`ui/dr-ui/src/lib.rs:1534`](../ui/dr-ui/src/lib.rs#L1534), [`ui/dr-ui/src/lib.rs:2303`](../ui/dr-ui/src/lib.rs#L2303), [`ui/dr-ui/src/lib.rs:2499`](../ui/dr-ui/src/lib.rs#L2499), [`ui/dr-ui/src/lib.rs:2671`](../ui/dr-ui/src/lib.rs#L2671), [`ui/dr-ui/src/lib.rs:2735`](../ui/dr-ui/src/lib.rs#L2735), [`ui/dr-ui/src/lib.rs:2789`](../ui/dr-ui/src/lib.rs#L2789), [`ui/dr-ui/src/lib.rs:327`](../ui/dr-ui/src/lib.rs#L327), [`ui/dr-ui/src/lib.rs:370`](../ui/dr-ui/src/lib.rs#L370), [`ui/dr-ui/src/lib.rs:393`](../ui/dr-ui/src/lib.rs#L393), [`ui/dr-ui/src/library.rs:506`](../ui/dr-ui/src/library.rs#L506), [`ui/dr-ui/src/masks_ui.rs:218`](../ui/dr-ui/src/masks_ui.rs#L218), [`ui/dr-ui/src/masks_ui.rs:41`](../ui/dr-ui/src/masks_ui.rs#L41), [`ui/dr-ui/src/masks_ui.rs:816`](../ui/dr-ui/src/masks_ui.rs#L816), [`ui/dr-ui/src/masks_ui.rs:930`](../ui/dr-ui/src/masks_ui.rs#L930), [`ui/dr-ui/src/segmentation.rs:219`](../ui/dr-ui/src/segmentation.rs#L219), [`ui/dr-ui/src/segmentation.rs:322`](../ui/dr-ui/src/segmentation.rs#L322), [`ui/dr-ui/src/segmentation.rs:350`](../ui/dr-ui/src/segmentation.rs#L350), [`ui/dr-ui/ui/adjust.slint:517`](../ui/dr-ui/ui/adjust.slint#L517), [`ui/dr-ui/ui/adjust.slint:635`](../ui/dr-ui/ui/adjust.slint#L635), [`ui/dr-ui/ui/app.slint:136`](../ui/dr-ui/ui/app.slint#L136), [`ui/dr-ui/ui/app.slint:182`](../ui/dr-ui/ui/app.slint#L182), [`ui/dr-ui/ui/app.slint:1895`](../ui/dr-ui/ui/app.slint#L1895), [`ui/dr-ui/ui/app.slint:890`](../ui/dr-ui/ui/app.slint#L890), [`ui/dr-ui/ui/masks.slint:524`](../ui/dr-ui/ui/masks.slint#L524) | +| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:2165`](../core/dr-gpu/src/adjust.rs#L2165), [`core/dr-gpu/src/adjust.rs:651`](../core/dr-gpu/src/adjust.rs#L651), [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/adjust.rs:84`](../core/dr-gpu/src/adjust.rs#L84), [`core/dr-gpu/tests/tone_curve.rs:1`](../core/dr-gpu/tests/tone_curve.rs#L1), [`core/dr-pipeline/src/detail.rs:434`](../core/dr-pipeline/src/detail.rs#L434), [`core/dr-pipeline/src/detail.rs:524`](../core/dr-pipeline/src/detail.rs#L524), [`core/dr-pipeline/src/framing.rs:177`](../core/dr-pipeline/src/framing.rs#L177), [`core/dr-pipeline/src/framing.rs:234`](../core/dr-pipeline/src/framing.rs#L234), [`core/dr-pipeline/src/framing.rs:314`](../core/dr-pipeline/src/framing.rs#L314), [`core/dr-pipeline/src/framing.rs:488`](../core/dr-pipeline/src/framing.rs#L488), [`core/dr-pipeline/src/framing.rs:743`](../core/dr-pipeline/src/framing.rs#L743), [`core/dr-pipeline/src/graph.rs:170`](../core/dr-pipeline/src/graph.rs#L170), [`core/dr-pipeline/src/graph.rs:578`](../core/dr-pipeline/src/graph.rs#L578), [`core/dr-pipeline/src/mask.rs:121`](../core/dr-pipeline/src/mask.rs#L121), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:516`](../core/dr-pipeline/src/operation.rs#L516), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:210`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L210), [`core/dr-pipeline/src/ops/curve.rs:100`](../core/dr-pipeline/src/ops/curve.rs#L100), [`core/dr-pipeline/src/ops/curve.rs:1`](../core/dr-pipeline/src/ops/curve.rs#L1), [`core/dr-pipeline/src/ops/curve.rs:219`](../core/dr-pipeline/src/ops/curve.rs#L219), [`core/dr-pipeline/src/ops/curve.rs:635`](../core/dr-pipeline/src/ops/curve.rs#L635), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:1`](../core/dr-pipeline/src/ops/noise_reduction.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:273`](../core/dr-pipeline/src/ops/noise_reduction.rs#L273), [`core/dr-pipeline/src/sidecar.rs:157`](../core/dr-pipeline/src/sidecar.rs#L157), [`core/dr-pipeline/src/sidecar.rs:1637`](../core/dr-pipeline/src/sidecar.rs#L1637), [`core/dr-pipeline/src/sidecar.rs:1697`](../core/dr-pipeline/src/sidecar.rs#L1697), [`core/dr-pipeline/tests/tone_curve.rs:1`](../core/dr-pipeline/tests/tone_curve.rs#L1), [`ui/dr-ui/src/develop.rs:102`](../ui/dr-ui/src/develop.rs#L102), [`ui/dr-ui/src/develop.rs:1448`](../ui/dr-ui/src/develop.rs#L1448), [`ui/dr-ui/src/develop.rs:164`](../ui/dr-ui/src/develop.rs#L164), [`ui/dr-ui/src/develop.rs:1926`](../ui/dr-ui/src/develop.rs#L1926), [`ui/dr-ui/src/develop.rs:1944`](../ui/dr-ui/src/develop.rs#L1944), [`ui/dr-ui/src/develop.rs:1958`](../ui/dr-ui/src/develop.rs#L1958), [`ui/dr-ui/src/develop.rs:1980`](../ui/dr-ui/src/develop.rs#L1980), [`ui/dr-ui/src/develop.rs:2126`](../ui/dr-ui/src/develop.rs#L2126), [`ui/dr-ui/src/develop.rs:2224`](../ui/dr-ui/src/develop.rs#L2224), [`ui/dr-ui/src/develop.rs:327`](../ui/dr-ui/src/develop.rs#L327), [`ui/dr-ui/src/develop.rs:3391`](../ui/dr-ui/src/develop.rs#L3391), [`ui/dr-ui/src/develop.rs:3421`](../ui/dr-ui/src/develop.rs#L3421), [`ui/dr-ui/src/develop.rs:3487`](../ui/dr-ui/src/develop.rs#L3487), [`ui/dr-ui/src/develop.rs:3501`](../ui/dr-ui/src/develop.rs#L3501), [`ui/dr-ui/src/develop.rs:364`](../ui/dr-ui/src/develop.rs#L364), [`ui/dr-ui/src/develop.rs:3693`](../ui/dr-ui/src/develop.rs#L3693), [`ui/dr-ui/src/develop.rs:4353`](../ui/dr-ui/src/develop.rs#L4353), [`ui/dr-ui/src/develop.rs:4407`](../ui/dr-ui/src/develop.rs#L4407), [`ui/dr-ui/src/develop.rs:4451`](../ui/dr-ui/src/develop.rs#L4451), [`ui/dr-ui/src/develop.rs:4501`](../ui/dr-ui/src/develop.rs#L4501), [`ui/dr-ui/src/develop.rs:587`](../ui/dr-ui/src/develop.rs#L587), [`ui/dr-ui/src/develop.rs:648`](../ui/dr-ui/src/develop.rs#L648), [`ui/dr-ui/src/develop.rs:746`](../ui/dr-ui/src/develop.rs#L746), [`ui/dr-ui/src/develop.rs:793`](../ui/dr-ui/src/develop.rs#L793), [`ui/dr-ui/src/develop.rs:822`](../ui/dr-ui/src/develop.rs#L822), [`ui/dr-ui/src/lib.rs:1534`](../ui/dr-ui/src/lib.rs#L1534), [`ui/dr-ui/src/lib.rs:2303`](../ui/dr-ui/src/lib.rs#L2303), [`ui/dr-ui/src/lib.rs:2499`](../ui/dr-ui/src/lib.rs#L2499), [`ui/dr-ui/src/lib.rs:2671`](../ui/dr-ui/src/lib.rs#L2671), [`ui/dr-ui/src/lib.rs:2735`](../ui/dr-ui/src/lib.rs#L2735), [`ui/dr-ui/src/lib.rs:2789`](../ui/dr-ui/src/lib.rs#L2789), [`ui/dr-ui/src/lib.rs:327`](../ui/dr-ui/src/lib.rs#L327), [`ui/dr-ui/src/lib.rs:370`](../ui/dr-ui/src/lib.rs#L370), [`ui/dr-ui/src/lib.rs:393`](../ui/dr-ui/src/lib.rs#L393), [`ui/dr-ui/src/library.rs:506`](../ui/dr-ui/src/library.rs#L506), [`ui/dr-ui/src/masks_ui.rs:218`](../ui/dr-ui/src/masks_ui.rs#L218), [`ui/dr-ui/src/masks_ui.rs:41`](../ui/dr-ui/src/masks_ui.rs#L41), [`ui/dr-ui/src/masks_ui.rs:816`](../ui/dr-ui/src/masks_ui.rs#L816), [`ui/dr-ui/src/masks_ui.rs:930`](../ui/dr-ui/src/masks_ui.rs#L930), [`ui/dr-ui/src/segmentation.rs:219`](../ui/dr-ui/src/segmentation.rs#L219), [`ui/dr-ui/src/segmentation.rs:322`](../ui/dr-ui/src/segmentation.rs#L322), [`ui/dr-ui/src/segmentation.rs:350`](../ui/dr-ui/src/segmentation.rs#L350), [`ui/dr-ui/ui/adjust.slint:517`](../ui/dr-ui/ui/adjust.slint#L517), [`ui/dr-ui/ui/adjust.slint:635`](../ui/dr-ui/ui/adjust.slint#L635), [`ui/dr-ui/ui/app.slint:136`](../ui/dr-ui/ui/app.slint#L136), [`ui/dr-ui/ui/app.slint:182`](../ui/dr-ui/ui/app.slint#L182), [`ui/dr-ui/ui/app.slint:1905`](../ui/dr-ui/ui/app.slint#L1905), [`ui/dr-ui/ui/app.slint:898`](../ui/dr-ui/ui/app.slint#L898), [`ui/dr-ui/ui/masks.slint:524`](../ui/dr-ui/ui/masks.slint#L524) | | FR-DEV-3a | [`core/dr-pipeline/build.rs:756`](../core/dr-pipeline/build.rs#L756), [`core/dr-pipeline/ops/exposure.yaml:1`](../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/descriptor.rs:194`](../core/dr-pipeline/src/descriptor.rs#L194), [`core/dr-pipeline/src/descriptor.rs:234`](../core/dr-pipeline/src/descriptor.rs#L234), [`core/dr-pipeline/src/descriptor.rs:258`](../core/dr-pipeline/src/descriptor.rs#L258), [`core/dr-pipeline/src/descriptor.rs:313`](../core/dr-pipeline/src/descriptor.rs#L313), [`core/dr-pipeline/src/framing.rs:385`](../core/dr-pipeline/src/framing.rs#L385), [`core/dr-pipeline/src/graph.rs:24`](../core/dr-pipeline/src/graph.rs#L24), [`core/dr-pipeline/src/graph.rs:251`](../core/dr-pipeline/src/graph.rs#L251), [`core/dr-pipeline/src/graph.rs:46`](../core/dr-pipeline/src/graph.rs#L46), [`core/dr-pipeline/src/graph.rs:59`](../core/dr-pipeline/src/graph.rs#L59), [`core/dr-pipeline/src/mask.rs:955`](../core/dr-pipeline/src/mask.rs#L955), [`core/dr-pipeline/src/operation.rs:232`](../core/dr-pipeline/src/operation.rs#L232), [`core/dr-pipeline/src/operation.rs:365`](../core/dr-pipeline/src/operation.rs#L365), [`core/dr-pipeline/src/ops/curve.rs:319`](../core/dr-pipeline/src/ops/curve.rs#L319), [`ui/dr-ui/src/develop.rs:1345`](../ui/dr-ui/src/develop.rs#L1345), [`ui/dr-ui/src/lib.rs:676`](../ui/dr-ui/src/lib.rs#L676), [`ui/dr-ui/tests/ui_names_no_operation.rs:1`](../ui/dr-ui/tests/ui_names_no_operation.rs#L1) | | FR-DEV-3b | [`core/dr-pipeline/src/descriptor.rs:258`](../core/dr-pipeline/src/descriptor.rs#L258), [`core/dr-pipeline/src/framing.rs:385`](../core/dr-pipeline/src/framing.rs#L385), [`core/dr-pipeline/src/graph.rs:59`](../core/dr-pipeline/src/graph.rs#L59), [`core/dr-pipeline/src/operation.rs:365`](../core/dr-pipeline/src/operation.rs#L365) | | FR-DEV-3c | [`core/dr-pipeline/build.rs:756`](../core/dr-pipeline/build.rs#L756), [`core/dr-pipeline/ops/exposure.yaml:1`](../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/graph.rs:251`](../core/dr-pipeline/src/graph.rs#L251), [`core/dr-pipeline/src/graph.rs:46`](../core/dr-pipeline/src/graph.rs#L46), [`core/dr-pipeline/src/mask.rs:955`](../core/dr-pipeline/src/mask.rs#L955), [`ui/dr-ui/src/develop.rs:5080`](../ui/dr-ui/src/develop.rs#L5080) | | FR-DEV-3d | [`core/dr-gpu/src/adjust.rs:1041`](../core/dr-gpu/src/adjust.rs#L1041), [`core/dr-gpu/src/adjust.rs:104`](../core/dr-gpu/src/adjust.rs#L104), [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/adjust.rs:84`](../core/dr-gpu/src/adjust.rs#L84), [`core/dr-gpu/src/adjust.rs:986`](../core/dr-gpu/src/adjust.rs#L986), [`core/dr-gpu/tests/capture_sharpen.rs:434`](../core/dr-gpu/tests/capture_sharpen.rs#L434), [`core/dr-gpu/tests/detail_stage.rs:242`](../core/dr-gpu/tests/detail_stage.rs#L242), [`core/dr-gpu/tests/local_contrast.rs:558`](../core/dr-gpu/tests/local_contrast.rs#L558), [`core/dr-gpu/tests/noise_reduction.rs:556`](../core/dr-gpu/tests/noise_reduction.rs#L556), [`core/dr-pipeline/src/framing.rs:314`](../core/dr-pipeline/src/framing.rs#L314), [`core/dr-pipeline/src/graph.rs:617`](../core/dr-pipeline/src/graph.rs#L617), [`core/dr-pipeline/src/operation.rs:32`](../core/dr-pipeline/src/operation.rs#L32), [`core/dr-pipeline/src/operation.rs:389`](../core/dr-pipeline/src/operation.rs#L389), [`core/dr-pipeline/src/operation.rs:53`](../core/dr-pipeline/src/operation.rs#L53), [`core/dr-pipeline/src/operation.rs:71`](../core/dr-pipeline/src/operation.rs#L71) | | FR-DEV-3e | [`core/dr-decode/src/base_curve.rs:145`](../core/dr-decode/src/base_curve.rs#L145), [`core/dr-decode/src/base_curve.rs:158`](../core/dr-decode/src/base_curve.rs#L158), [`core/dr-decode/src/base_curve.rs:1`](../core/dr-decode/src/base_curve.rs#L1), [`core/dr-decode/src/base_curve.rs:267`](../core/dr-decode/src/base_curve.rs#L267), [`core/dr-decode/src/base_curve.rs:347`](../core/dr-decode/src/base_curve.rs#L347), [`core/dr-decode/src/base_curve.rs:55`](../core/dr-decode/src/base_curve.rs#L55), [`core/dr-decode/src/lib.rs:121`](../core/dr-decode/src/lib.rs#L121), [`core/dr-decode/src/lib.rs:708`](../core/dr-decode/src/lib.rs#L708), [`core/dr-decode/src/lib.rs:748`](../core/dr-decode/src/lib.rs#L748), [`core/dr-decode/src/profile.rs:102`](../core/dr-decode/src/profile.rs#L102), [`core/dr-decode/src/profile.rs:151`](../core/dr-decode/src/profile.rs#L151), [`core/dr-decode/src/profile.rs:1`](../core/dr-decode/src/profile.rs#L1), [`core/dr-decode/src/profile.rs:235`](../core/dr-decode/src/profile.rs#L235), [`core/dr-decode/src/profile.rs:286`](../core/dr-decode/src/profile.rs#L286), [`core/dr-decode/src/profile.rs:343`](../core/dr-decode/src/profile.rs#L343), [`core/dr-decode/src/profile.rs:458`](../core/dr-decode/src/profile.rs#L458), [`core/dr-decode/src/profile.rs:492`](../core/dr-decode/src/profile.rs#L492), [`core/dr-decode/src/profile.rs:630`](../core/dr-decode/src/profile.rs#L630), [`core/dr-gpu/src/adjust.rs:37`](../core/dr-gpu/src/adjust.rs#L37), [`core/dr-gpu/src/adjust.rs:967`](../core/dr-gpu/src/adjust.rs#L967), [`core/dr-gpu/src/demosaic.rs:121`](../core/dr-gpu/src/demosaic.rs#L121), [`core/dr-gpu/src/demosaic.rs:86`](../core/dr-gpu/src/demosaic.rs#L86), [`core/dr-gpu/tests/base_curve.rs:1`](../core/dr-gpu/tests/base_curve.rs#L1), [`core/dr-pipeline/src/operation.rs:1495`](../core/dr-pipeline/src/operation.rs#L1495), [`core/dr-pipeline/src/operation.rs:1576`](../core/dr-pipeline/src/operation.rs#L1576), [`core/dr-pipeline/src/operation.rs:1601`](../core/dr-pipeline/src/operation.rs#L1601), [`core/dr-pipeline/src/operation.rs:1616`](../core/dr-pipeline/src/operation.rs#L1616), [`core/dr-pipeline/src/operation.rs:1640`](../core/dr-pipeline/src/operation.rs#L1640), [`core/dr-pipeline/src/operation.rs:310`](../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/operation.rs:440`](../core/dr-pipeline/src/operation.rs#L440), [`core/dr-pipeline/src/operation.rs:450`](../core/dr-pipeline/src/operation.rs#L450), [`core/dr-pipeline/src/operation.rs:600`](../core/dr-pipeline/src/operation.rs#L600) | -| FR-DEV-3f | [`core/dr-film/src/bake.rs:271`](../core/dr-film/src/bake.rs#L271), [`core/dr-film/src/bake.rs:62`](../core/dr-film/src/bake.rs#L62), [`core/dr-film/src/boolean_grain.rs:1`](../core/dr-film/src/boolean_grain.rs#L1), [`core/dr-film/src/boolean_grain.rs:78`](../core/dr-film/src/boolean_grain.rs#L78), [`core/dr-film/src/grain.rs:140`](../core/dr-film/src/grain.rs#L140), [`core/dr-film/src/grain.rs:1`](../core/dr-film/src/grain.rs#L1), [`core/dr-film/src/grain.rs:302`](../core/dr-film/src/grain.rs#L302), [`core/dr-film/src/grain.rs:79`](../core/dr-film/src/grain.rs#L79), [`core/dr-film/src/lib.rs:160`](../core/dr-film/src/lib.rs#L160), [`core/dr-film/src/lib.rs:1`](../core/dr-film/src/lib.rs#L1), [`core/dr-film/src/profile.rs:100`](../core/dr-film/src/profile.rs#L100), [`core/dr-film/src/profile.rs:142`](../core/dr-film/src/profile.rs#L142), [`core/dr-film/src/profile.rs:182`](../core/dr-film/src/profile.rs#L182), [`core/dr-film/src/profile.rs:259`](../core/dr-film/src/profile.rs#L259), [`core/dr-film/src/profile.rs:502`](../core/dr-film/src/profile.rs#L502), [`core/dr-film/src/profile.rs:73`](../core/dr-film/src/profile.rs#L73), [`core/dr-gpu/src/adjust.rs:139`](../core/dr-gpu/src/adjust.rs#L139), [`core/dr-gpu/src/adjust.rs:196`](../core/dr-gpu/src/adjust.rs#L196), [`core/dr-gpu/src/adjust.rs:357`](../core/dr-gpu/src/adjust.rs#L357), [`core/dr-gpu/src/adjust.rs:483`](../core/dr-gpu/src/adjust.rs#L483), [`core/dr-gpu/src/adjust.rs:77`](../core/dr-gpu/src/adjust.rs#L77), [`core/dr-gpu/tests/film_sim.rs:191`](../core/dr-gpu/tests/film_sim.rs#L191), [`core/dr-gpu/tests/film_sim.rs:1`](../core/dr-gpu/tests/film_sim.rs#L1), [`core/dr-pipeline/src/graph.rs:102`](../core/dr-pipeline/src/graph.rs#L102), [`core/dr-pipeline/src/graph.rs:125`](../core/dr-pipeline/src/graph.rs#L125), [`core/dr-pipeline/src/graph.rs:325`](../core/dr-pipeline/src/graph.rs#L325), [`core/dr-pipeline/src/operation.rs:1065`](../core/dr-pipeline/src/operation.rs#L1065), [`core/dr-pipeline/src/operation.rs:1094`](../core/dr-pipeline/src/operation.rs#L1094), [`core/dr-pipeline/src/operation.rs:1495`](../core/dr-pipeline/src/operation.rs#L1495), [`core/dr-pipeline/src/operation.rs:296`](../core/dr-pipeline/src/operation.rs#L296), [`core/dr-pipeline/src/operation.rs:310`](../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/ops/film_sim.rs:129`](../core/dr-pipeline/src/ops/film_sim.rs#L129), [`core/dr-pipeline/src/ops/film_sim.rs:153`](../core/dr-pipeline/src/ops/film_sim.rs#L153), [`core/dr-pipeline/src/ops/film_sim.rs:1`](../core/dr-pipeline/src/ops/film_sim.rs#L1), [`core/dr-pipeline/src/ops/film_sim.rs:331`](../core/dr-pipeline/src/ops/film_sim.rs#L331), [`core/dr-pipeline/src/ops/film_sim.rs:43`](../core/dr-pipeline/src/ops/film_sim.rs#L43), [`core/dr-pipeline/src/ops/film_sim.rs:87`](../core/dr-pipeline/src/ops/film_sim.rs#L87), [`core/dr-pipeline/src/ops/film_sim.rs:92`](../core/dr-pipeline/src/ops/film_sim.rs#L92), [`core/dr-pipeline/src/sidecar.rs:112`](../core/dr-pipeline/src/sidecar.rs#L112), [`core/dr-pipeline/src/sidecar.rs:168`](../core/dr-pipeline/src/sidecar.rs#L168), [`core/dr-pipeline/src/sidecar.rs:1958`](../core/dr-pipeline/src/sidecar.rs#L1958), [`core/dr-pipeline/src/sidecar.rs:2034`](../core/dr-pipeline/src/sidecar.rs#L2034), [`core/dr-pipeline/src/sidecar.rs:534`](../core/dr-pipeline/src/sidecar.rs#L534), [`core/dr-pipeline/src/sidecar.rs:661`](../core/dr-pipeline/src/sidecar.rs#L661), [`core/dr-pipeline/src/sidecar.rs:793`](../core/dr-pipeline/src/sidecar.rs#L793), [`core/dr-pipeline/src/state.rs:100`](../core/dr-pipeline/src/state.rs#L100), [`core/dr-pipeline/src/state.rs:115`](../core/dr-pipeline/src/state.rs#L115), [`core/dr-pipeline/src/state.rs:60`](../core/dr-pipeline/src/state.rs#L60), [`ui/dr-ui/src/develop.rs:3135`](../ui/dr-ui/src/develop.rs#L3135), [`ui/dr-ui/src/develop.rs:3152`](../ui/dr-ui/src/develop.rs#L3152), [`ui/dr-ui/src/develop.rs:3164`](../ui/dr-ui/src/develop.rs#L3164), [`ui/dr-ui/src/develop.rs:3202`](../ui/dr-ui/src/develop.rs#L3202), [`ui/dr-ui/src/develop.rs:3211`](../ui/dr-ui/src/develop.rs#L3211), [`ui/dr-ui/src/develop.rs:3314`](../ui/dr-ui/src/develop.rs#L3314), [`ui/dr-ui/src/develop.rs:3730`](../ui/dr-ui/src/develop.rs#L3730), [`ui/dr-ui/src/develop.rs:3745`](../ui/dr-ui/src/develop.rs#L3745), [`ui/dr-ui/src/lib.rs:2277`](../ui/dr-ui/src/lib.rs#L2277), [`ui/dr-ui/src/lib.rs:609`](../ui/dr-ui/src/lib.rs#L609), [`ui/dr-ui/src/lib.rs:667`](../ui/dr-ui/src/lib.rs#L667), [`ui/dr-ui/src/library.rs:497`](../ui/dr-ui/src/library.rs#L497), [`ui/dr-ui/src/library.rs:745`](../ui/dr-ui/src/library.rs#L745), [`ui/dr-ui/src/presets.rs:395`](../ui/dr-ui/src/presets.rs#L395), [`ui/dr-ui/ui/adjust.slint:1034`](../ui/dr-ui/ui/adjust.slint#L1034), [`ui/dr-ui/ui/adjust.slint:1116`](../ui/dr-ui/ui/adjust.slint#L1116), [`ui/dr-ui/ui/app.slint:2430`](../ui/dr-ui/ui/app.slint#L2430), [`ui/dr-ui/ui/app.slint:618`](../ui/dr-ui/ui/app.slint#L618) | +| FR-DEV-3f | [`core/dr-film/src/bake.rs:271`](../core/dr-film/src/bake.rs#L271), [`core/dr-film/src/bake.rs:62`](../core/dr-film/src/bake.rs#L62), [`core/dr-film/src/boolean_grain.rs:1`](../core/dr-film/src/boolean_grain.rs#L1), [`core/dr-film/src/boolean_grain.rs:78`](../core/dr-film/src/boolean_grain.rs#L78), [`core/dr-film/src/grain.rs:140`](../core/dr-film/src/grain.rs#L140), [`core/dr-film/src/grain.rs:1`](../core/dr-film/src/grain.rs#L1), [`core/dr-film/src/grain.rs:302`](../core/dr-film/src/grain.rs#L302), [`core/dr-film/src/grain.rs:79`](../core/dr-film/src/grain.rs#L79), [`core/dr-film/src/lib.rs:160`](../core/dr-film/src/lib.rs#L160), [`core/dr-film/src/lib.rs:1`](../core/dr-film/src/lib.rs#L1), [`core/dr-film/src/profile.rs:100`](../core/dr-film/src/profile.rs#L100), [`core/dr-film/src/profile.rs:142`](../core/dr-film/src/profile.rs#L142), [`core/dr-film/src/profile.rs:182`](../core/dr-film/src/profile.rs#L182), [`core/dr-film/src/profile.rs:259`](../core/dr-film/src/profile.rs#L259), [`core/dr-film/src/profile.rs:502`](../core/dr-film/src/profile.rs#L502), [`core/dr-film/src/profile.rs:73`](../core/dr-film/src/profile.rs#L73), [`core/dr-gpu/src/adjust.rs:139`](../core/dr-gpu/src/adjust.rs#L139), [`core/dr-gpu/src/adjust.rs:196`](../core/dr-gpu/src/adjust.rs#L196), [`core/dr-gpu/src/adjust.rs:357`](../core/dr-gpu/src/adjust.rs#L357), [`core/dr-gpu/src/adjust.rs:483`](../core/dr-gpu/src/adjust.rs#L483), [`core/dr-gpu/src/adjust.rs:77`](../core/dr-gpu/src/adjust.rs#L77), [`core/dr-gpu/tests/film_sim.rs:191`](../core/dr-gpu/tests/film_sim.rs#L191), [`core/dr-gpu/tests/film_sim.rs:1`](../core/dr-gpu/tests/film_sim.rs#L1), [`core/dr-pipeline/src/graph.rs:102`](../core/dr-pipeline/src/graph.rs#L102), [`core/dr-pipeline/src/graph.rs:125`](../core/dr-pipeline/src/graph.rs#L125), [`core/dr-pipeline/src/graph.rs:325`](../core/dr-pipeline/src/graph.rs#L325), [`core/dr-pipeline/src/operation.rs:1065`](../core/dr-pipeline/src/operation.rs#L1065), [`core/dr-pipeline/src/operation.rs:1094`](../core/dr-pipeline/src/operation.rs#L1094), [`core/dr-pipeline/src/operation.rs:1495`](../core/dr-pipeline/src/operation.rs#L1495), [`core/dr-pipeline/src/operation.rs:296`](../core/dr-pipeline/src/operation.rs#L296), [`core/dr-pipeline/src/operation.rs:310`](../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/ops/film_sim.rs:129`](../core/dr-pipeline/src/ops/film_sim.rs#L129), [`core/dr-pipeline/src/ops/film_sim.rs:153`](../core/dr-pipeline/src/ops/film_sim.rs#L153), [`core/dr-pipeline/src/ops/film_sim.rs:1`](../core/dr-pipeline/src/ops/film_sim.rs#L1), [`core/dr-pipeline/src/ops/film_sim.rs:331`](../core/dr-pipeline/src/ops/film_sim.rs#L331), [`core/dr-pipeline/src/ops/film_sim.rs:43`](../core/dr-pipeline/src/ops/film_sim.rs#L43), [`core/dr-pipeline/src/ops/film_sim.rs:87`](../core/dr-pipeline/src/ops/film_sim.rs#L87), [`core/dr-pipeline/src/ops/film_sim.rs:92`](../core/dr-pipeline/src/ops/film_sim.rs#L92), [`core/dr-pipeline/src/sidecar.rs:112`](../core/dr-pipeline/src/sidecar.rs#L112), [`core/dr-pipeline/src/sidecar.rs:168`](../core/dr-pipeline/src/sidecar.rs#L168), [`core/dr-pipeline/src/sidecar.rs:1958`](../core/dr-pipeline/src/sidecar.rs#L1958), [`core/dr-pipeline/src/sidecar.rs:2034`](../core/dr-pipeline/src/sidecar.rs#L2034), [`core/dr-pipeline/src/sidecar.rs:534`](../core/dr-pipeline/src/sidecar.rs#L534), [`core/dr-pipeline/src/sidecar.rs:661`](../core/dr-pipeline/src/sidecar.rs#L661), [`core/dr-pipeline/src/sidecar.rs:793`](../core/dr-pipeline/src/sidecar.rs#L793), [`core/dr-pipeline/src/state.rs:100`](../core/dr-pipeline/src/state.rs#L100), [`core/dr-pipeline/src/state.rs:115`](../core/dr-pipeline/src/state.rs#L115), [`core/dr-pipeline/src/state.rs:60`](../core/dr-pipeline/src/state.rs#L60), [`ui/dr-ui/src/develop.rs:3135`](../ui/dr-ui/src/develop.rs#L3135), [`ui/dr-ui/src/develop.rs:3152`](../ui/dr-ui/src/develop.rs#L3152), [`ui/dr-ui/src/develop.rs:3164`](../ui/dr-ui/src/develop.rs#L3164), [`ui/dr-ui/src/develop.rs:3202`](../ui/dr-ui/src/develop.rs#L3202), [`ui/dr-ui/src/develop.rs:3211`](../ui/dr-ui/src/develop.rs#L3211), [`ui/dr-ui/src/develop.rs:3314`](../ui/dr-ui/src/develop.rs#L3314), [`ui/dr-ui/src/develop.rs:3730`](../ui/dr-ui/src/develop.rs#L3730), [`ui/dr-ui/src/develop.rs:3745`](../ui/dr-ui/src/develop.rs#L3745), [`ui/dr-ui/src/lib.rs:2277`](../ui/dr-ui/src/lib.rs#L2277), [`ui/dr-ui/src/lib.rs:609`](../ui/dr-ui/src/lib.rs#L609), [`ui/dr-ui/src/lib.rs:667`](../ui/dr-ui/src/lib.rs#L667), [`ui/dr-ui/src/library.rs:497`](../ui/dr-ui/src/library.rs#L497), [`ui/dr-ui/src/library.rs:745`](../ui/dr-ui/src/library.rs#L745), [`ui/dr-ui/src/presets.rs:395`](../ui/dr-ui/src/presets.rs#L395), [`ui/dr-ui/ui/adjust.slint:1034`](../ui/dr-ui/ui/adjust.slint#L1034), [`ui/dr-ui/ui/adjust.slint:1116`](../ui/dr-ui/ui/adjust.slint#L1116), [`ui/dr-ui/ui/app.slint:2440`](../ui/dr-ui/ui/app.slint#L2440), [`ui/dr-ui/ui/app.slint:626`](../ui/dr-ui/ui/app.slint#L626) | | FR-DEV-3h | [`core/dr-decode/src/lib.rs:404`](../core/dr-decode/src/lib.rs#L404), [`core/dr-decode/src/preview.rs:29`](../core/dr-decode/src/preview.rs#L29), [`core/dr-pipeline/src/framing.rs:1050`](../core/dr-pipeline/src/framing.rs#L1050), [`core/dr-pipeline/src/framing.rs:328`](../core/dr-pipeline/src/framing.rs#L328), [`core/dr-pipeline/src/framing.rs:488`](../core/dr-pipeline/src/framing.rs#L488), [`core/dr-types/src/lib.rs:337`](../core/dr-types/src/lib.rs#L337), [`core/dr-types/src/lib.rs:445`](../core/dr-types/src/lib.rs#L445), [`core/dr-types/src/lib.rs:457`](../core/dr-types/src/lib.rs#L457), [`core/dr-types/src/lib.rs:473`](../core/dr-types/src/lib.rs#L473), [`ui/dr-ui/src/develop.rs:139`](../ui/dr-ui/src/develop.rs#L139), [`ui/dr-ui/src/develop.rs:2143`](../ui/dr-ui/src/develop.rs#L2143), [`ui/dr-ui/src/segmentation.rs:322`](../ui/dr-ui/src/segmentation.rs#L322) | | FR-DEV-4 | [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/lib.rs:338`](../core/dr-gpu/src/lib.rs#L338), [`ui/dr-ui/ui/crop.slint:1`](../ui/dr-ui/ui/crop.slint#L1) | | FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:346`](../core/dr-pipeline/src/graph.rs#L346), [`core/dr-pipeline/src/graph.rs:385`](../core/dr-pipeline/src/graph.rs#L385), [`core/dr-pipeline/src/history.rs:102`](../core/dr-pipeline/src/history.rs#L102), [`core/dr-pipeline/src/history.rs:110`](../core/dr-pipeline/src/history.rs#L110), [`core/dr-pipeline/src/history.rs:127`](../core/dr-pipeline/src/history.rs#L127), [`core/dr-pipeline/src/history.rs:184`](../core/dr-pipeline/src/history.rs#L184), [`core/dr-pipeline/src/history.rs:1`](../core/dr-pipeline/src/history.rs#L1), [`core/dr-pipeline/src/history.rs:214`](../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:234`](../core/dr-pipeline/src/history.rs#L234), [`core/dr-pipeline/src/history.rs:293`](../core/dr-pipeline/src/history.rs#L293), [`core/dr-pipeline/src/history.rs:479`](../core/dr-pipeline/src/history.rs#L479), [`core/dr-pipeline/src/history.rs:489`](../core/dr-pipeline/src/history.rs#L489), [`core/dr-pipeline/src/history.rs:499`](../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../core/dr-pipeline/src/history.rs#L526), [`core/dr-pipeline/src/history.rs:86`](../core/dr-pipeline/src/history.rs#L86), [`core/dr-pipeline/src/state.rs:1`](../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../core/dr-pipeline/src/state.rs#L75), [`ui/dr-ui/src/develop.rs:3164`](../ui/dr-ui/src/develop.rs#L3164), [`ui/dr-ui/src/develop.rs:3745`](../ui/dr-ui/src/develop.rs#L3745), [`ui/dr-ui/src/develop.rs:3775`](../ui/dr-ui/src/develop.rs#L3775), [`ui/dr-ui/src/develop.rs:3788`](../ui/dr-ui/src/develop.rs#L3788), [`ui/dr-ui/src/develop.rs:3800`](../ui/dr-ui/src/develop.rs#L3800), [`ui/dr-ui/src/develop.rs:3816`](../ui/dr-ui/src/develop.rs#L3816), [`ui/dr-ui/src/develop.rs:3848`](../ui/dr-ui/src/develop.rs#L3848), [`ui/dr-ui/src/develop.rs:3852`](../ui/dr-ui/src/develop.rs#L3852), [`ui/dr-ui/src/develop.rs:3871`](../ui/dr-ui/src/develop.rs#L3871), [`ui/dr-ui/src/develop.rs:3887`](../ui/dr-ui/src/develop.rs#L3887), [`ui/dr-ui/src/develop.rs:709`](../ui/dr-ui/src/develop.rs#L709), [`ui/dr-ui/src/labels.rs:12`](../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:215`](../ui/dr-ui/src/labels.rs#L215), [`ui/dr-ui/src/lib.rs:1469`](../ui/dr-ui/src/lib.rs#L1469), [`ui/dr-ui/src/lib.rs:1512`](../ui/dr-ui/src/lib.rs#L1512), [`ui/dr-ui/src/lib.rs:1520`](../ui/dr-ui/src/lib.rs#L1520), [`ui/dr-ui/src/lib.rs:2473`](../ui/dr-ui/src/lib.rs#L2473), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1) | -| FR-DEV-6 | [`core/dr-pipeline/src/preset.rs:1`](../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:381`](../core/dr-pipeline/src/preset.rs#L381), [`core/dr-pipeline/src/preset.rs:414`](../core/dr-pipeline/src/preset.rs#L414), [`core/dr-pipeline/src/starter.rs:1`](../core/dr-pipeline/src/starter.rs#L1), [`core/dr-preset-xmp/src/lib.rs:1`](../core/dr-preset-xmp/src/lib.rs#L1), [`core/dr-types/src/settings.rs:182`](../core/dr-types/src/settings.rs#L182), [`ui/dr-ui/src/develop.rs:3687`](../ui/dr-ui/src/develop.rs#L3687), [`ui/dr-ui/src/develop.rs:3708`](../ui/dr-ui/src/develop.rs#L3708), [`ui/dr-ui/src/lib.rs:1436`](../ui/dr-ui/src/lib.rs#L1436), [`ui/dr-ui/src/lib.rs:2088`](../ui/dr-ui/src/lib.rs#L2088), [`ui/dr-ui/src/lib.rs:2117`](../ui/dr-ui/src/lib.rs#L2117), [`ui/dr-ui/src/library.rs:1787`](../ui/dr-ui/src/library.rs#L1787), [`ui/dr-ui/src/library.rs:459`](../ui/dr-ui/src/library.rs#L459), [`ui/dr-ui/src/library.rs:487`](../ui/dr-ui/src/library.rs#L487), [`ui/dr-ui/src/library_ui.rs:2592`](../ui/dr-ui/src/library_ui.rs#L2592), [`ui/dr-ui/src/library_ui.rs:2992`](../ui/dr-ui/src/library_ui.rs#L2992), [`ui/dr-ui/src/library_ui.rs:472`](../ui/dr-ui/src/library_ui.rs#L472), [`ui/dr-ui/src/preset_store.rs:1`](../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/presets.rs:1`](../ui/dr-ui/src/presets.rs#L1), [`ui/dr-ui/src/presets.rs:657`](../ui/dr-ui/src/presets.rs#L657), [`ui/dr-ui/src/presets.rs:691`](../ui/dr-ui/src/presets.rs#L691), [`ui/dr-ui/ui/adjust.slint:709`](../ui/dr-ui/ui/adjust.slint#L709), [`ui/dr-ui/ui/adjust.slint:736`](../ui/dr-ui/ui/adjust.slint#L736), [`ui/dr-ui/ui/adjust.slint:779`](../ui/dr-ui/ui/adjust.slint#L779), [`ui/dr-ui/ui/app.slint:1477`](../ui/dr-ui/ui/app.slint#L1477), [`ui/dr-ui/ui/app.slint:2519`](../ui/dr-ui/ui/app.slint#L2519), [`ui/dr-ui/ui/app.slint:690`](../ui/dr-ui/ui/app.slint#L690), [`ui/dr-ui/ui/app.slint:701`](../ui/dr-ui/ui/app.slint#L701), [`ui/dr-ui/ui/library.slint:1389`](../ui/dr-ui/ui/library.slint#L1389), [`ui/dr-ui/ui/library.slint:1396`](../ui/dr-ui/ui/library.slint#L1396), [`ui/dr-ui/ui/library.slint:837`](../ui/dr-ui/ui/library.slint#L837), [`ui/dr-ui/ui/library.slint:853`](../ui/dr-ui/ui/library.slint#L853), [`ui/dr-ui/ui/library.slint:922`](../ui/dr-ui/ui/library.slint#L922), [`ui/dr-ui/ui/library.slint:937`](../ui/dr-ui/ui/library.slint#L937), [`ui/dr-ui/ui/presets.slint:105`](../ui/dr-ui/ui/presets.slint#L105), [`ui/dr-ui/ui/presets.slint:113`](../ui/dr-ui/ui/presets.slint#L113), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/presets.slint:276`](../ui/dr-ui/ui/presets.slint#L276), [`ui/dr-ui/ui/presets.slint:297`](../ui/dr-ui/ui/presets.slint#L297), [`ui/dr-ui/ui/presets.slint:5`](../ui/dr-ui/ui/presets.slint#L5), [`ui/dr-ui/ui/presets.slint:60`](../ui/dr-ui/ui/presets.slint#L60), [`ui/dr-ui/ui/settings.slint:101`](../ui/dr-ui/ui/settings.slint#L101), [`ui/dr-ui/ui/settings.slint:557`](../ui/dr-ui/ui/settings.slint#L557) | +| FR-DEV-6 | [`core/dr-pipeline/src/preset.rs:1`](../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:381`](../core/dr-pipeline/src/preset.rs#L381), [`core/dr-pipeline/src/preset.rs:414`](../core/dr-pipeline/src/preset.rs#L414), [`core/dr-pipeline/src/starter.rs:1`](../core/dr-pipeline/src/starter.rs#L1), [`core/dr-preset-xmp/src/lib.rs:1`](../core/dr-preset-xmp/src/lib.rs#L1), [`core/dr-types/src/settings.rs:182`](../core/dr-types/src/settings.rs#L182), [`ui/dr-ui/src/develop.rs:3687`](../ui/dr-ui/src/develop.rs#L3687), [`ui/dr-ui/src/develop.rs:3708`](../ui/dr-ui/src/develop.rs#L3708), [`ui/dr-ui/src/lib.rs:1436`](../ui/dr-ui/src/lib.rs#L1436), [`ui/dr-ui/src/lib.rs:2088`](../ui/dr-ui/src/lib.rs#L2088), [`ui/dr-ui/src/lib.rs:2117`](../ui/dr-ui/src/lib.rs#L2117), [`ui/dr-ui/src/library.rs:1787`](../ui/dr-ui/src/library.rs#L1787), [`ui/dr-ui/src/library.rs:459`](../ui/dr-ui/src/library.rs#L459), [`ui/dr-ui/src/library.rs:487`](../ui/dr-ui/src/library.rs#L487), [`ui/dr-ui/src/library_ui.rs:2592`](../ui/dr-ui/src/library_ui.rs#L2592), [`ui/dr-ui/src/library_ui.rs:2992`](../ui/dr-ui/src/library_ui.rs#L2992), [`ui/dr-ui/src/library_ui.rs:472`](../ui/dr-ui/src/library_ui.rs#L472), [`ui/dr-ui/src/preset_store.rs:1`](../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/presets.rs:1`](../ui/dr-ui/src/presets.rs#L1), [`ui/dr-ui/src/presets.rs:657`](../ui/dr-ui/src/presets.rs#L657), [`ui/dr-ui/src/presets.rs:691`](../ui/dr-ui/src/presets.rs#L691), [`ui/dr-ui/ui/adjust.slint:709`](../ui/dr-ui/ui/adjust.slint#L709), [`ui/dr-ui/ui/adjust.slint:736`](../ui/dr-ui/ui/adjust.slint#L736), [`ui/dr-ui/ui/adjust.slint:779`](../ui/dr-ui/ui/adjust.slint#L779), [`ui/dr-ui/ui/app.slint:1487`](../ui/dr-ui/ui/app.slint#L1487), [`ui/dr-ui/ui/app.slint:2529`](../ui/dr-ui/ui/app.slint#L2529), [`ui/dr-ui/ui/app.slint:698`](../ui/dr-ui/ui/app.slint#L698), [`ui/dr-ui/ui/app.slint:709`](../ui/dr-ui/ui/app.slint#L709), [`ui/dr-ui/ui/library.slint:1410`](../ui/dr-ui/ui/library.slint#L1410), [`ui/dr-ui/ui/library.slint:1417`](../ui/dr-ui/ui/library.slint#L1417), [`ui/dr-ui/ui/library.slint:837`](../ui/dr-ui/ui/library.slint#L837), [`ui/dr-ui/ui/library.slint:853`](../ui/dr-ui/ui/library.slint#L853), [`ui/dr-ui/ui/library.slint:922`](../ui/dr-ui/ui/library.slint#L922), [`ui/dr-ui/ui/library.slint:937`](../ui/dr-ui/ui/library.slint#L937), [`ui/dr-ui/ui/presets.slint:105`](../ui/dr-ui/ui/presets.slint#L105), [`ui/dr-ui/ui/presets.slint:113`](../ui/dr-ui/ui/presets.slint#L113), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/presets.slint:276`](../ui/dr-ui/ui/presets.slint#L276), [`ui/dr-ui/ui/presets.slint:297`](../ui/dr-ui/ui/presets.slint#L297), [`ui/dr-ui/ui/presets.slint:5`](../ui/dr-ui/ui/presets.slint#L5), [`ui/dr-ui/ui/presets.slint:60`](../ui/dr-ui/ui/presets.slint#L60), [`ui/dr-ui/ui/settings.slint:101`](../ui/dr-ui/ui/settings.slint#L101), [`ui/dr-ui/ui/settings.slint:557`](../ui/dr-ui/ui/settings.slint#L557) | | FR-DEV-7 | [`core/dr-pipeline/src/history.rs:214`](../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:499`](../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../core/dr-pipeline/src/history.rs#L526), [`ui/dr-ui/src/develop.rs:3816`](../ui/dr-ui/src/develop.rs#L3816), [`ui/dr-ui/src/develop.rs:3848`](../ui/dr-ui/src/develop.rs#L3848), [`ui/dr-ui/src/lib.rs:1520`](../ui/dr-ui/src/lib.rs#L1520), [`ui/dr-ui/src/lib.rs:2473`](../ui/dr-ui/src/lib.rs#L2473), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1) | -| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:387`](../core/dr-gpu/src/detail.rs#L387), [`core/dr-gpu/src/detail.rs:592`](../core/dr-gpu/src/detail.rs#L592), [`core/dr-gpu/tests/detail_instances.rs:1`](../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:410`](../core/dr-pipeline/src/detail.rs#L410), [`core/dr-pipeline/src/detail.rs:434`](../core/dr-pipeline/src/detail.rs#L434), [`core/dr-pipeline/src/detail.rs:469`](../core/dr-pipeline/src/detail.rs#L469), [`core/dr-pipeline/src/detail.rs:555`](../core/dr-pipeline/src/detail.rs#L555), [`core/dr-pipeline/src/graph.rs:114`](../core/dr-pipeline/src/graph.rs#L114), [`core/dr-pipeline/src/graph.rs:192`](../core/dr-pipeline/src/graph.rs#L192), [`core/dr-pipeline/src/graph.rs:686`](../core/dr-pipeline/src/graph.rs#L686), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:554`](../core/dr-pipeline/src/operation.rs#L554), [`core/dr-pipeline/src/sidecar.rs:184`](../core/dr-pipeline/src/sidecar.rs#L184), [`core/dr-pipeline/src/sidecar.rs:353`](../core/dr-pipeline/src/sidecar.rs#L353), [`core/dr-pipeline/src/sidecar.rs:673`](../core/dr-pipeline/src/sidecar.rs#L673), [`core/dr-pipeline/src/sidecar.rs:809`](../core/dr-pipeline/src/sidecar.rs#L809), [`core/dr-pipeline/src/sidecar.rs:863`](../core/dr-pipeline/src/sidecar.rs#L863), [`core/dr-pipeline/src/sidecar.rs:893`](../core/dr-pipeline/src/sidecar.rs#L893), [`core/dr-pipeline/src/spot.rs:115`](../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop.rs:2295`](../ui/dr-ui/src/develop.rs#L2295), [`ui/dr-ui/src/develop.rs:2333`](../ui/dr-ui/src/develop.rs#L2333), [`ui/dr-ui/src/develop.rs:2398`](../ui/dr-ui/src/develop.rs#L2398), [`ui/dr-ui/src/develop.rs:2481`](../ui/dr-ui/src/develop.rs#L2481), [`ui/dr-ui/src/develop.rs:2495`](../ui/dr-ui/src/develop.rs#L2495), [`ui/dr-ui/src/develop.rs:776`](../ui/dr-ui/src/develop.rs#L776), [`ui/dr-ui/src/labels.rs:52`](../ui/dr-ui/src/labels.rs#L52), [`ui/dr-ui/src/lib.rs:1541`](../ui/dr-ui/src/lib.rs#L1541), [`ui/dr-ui/src/lib.rs:2591`](../ui/dr-ui/src/lib.rs#L2591), [`ui/dr-ui/src/lib.rs:332`](../ui/dr-ui/src/lib.rs#L332), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/adjust.slint:810`](../ui/dr-ui/ui/adjust.slint#L810), [`ui/dr-ui/ui/app.slint:126`](../ui/dr-ui/ui/app.slint#L126), [`ui/dr-ui/ui/app.slint:1798`](../ui/dr-ui/ui/app.slint#L1798), [`ui/dr-ui/ui/app.slint:1973`](../ui/dr-ui/ui/app.slint#L1973), [`ui/dr-ui/ui/app.slint:2336`](../ui/dr-ui/ui/app.slint#L2336), [`ui/dr-ui/ui/spots.slint:180`](../ui/dr-ui/ui/spots.slint#L180), [`ui/dr-ui/ui/spots.slint:48`](../ui/dr-ui/ui/spots.slint#L48), [`ui/dr-ui/ui/spots.slint:5`](../ui/dr-ui/ui/spots.slint#L5) | +| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:387`](../core/dr-gpu/src/detail.rs#L387), [`core/dr-gpu/src/detail.rs:592`](../core/dr-gpu/src/detail.rs#L592), [`core/dr-gpu/tests/detail_instances.rs:1`](../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:410`](../core/dr-pipeline/src/detail.rs#L410), [`core/dr-pipeline/src/detail.rs:434`](../core/dr-pipeline/src/detail.rs#L434), [`core/dr-pipeline/src/detail.rs:469`](../core/dr-pipeline/src/detail.rs#L469), [`core/dr-pipeline/src/detail.rs:555`](../core/dr-pipeline/src/detail.rs#L555), [`core/dr-pipeline/src/graph.rs:114`](../core/dr-pipeline/src/graph.rs#L114), [`core/dr-pipeline/src/graph.rs:192`](../core/dr-pipeline/src/graph.rs#L192), [`core/dr-pipeline/src/graph.rs:686`](../core/dr-pipeline/src/graph.rs#L686), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:554`](../core/dr-pipeline/src/operation.rs#L554), [`core/dr-pipeline/src/sidecar.rs:184`](../core/dr-pipeline/src/sidecar.rs#L184), [`core/dr-pipeline/src/sidecar.rs:353`](../core/dr-pipeline/src/sidecar.rs#L353), [`core/dr-pipeline/src/sidecar.rs:673`](../core/dr-pipeline/src/sidecar.rs#L673), [`core/dr-pipeline/src/sidecar.rs:809`](../core/dr-pipeline/src/sidecar.rs#L809), [`core/dr-pipeline/src/sidecar.rs:863`](../core/dr-pipeline/src/sidecar.rs#L863), [`core/dr-pipeline/src/sidecar.rs:893`](../core/dr-pipeline/src/sidecar.rs#L893), [`core/dr-pipeline/src/spot.rs:115`](../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop.rs:2295`](../ui/dr-ui/src/develop.rs#L2295), [`ui/dr-ui/src/develop.rs:2333`](../ui/dr-ui/src/develop.rs#L2333), [`ui/dr-ui/src/develop.rs:2398`](../ui/dr-ui/src/develop.rs#L2398), [`ui/dr-ui/src/develop.rs:2481`](../ui/dr-ui/src/develop.rs#L2481), [`ui/dr-ui/src/develop.rs:2495`](../ui/dr-ui/src/develop.rs#L2495), [`ui/dr-ui/src/develop.rs:776`](../ui/dr-ui/src/develop.rs#L776), [`ui/dr-ui/src/labels.rs:52`](../ui/dr-ui/src/labels.rs#L52), [`ui/dr-ui/src/lib.rs:1541`](../ui/dr-ui/src/lib.rs#L1541), [`ui/dr-ui/src/lib.rs:2591`](../ui/dr-ui/src/lib.rs#L2591), [`ui/dr-ui/src/lib.rs:332`](../ui/dr-ui/src/lib.rs#L332), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/adjust.slint:810`](../ui/dr-ui/ui/adjust.slint#L810), [`ui/dr-ui/ui/app.slint:126`](../ui/dr-ui/ui/app.slint#L126), [`ui/dr-ui/ui/app.slint:1808`](../ui/dr-ui/ui/app.slint#L1808), [`ui/dr-ui/ui/app.slint:1983`](../ui/dr-ui/ui/app.slint#L1983), [`ui/dr-ui/ui/app.slint:2346`](../ui/dr-ui/ui/app.slint#L2346), [`ui/dr-ui/ui/spots.slint:180`](../ui/dr-ui/ui/spots.slint#L180), [`ui/dr-ui/ui/spots.slint:48`](../ui/dr-ui/ui/spots.slint#L48), [`ui/dr-ui/ui/spots.slint:5`](../ui/dr-ui/ui/spots.slint#L5) | | FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:2088`](../core/dr-gpu/src/adjust.rs#L2088), [`core/dr-gpu/src/adjust.rs:2165`](../core/dr-gpu/src/adjust.rs#L2165), [`core/dr-gpu/src/adjust.rs:2250`](../core/dr-gpu/src/adjust.rs#L2250), [`core/dr-gpu/src/adjust.rs:54`](../core/dr-gpu/src/adjust.rs#L54), [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/lib.rs:159`](../core/dr-gpu/src/lib.rs#L159), [`core/dr-gpu/src/lib.rs:179`](../core/dr-gpu/src/lib.rs#L179), [`core/dr-gpu/src/lib.rs:57`](../core/dr-gpu/src/lib.rs#L57), [`core/dr-gpu/src/lib.rs:80`](../core/dr-gpu/src/lib.rs#L80), [`core/dr-gpu/tests/capture_sharpen.rs:200`](../core/dr-gpu/tests/capture_sharpen.rs#L200), [`core/dr-gpu/tests/detail_stage.rs:328`](../core/dr-gpu/tests/detail_stage.rs#L328), [`core/dr-gpu/tests/local_contrast.rs:264`](../core/dr-gpu/tests/local_contrast.rs#L264), [`core/dr-gpu/tests/noise_reduction.rs:378`](../core/dr-gpu/tests/noise_reduction.rs#L378), [`core/dr-pipeline/src/detail.rs:136`](../core/dr-pipeline/src/detail.rs#L136), [`core/dr-pipeline/src/detail.rs:524`](../core/dr-pipeline/src/detail.rs#L524), [`core/dr-pipeline/src/graph.rs:548`](../core/dr-pipeline/src/graph.rs#L548), [`core/dr-pipeline/src/graph.rs:578`](../core/dr-pipeline/src/graph.rs#L578), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:659`](../core/dr-pipeline/src/ops/capture_sharpen.rs#L659), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/local_contrast.rs:971`](../core/dr-pipeline/src/ops/local_contrast.rs#L971), [`core/dr-pipeline/src/ops/noise_reduction.rs:700`](../core/dr-pipeline/src/ops/noise_reduction.rs#L700), [`core/dr-pipeline/src/spot.rs:673`](../core/dr-pipeline/src/spot.rs#L673), [`ui/dr-ui/src/develop.rs:2819`](../ui/dr-ui/src/develop.rs#L2819), [`ui/dr-ui/src/develop.rs:4142`](../ui/dr-ui/src/develop.rs#L4142), [`ui/dr-ui/src/develop.rs:4625`](../ui/dr-ui/src/develop.rs#L4625), [`ui/dr-ui/src/develop.rs:4659`](../ui/dr-ui/src/develop.rs#L4659), [`ui/dr-ui/src/lib.rs:74`](../ui/dr-ui/src/lib.rs#L74), [`ui/dr-ui/src/lib.rs:817`](../ui/dr-ui/src/lib.rs#L817), [`ui/dr-ui/src/lib.rs:876`](../ui/dr-ui/src/lib.rs#L876) | | FR-DSP-3 | [`core/dr-gpu/tests/frame_budget.rs:101`](../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/local_contrast.rs:329`](../core/dr-gpu/tests/local_contrast.rs#L329), [`core/dr-pipeline/src/ops/local_contrast.rs:447`](../core/dr-pipeline/src/ops/local_contrast.rs#L447) | | FR-DSP-5 | [`core/dr-gpu/tests/frame_budget.rs:101`](../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/zoom_resolution.rs:135`](../core/dr-gpu/tests/zoom_resolution.rs#L135), [`core/dr-gpu/tests/zoom_resolution.rs:166`](../core/dr-gpu/tests/zoom_resolution.rs#L166), [`core/dr-gpu/tests/zoom_resolution.rs:1`](../core/dr-gpu/tests/zoom_resolution.rs#L1), [`core/dr-gpu/tests/zoom_resolution.rs:216`](../core/dr-gpu/tests/zoom_resolution.rs#L216) | | FR-DSP-6 | [`core/dr-pipeline/src/operation.rs:483`](../core/dr-pipeline/src/operation.rs#L483), [`core/dr-types/src/colour.rs:1`](../core/dr-types/src/colour.rs#L1), [`ui/dr-ui/src/develop.rs:2849`](../ui/dr-ui/src/develop.rs#L2849), [`ui/dr-ui/src/develop.rs:5917`](../ui/dr-ui/src/develop.rs#L5917), [`ui/dr-ui/src/lib.rs:1497`](../ui/dr-ui/src/lib.rs#L1497), [`ui/dr-ui/src/lib.rs:2974`](../ui/dr-ui/src/lib.rs#L2974) | | FR-DSP-7 | [`core/dr-gpu/src/histogram.rs:147`](../core/dr-gpu/src/histogram.rs#L147), [`core/dr-gpu/src/histogram.rs:1`](../core/dr-gpu/src/histogram.rs#L1), [`core/dr-gpu/src/histogram.rs:281`](../core/dr-gpu/src/histogram.rs#L281), [`core/dr-gpu/src/histogram.rs:50`](../core/dr-gpu/src/histogram.rs#L50), [`core/dr-gpu/src/shaders/histogram.wgsl:1`](../core/dr-gpu/src/shaders/histogram.wgsl#L1), [`ui/dr-ui/src/develop.rs:2898`](../ui/dr-ui/src/develop.rs#L2898), [`ui/dr-ui/src/develop.rs:5727`](../ui/dr-ui/src/develop.rs#L5727), [`ui/dr-ui/src/develop.rs:5759`](../ui/dr-ui/src/develop.rs#L5759), [`ui/dr-ui/src/develop.rs:720`](../ui/dr-ui/src/develop.rs#L720), [`ui/dr-ui/src/histogram.rs:1`](../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/lib.rs:1607`](../ui/dr-ui/src/lib.rs#L1607), [`ui/dr-ui/src/lib.rs:316`](../ui/dr-ui/src/lib.rs#L316), [`ui/dr-ui/ui/app.slint:70`](../ui/dr-ui/ui/app.slint#L70), [`ui/dr-ui/ui/histogram.slint:122`](../ui/dr-ui/ui/histogram.slint#L122), [`ui/dr-ui/ui/histogram.slint:1`](../ui/dr-ui/ui/histogram.slint#L1) | -| FR-DSP-8 | [`platform/dr-plat/src/display.rs:1`](../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/icc.rs:1`](../platform/dr-plat/src/display/icc.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../platform/dr-plat/src/display/x11.rs#L1), [`ui/dr-ui/src/develop.rs:2795`](../ui/dr-ui/src/develop.rs#L2795), [`ui/dr-ui/src/develop.rs:2849`](../ui/dr-ui/src/develop.rs#L2849), [`ui/dr-ui/src/develop.rs:5917`](../ui/dr-ui/src/develop.rs#L5917), [`ui/dr-ui/src/develop.rs:5963`](../ui/dr-ui/src/develop.rs#L5963), [`ui/dr-ui/src/develop.rs:5982`](../ui/dr-ui/src/develop.rs#L5982), [`ui/dr-ui/src/develop.rs:807`](../ui/dr-ui/src/develop.rs#L807), [`ui/dr-ui/src/display_ui.rs:192`](../ui/dr-ui/src/display_ui.rs#L192), [`ui/dr-ui/src/display_ui.rs:1`](../ui/dr-ui/src/display_ui.rs#L1), [`ui/dr-ui/src/display_ui.rs:325`](../ui/dr-ui/src/display_ui.rs#L325), [`ui/dr-ui/src/display_ui.rs:346`](../ui/dr-ui/src/display_ui.rs#L346), [`ui/dr-ui/src/display_ui.rs:379`](../ui/dr-ui/src/display_ui.rs#L379), [`ui/dr-ui/src/lib.rs:1458`](../ui/dr-ui/src/lib.rs#L1458), [`ui/dr-ui/src/lib.rs:1497`](../ui/dr-ui/src/lib.rs#L1497), [`ui/dr-ui/src/lib.rs:2887`](../ui/dr-ui/src/lib.rs#L2887), [`ui/dr-ui/src/lib.rs:2974`](../ui/dr-ui/src/lib.rs#L2974), [`ui/dr-ui/ui/app.slint:1646`](../ui/dr-ui/ui/app.slint#L1646), [`ui/dr-ui/ui/app.slint:49`](../ui/dr-ui/ui/app.slint#L49), [`ui/dr-ui/ui/settings.slint:124`](../ui/dr-ui/ui/settings.slint#L124), [`ui/dr-ui/ui/settings.slint:794`](../ui/dr-ui/ui/settings.slint#L794) | +| FR-DSP-8 | [`platform/dr-plat/src/display.rs:1`](../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/icc.rs:1`](../platform/dr-plat/src/display/icc.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../platform/dr-plat/src/display/x11.rs#L1), [`ui/dr-ui/src/develop.rs:2795`](../ui/dr-ui/src/develop.rs#L2795), [`ui/dr-ui/src/develop.rs:2849`](../ui/dr-ui/src/develop.rs#L2849), [`ui/dr-ui/src/develop.rs:5917`](../ui/dr-ui/src/develop.rs#L5917), [`ui/dr-ui/src/develop.rs:5963`](../ui/dr-ui/src/develop.rs#L5963), [`ui/dr-ui/src/develop.rs:5982`](../ui/dr-ui/src/develop.rs#L5982), [`ui/dr-ui/src/develop.rs:807`](../ui/dr-ui/src/develop.rs#L807), [`ui/dr-ui/src/display_ui.rs:192`](../ui/dr-ui/src/display_ui.rs#L192), [`ui/dr-ui/src/display_ui.rs:1`](../ui/dr-ui/src/display_ui.rs#L1), [`ui/dr-ui/src/display_ui.rs:325`](../ui/dr-ui/src/display_ui.rs#L325), [`ui/dr-ui/src/display_ui.rs:346`](../ui/dr-ui/src/display_ui.rs#L346), [`ui/dr-ui/src/display_ui.rs:379`](../ui/dr-ui/src/display_ui.rs#L379), [`ui/dr-ui/src/lib.rs:1458`](../ui/dr-ui/src/lib.rs#L1458), [`ui/dr-ui/src/lib.rs:1497`](../ui/dr-ui/src/lib.rs#L1497), [`ui/dr-ui/src/lib.rs:2887`](../ui/dr-ui/src/lib.rs#L2887), [`ui/dr-ui/src/lib.rs:2974`](../ui/dr-ui/src/lib.rs#L2974), [`ui/dr-ui/ui/app.slint:1656`](../ui/dr-ui/ui/app.slint#L1656), [`ui/dr-ui/ui/app.slint:49`](../ui/dr-ui/ui/app.slint#L49), [`ui/dr-ui/ui/settings.slint:124`](../ui/dr-ui/ui/settings.slint#L124), [`ui/dr-ui/ui/settings.slint:794`](../ui/dr-ui/ui/settings.slint#L794) | | FR-EXP-1 | [`core/dr-export/src/encode.rs:1`](../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-2 | [`core/dr-export/src/encode.rs:1`](../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/error.rs:26`](../core/dr-export/src/error.rs#L26), [`core/dr-export/src/icc.rs:1`](../core/dr-export/src/icc.rs#L1), [`core/dr-export/src/lib.rs:153`](../core/dr-export/src/lib.rs#L153), [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/lib.rs:53`](../core/dr-export/src/lib.rs#L53), [`core/dr-gpu/src/adjust.rs:2398`](../core/dr-gpu/src/adjust.rs#L2398), [`core/dr-pipeline/src/graph.rs:538`](../core/dr-pipeline/src/graph.rs#L538), [`core/dr-pipeline/src/graph.rs:592`](../core/dr-pipeline/src/graph.rs#L592), [`core/dr-pipeline/src/operation.rs:483`](../core/dr-pipeline/src/operation.rs#L483), [`core/dr-types/src/colour.rs:1`](../core/dr-types/src/colour.rs#L1), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:623`](../core/dr-types/src/settings.rs#L623), [`ui/dr-ui/src/develop.rs:5982`](../ui/dr-ui/src/develop.rs#L5982), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-3 | [`core/dr-export/src/lib.rs:182`](../core/dr-export/src/lib.rs#L182), [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/size.rs:136`](../core/dr-export/src/size.rs#L136), [`core/dr-export/src/size.rs:1`](../core/dr-export/src/size.rs#L1), [`core/dr-export/src/size.rs:25`](../core/dr-export/src/size.rs#L25), [`core/dr-export/src/size.rs:84`](../core/dr-export/src/size.rs#L84), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:668`](../core/dr-types/src/settings.rs#L668), [`core/dr-types/src/settings.rs:676`](../core/dr-types/src/settings.rs#L676), [`core/dr-types/src/settings.rs:692`](../core/dr-types/src/settings.rs#L692), [`core/dr-types/src/settings.rs:761`](../core/dr-types/src/settings.rs#L761), [`core/dr-types/src/settings.rs:789`](../core/dr-types/src/settings.rs#L789), [`core/dr-types/src/settings.rs:800`](../core/dr-types/src/settings.rs#L800), [`core/dr-types/src/settings.rs:806`](../core/dr-types/src/settings.rs#L806), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:203`](../ui/dr-ui/src/settings_ui.rs#L203), [`ui/dr-ui/src/settings_ui.rs:216`](../ui/dr-ui/src/settings_ui.rs#L216), [`ui/dr-ui/src/settings_ui.rs:231`](../ui/dr-ui/src/settings_ui.rs#L231), [`ui/dr-ui/src/settings_ui.rs:561`](../ui/dr-ui/src/settings_ui.rs#L561), [`ui/dr-ui/ui/settings.slint:697`](../ui/dr-ui/ui/settings.slint#L697), [`ui/dr-ui/ui/settings.slint:707`](../ui/dr-ui/ui/settings.slint#L707) | | FR-EXP-4 | [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/sharpen.rs:1`](../core/dr-export/src/sharpen.rs#L1), [`core/dr-export/src/size.rs:1`](../core/dr-export/src/size.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-5 | [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1) | | FR-EXP-6 | [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/name.rs:1`](../core/dr-export/src/name.rs#L1), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/export.rs:1`](../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/lib.rs:422`](../ui/dr-ui/src/lib.rs#L422), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:49`](../ui/dr-ui/src/settings_ui.rs#L49), [`ui/dr-ui/src/settings_ui.rs:675`](../ui/dr-ui/src/settings_ui.rs#L675) | -| FR-EXP-7 | [`ui/dr-ui/src/activity.rs:83`](../ui/dr-ui/src/activity.rs#L83), [`ui/dr-ui/src/export.rs:1`](../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/export.rs:942`](../ui/dr-ui/src/export.rs#L942), [`ui/dr-ui/src/lib.rs:206`](../ui/dr-ui/src/lib.rs#L206), [`ui/dr-ui/src/lib.rs:2219`](../ui/dr-ui/src/lib.rs#L2219), [`ui/dr-ui/src/lib.rs:422`](../ui/dr-ui/src/lib.rs#L422), [`ui/dr-ui/src/lib.rs:457`](../ui/dr-ui/src/lib.rs#L457), [`ui/dr-ui/src/lib.rs:484`](../ui/dr-ui/src/lib.rs#L484), [`ui/dr-ui/src/library_ui.rs:3375`](../ui/dr-ui/src/library_ui.rs#L3375), [`ui/dr-ui/src/library_ui.rs:563`](../ui/dr-ui/src/library_ui.rs#L563), [`ui/dr-ui/src/library_ui.rs:6371`](../ui/dr-ui/src/library_ui.rs#L6371), [`ui/dr-ui/src/library_ui.rs:6448`](../ui/dr-ui/src/library_ui.rs#L6448), [`ui/dr-ui/src/library_ui.rs:6460`](../ui/dr-ui/src/library_ui.rs#L6460), [`ui/dr-ui/src/library_ui.rs:663`](../ui/dr-ui/src/library_ui.rs#L663), [`ui/dr-ui/src/library_ui.rs:720`](../ui/dr-ui/src/library_ui.rs#L720), [`ui/dr-ui/ui/app.slint:1026`](../ui/dr-ui/ui/app.slint#L1026), [`ui/dr-ui/ui/app.slint:1487`](../ui/dr-ui/ui/app.slint#L1487), [`ui/dr-ui/ui/library.slint:1399`](../ui/dr-ui/ui/library.slint#L1399), [`ui/dr-ui/ui/library.slint:841`](../ui/dr-ui/ui/library.slint#L841), [`ui/dr-ui/ui/library.slint:951`](../ui/dr-ui/ui/library.slint#L951) | +| FR-EXP-7 | [`ui/dr-ui/src/activity.rs:83`](../ui/dr-ui/src/activity.rs#L83), [`ui/dr-ui/src/export.rs:1`](../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/export.rs:942`](../ui/dr-ui/src/export.rs#L942), [`ui/dr-ui/src/lib.rs:206`](../ui/dr-ui/src/lib.rs#L206), [`ui/dr-ui/src/lib.rs:2219`](../ui/dr-ui/src/lib.rs#L2219), [`ui/dr-ui/src/lib.rs:422`](../ui/dr-ui/src/lib.rs#L422), [`ui/dr-ui/src/lib.rs:457`](../ui/dr-ui/src/lib.rs#L457), [`ui/dr-ui/src/lib.rs:484`](../ui/dr-ui/src/lib.rs#L484), [`ui/dr-ui/src/library_ui.rs:3375`](../ui/dr-ui/src/library_ui.rs#L3375), [`ui/dr-ui/src/library_ui.rs:563`](../ui/dr-ui/src/library_ui.rs#L563), [`ui/dr-ui/src/library_ui.rs:6371`](../ui/dr-ui/src/library_ui.rs#L6371), [`ui/dr-ui/src/library_ui.rs:6448`](../ui/dr-ui/src/library_ui.rs#L6448), [`ui/dr-ui/src/library_ui.rs:6460`](../ui/dr-ui/src/library_ui.rs#L6460), [`ui/dr-ui/src/library_ui.rs:663`](../ui/dr-ui/src/library_ui.rs#L663), [`ui/dr-ui/src/library_ui.rs:720`](../ui/dr-ui/src/library_ui.rs#L720), [`ui/dr-ui/ui/app.slint:1034`](../ui/dr-ui/ui/app.slint#L1034), [`ui/dr-ui/ui/app.slint:1497`](../ui/dr-ui/ui/app.slint#L1497), [`ui/dr-ui/ui/library.slint:1420`](../ui/dr-ui/ui/library.slint#L1420), [`ui/dr-ui/ui/library.slint:841`](../ui/dr-ui/ui/library.slint#L841), [`ui/dr-ui/ui/library.slint:951`](../ui/dr-ui/ui/library.slint#L951) | | FR-EXP-8 | [`core/dr-decode/src/lib.rs:326`](../core/dr-decode/src/lib.rs#L326), [`core/dr-decode/src/lib.rs:350`](../core/dr-decode/src/lib.rs#L350), [`core/dr-decode/src/lib.rs:364`](../core/dr-decode/src/lib.rs#L364), [`core/dr-decode/src/lib.rs:71`](../core/dr-decode/src/lib.rs#L71), [`core/dr-decode/src/lib.rs:79`](../core/dr-decode/src/lib.rs#L79), [`core/dr-decode/src/lib.rs:82`](../core/dr-decode/src/lib.rs#L82), [`core/dr-decode/src/locate.rs:1164`](../core/dr-decode/src/locate.rs#L1164), [`core/dr-decode/src/locate.rs:1223`](../core/dr-decode/src/locate.rs#L1223), [`core/dr-decode/src/locate.rs:316`](../core/dr-decode/src/locate.rs#L316), [`core/dr-decode/src/locate.rs:487`](../core/dr-decode/src/locate.rs#L487), [`core/dr-decode/src/locate.rs:571`](../core/dr-decode/src/locate.rs#L571), [`core/dr-decode/src/locate.rs:584`](../core/dr-decode/src/locate.rs#L584), [`core/dr-decode/src/locate.rs:667`](../core/dr-decode/src/locate.rs#L667), [`core/dr-export/examples/export.rs:99`](../core/dr-export/examples/export.rs#L99), [`core/dr-export/src/encode.rs:117`](../core/dr-export/src/encode.rs#L117), [`core/dr-export/src/encode.rs:161`](../core/dr-export/src/encode.rs#L161), [`core/dr-export/src/encode.rs:1`](../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/encode.rs:206`](../core/dr-export/src/encode.rs#L206), [`core/dr-export/src/encode.rs:235`](../core/dr-export/src/encode.rs#L235), [`core/dr-export/src/encode.rs:311`](../core/dr-export/src/encode.rs#L311), [`core/dr-export/src/encode.rs:325`](../core/dr-export/src/encode.rs#L325), [`core/dr-export/src/encode.rs:408`](../core/dr-export/src/encode.rs#L408), [`core/dr-export/src/encode.rs:456`](../core/dr-export/src/encode.rs#L456), [`core/dr-export/src/encode.rs:70`](../core/dr-export/src/encode.rs#L70), [`core/dr-export/src/encode.rs:795`](../core/dr-export/src/encode.rs#L795), [`core/dr-export/src/encode.rs:809`](../core/dr-export/src/encode.rs#L809), [`core/dr-export/src/encode.rs:850`](../core/dr-export/src/encode.rs#L850), [`core/dr-export/src/encode.rs:898`](../core/dr-export/src/encode.rs#L898), [`core/dr-export/src/exif.rs:1`](../core/dr-export/src/exif.rs#L1), [`core/dr-export/src/lib.rs:136`](../core/dr-export/src/lib.rs#L136), [`core/dr-export/src/metadata.rs:1`](../core/dr-export/src/metadata.rs#L1), [`core/dr-export/src/metadata.rs:41`](../core/dr-export/src/metadata.rs#L41), [`core/dr-export/src/metadata.rs:74`](../core/dr-export/src/metadata.rs#L74), [`core/dr-types/src/lib.rs:653`](../core/dr-types/src/lib.rs#L653), [`core/dr-types/src/settings.rs:336`](../core/dr-types/src/settings.rs#L336), [`ui/dr-ui/src/export.rs:619`](../ui/dr-ui/src/export.rs#L619), [`ui/dr-ui/src/export.rs:647`](../ui/dr-ui/src/export.rs#L647), [`ui/dr-ui/src/export.rs:777`](../ui/dr-ui/src/export.rs#L777), [`ui/dr-ui/src/export.rs:794`](../ui/dr-ui/src/export.rs#L794), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-9 | [`core/dr-decode/src/lib.rs:506`](../core/dr-decode/src/lib.rs#L506), [`core/dr-export/src/lib.rs:128`](../core/dr-export/src/lib.rs#L128), [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-gpu/src/adjust.rs:1068`](../core/dr-gpu/src/adjust.rs#L1068), [`ui/dr-ui/src/develop.rs:3079`](../ui/dr-ui/src/develop.rs#L3079), [`ui/dr-ui/src/lib.rs:422`](../ui/dr-ui/src/lib.rs#L422) | | FR-NC-1 | [`core/dr-sync-nextcloud/src/auth.rs:132`](../core/dr-sync-nextcloud/src/auth.rs#L132), [`core/dr-sync-nextcloud/src/auth.rs:44`](../core/dr-sync-nextcloud/src/auth.rs#L44), [`core/dr-sync-nextcloud/src/provider.rs:1`](../core/dr-sync-nextcloud/src/provider.rs#L1), [`core/dr-sync/src/account.rs:355`](../core/dr-sync/src/account.rs#L355), [`ui/dr-ui/src/launch.rs:277`](../ui/dr-ui/src/launch.rs#L277), [`ui/dr-ui/src/launch.rs:61`](../ui/dr-ui/src/launch.rs#L61), [`ui/dr-ui/src/launch_ui.rs:417`](../ui/dr-ui/src/launch_ui.rs#L417) | @@ -92,13 +92,13 @@ _None._ | FR-NC-12 | [`core/dr-sync-folder/src/lib.rs:1`](../core/dr-sync-folder/src/lib.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:40`](../core/dr-sync-nextcloud/src/lib.rs#L40), [`core/dr-sync-nextcloud/src/lib.rs:914`](../core/dr-sync-nextcloud/src/lib.rs#L914), [`core/dr-sync-nextcloud/src/provider.rs:1`](../core/dr-sync-nextcloud/src/provider.rs#L1), [`core/dr-sync/src/account.rs:1`](../core/dr-sync/src/account.rs#L1), [`core/dr-sync/src/account.rs:81`](../core/dr-sync/src/account.rs#L81), [`core/dr-sync/src/lib.rs:218`](../core/dr-sync/src/lib.rs#L218), [`core/dr-sync/src/lib.rs:51`](../core/dr-sync/src/lib.rs#L51), [`core/dr-sync/src/provider.rs:106`](../core/dr-sync/src/provider.rs#L106), [`core/dr-sync/src/provider.rs:1`](../core/dr-sync/src/provider.rs#L1), [`core/dr-sync/src/provider.rs:53`](../core/dr-sync/src/provider.rs#L53), [`core/dr-sync/src/reachability.rs:1`](../core/dr-sync/src/reachability.rs#L1), [`ui/dr-ui/src/remote.rs:1`](../ui/dr-ui/src/remote.rs#L1) | | FR-NC-13 | [`core/dr-sync-folder/src/lib.rs:197`](../core/dr-sync-folder/src/lib.rs#L197), [`core/dr-sync-folder/src/lib.rs:1`](../core/dr-sync-folder/src/lib.rs#L1), [`core/dr-sync-folder/src/lib.rs:73`](../core/dr-sync-folder/src/lib.rs#L73), [`core/dr-sync/src/provider.rs:106`](../core/dr-sync/src/provider.rs#L106), [`ui/dr-ui/src/launch_ui.rs:316`](../ui/dr-ui/src/launch_ui.rs#L316), [`ui/dr-ui/src/remote.rs:1`](../ui/dr-ui/src/remote.rs#L1) | | FR-NC-2 | [`core/dr-sync/src/account.rs:1`](../core/dr-sync/src/account.rs#L1), [`core/dr-sync/src/account.rs:298`](../core/dr-sync/src/account.rs#L298), [`core/dr-sync/src/account.rs:355`](../core/dr-sync/src/account.rs#L355), [`core/dr-sync/src/account.rs:59`](../core/dr-sync/src/account.rs#L59), [`platform/dr-plat/src/secrets.rs:82`](../platform/dr-plat/src/secrets.rs#L82) | -| FR-NC-3 | [`core/dr-decode/src/locate.rs:1`](../core/dr-decode/src/locate.rs#L1), [`core/dr-decode/src/preview.rs:148`](../core/dr-decode/src/preview.rs#L148), [`core/dr-sync/src/capability.rs:85`](../core/dr-sync/src/capability.rs#L85), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:2848`](../ui/dr-ui/src/library.rs#L2848), [`ui/dr-ui/src/library.rs:3356`](../ui/dr-ui/src/library.rs#L3356), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1), [`ui/dr-ui/src/library_ui.rs:3627`](../ui/dr-ui/src/library_ui.rs#L3627), [`ui/dr-ui/src/library_ui.rs:4592`](../ui/dr-ui/src/library_ui.rs#L4592), [`ui/dr-ui/ui/app.slint:366`](../ui/dr-ui/ui/app.slint#L366), [`ui/dr-ui/ui/settings.slint:387`](../ui/dr-ui/ui/settings.slint#L387), [`ui/dr-ui/ui/settings.slint:73`](../ui/dr-ui/ui/settings.slint#L73) | +| FR-NC-3 | [`core/dr-decode/src/locate.rs:1`](../core/dr-decode/src/locate.rs#L1), [`core/dr-decode/src/preview.rs:148`](../core/dr-decode/src/preview.rs#L148), [`core/dr-sync/src/capability.rs:85`](../core/dr-sync/src/capability.rs#L85), [`core/dr-thumbs/src/lib.rs:1`](../core/dr-thumbs/src/lib.rs#L1), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:2848`](../ui/dr-ui/src/library.rs#L2848), [`ui/dr-ui/src/library.rs:3356`](../ui/dr-ui/src/library.rs#L3356), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1), [`ui/dr-ui/src/library_ui.rs:3627`](../ui/dr-ui/src/library_ui.rs#L3627), [`ui/dr-ui/src/library_ui.rs:4592`](../ui/dr-ui/src/library_ui.rs#L4592), [`ui/dr-ui/ui/app.slint:374`](../ui/dr-ui/ui/app.slint#L374), [`ui/dr-ui/ui/settings.slint:387`](../ui/dr-ui/ui/settings.slint#L387), [`ui/dr-ui/ui/settings.slint:73`](../ui/dr-ui/ui/settings.slint#L73) | | FR-NC-4 | [`core/dr-sync-folder/src/lib.rs:197`](../core/dr-sync-folder/src/lib.rs#L197), [`core/dr-sync-nextcloud/src/propfind.rs:103`](../core/dr-sync-nextcloud/src/propfind.rs#L103), [`core/dr-sync-nextcloud/src/propfind.rs:51`](../core/dr-sync-nextcloud/src/propfind.rs#L51), [`core/dr-sync/src/capability.rs:6`](../core/dr-sync/src/capability.rs#L6), [`core/dr-sync/src/lib.rs:218`](../core/dr-sync/src/lib.rs#L218), [`core/dr-sync/src/scan.rs:93`](../core/dr-sync/src/scan.rs#L93), [`ui/dr-ui/src/launch.rs:61`](../ui/dr-ui/src/launch.rs#L61) | | FR-NC-5 | [`core/dr-sync-nextcloud/src/propfind.rs:51`](../core/dr-sync-nextcloud/src/propfind.rs#L51), [`ui/dr-ui/src/import.rs:488`](../ui/dr-ui/src/import.rs#L488) | | FR-NC-6 | [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1) | -| FR-NC-6a | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/cache.rs:225`](../core/dr-catalog/src/cache.rs#L225), [`core/dr-catalog/src/schema.rs:1014`](../core/dr-catalog/src/schema.rs#L1014), [`core/dr-catalog/src/schema.rs:613`](../core/dr-catalog/src/schema.rs#L613), [`core/dr-sync-folder/src/borrow.rs:1`](../core/dr-sync-folder/src/borrow.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/collections_ui.rs:3241`](../ui/dr-ui/src/collections_ui.rs#L3241), [`ui/dr-ui/src/collections_ui.rs:621`](../ui/dr-ui/src/collections_ui.rs#L621), [`ui/dr-ui/src/collections_ui.rs:683`](../ui/dr-ui/src/collections_ui.rs#L683), [`ui/dr-ui/src/lib.rs:1923`](../ui/dr-ui/src/lib.rs#L1923), [`ui/dr-ui/src/lib.rs:3037`](../ui/dr-ui/src/lib.rs#L3037), [`ui/dr-ui/src/library.rs:1449`](../ui/dr-ui/src/library.rs#L1449), [`ui/dr-ui/src/library.rs:1472`](../ui/dr-ui/src/library.rs#L1472), [`ui/dr-ui/src/library.rs:1747`](../ui/dr-ui/src/library.rs#L1747), [`ui/dr-ui/src/library_ui.rs:1065`](../ui/dr-ui/src/library_ui.rs#L1065), [`ui/dr-ui/src/library_ui.rs:1138`](../ui/dr-ui/src/library_ui.rs#L1138), [`ui/dr-ui/src/library_ui.rs:1239`](../ui/dr-ui/src/library_ui.rs#L1239), [`ui/dr-ui/src/library_ui.rs:1294`](../ui/dr-ui/src/library_ui.rs#L1294), [`ui/dr-ui/src/library_ui.rs:1429`](../ui/dr-ui/src/library_ui.rs#L1429), [`ui/dr-ui/src/library_ui.rs:1547`](../ui/dr-ui/src/library_ui.rs#L1547), [`ui/dr-ui/src/library_ui.rs:2074`](../ui/dr-ui/src/library_ui.rs#L2074), [`ui/dr-ui/src/library_ui.rs:273`](../ui/dr-ui/src/library_ui.rs#L273), [`ui/dr-ui/src/library_ui.rs:284`](../ui/dr-ui/src/library_ui.rs#L284), [`ui/dr-ui/src/library_ui.rs:292`](../ui/dr-ui/src/library_ui.rs#L292), [`ui/dr-ui/src/library_ui.rs:304`](../ui/dr-ui/src/library_ui.rs#L304), [`ui/dr-ui/src/library_ui.rs:313`](../ui/dr-ui/src/library_ui.rs#L313), [`ui/dr-ui/src/library_ui.rs:405`](../ui/dr-ui/src/library_ui.rs#L405), [`ui/dr-ui/src/library_ui.rs:415`](../ui/dr-ui/src/library_ui.rs#L415), [`ui/dr-ui/src/library_ui.rs:457`](../ui/dr-ui/src/library_ui.rs#L457), [`ui/dr-ui/src/library_ui.rs:520`](../ui/dr-ui/src/library_ui.rs#L520), [`ui/dr-ui/src/library_ui.rs:5318`](../ui/dr-ui/src/library_ui.rs#L5318), [`ui/dr-ui/src/library_ui.rs:5336`](../ui/dr-ui/src/library_ui.rs#L5336), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/src/library_ui.rs:551`](../ui/dr-ui/src/library_ui.rs#L551), [`ui/dr-ui/src/library_ui.rs:563`](../ui/dr-ui/src/library_ui.rs#L563), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/ui/app.slint:2509`](../ui/dr-ui/ui/app.slint#L2509), [`ui/dr-ui/ui/app.slint:481`](../ui/dr-ui/ui/app.slint#L481), [`ui/dr-ui/ui/collections.slint:249`](../ui/dr-ui/ui/collections.slint#L249), [`ui/dr-ui/ui/collections.slint:369`](../ui/dr-ui/ui/collections.slint#L369), [`ui/dr-ui/ui/collections.slint:52`](../ui/dr-ui/ui/collections.slint#L52), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/collections.slint:84`](../ui/dr-ui/ui/collections.slint#L84), [`ui/dr-ui/ui/icons.slint:260`](../ui/dr-ui/ui/icons.slint#L260), [`ui/dr-ui/ui/library.slint:997`](../ui/dr-ui/ui/library.slint#L997) | +| FR-NC-6a | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/cache.rs:225`](../core/dr-catalog/src/cache.rs#L225), [`core/dr-catalog/src/schema.rs:1014`](../core/dr-catalog/src/schema.rs#L1014), [`core/dr-catalog/src/schema.rs:613`](../core/dr-catalog/src/schema.rs#L613), [`core/dr-sync-folder/src/borrow.rs:1`](../core/dr-sync-folder/src/borrow.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/collections_ui.rs:3359`](../ui/dr-ui/src/collections_ui.rs#L3359), [`ui/dr-ui/src/collections_ui.rs:622`](../ui/dr-ui/src/collections_ui.rs#L622), [`ui/dr-ui/src/collections_ui.rs:690`](../ui/dr-ui/src/collections_ui.rs#L690), [`ui/dr-ui/src/lib.rs:1923`](../ui/dr-ui/src/lib.rs#L1923), [`ui/dr-ui/src/lib.rs:3037`](../ui/dr-ui/src/lib.rs#L3037), [`ui/dr-ui/src/library.rs:1449`](../ui/dr-ui/src/library.rs#L1449), [`ui/dr-ui/src/library.rs:1472`](../ui/dr-ui/src/library.rs#L1472), [`ui/dr-ui/src/library.rs:1747`](../ui/dr-ui/src/library.rs#L1747), [`ui/dr-ui/src/library_ui.rs:1065`](../ui/dr-ui/src/library_ui.rs#L1065), [`ui/dr-ui/src/library_ui.rs:1138`](../ui/dr-ui/src/library_ui.rs#L1138), [`ui/dr-ui/src/library_ui.rs:1239`](../ui/dr-ui/src/library_ui.rs#L1239), [`ui/dr-ui/src/library_ui.rs:1294`](../ui/dr-ui/src/library_ui.rs#L1294), [`ui/dr-ui/src/library_ui.rs:1429`](../ui/dr-ui/src/library_ui.rs#L1429), [`ui/dr-ui/src/library_ui.rs:1547`](../ui/dr-ui/src/library_ui.rs#L1547), [`ui/dr-ui/src/library_ui.rs:2074`](../ui/dr-ui/src/library_ui.rs#L2074), [`ui/dr-ui/src/library_ui.rs:273`](../ui/dr-ui/src/library_ui.rs#L273), [`ui/dr-ui/src/library_ui.rs:284`](../ui/dr-ui/src/library_ui.rs#L284), [`ui/dr-ui/src/library_ui.rs:292`](../ui/dr-ui/src/library_ui.rs#L292), [`ui/dr-ui/src/library_ui.rs:304`](../ui/dr-ui/src/library_ui.rs#L304), [`ui/dr-ui/src/library_ui.rs:313`](../ui/dr-ui/src/library_ui.rs#L313), [`ui/dr-ui/src/library_ui.rs:405`](../ui/dr-ui/src/library_ui.rs#L405), [`ui/dr-ui/src/library_ui.rs:415`](../ui/dr-ui/src/library_ui.rs#L415), [`ui/dr-ui/src/library_ui.rs:457`](../ui/dr-ui/src/library_ui.rs#L457), [`ui/dr-ui/src/library_ui.rs:520`](../ui/dr-ui/src/library_ui.rs#L520), [`ui/dr-ui/src/library_ui.rs:5318`](../ui/dr-ui/src/library_ui.rs#L5318), [`ui/dr-ui/src/library_ui.rs:5336`](../ui/dr-ui/src/library_ui.rs#L5336), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/src/library_ui.rs:551`](../ui/dr-ui/src/library_ui.rs#L551), [`ui/dr-ui/src/library_ui.rs:563`](../ui/dr-ui/src/library_ui.rs#L563), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/ui/app.slint:2519`](../ui/dr-ui/ui/app.slint#L2519), [`ui/dr-ui/ui/app.slint:489`](../ui/dr-ui/ui/app.slint#L489), [`ui/dr-ui/ui/collections.slint:249`](../ui/dr-ui/ui/collections.slint#L249), [`ui/dr-ui/ui/collections.slint:369`](../ui/dr-ui/ui/collections.slint#L369), [`ui/dr-ui/ui/collections.slint:52`](../ui/dr-ui/ui/collections.slint#L52), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/collections.slint:84`](../ui/dr-ui/ui/collections.slint#L84), [`ui/dr-ui/ui/icons.slint:260`](../ui/dr-ui/ui/icons.slint#L260), [`ui/dr-ui/ui/library.slint:997`](../ui/dr-ui/ui/library.slint#L997) | | FR-NC-6b | [`ui/dr-ui/src/library_ui.rs:1294`](../ui/dr-ui/src/library_ui.rs#L1294) | -| FR-NC-6c | [`core/dr-catalog/src/cache.rs:225`](../core/dr-catalog/src/cache.rs#L225), [`core/dr-sync-folder/src/borrow.rs:1`](../core/dr-sync-folder/src/borrow.rs#L1), [`core/dr-sync-folder/src/lib.rs:197`](../core/dr-sync-folder/src/lib.rs#L197), [`core/dr-sync-folder/src/lib.rs:73`](../core/dr-sync-folder/src/lib.rs#L73), [`core/dr-sync-folder/src/lib.rs:803`](../core/dr-sync-folder/src/lib.rs#L803), [`core/dr-sync-folder/src/lib.rs:842`](../core/dr-sync-folder/src/lib.rs#L842), [`core/dr-sync-folder/src/vfs.rs:1`](../core/dr-sync-folder/src/vfs.rs#L1), [`core/dr-sync-nextcloud/src/desktop_client.rs:167`](../core/dr-sync-nextcloud/src/desktop_client.rs#L167), [`core/dr-sync-nextcloud/src/desktop_client.rs:30`](../core/dr-sync-nextcloud/src/desktop_client.rs#L30), [`core/dr-sync/src/capability.rs:41`](../core/dr-sync/src/capability.rs#L41), [`core/dr-sync/src/error.rs:39`](../core/dr-sync/src/error.rs#L39), [`core/dr-sync/src/lib.rs:158`](../core/dr-sync/src/lib.rs#L158), [`core/dr-sync/src/types.rs:101`](../core/dr-sync/src/types.rs#L101), [`core/dr-types/src/lib.rs:120`](../core/dr-types/src/lib.rs#L120), [`core/dr-types/src/lib.rs:202`](../core/dr-types/src/lib.rs#L202), [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1), [`ui/dr-ui/src/collections_ui.rs:3241`](../ui/dr-ui/src/collections_ui.rs#L3241), [`ui/dr-ui/src/collections_ui.rs:621`](../ui/dr-ui/src/collections_ui.rs#L621), [`ui/dr-ui/src/collections_ui.rs:683`](../ui/dr-ui/src/collections_ui.rs#L683), [`ui/dr-ui/src/derived_sync.rs:555`](../ui/dr-ui/src/derived_sync.rs#L555), [`ui/dr-ui/src/derived_sync.rs:627`](../ui/dr-ui/src/derived_sync.rs#L627), [`ui/dr-ui/src/library.rs:1569`](../ui/dr-ui/src/library.rs#L1569), [`ui/dr-ui/src/library.rs:1659`](../ui/dr-ui/src/library.rs#L1659), [`ui/dr-ui/src/library.rs:3138`](../ui/dr-ui/src/library.rs#L3138), [`ui/dr-ui/src/library.rs:3476`](../ui/dr-ui/src/library.rs#L3476), [`ui/dr-ui/src/library.rs:948`](../ui/dr-ui/src/library.rs#L948), [`ui/dr-ui/src/library_ui.rs:1065`](../ui/dr-ui/src/library_ui.rs#L1065), [`ui/dr-ui/src/library_ui.rs:1138`](../ui/dr-ui/src/library_ui.rs#L1138), [`ui/dr-ui/src/library_ui.rs:1337`](../ui/dr-ui/src/library_ui.rs#L1337), [`ui/dr-ui/src/remote.rs:40`](../ui/dr-ui/src/remote.rs#L40), [`ui/dr-ui/ui/collections.slint:249`](../ui/dr-ui/ui/collections.slint#L249), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/icons.slint:260`](../ui/dr-ui/ui/icons.slint#L260) | +| FR-NC-6c | [`core/dr-catalog/src/cache.rs:225`](../core/dr-catalog/src/cache.rs#L225), [`core/dr-sync-folder/src/borrow.rs:1`](../core/dr-sync-folder/src/borrow.rs#L1), [`core/dr-sync-folder/src/lib.rs:197`](../core/dr-sync-folder/src/lib.rs#L197), [`core/dr-sync-folder/src/lib.rs:73`](../core/dr-sync-folder/src/lib.rs#L73), [`core/dr-sync-folder/src/lib.rs:803`](../core/dr-sync-folder/src/lib.rs#L803), [`core/dr-sync-folder/src/lib.rs:842`](../core/dr-sync-folder/src/lib.rs#L842), [`core/dr-sync-folder/src/vfs.rs:1`](../core/dr-sync-folder/src/vfs.rs#L1), [`core/dr-sync-nextcloud/src/desktop_client.rs:167`](../core/dr-sync-nextcloud/src/desktop_client.rs#L167), [`core/dr-sync-nextcloud/src/desktop_client.rs:30`](../core/dr-sync-nextcloud/src/desktop_client.rs#L30), [`core/dr-sync/src/capability.rs:41`](../core/dr-sync/src/capability.rs#L41), [`core/dr-sync/src/error.rs:39`](../core/dr-sync/src/error.rs#L39), [`core/dr-sync/src/lib.rs:158`](../core/dr-sync/src/lib.rs#L158), [`core/dr-sync/src/types.rs:101`](../core/dr-sync/src/types.rs#L101), [`core/dr-types/src/lib.rs:120`](../core/dr-types/src/lib.rs#L120), [`core/dr-types/src/lib.rs:202`](../core/dr-types/src/lib.rs#L202), [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1), [`ui/dr-ui/src/collections_ui.rs:3359`](../ui/dr-ui/src/collections_ui.rs#L3359), [`ui/dr-ui/src/collections_ui.rs:622`](../ui/dr-ui/src/collections_ui.rs#L622), [`ui/dr-ui/src/collections_ui.rs:690`](../ui/dr-ui/src/collections_ui.rs#L690), [`ui/dr-ui/src/derived_sync.rs:555`](../ui/dr-ui/src/derived_sync.rs#L555), [`ui/dr-ui/src/derived_sync.rs:627`](../ui/dr-ui/src/derived_sync.rs#L627), [`ui/dr-ui/src/library.rs:1569`](../ui/dr-ui/src/library.rs#L1569), [`ui/dr-ui/src/library.rs:1659`](../ui/dr-ui/src/library.rs#L1659), [`ui/dr-ui/src/library.rs:3138`](../ui/dr-ui/src/library.rs#L3138), [`ui/dr-ui/src/library.rs:3476`](../ui/dr-ui/src/library.rs#L3476), [`ui/dr-ui/src/library.rs:948`](../ui/dr-ui/src/library.rs#L948), [`ui/dr-ui/src/library_ui.rs:1065`](../ui/dr-ui/src/library_ui.rs#L1065), [`ui/dr-ui/src/library_ui.rs:1138`](../ui/dr-ui/src/library_ui.rs#L1138), [`ui/dr-ui/src/library_ui.rs:1337`](../ui/dr-ui/src/library_ui.rs#L1337), [`ui/dr-ui/src/remote.rs:40`](../ui/dr-ui/src/remote.rs#L40), [`ui/dr-ui/ui/collections.slint:249`](../ui/dr-ui/ui/collections.slint#L249), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/icons.slint:260`](../ui/dr-ui/ui/icons.slint#L260) | | FR-NC-6d | [`core/dr-sync-folder/src/borrow.rs:1`](../core/dr-sync-folder/src/borrow.rs#L1), [`core/dr-sync-folder/src/lib.rs:1`](../core/dr-sync-folder/src/lib.rs#L1), [`core/dr-sync-folder/src/vfs.rs:1`](../core/dr-sync-folder/src/vfs.rs#L1) | | FR-NC-7 | [`core/dr-catalog/src/face_shard.rs:1`](../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:105`](../core/dr-sync-nextcloud/src/lib.rs#L105), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library.rs:3356`](../ui/dr-ui/src/library.rs#L3356), [`ui/dr-ui/src/library_ui.rs:3627`](../ui/dr-ui/src/library_ui.rs#L3627), [`ui/dr-ui/ui/settings.slint:387`](../ui/dr-ui/ui/settings.slint#L387) | | FR-NC-7a | [`core/dr-ingest/src/layout.rs:1`](../core/dr-ingest/src/layout.rs#L1), [`core/dr-sync/src/upload.rs:1`](../core/dr-sync/src/upload.rs#L1), [`core/dr-sync/src/upload.rs:40`](../core/dr-sync/src/upload.rs#L40), [`core/dr-types/src/settings.rs:116`](../core/dr-types/src/settings.rs#L116), [`ui/dr-ui/src/import.rs:1`](../ui/dr-ui/src/import.rs#L1), [`ui/dr-ui/src/import.rs:97`](../ui/dr-ui/src/import.rs#L97), [`ui/dr-ui/src/import_ui.rs:1`](../ui/dr-ui/src/import_ui.rs#L1), [`ui/dr-ui/src/lib.rs:1183`](../ui/dr-ui/src/lib.rs#L1183), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | @@ -116,21 +116,21 @@ _None._ | FR-RAW-4 | [`core/dr-decode/src/error.rs:1`](../core/dr-decode/src/error.rs#L1), [`ui/dr-ui/src/lib.rs:206`](../ui/dr-ui/src/lib.rs#L206) | | FR-RAW-5 | [`core/dr-decode/src/lib.rs:167`](../core/dr-decode/src/lib.rs#L167), [`core/dr-gpu/src/demosaic.rs:34`](../core/dr-gpu/src/demosaic.rs#L34), [`core/dr-gpu/src/demosaic.rs:602`](../core/dr-gpu/src/demosaic.rs#L602), [`core/dr-gpu/src/demosaic.rs:681`](../core/dr-gpu/src/demosaic.rs#L681), [`core/dr-gpu/src/demosaic.rs:805`](../core/dr-gpu/src/demosaic.rs#L805) | | FR-UI-1 | [`ui/dr-ui/src/lib.rs:3119`](../ui/dr-ui/src/lib.rs#L3119), [`ui/dr-ui/src/lib.rs:82`](../ui/dr-ui/src/lib.rs#L82), [`ui/dr-ui/src/masks_ui.rs:816`](../ui/dr-ui/src/masks_ui.rs#L816), [`ui/dr-ui/ui/identity.slint:164`](../ui/dr-ui/ui/identity.slint#L164), [`ui/dr-ui/ui/library.slint:1063`](../ui/dr-ui/ui/library.slint#L1063) | -| FR-UI-2 | [`ui/dr-ui/src/collections_ui.rs:1005`](../ui/dr-ui/src/collections_ui.rs#L1005), [`ui/dr-ui/src/collections_ui.rs:118`](../ui/dr-ui/src/collections_ui.rs#L118), [`ui/dr-ui/src/collections_ui.rs:1488`](../ui/dr-ui/src/collections_ui.rs#L1488), [`ui/dr-ui/src/collections_ui.rs:1502`](../ui/dr-ui/src/collections_ui.rs#L1502), [`ui/dr-ui/src/collections_ui.rs:1548`](../ui/dr-ui/src/collections_ui.rs#L1548), [`ui/dr-ui/src/collections_ui.rs:159`](../ui/dr-ui/src/collections_ui.rs#L159), [`ui/dr-ui/src/collections_ui.rs:1713`](../ui/dr-ui/src/collections_ui.rs#L1713), [`ui/dr-ui/src/collections_ui.rs:485`](../ui/dr-ui/src/collections_ui.rs#L485), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:995`](../ui/dr-ui/src/collections_ui.rs#L995), [`ui/dr-ui/src/lib.rs:82`](../ui/dr-ui/src/lib.rs#L82), [`ui/dr-ui/src/lib.rs:89`](../ui/dr-ui/src/lib.rs#L89), [`ui/dr-ui/src/library_ui.rs:292`](../ui/dr-ui/src/library_ui.rs#L292), [`ui/dr-ui/src/library_ui.rs:5203`](../ui/dr-ui/src/library_ui.rs#L5203), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/src/library_ui.rs:6479`](../ui/dr-ui/src/library_ui.rs#L6479), [`ui/dr-ui/ui/adjust.slint:1072`](../ui/dr-ui/ui/adjust.slint#L1072), [`ui/dr-ui/ui/adjust.slint:544`](../ui/dr-ui/ui/adjust.slint#L544), [`ui/dr-ui/ui/adjust.slint:741`](../ui/dr-ui/ui/adjust.slint#L741), [`ui/dr-ui/ui/app.slint:2079`](../ui/dr-ui/ui/app.slint#L2079), [`ui/dr-ui/ui/app.slint:511`](../ui/dr-ui/ui/app.slint#L511), [`ui/dr-ui/ui/app.slint:518`](../ui/dr-ui/ui/app.slint#L518), [`ui/dr-ui/ui/app.slint:56`](../ui/dr-ui/ui/app.slint#L56), [`ui/dr-ui/ui/app.slint:861`](../ui/dr-ui/ui/app.slint#L861), [`ui/dr-ui/ui/controls.slint:474`](../ui/dr-ui/ui/controls.slint#L474), [`ui/dr-ui/ui/develop.slint:223`](../ui/dr-ui/ui/develop.slint#L223), [`ui/dr-ui/ui/histogram.slint:127`](../ui/dr-ui/ui/histogram.slint#L127), [`ui/dr-ui/ui/history.slint:118`](../ui/dr-ui/ui/history.slint#L118), [`ui/dr-ui/ui/library.slint:1219`](../ui/dr-ui/ui/library.slint#L1219), [`ui/dr-ui/ui/library.slint:1226`](../ui/dr-ui/ui/library.slint#L1226), [`ui/dr-ui/ui/library.slint:1232`](../ui/dr-ui/ui/library.slint#L1232), [`ui/dr-ui/ui/library.slint:1252`](../ui/dr-ui/ui/library.slint#L1252), [`ui/dr-ui/ui/library.slint:2447`](../ui/dr-ui/ui/library.slint#L2447), [`ui/dr-ui/ui/library.slint:829`](../ui/dr-ui/ui/library.slint#L829), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/masks.slint:314`](../ui/dr-ui/ui/masks.slint#L314), [`ui/dr-ui/ui/peaking.slint:82`](../ui/dr-ui/ui/peaking.slint#L82), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/settings.slint:110`](../ui/dr-ui/ui/settings.slint#L110), [`ui/dr-ui/ui/spots.slint:88`](../ui/dr-ui/ui/spots.slint#L88) | -| FR-UI-3 | [`ui/dr-ui/src/develop.rs:2224`](../ui/dr-ui/src/develop.rs#L2224), [`ui/dr-ui/src/develop.rs:2333`](../ui/dr-ui/src/develop.rs#L2333), [`ui/dr-ui/src/library_ui.rs:4387`](../ui/dr-ui/src/library_ui.rs#L4387), [`ui/dr-ui/src/masks_ui.rs:218`](../ui/dr-ui/src/masks_ui.rs#L218), [`ui/dr-ui/src/masks_ui.rs:908`](../ui/dr-ui/src/masks_ui.rs#L908), [`ui/dr-ui/src/masks_ui.rs:930`](../ui/dr-ui/src/masks_ui.rs#L930), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:1895`](../ui/dr-ui/ui/app.slint#L1895), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/masks.slint:524`](../ui/dr-ui/ui/masks.slint#L524) | -| FR-UI-4 | [`ui/dr-ui/src/collections_ui.rs:1005`](../ui/dr-ui/src/collections_ui.rs#L1005), [`ui/dr-ui/src/collections_ui.rs:118`](../ui/dr-ui/src/collections_ui.rs#L118), [`ui/dr-ui/src/collections_ui.rs:131`](../ui/dr-ui/src/collections_ui.rs#L131), [`ui/dr-ui/src/collections_ui.rs:1488`](../ui/dr-ui/src/collections_ui.rs#L1488), [`ui/dr-ui/src/collections_ui.rs:1502`](../ui/dr-ui/src/collections_ui.rs#L1502), [`ui/dr-ui/src/collections_ui.rs:1548`](../ui/dr-ui/src/collections_ui.rs#L1548), [`ui/dr-ui/src/collections_ui.rs:1577`](../ui/dr-ui/src/collections_ui.rs#L1577), [`ui/dr-ui/src/collections_ui.rs:159`](../ui/dr-ui/src/collections_ui.rs#L159), [`ui/dr-ui/src/collections_ui.rs:1713`](../ui/dr-ui/src/collections_ui.rs#L1713), [`ui/dr-ui/src/collections_ui.rs:1740`](../ui/dr-ui/src/collections_ui.rs#L1740), [`ui/dr-ui/src/collections_ui.rs:485`](../ui/dr-ui/src/collections_ui.rs#L485), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:582`](../ui/dr-ui/src/collections_ui.rs#L582), [`ui/dr-ui/src/collections_ui.rs:995`](../ui/dr-ui/src/collections_ui.rs#L995), [`ui/dr-ui/src/library_ui.rs:4387`](../ui/dr-ui/src/library_ui.rs#L4387), [`ui/dr-ui/src/library_ui.rs:4432`](../ui/dr-ui/src/library_ui.rs#L4432), [`ui/dr-ui/src/library_ui.rs:4535`](../ui/dr-ui/src/library_ui.rs#L4535), [`ui/dr-ui/src/library_ui.rs:4563`](../ui/dr-ui/src/library_ui.rs#L4563), [`ui/dr-ui/src/library_ui.rs:5336`](../ui/dr-ui/src/library_ui.rs#L5336), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/ui/app.slint:1735`](../ui/dr-ui/ui/app.slint#L1735), [`ui/dr-ui/ui/app.slint:487`](../ui/dr-ui/ui/app.slint#L487), [`ui/dr-ui/ui/app.slint:518`](../ui/dr-ui/ui/app.slint#L518), [`ui/dr-ui/ui/library.slint:1219`](../ui/dr-ui/ui/library.slint#L1219), [`ui/dr-ui/ui/library.slint:1226`](../ui/dr-ui/ui/library.slint#L1226), [`ui/dr-ui/ui/library.slint:1232`](../ui/dr-ui/ui/library.slint#L1232), [`ui/dr-ui/ui/library.slint:1245`](../ui/dr-ui/ui/library.slint#L1245), [`ui/dr-ui/ui/library.slint:1252`](../ui/dr-ui/ui/library.slint#L1252), [`ui/dr-ui/ui/library.slint:2447`](../ui/dr-ui/ui/library.slint#L2447), [`ui/dr-ui/ui/library.slint:829`](../ui/dr-ui/ui/library.slint#L829), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/library.slint:901`](../ui/dr-ui/ui/library.slint#L901) | +| FR-UI-2 | [`ui/dr-ui/src/collections_ui.rs:1025`](../ui/dr-ui/src/collections_ui.rs#L1025), [`ui/dr-ui/src/collections_ui.rs:1035`](../ui/dr-ui/src/collections_ui.rs#L1035), [`ui/dr-ui/src/collections_ui.rs:119`](../ui/dr-ui/src/collections_ui.rs#L119), [`ui/dr-ui/src/collections_ui.rs:1518`](../ui/dr-ui/src/collections_ui.rs#L1518), [`ui/dr-ui/src/collections_ui.rs:1532`](../ui/dr-ui/src/collections_ui.rs#L1532), [`ui/dr-ui/src/collections_ui.rs:1578`](../ui/dr-ui/src/collections_ui.rs#L1578), [`ui/dr-ui/src/collections_ui.rs:160`](../ui/dr-ui/src/collections_ui.rs#L160), [`ui/dr-ui/src/collections_ui.rs:1830`](../ui/dr-ui/src/collections_ui.rs#L1830), [`ui/dr-ui/src/collections_ui.rs:486`](../ui/dr-ui/src/collections_ui.rs#L486), [`ui/dr-ui/src/collections_ui.rs:515`](../ui/dr-ui/src/collections_ui.rs#L515), [`ui/dr-ui/src/lib.rs:82`](../ui/dr-ui/src/lib.rs#L82), [`ui/dr-ui/src/lib.rs:89`](../ui/dr-ui/src/lib.rs#L89), [`ui/dr-ui/src/library_ui.rs:292`](../ui/dr-ui/src/library_ui.rs#L292), [`ui/dr-ui/src/library_ui.rs:5203`](../ui/dr-ui/src/library_ui.rs#L5203), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/src/library_ui.rs:6479`](../ui/dr-ui/src/library_ui.rs#L6479), [`ui/dr-ui/ui/adjust.slint:1072`](../ui/dr-ui/ui/adjust.slint#L1072), [`ui/dr-ui/ui/adjust.slint:544`](../ui/dr-ui/ui/adjust.slint#L544), [`ui/dr-ui/ui/adjust.slint:741`](../ui/dr-ui/ui/adjust.slint#L741), [`ui/dr-ui/ui/app.slint:2089`](../ui/dr-ui/ui/app.slint#L2089), [`ui/dr-ui/ui/app.slint:519`](../ui/dr-ui/ui/app.slint#L519), [`ui/dr-ui/ui/app.slint:526`](../ui/dr-ui/ui/app.slint#L526), [`ui/dr-ui/ui/app.slint:56`](../ui/dr-ui/ui/app.slint#L56), [`ui/dr-ui/ui/app.slint:869`](../ui/dr-ui/ui/app.slint#L869), [`ui/dr-ui/ui/controls.slint:474`](../ui/dr-ui/ui/controls.slint#L474), [`ui/dr-ui/ui/develop.slint:223`](../ui/dr-ui/ui/develop.slint#L223), [`ui/dr-ui/ui/histogram.slint:127`](../ui/dr-ui/ui/histogram.slint#L127), [`ui/dr-ui/ui/history.slint:118`](../ui/dr-ui/ui/history.slint#L118), [`ui/dr-ui/ui/library.slint:1219`](../ui/dr-ui/ui/library.slint#L1219), [`ui/dr-ui/ui/library.slint:1226`](../ui/dr-ui/ui/library.slint#L1226), [`ui/dr-ui/ui/library.slint:1232`](../ui/dr-ui/ui/library.slint#L1232), [`ui/dr-ui/ui/library.slint:1273`](../ui/dr-ui/ui/library.slint#L1273), [`ui/dr-ui/ui/library.slint:2468`](../ui/dr-ui/ui/library.slint#L2468), [`ui/dr-ui/ui/library.slint:829`](../ui/dr-ui/ui/library.slint#L829), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/masks.slint:314`](../ui/dr-ui/ui/masks.slint#L314), [`ui/dr-ui/ui/peaking.slint:82`](../ui/dr-ui/ui/peaking.slint#L82), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/settings.slint:110`](../ui/dr-ui/ui/settings.slint#L110), [`ui/dr-ui/ui/spots.slint:88`](../ui/dr-ui/ui/spots.slint#L88) | +| FR-UI-3 | [`ui/dr-ui/src/develop.rs:2224`](../ui/dr-ui/src/develop.rs#L2224), [`ui/dr-ui/src/develop.rs:2333`](../ui/dr-ui/src/develop.rs#L2333), [`ui/dr-ui/src/library_ui.rs:4387`](../ui/dr-ui/src/library_ui.rs#L4387), [`ui/dr-ui/src/masks_ui.rs:218`](../ui/dr-ui/src/masks_ui.rs#L218), [`ui/dr-ui/src/masks_ui.rs:908`](../ui/dr-ui/src/masks_ui.rs#L908), [`ui/dr-ui/src/masks_ui.rs:930`](../ui/dr-ui/src/masks_ui.rs#L930), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:1905`](../ui/dr-ui/ui/app.slint#L1905), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:682`](../ui/dr-ui/ui/collections.slint#L682), [`ui/dr-ui/ui/masks.slint:524`](../ui/dr-ui/ui/masks.slint#L524) | +| FR-UI-4 | [`ui/dr-ui/src/collections_ui.rs:1025`](../ui/dr-ui/src/collections_ui.rs#L1025), [`ui/dr-ui/src/collections_ui.rs:1035`](../ui/dr-ui/src/collections_ui.rs#L1035), [`ui/dr-ui/src/collections_ui.rs:119`](../ui/dr-ui/src/collections_ui.rs#L119), [`ui/dr-ui/src/collections_ui.rs:132`](../ui/dr-ui/src/collections_ui.rs#L132), [`ui/dr-ui/src/collections_ui.rs:1518`](../ui/dr-ui/src/collections_ui.rs#L1518), [`ui/dr-ui/src/collections_ui.rs:1532`](../ui/dr-ui/src/collections_ui.rs#L1532), [`ui/dr-ui/src/collections_ui.rs:1578`](../ui/dr-ui/src/collections_ui.rs#L1578), [`ui/dr-ui/src/collections_ui.rs:160`](../ui/dr-ui/src/collections_ui.rs#L160), [`ui/dr-ui/src/collections_ui.rs:1694`](../ui/dr-ui/src/collections_ui.rs#L1694), [`ui/dr-ui/src/collections_ui.rs:1830`](../ui/dr-ui/src/collections_ui.rs#L1830), [`ui/dr-ui/src/collections_ui.rs:1857`](../ui/dr-ui/src/collections_ui.rs#L1857), [`ui/dr-ui/src/collections_ui.rs:486`](../ui/dr-ui/src/collections_ui.rs#L486), [`ui/dr-ui/src/collections_ui.rs:515`](../ui/dr-ui/src/collections_ui.rs#L515), [`ui/dr-ui/src/collections_ui.rs:583`](../ui/dr-ui/src/collections_ui.rs#L583), [`ui/dr-ui/src/library_ui.rs:4387`](../ui/dr-ui/src/library_ui.rs#L4387), [`ui/dr-ui/src/library_ui.rs:4432`](../ui/dr-ui/src/library_ui.rs#L4432), [`ui/dr-ui/src/library_ui.rs:4535`](../ui/dr-ui/src/library_ui.rs#L4535), [`ui/dr-ui/src/library_ui.rs:4563`](../ui/dr-ui/src/library_ui.rs#L4563), [`ui/dr-ui/src/library_ui.rs:5336`](../ui/dr-ui/src/library_ui.rs#L5336), [`ui/dr-ui/src/library_ui.rs:5348`](../ui/dr-ui/src/library_ui.rs#L5348), [`ui/dr-ui/ui/app.slint:1745`](../ui/dr-ui/ui/app.slint#L1745), [`ui/dr-ui/ui/app.slint:495`](../ui/dr-ui/ui/app.slint#L495), [`ui/dr-ui/ui/app.slint:526`](../ui/dr-ui/ui/app.slint#L526), [`ui/dr-ui/ui/library.slint:1219`](../ui/dr-ui/ui/library.slint#L1219), [`ui/dr-ui/ui/library.slint:1226`](../ui/dr-ui/ui/library.slint#L1226), [`ui/dr-ui/ui/library.slint:1232`](../ui/dr-ui/ui/library.slint#L1232), [`ui/dr-ui/ui/library.slint:1266`](../ui/dr-ui/ui/library.slint#L1266), [`ui/dr-ui/ui/library.slint:1273`](../ui/dr-ui/ui/library.slint#L1273), [`ui/dr-ui/ui/library.slint:2468`](../ui/dr-ui/ui/library.slint#L2468), [`ui/dr-ui/ui/library.slint:829`](../ui/dr-ui/ui/library.slint#L829), [`ui/dr-ui/ui/library.slint:882`](../ui/dr-ui/ui/library.slint#L882), [`ui/dr-ui/ui/library.slint:901`](../ui/dr-ui/ui/library.slint#L901) | | FR-UI-5 | [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/lib.rs:2556`](../ui/dr-ui/src/lib.rs#L2556), [`ui/dr-ui/src/lib.rs:3158`](../ui/dr-ui/src/lib.rs#L3158), [`ui/dr-ui/src/lib.rs:3343`](../ui/dr-ui/src/lib.rs#L3343), [`ui/dr-ui/src/masks_ui.rs:863`](../ui/dr-ui/src/masks_ui.rs#L863), [`ui/dr-ui/ui/app.slint:107`](../ui/dr-ui/ui/app.slint#L107), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4) | | FR-UI-6 | [`ui/dr-ui/ui/widgets.slint:1`](../ui/dr-ui/ui/widgets.slint#L1) | | FR-UI-7 | [`core/dr-pipeline/src/descriptor.rs:177`](../core/dr-pipeline/src/descriptor.rs#L177), [`core/dr-pipeline/src/framing.rs:385`](../core/dr-pipeline/src/framing.rs#L385) | | NFR-ARCH-2 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/library.rs:2953`](../ui/dr-ui/src/library.rs#L2953) | -| NFR-ARCH-3 | [`ui/dr-ui/src/export.rs:1553`](../ui/dr-ui/src/export.rs#L1553), [`ui/dr-ui/src/export.rs:1579`](../ui/dr-ui/src/export.rs#L1579), [`ui/dr-ui/src/export.rs:409`](../ui/dr-ui/src/export.rs#L409), [`ui/dr-ui/src/export.rs:435`](../ui/dr-ui/src/export.rs#L435), [`ui/dr-ui/src/lib.rs:2253`](../ui/dr-ui/src/lib.rs#L2253), [`ui/dr-ui/ui/app.slint:1037`](../ui/dr-ui/ui/app.slint#L1037), [`ui/dr-ui/ui/library.slint:951`](../ui/dr-ui/ui/library.slint#L951) | +| NFR-ARCH-3 | [`ui/dr-ui/src/export.rs:1553`](../ui/dr-ui/src/export.rs#L1553), [`ui/dr-ui/src/export.rs:1579`](../ui/dr-ui/src/export.rs#L1579), [`ui/dr-ui/src/export.rs:409`](../ui/dr-ui/src/export.rs#L409), [`ui/dr-ui/src/export.rs:435`](../ui/dr-ui/src/export.rs#L435), [`ui/dr-ui/src/lib.rs:2253`](../ui/dr-ui/src/lib.rs#L2253), [`ui/dr-ui/ui/app.slint:1045`](../ui/dr-ui/ui/app.slint#L1045), [`ui/dr-ui/ui/library.slint:951`](../ui/dr-ui/ui/library.slint#L951) | | NFR-ARCH-4 | [`core/dr-catalog/src/error.rs:1`](../core/dr-catalog/src/error.rs#L1), [`core/dr-export/src/error.rs:1`](../core/dr-export/src/error.rs#L1), [`core/dr-thumbs/src/error.rs:1`](../core/dr-thumbs/src/error.rs#L1), [`platform/dr-plat/src/storage.rs:148`](../platform/dr-plat/src/storage.rs#L148), [`ui/dr-ui/src/export.rs:499`](../ui/dr-ui/src/export.rs#L499) | | NFR-OPS-1 | [`tools/traceability/src/lib.rs:266`](../tools/traceability/src/lib.rs#L266) | | NFR-OPS-3 | [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1) | | NFR-P1 | [`core/dr-catalog/src/lib.rs:1`](../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/walk.rs:162`](../core/dr-catalog/src/walk.rs#L162), [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`tools/traceability/src/lib.rs:479`](../tools/traceability/src/lib.rs#L479) | | NFR-P13 | [`core/dr-decode/src/preview.rs:121`](../core/dr-decode/src/preview.rs#L121) | | NFR-P14 | [`core/dr-gpu/src/focus.rs:186`](../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`ui/dr-ui/src/develop.rs:2964`](../ui/dr-ui/src/develop.rs#L2964), [`ui/dr-ui/src/lib.rs:1626`](../ui/dr-ui/src/lib.rs#L1626) | -| NFR-P5 | [`core/dr-catalog/src/schema.rs:318`](../core/dr-catalog/src/schema.rs#L318), [`ui/dr-ui/src/library.rs:4003`](../ui/dr-ui/src/library.rs#L4003), [`ui/dr-ui/src/library.rs:4795`](../ui/dr-ui/src/library.rs#L4795), [`ui/dr-ui/src/library_ui.rs:4072`](../ui/dr-ui/src/library_ui.rs#L4072), [`ui/dr-ui/src/library_ui.rs:64`](../ui/dr-ui/src/library_ui.rs#L64) | +| NFR-P5 | [`core/dr-catalog/src/schema.rs:318`](../core/dr-catalog/src/schema.rs#L318), [`ui/dr-ui/src/library.rs:4013`](../ui/dr-ui/src/library.rs#L4013), [`ui/dr-ui/src/library.rs:4945`](../ui/dr-ui/src/library.rs#L4945), [`ui/dr-ui/src/library_ui.rs:4072`](../ui/dr-ui/src/library_ui.rs#L4072), [`ui/dr-ui/src/library_ui.rs:64`](../ui/dr-ui/src/library_ui.rs#L64) | | NFR-P9 | [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/export.rs:942`](../ui/dr-ui/src/export.rs#L942), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1) | | NFR-PORT-1 | [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`core/dr-types/src/lib.rs:270`](../core/dr-types/src/lib.rs#L270), [`core/dr-types/src/lib.rs:303`](../core/dr-types/src/lib.rs#L303), [`platform/dr-plat/src/display.rs:1`](../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/storage.rs:1`](../platform/dr-plat/src/storage.rs#L1), [`platform/dr-plat/src/storage.rs:216`](../platform/dr-plat/src/storage.rs#L216), [`platform/dr-plat/src/storage.rs:287`](../platform/dr-plat/src/storage.rs#L287), [`platform/dr-plat/src/storage.rs:344`](../platform/dr-plat/src/storage.rs#L344), [`platform/dr-plat/src/volumes.rs:1`](../platform/dr-plat/src/volumes.rs#L1), [`platform/dr-plat/src/volumes.rs:62`](../platform/dr-plat/src/volumes.rs#L62) | | NFR-PORT-2 | [`core/dr-gpu/src/lib.rs:1`](../core/dr-gpu/src/lib.rs#L1) | diff --git a/ui/dr-ui/src/collections_ui.rs b/ui/dr-ui/src/collections_ui.rs index e9e0ea5..a2c3eb2 100644 --- a/ui/dr-ui/src/collections_ui.rs +++ b/ui/dr-ui/src/collections_ui.rs @@ -43,6 +43,7 @@ use dr_types::{CollectionId, ImageId}; use rusqlite::OptionalExtension as _; use slint::{ComponentHandle, Model as _}; +use crate::library; use crate::{AppWindow, CollectionRow}; /// The selection as it stood before a press, for [`cancel_press`]. @@ -678,6 +679,12 @@ pub fn refresh_tree(window: &AppWindow, ctl: &Rc, catalog *ctl.row_smart.borrow_mut() = smart; *ctl.row_has_children.borrow_mut() = has_kids; window.set_collection_rows(slint::ModelRc::new(slint::VecModel::from(out))); + + // The rows are what `sync_reorderable` reads, so it has to be told they + // changed: a collection that gains a child, or one that is deleted out from + // under the scope, changes whether the grid can be reordered without the + // scope itself moving. + sync_reorderable(window); } /// TRACES: FR-NC-6a | FR-NC-6c @@ -935,6 +942,29 @@ pub fn sync_selection(window: &AppWindow, ctl: &Rc, ids: window.set_library_selected_count(selection.len() as i32); } +/// TRACES: FR-CAT-7 +/// Whether what the grid is showing has an order the user can change. +/// +/// A single manual collection: not the whole library, not a saved filter whose +/// membership is a rule, and not a set — a set draws its descendants' images +/// too, and two children's `position` columns are unrelated integers that would +/// interleave arbitrarily. +/// +/// Read off the tree rows the sidebar already draws rather than asked of the +/// catalog. `smart` and `has_children` are the only two facts it needs and both +/// are in the model already, so this cannot disagree with what the user is +/// looking at, and a scope change costs no extra query. +fn sync_reorderable(window: &AppWindow) { + let id = window.get_collection_selected(); + let rows = window.get_collection_rows(); + let manual = id > 0 + && (0..rows.row_count()) + .filter_map(|i| rows.row_data(i)) + .find(|r| r.id == id) + .is_some_and(|r| !r.smart && !r.has_children); + window.set_library_reorderable(manual); +} + /// Refresh the per-cell "in this many collections" badges. /// /// One query for the whole window rather than one per cell: 120 cells is 120 @@ -1574,6 +1604,93 @@ pub fn wire( }); } + // TRACES: FR-CAT-7 + // Drag a photograph, or a whole selection of them, to a new place in the + // collection being shown. + // + // `collection_members.position` and `Sort::CollectionPosition` have been in + // the catalog since collections were, and until now nothing above it ever + // wrote or read them — the grid ordered by capture time whatever it was + // scoped to. `library::grid_order_for` reads them; this writes them. + // + // The membership is rewritten whole rather than patched. `set_order` sets + // the positions it is given and leaves the rest, so a partial write would + // interleave the moved run with rows whose positions nobody touched — and + // it is read unfiltered for the same reason: the user reorders what they + // can see, and what the filter is hiding keeps its place relative to it. + { + let weak = window.as_weak(); + let ctl = ctl.clone(); + let catalog = catalog.clone(); + let visible = visible_ids.clone(); + let reload = on_scope_changed.clone(); + window.on_library_reorder_to(move |row, after| { + let Some(w) = weak.upgrade() else { return }; + // Both guards belong here rather than only in `library.slint`: the + // scope can change between the drag starting and the drop landing. + if !w.get_library_reorderable() { + return; + } + let Some(scope) = *ctl.scope.borrow() else { + return; + }; + + let moving = ctl.selected(); + if moving.is_empty() { + return; + } + + let ids = visible(); + let Some(&target) = usize::try_from(row).ok().and_then(|r| ids.get(r)) else { + return; + }; + + // Dropped on one of its own. There is no gap between a run and + // itself to land in, and rewriting the whole membership to say so + // would be a revision bump for no change. + if moving.contains(&target) { + return; + } + + let borrow = catalog.borrow(); + let Some(cat) = borrow.as_ref() else { return }; + + let current = match library::read_member_order(cat, scope) { + Ok(current) => current, + Err(e) => { + w.set_collection_error(format!("reading the collection's order: {e}").into()); + return; + } + }; + let wanted = library::reordered(¤t, &moving, target, after); + + match coll::set_order(cat.connection(), scope, &wanted) { + Ok(()) => { + w.set_collection_error(slint::SharedString::new()); + w.set_library_status( + format!( + "{} photograph{} moved", + moving.len(), + if moving.len() == 1 { "" } else { "s" } + ) + .into(), + ); + drop(borrow); + + // The selection survives. It is what was just moved, and + // dropping it would make a second nudge — which is how a + // drag-to-reorder is usually corrected — start over. + reload(); + sync_selection(&w, &ctl, &visible()); + } + Err(e) => { + drop(borrow); + w.set_collection_error(format!("reordering: {e}").into()); + } + } + }); + } + // TRACES: FR-CAT-5 | FR-UI-4 // Everything the grid is showing. // @@ -2231,6 +2348,7 @@ pub fn wire( }; w.set_collection_selected(id); w.set_collection_scope_label(label.into()); + sync_reorderable(&w); reload(); }); } diff --git a/ui/dr-ui/src/library.rs b/ui/dr-ui/src/library.rs index 8bc230c..25e4473 100644 --- a/ui/dr-ui/src/library.rs +++ b/ui/dr-ui/src/library.rs @@ -3794,9 +3794,10 @@ pub fn read_cells( /// look broken. The id list comes from /// [`dr_catalog::collections::descendants`], which is depth-guarded. /// -/// Ordering matches the unscoped grid (capture time, then name) rather than -/// manual position: position is only meaningful inside one collection and this -/// query also serves sets, where two children's positions are unrelated. +/// Ordering comes from [`grid_order_for`]: manual position for a single manual +/// collection, capture time for a set — because position is only meaningful +/// inside one collection, and this query also serves sets, where two children's +/// positions are unrelated integers. pub fn read_cells_scoped( catalog: &Catalog, scope: Option, @@ -3814,20 +3815,24 @@ pub fn read_cells_scoped( .collect::>() .join(","); let rated = filter.sql(); + let (order, order_params) = grid_order_for(catalog, Some(scope)); let sql = format!( "SELECT {CELL_COLUMNS} FROM images i WHERE {VISIBLE}{rated} AND i.id IN (SELECT image_id FROM collection_members WHERE collection_id IN ({placeholders})) - {GRID_ORDER} + {order} LIMIT ? OFFSET ?" ); + // Bound in the order the `?`s appear: the scope's ids in the WHERE, then + // whatever the ORDER BY needs, then the window. let mut params: Vec = ids .iter() .map(|c| rusqlite::types::Value::Integer(c.0 as i64)) .collect(); + params.extend(order_params); params.push(rusqlite::types::Value::Integer(limit as i64)); params.push(rusqlite::types::Value::Integer(offset as i64)); @@ -3952,13 +3957,18 @@ pub fn read_ids_span( Vec::new(), ) } else { - let (clause, params) = scope_clause(catalog, scope)?; + let (clause, mut params) = scope_clause(catalog, scope)?; let rated = filter.sql(); + // The same ordering the cells were drawn with, from the same place. + // A range is a pair of ordinals, and an ordinal read through a + // different ORDER BY names a different photograph. + let (order, order_params) = grid_order_for(catalog, scope); + params.extend(order_params); ( format!( "SELECT i.id FROM images i WHERE {VISIBLE}{rated}{clause} - {GRID_ORDER} + {order} LIMIT ? OFFSET ?" ), params, @@ -4105,6 +4115,146 @@ pub fn total_images_scoped( Ok(n as usize) } +/// TRACES: FR-CAT-7 +/// Every member of `scope`, in the order its positions put them. +/// +/// The *whole* membership, not the window and not the filtered view. A reorder +/// rewrites positions, and [`dr_catalog::collections::set_order`] only touches +/// the rows it is given — so writing back a filtered subset would leave the +/// images the filter is hiding at their old positions, interleaved with the new +/// ones arbitrarily. The user reorders what they can see; the rows they cannot +/// keep their place relative to it. +pub fn read_member_order( + catalog: &Catalog, + scope: dr_types::CollectionId, +) -> Result, dr_catalog::CatalogError> { + let mut stmt = catalog.connection().prepare( + "SELECT image_id FROM collection_members + WHERE collection_id = ?1 + ORDER BY position ASC, image_id ASC", + )?; + let ids = stmt + .query_map([scope.0 as i64], |r| { + Ok(dr_types::ImageId(r.get::<_, i64>(0)? as u64)) + })? + .collect::, _>>()?; + Ok(ids) +} + +/// TRACES: FR-CAT-7 +/// `current` with `moving` lifted out and set down beside `target`. +/// +/// `target` names a *photograph*, not an index, and that is the point: the grid +/// may be filtered, so the cell the user dropped on sits at one position in +/// what they can see and another in the membership being rewritten. An id +/// survives both. `after` puts the run on the far side of it, which is the only +/// way to name the last place in a collection — there is no cell beyond the +/// last one to drop in front of. +/// +/// The run keeps the order `current` has it in rather than the order the +/// selection was built in: the user is looking at the grid, and a selection +/// gathered by tapping the last frame first should not reverse itself on being +/// moved. +/// +/// A `target` that is itself being moved leaves the run at the end. There is no +/// gap between a run and itself to land in, so the caller refuses that drop +/// before it gets here; this is what the function does rather than panicking if +/// one ever arrives. +/// +/// Pure, so the awkward half of a drag can be tested without a window. +pub fn reordered( + current: &[dr_types::ImageId], + moving: &[dr_types::ImageId], + target: dr_types::ImageId, + after: bool, +) -> Vec { + let lifting: std::collections::BTreeSet<_> = moving.iter().copied().collect(); + let rest: Vec<_> = current + .iter() + .copied() + .filter(|id| !lifting.contains(id)) + .collect(); + let run: Vec<_> = current + .iter() + .copied() + .filter(|id| lifting.contains(id)) + .collect(); + + // Resolved against `rest`, not against `current`: the run has already been + // lifted, so an index into the original list would be off by however many + // of it sat ahead of the target. + let at = match rest.iter().position(|id| *id == target) { + Some(at) if after => at + 1, + Some(at) => at, + None => rest.len(), + }; + + let mut out = Vec::with_capacity(current.len()); + out.extend_from_slice(&rest[..at]); + out.extend(run); + out.extend_from_slice(&rest[at..]); + out +} + +/// TRACES: FR-CAT-7 +/// The ORDER BY the grid reads `scope` with, and the parameters it binds. +/// +/// Manual position where the grid is scoped to a single manual collection with +/// no children; [`GRID_ORDER`] — capture time, then filename — everywhere else. +/// +/// **Why the narrowing.** `position` is a column of `collection_members`, so it +/// only exists relative to one collection. A collection *set* shows its +/// descendants' images too, and two children's positions are unrelated integers +/// that would interleave arbitrarily; a smart collection has no member rows to +/// carry a position at all. Outside those cases there is no manual order to +/// read, and falling back is the only honest answer. +/// +/// **Why every reader must agree.** An ordinal only names a photograph relative +/// to an ordering. The window read and the span read are two halves of one +/// grid: a shift-click resolved through a different ORDER BY than the cells +/// were drawn with selects a different run than the one on screen, and the user +/// finds out when the export runs. That is the same invariant +/// [`read_ids_span`] already states about `GRID_ORDER`, widened to cover the +/// case where the ordering depends on the scope. +/// +/// A correlated subquery rather than a join, so the FROM and WHERE the two +/// readers already share are untouched: position is looked up per row through +/// `collection_members`' primary key, which is `(collection_id, image_id)`. +fn grid_order_for( + catalog: &Catalog, + scope: Option, +) -> (String, Vec) { + let Some(id) = scope else { + return (GRID_ORDER.to_string(), Vec::new()); + }; + + // A set orders by capture time. `descendants` includes the collection + // itself, so one entry means it has no children. + let alone = dr_catalog::collections::descendants(catalog.connection(), id) + .map(|d| d.len() == 1) + .unwrap_or(false); + let manual = matches!( + dr_catalog::collections::kind(catalog.connection(), id), + Ok(Some(dr_catalog::collections::CollectionKind::Manual)) + ); + if !alone || !manual { + return (GRID_ORDER.to_string(), Vec::new()); + } + + // `i.id` breaks the tie. Positions are dense after a `set_order`, but a + // collection that has never been reordered by hand has whatever + // `add_images` assigned, and two rows can share a position if a merge from + // another device brought one in — an ordering that is not total is an + // ordering the window read and the span read can disagree about. + ( + "ORDER BY (SELECT cm.position FROM collection_members cm + WHERE cm.collection_id = ? AND cm.image_id = i.id) ASC, + i.id ASC" + .to_string(), + vec![rusqlite::types::Value::Integer(id.0 as i64)], + ) +} + /// The SQL restricting a query to `scope` and its descendants, with the bound /// parameters to go with it. /// @@ -5333,6 +5483,180 @@ mod tests { assert_eq!(read_trashed_cells(&catalog, 0, 50).unwrap().len(), 3); } + // --- manual order within a collection (FR-CAT-7) ------------------------ + + fn ids(n: &[u64]) -> Vec { + n.iter().copied().map(dr_types::ImageId).collect() + } + + #[test] + fn a_run_moved_forward_lands_before_the_photograph_it_was_dropped_on() { + let current = ids(&[1, 2, 3, 4, 5]); + assert_eq!( + reordered(¤t, &ids(&[4]), dr_types::ImageId(2), false), + ids(&[1, 4, 2, 3, 5]) + ); + } + + #[test] + fn a_run_moved_backward_lands_before_it_too() { + // The direction of travel must not change what "before this one" means, + // or the same drop would land in two different places depending on + // where the photograph came from. + let current = ids(&[1, 2, 3, 4, 5]); + assert_eq!( + reordered(¤t, &ids(&[2]), dr_types::ImageId(5), false), + ids(&[1, 3, 4, 2, 5]) + ); + } + + #[test] + fn the_trailing_half_of_the_last_cell_is_how_the_end_is_reached() { + // There is no cell beyond the last one to drop in front of, so without + // `after` the final position is unreachable — which is exactly the + // place a "put this at the end" drag is aiming for. + let current = ids(&[1, 2, 3]); + assert_eq!( + reordered(¤t, &ids(&[1]), dr_types::ImageId(3), true), + ids(&[2, 3, 1]) + ); + } + + #[test] + fn a_moved_run_keeps_the_order_the_grid_shows_it_in() { + // Not the order the selection was built in. A user who tapped the last + // frame first has said nothing about how the run should be arranged — + // only about where it should go. + let current = ids(&[1, 2, 3, 4, 5]); + assert_eq!( + reordered(¤t, &ids(&[5, 1]), dr_types::ImageId(3), false), + ids(&[2, 1, 5, 3, 4]) + ); + } + + #[test] + fn a_run_dropped_on_one_of_its_own_members_stays_together() { + // The caller refuses this drop, so it is only reachable if that guard + // is ever lost. It must not lose photographs when it is. + let current = ids(&[1, 2, 3, 4]); + let moved = reordered(¤t, &ids(&[2, 3]), dr_types::ImageId(3), false); + assert_eq!(moved.len(), current.len(), "nothing was dropped"); + let mut sorted = moved.clone(); + sorted.sort(); + assert_eq!(sorted, ids(&[1, 2, 3, 4]), "and nothing was invented"); + } + + #[test] + fn a_reorder_never_loses_or_duplicates_a_member() { + // The property that matters most: this writes the whole membership + // back, so a run that dropped one image would delete it from the + // collection. + let current = ids(&[1, 2, 3, 4, 5, 6]); + for target in [1u64, 2, 3, 4, 5, 6] { + for after in [false, true] { + let moved = reordered(¤t, &ids(&[2, 5]), dr_types::ImageId(target), after); + let mut sorted = moved.clone(); + sorted.sort(); + assert_eq!( + sorted, + ids(&[1, 2, 3, 4, 5, 6]), + "target {target}, after {after}" + ); + } + } + } + + /// The scoped grid and the range a shift-click resolves are two halves of + /// one ordering. This is the assertion that keeps them one: an ordinal read + /// through a different ORDER BY names a different photograph, and the user + /// finds out when the export runs. + #[test] + fn a_manual_collection_is_read_and_spanned_in_the_order_it_was_given() { + let catalog = with_images(5); + let all = image_ids(&catalog); + let id = dr_catalog::collections::create( + catalog.connection(), + "Trip", + None, + dr_catalog::collections::CollectionKind::Manual, + ) + .unwrap(); + dr_catalog::collections::add_images(catalog.connection(), id, &all).unwrap(); + + // Reversed, so position and capture time disagree about everything. + let wanted: Vec<_> = all.iter().rev().copied().collect(); + dr_catalog::collections::set_order(catalog.connection(), id, &wanted).unwrap(); + + let cells = read_cells_scoped(&catalog, Some(id), &RatingFilter::default(), 0, 50).unwrap(); + let drawn: Vec<_> = cells + .iter() + .map(|c| dr_types::ImageId(c.image_id as u64)) + .collect(); + assert_eq!(drawn, wanted, "the grid draws the order that was written"); + + let spanned = + read_ids_span(&catalog, Some(id), &RatingFilter::default(), false, 0, 4).unwrap(); + assert_eq!(spanned, wanted, "and a range resolves through the same one"); + + assert_eq!( + read_member_order(&catalog, id).unwrap(), + wanted, + "and so does the membership a reorder rewrites" + ); + } + + #[test] + fn a_collection_with_children_falls_back_to_capture_time() { + // A set draws its descendants' images too, and two children's positions + // are unrelated integers. Ordering by them interleaves the two + // arbitrarily, which is worse than an order that at least means + // something. + let catalog = with_images(4); + let all = image_ids(&catalog); + let parent = dr_catalog::collections::create( + catalog.connection(), + "Iceland", + None, + dr_catalog::collections::CollectionKind::Manual, + ) + .unwrap(); + dr_catalog::collections::create( + catalog.connection(), + "Day one", + Some(parent), + dr_catalog::collections::CollectionKind::Manual, + ) + .unwrap(); + dr_catalog::collections::add_images(catalog.connection(), parent, &all).unwrap(); + let reversed: Vec<_> = all.iter().rev().copied().collect(); + dr_catalog::collections::set_order(catalog.connection(), parent, &reversed).unwrap(); + + let cells = + read_cells_scoped(&catalog, Some(parent), &RatingFilter::default(), 0, 50).unwrap(); + let drawn: Vec<_> = cells + .iter() + .map(|c| dr_types::ImageId(c.image_id as u64)) + .collect(); + assert_eq!(drawn, all, "capture time, not the positions that were set"); + } + + #[test] + fn a_smart_collection_has_no_manual_order_to_read() { + // No member rows at all, so `position` is not a column any of its + // images have. Falling back is the only thing there is to do. + let catalog = with_images(3); + let id = dr_catalog::collections::create( + catalog.connection(), + "Picks", + None, + dr_catalog::collections::CollectionKind::Smart, + ) + .unwrap(); + let (order, params) = grid_order_for(&catalog, Some(id)); + assert_eq!(order, GRID_ORDER); + assert!(params.is_empty()); + } + #[test] fn the_most_recently_trashed_image_is_listed_first() { // A mistaken delete is corrected within seconds, so the row the user diff --git a/ui/dr-ui/ui/app.slint b/ui/dr-ui/ui/app.slint index 80a8bc1..b5e9ec3 100644 --- a/ui/dr-ui/ui/app.slint +++ b/ui/dr-ui/ui/app.slint @@ -310,6 +310,14 @@ export component AppWindow inherits Window { /// TRACES: FR-CAT-5 callback library-clear-selection(); callback library-select-all(); + /// TRACES: FR-CAT-7 + /// Whether the grid is showing something with a manual order to change — + /// a single manual collection, not a set and not a saved filter. + in property library-reorderable: false; + /// Move the selection beside the photograph at this row of the loaded + /// window: after it where the drop landed on the cell's trailing half, + /// before it otherwise. + callback library-reorder-to(int, bool); callback library-collection-from-selection(string); /// TRACES: FR-CAT-6 in property library-range-from; @@ -1442,6 +1450,8 @@ in property panel-visible: true; toggle-date-range() => { root.library-toggle-date-range(); } clear-selection() => { root.library-clear-selection(); } select-all() => { root.library-select-all(); } + reorderable: root.library-reorderable; + reorder-to(row, after) => { root.library-reorder-to(row, after); } collection-from-selection(name) => { root.library-collection-from-selection(name); } diff --git a/ui/dr-ui/ui/library.slint b/ui/dr-ui/ui/library.slint index 76a60fa..a058918 100644 --- a/ui/dr-ui/ui/library.slint +++ b/ui/dr-ui/ui/library.slint @@ -1240,6 +1240,27 @@ export component LibraryGrid inherits Rectangle { in property select-mode: false; callback toggle-select-mode(); /// TRACES: FR-CAT-5 + // --- reordering a manual collection (FR-CAT-7) -------------------------- + // + // `collection_members.position` and `Sort::CollectionPosition` have existed + // in the catalog since collections did, and nothing above it ever wrote or + // read them: the grid ordered everything by capture time, always. This is + // the gesture that makes the column mean something. + // + // Only where there is a manual order to change — a single manual collection + // with no children. A set interleaves two children's unrelated positions + // and a smart collection has no member rows at all, so both fall back to + // capture time and refuse the drop rather than pretending. + /// Whether a drop on a cell should move photographs within the collection + /// being shown. Set by Rust from the scope, because what a scope *is* is a + /// catalog question. + in property reorderable: false; + /// Move the selection so it sits beside the photograph at this row of the + /// loaded window — before it, or after it where the drop landed on the + /// cell's trailing half. The trailing half is what makes the last position + /// reachable at all; without it there is no cell to drop "before". + callback reorder-to(int, bool); + /// Drop the selection without leaving select mode. callback clear-selection(); /// TRACES: FR-CAT-5 | FR-UI-4 @@ -2777,6 +2798,41 @@ export component LibraryGrid inherits Rectangle { } drag-finished(action) => { root.drag-finished(); } + // Where a reorder lands. Behind the cell's content and + // before it in the file, for the reason `TreeRow`'s drop + // area gives: a `DropArea` only takes part in a drag, so it + // does not block the presses the cell's own TouchArea + // needs — but drawn first it cannot paint over the + // thumbnail either. + // + // Present on every cell rather than wrapped in an `if`, so + // the marker below can name it. `can-drop` is where the + // refusal lives, which also means the cursor says no while + // the user can still aim somewhere else. + reorder-drop := DropArea { + width: 100%; + height: 100%; + + /// Whether the run would land after this photograph + /// rather than before it. Tracked during the hover so + /// the marker can move to the edge the drop will + /// actually use. + property after: false; + + can-drop(ev) => { + if (!root.reorderable) { + return DragAction.none; + } + self.after = ev.position.x > self.width / 2; + return DragAction.copy; + } + + dropped(ev) => { + root.reorder-to(i, ev.position.x > self.width / 2); + return DragAction.copy; + } + } + Rectangle { // Lifted cells shrink toward their own centre, as though pulled // off the page. Inset rather than scaled: Slint has no transform @@ -3051,6 +3107,28 @@ export component LibraryGrid inherits Rectangle { } } } + // Where the run would land. A bar in the gutter beside the + // cell it would sit next to, on whichever side the drop + // will actually use — the trailing edge is what makes the + // last place in a collection reachable, and a marker that + // did not move with it would be pointing at the wrong gap + // half the time. + // + // Last child of the `DragArea`, so it draws over the + // thumbnail rather than under it. In the gutter rather than + // on the cell, because a bar drawn *on* the first cell of a + // row reads as belonging to that cell instead of to the + // space before it. + if reorder-drop.has-drag: Rectangle { + x: reorder-drop.after + ? parent.width + Theme.gap / 2 - 1.5px + : -Theme.gap / 2 - 1.5px; + y: 0; + width: 3px; + height: parent.height; + background: Theme.active; + border-radius: 1.5px; + } } }