From 83f4253b6a8ef690c7a46e62e5be6688f43155c0 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sat, 19 Sep 2026 13:52:52 +0200 Subject: [PATCH] Filter the grid to a person with their eyes open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An "Eyes open" chip beside the people chips, offered only while someone is chosen and dropped when the last person goes, so no term narrows the grid with nothing on the bar to say so. It compiles the rule in dr_face::eyes into the person's face subquery — Anna, eyes open, whoever else is blinking beside her — and drops a frame only on a closed eye that could be read: sunglasses, eyes too small or soft to read, and faces never read all pass, so an old library shows everything under the chip until the measuring pass has run. A test drives the same readings through the SQL and through the rule and requires them to agree. The People screen badges a face "Eyes closed", "Sunglasses" or "Eyes unclear" so the reason a frame is or is not in the grid can be read off the face; the sweep loads the three models when they are beside the pair and reads eyes on the indexing and measuring passes from the native render; the coverage line counts unread faces as work to measure so an already-indexed library keeps its Index button. The term travels with the place. --- core/dr-types/src/place.rs | 5 + docs/gestures.md | 59 ++-- docs/traceability.md | 144 +++++----- ui/dr-ui/examples/face_index.rs | 13 +- ui/dr-ui/examples/face_native.rs | 47 +++- ui/dr-ui/src/faces.rs | 159 ++++++++++- ui/dr-ui/src/gesture_book.rs | 7 + ui/dr-ui/src/identity.rs | 75 ++++++ ui/dr-ui/src/identity_ui.rs | 98 +++++-- ui/dr-ui/src/lib.rs | 12 +- ui/dr-ui/src/library.rs | 446 ++++++++++++++++++++++++++++--- ui/dr-ui/src/library_ui.rs | 31 +++ ui/dr-ui/src/place.rs | 4 + ui/dr-ui/ui/app.slint | 6 + ui/dr-ui/ui/identity.slint | 27 ++ ui/dr-ui/ui/library.slint | 34 ++- 16 files changed, 984 insertions(+), 183 deletions(-) diff --git a/core/dr-types/src/place.rs b/core/dr-types/src/place.rs index 390cd0a..b7be304 100644 --- a/core/dr-types/src/place.rs +++ b/core/dr-types/src/place.rs @@ -126,6 +126,11 @@ pub struct StoredFilter { /// does not derive serde — and "all of them" is the only thing the second /// variant means. pub people_all: bool, + /// TRACES: FR-CULL-13 + /// Whether the grid was narrowed to photographs with nobody blinking. + /// Travels: it is a narrowing like `local_only`, and a record without it + /// — from a build before it existed — reads as off. + pub eyes_open: bool, } /// Where the photographer was, at the moment they were there. diff --git a/docs/gestures.md b/docs/gestures.md index 9f043b3..fe90f1e 100644 --- a/docs/gestures.md +++ b/docs/gestures.md @@ -5,7 +5,7 @@ Every entry here is extracted from the comment beside the code that implements it, so this file cannot describe a gesture the application does not have. Add one by writing a `GESTURE:` block next to the implementation; there is nowhere else to write it. -40 gestures, in 4 places. +41 gestures, in 4 places. ## Develop @@ -25,7 +25,7 @@ Sampling a neutral is the first move of the tonal pass — every colour judgemen Anchored on the fingers' midpoint, and on the pointer, so the gesture reads as magnifying the picture rather than sliding it about. Double-tap is the way to an exact 1:1; this is the way to everything in between. -`ui/dr-ui/ui/app.slint:1980` +`ui/dr-ui/ui/app.slint:1986` ### Move a magnified photograph about @@ -34,7 +34,7 @@ Anchored on the fingers' midpoint, and on the pointer, so the gesture reads as m Only once there is something outside the viewport to reach, which is why the cursor becomes a hand exactly then. The view is clamped to the frame: panning past the edge would show undefined area beside the photograph, and that reads as a rendering fault rather than as the end of the picture. -`ui/dr-ui/ui/app.slint:2071` +`ui/dr-ui/ui/app.slint:2077` ### Paint a mask by hand @@ -43,7 +43,7 @@ Only once there is something outside the viewport to reach, which is why the cur A model's mask stops inside a shoulder and leaks into the hair, and no single edge control fixes two errors that go opposite ways. The whole stroke is one step in the history, so taking a mark back costs one press however long it took to make. -`ui/dr-ui/ui/app.slint:2158` +`ui/dr-ui/ui/app.slint:2164` ### Take back the last change @@ -53,7 +53,7 @@ A model's mask stops inside a shoulder and leaks into the hair, and no single ed A whole drag is one step, so undo takes back a decision rather than a frame of a gesture. The list is there because arriving six steps back costs what arriving from one does. -`ui/dr-ui/ui/app.slint:2379` +`ui/dr-ui/ui/app.slint:2385` ### Do it again after taking it back @@ -61,7 +61,7 @@ A whole drag is one step, so undo takes back a decision rather than a frame of a - **Pointer** — Click it, or press Redo in the History header - **Keyboard** — Ctrl+Shift+Z -`ui/dr-ui/ui/app.slint:2392` +`ui/dr-ui/ui/app.slint:2398` ### Copy the settings from this photograph @@ -71,7 +71,7 @@ A whole drag is one step, so undo takes back a decision rather than a frame of a The panel is the copy that has to work: a tablet has no modifier key to hold and no menu bar to hang the action from. The shortcut is an accelerator for a control that is on screen either way. -`ui/dr-ui/ui/app.slint:2425` +`ui/dr-ui/ui/app.slint:2431` ### Paste the settings onto this photograph @@ -81,7 +81,7 @@ The panel is the copy that has to work: a tablet has no modifier key to hold and The button names what would be pasted — "3 adjustments", and whether the crop is coming with it — which the shortcut cannot say. Both paste the same scope. -`ui/dr-ui/ui/app.slint:2437` +`ui/dr-ui/ui/app.slint:2443` ### Change which group of adjustments is on screen @@ -91,7 +91,7 @@ The button names what would be pasted — "3 adjustments", and whether the crop The groups are whatever the operation set declares itself to be about, so there are as many as the pipeline has and no key can be assigned to one of them by name. Stepping is the binding that survives a node being added. -`ui/dr-ui/ui/app.slint:2465` +`ui/dr-ui/ui/app.slint:2471` ### Look at the photograph at 1:1 @@ -101,7 +101,7 @@ The groups are whatever the operation set declares itself to be about, so there Noise reduction and capture sharpening are judgements about single pixels, and a fitted view averages several of the file's into each one on screen — so the frame looks softer than it is and the correction goes too far. The point and the magnification survive opening the next photograph, which is what makes checking the same eye across forty portraits forty keystrokes rather than forty pans. -`ui/dr-ui/ui/app.slint:2500` +`ui/dr-ui/ui/app.slint:2506` ### Move to the next or previous photograph @@ -111,7 +111,7 @@ Noise reduction and capture sharpening are judgements about single pixels, and a The edit on screen is saved on the way out, so stepping through a folder is as much a departure as going back to the grid and loses nothing. -`ui/dr-ui/ui/app.slint:2552` +`ui/dr-ui/ui/app.slint:2558` ### See the photograph before you edited it @@ -121,7 +121,7 @@ The edit on screen is saved on the way out, so stepping through a folder is as m Held rather than toggled, and no split screen: a split halves the working image on the tablet the column was sized for, and the comparison photographers describe making is a flick back and forth. It takes no history step, so checking whether a frame is overcooked costs nothing to undo afterwards. -`ui/dr-ui/ui/app.slint:2676` +`ui/dr-ui/ui/app.slint:2682` ### Put one control back to its default @@ -226,7 +226,7 @@ Double-click is what a file manager and a Lightroom panel use for the same thing Grouping over-merges on siblings, on parents and children, and on the same person a decade apart, so splitting is as prominent as merging. A tool that can only merge makes its own errors permanent. -`ui/dr-ui/ui/identity.slint:161` +`ui/dr-ui/ui/identity.slint:188` ### Rule on a suggested face @@ -235,7 +235,7 @@ Grouping over-merges on siblings, on parents and children, and on the same perso A face is either the system's guess or the user's judgement, and the two are never conflated. A rejection is remembered, so the face is not suggested for that person again. The gesture note above is the whole label: a tick and a cross are only "confirm" and "reject" to someone who can see the suggestion they sit beside, and `IconButton`'s fallback would announce them as "check" and "cross" — two icon names that say nothing about which person is being ruled on. -`ui/dr-ui/ui/identity.slint:181` +`ui/dr-ui/ui/identity.slint:208` ### See a person's photographs @@ -244,7 +244,7 @@ A face is either the system's guess or the user's judgement, and the two are nev This is the point of having identified anybody. Without it the screen is a filing cabinet with no drawer handles. -`ui/dr-ui/ui/identity.slint:602` +`ui/dr-ui/ui/identity.slint:629` ### Change how faces are grouped @@ -253,7 +253,7 @@ This is the point of having identified anybody. Without it the screen is a filin The right match confidence is a property of your library, not of the model. "What would this do?" answers for this library without writing anything; names, confirmations and the groups you have set aside are kept whatever the dials say. -`ui/dr-ui/ui/identity.slint:639` +`ui/dr-ui/ui/identity.slint:666` ## Library grid @@ -301,6 +301,15 @@ This replaced a double tap, which had no visible state and could take forty phot `ui/dr-ui/ui/library.slint:1414` +### Take the blinks out of a burst + +- **Touch** — Narrow to a person, then tap "Eyes open" beside their name on the filter bar +- **Pointer** — Narrow to a person, then click "Eyes open" beside their name on the filter bar + +Face indexing reads each face's eyes. The chip drops frames where the chosen people are caught blinking, and leaves sunglasses and eyes it could not read alone. + +`ui/dr-ui/ui/library.slint:2102` + ### Find photographs with two people in them - **Touch** — Open the People chip on the filter bar, tap each name, then switch the chip beside them to "all of them" @@ -308,7 +317,7 @@ This replaced a double tap, which had no visible state and could take forty phot "Any of them" is a union and "all of them" is an intersection. The tray is where both terms and the choice between them live, because a filter belongs on the filter bar. -`ui/dr-ui/ui/library.slint:2102` +`ui/dr-ui/ui/library.slint:2131` ### Resize the thumbnails @@ -317,7 +326,7 @@ This replaced a double tap, which had no visible state and could take forty phot There is no wheel on a tablet, so without the pinch the cell size could only be changed by a control a finger cannot reach. -`ui/dr-ui/ui/library.slint:2755` +`ui/dr-ui/ui/library.slint:2785` ### File photographs in a collection @@ -326,7 +335,7 @@ There is no wheel on a tablet, so without the pinch the cell size could only be The selection is what the drag carries, which is why selecting several is worth the mode: forty photographs file in one gesture. -`ui/dr-ui/ui/library.slint:2952` +`ui/dr-ui/ui/library.slint:2982` ### Open a photograph @@ -335,7 +344,7 @@ The selection is what the drag carries, which is why selecting several is worth A tap opens; a tap that *moved* does not. Travel is what separates a deliberate tap from a hand brushing past, and it is the only thing that does: the two are the same length. An earlier version required the finger to dwell 120 ms instead, and that rejected ordinary taps — a real tap is often quicker than a brush. -`ui/dr-ui/ui/library.slint:3220` +`ui/dr-ui/ui/library.slint:3250` ### Rate a photograph without opening it @@ -345,7 +354,7 @@ A tap opens; a tap that *moved* does not. Travel is what separates a deliberate A star has to take the press without it also reaching the cell, or every rating throws the user into develop. -`ui/dr-ui/ui/library.slint:3340` +`ui/dr-ui/ui/library.slint:3370` ### Choose the frame a folded burst shows @@ -354,7 +363,7 @@ A star has to take the press without it also reaching the cell, or every rating A folded burst draws its earliest frame, which is a fact about the clock and not a judgement about the photograph — nothing in this application ranks a frame (FR-CULL-5). But the point of a burst is that one of the twelve is better than the other eleven, and the photographer is the only one who knows which. So the choice is offered on the frames themselves, while they are open and side by side, which is the one moment the alternatives are on screen to be compared. -`ui/dr-ui/ui/library.slint:3471` +`ui/dr-ui/ui/library.slint:3501` ### Drop the selection but keep selecting @@ -363,7 +372,7 @@ A folded burst draws its earliest frame, which is a fact about the clock and not Distinct from Done, which leaves the mode entirely. Clearing keeps it, so the next selection can start straight away. -`ui/dr-ui/ui/library.slint:4132` +`ui/dr-ui/ui/library.slint:4162` ### Select everything the grid is showing @@ -372,7 +381,7 @@ Distinct from Done, which leaves the mode entirely. Clearing keeps it, so the ne A scoped grid of two hundred frames is two hundred taps otherwise, and "all of them, except those three" is a far more common shape than the taps it took to say it. -`ui/dr-ui/ui/library.slint:4149` +`ui/dr-ui/ui/library.slint:4179` ### Take photographs out of a collection @@ -381,4 +390,4 @@ A scoped grid of two hundred frames is two hundred taps otherwise, and "all of t The badge on a cell says a photograph is filed in three collections and never which. This is the sheet that names them, and the only way out of one the grid is not currently scoped to. -`ui/dr-ui/ui/library.slint:4264` +`ui/dr-ui/ui/library.slint:4294` diff --git a/docs/traceability.md b/docs/traceability.md index 608b340..5c4c7aa 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 | 358 | -| TRACES tags found | 1506 | +| TRACES tags found | 1518 | | Requirements defined | 171 | | Requirements deferred (post-v1) | 24 | | Requirements covered | 143 | @@ -35,144 +35,144 @@ _None._ | ID | Tagged in | |---|---| | FR-CAT-1 | [`core/dr-catalog/src/scan.rs:1`](../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/walk.rs:109`](../core/dr-catalog/src/walk.rs#L109), [`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-sync/src/scan.rs:129`](../core/dr-sync/src/scan.rs#L129), [`core/dr-types/src/lib.rs:203`](../core/dr-types/src/lib.rs#L203), [`core/dr-types/src/lib.rs:272`](../core/dr-types/src/lib.rs#L272), [`core/dr-types/src/lib.rs:305`](../core/dr-types/src/lib.rs#L305), [`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), [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1) | -| FR-CAT-10 | [`core/dr-ingest/src/layout.rs:1`](../core/dr-ingest/src/layout.rs#L1), [`core/dr-ingest/src/lib.rs:1`](../core/dr-ingest/src/lib.rs#L1), [`core/dr-ingest/src/lib.rs:733`](../core/dr-ingest/src/lib.rs#L733), [`core/dr-types/src/settings.rs:353`](../core/dr-types/src/settings.rs#L353), [`platform/dr-plat/src/storage.rs:287`](../platform/dr-plat/src/storage.rs#L287), [`platform/dr-plat/src/storage.rs:586`](../platform/dr-plat/src/storage.rs#L586), [`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), [`ui/dr-ui/src/import.rs:1`](../ui/dr-ui/src/import.rs#L1), [`ui/dr-ui/src/import.rs:336`](../ui/dr-ui/src/import.rs#L336), [`ui/dr-ui/src/import_ui.rs:1`](../ui/dr-ui/src/import_ui.rs#L1), [`ui/dr-ui/src/lib.rs:1527`](../ui/dr-ui/src/lib.rs#L1527), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5), [`ui/dr-ui/ui/library.slint:1033`](../ui/dr-ui/ui/library.slint#L1033), [`ui/dr-ui/ui/library.slint:1254`](../ui/dr-ui/ui/library.slint#L1254), [`ui/dr-ui/ui/library.slint:979`](../ui/dr-ui/ui/library.slint#L979) | -| 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:1527`](../ui/dr-ui/src/lib.rs#L1527), [`ui/dr-ui/src/library.rs:183`](../ui/dr-ui/src/library.rs#L183), [`ui/dr-ui/src/library.rs:3303`](../ui/dr-ui/src/library.rs#L3303), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | +| FR-CAT-10 | [`core/dr-ingest/src/layout.rs:1`](../core/dr-ingest/src/layout.rs#L1), [`core/dr-ingest/src/lib.rs:1`](../core/dr-ingest/src/lib.rs#L1), [`core/dr-ingest/src/lib.rs:733`](../core/dr-ingest/src/lib.rs#L733), [`core/dr-types/src/settings.rs:353`](../core/dr-types/src/settings.rs#L353), [`platform/dr-plat/src/storage.rs:287`](../platform/dr-plat/src/storage.rs#L287), [`platform/dr-plat/src/storage.rs:586`](../platform/dr-plat/src/storage.rs#L586), [`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), [`ui/dr-ui/src/import.rs:1`](../ui/dr-ui/src/import.rs#L1), [`ui/dr-ui/src/import.rs:336`](../ui/dr-ui/src/import.rs#L336), [`ui/dr-ui/src/import_ui.rs:1`](../ui/dr-ui/src/import_ui.rs#L1), [`ui/dr-ui/src/lib.rs:1528`](../ui/dr-ui/src/lib.rs#L1528), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5), [`ui/dr-ui/ui/library.slint:1033`](../ui/dr-ui/ui/library.slint#L1033), [`ui/dr-ui/ui/library.slint:1254`](../ui/dr-ui/ui/library.slint#L1254), [`ui/dr-ui/ui/library.slint:979`](../ui/dr-ui/ui/library.slint#L979) | +| 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:1528`](../ui/dr-ui/src/lib.rs#L1528), [`ui/dr-ui/src/library.rs:183`](../ui/dr-ui/src/library.rs#L183), [`ui/dr-ui/src/library.rs:3367`](../ui/dr-ui/src/library.rs#L3367), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | | FR-CAT-12 | [`core/dr-pipeline/src/sidecar.rs:122`](../core/dr-pipeline/src/sidecar.rs#L122) | -| FR-CAT-13 | [`core/dr-catalog/src/rating.rs:278`](../core/dr-catalog/src/rating.rs#L278), [`core/dr-catalog/src/schema.rs:706`](../core/dr-catalog/src/schema.rs#L706), [`core/dr-sync/src/scan.rs:40`](../core/dr-sync/src/scan.rs#L40), [`core/dr-sync/src/scan.rs:944`](../core/dr-sync/src/scan.rs#L944), [`core/dr-types/src/settings.rs:92`](../core/dr-types/src/settings.rs#L92), [`core/dr-xmp/src/lib.rs:1`](../core/dr-xmp/src/lib.rs#L1), [`core/dr-xmp/src/lib.rs:331`](../core/dr-xmp/src/lib.rs#L331), [`core/dr-xmp/src/lib.rs:442`](../core/dr-xmp/src/lib.rs#L442), [`core/dr-xmp/src/lib.rs:535`](../core/dr-xmp/src/lib.rs#L535), [`core/dr-xmp/src/lib.rs:733`](../core/dr-xmp/src/lib.rs#L733), [`core/dr-xmp/src/lib.rs:746`](../core/dr-xmp/src/lib.rs#L746), [`core/dr-xmp/src/read.rs:1`](../core/dr-xmp/src/read.rs#L1), [`core/dr-xmp/src/write.rs:1`](../core/dr-xmp/src/write.rs#L1), [`core/dr-xmp/tests/round_trip.rs:1`](../core/dr-xmp/tests/round_trip.rs#L1), [`ui/dr-ui/src/library.rs:1500`](../ui/dr-ui/src/library.rs#L1500), [`ui/dr-ui/src/library.rs:1563`](../ui/dr-ui/src/library.rs#L1563), [`ui/dr-ui/src/library.rs:1579`](../ui/dr-ui/src/library.rs#L1579), [`ui/dr-ui/src/library.rs:1686`](../ui/dr-ui/src/library.rs#L1686), [`ui/dr-ui/src/library_ui.rs:1327`](../ui/dr-ui/src/library_ui.rs#L1327), [`ui/dr-ui/src/library_ui.rs:301`](../ui/dr-ui/src/library_ui.rs#L301), [`ui/dr-ui/src/library_ui.rs:3453`](../ui/dr-ui/src/library_ui.rs#L3453), [`ui/dr-ui/src/library_ui.rs:3509`](../ui/dr-ui/src/library_ui.rs#L3509), [`ui/dr-ui/src/library_ui.rs:3607`](../ui/dr-ui/src/library_ui.rs#L3607), [`ui/dr-ui/src/library_ui.rs:392`](../ui/dr-ui/src/library_ui.rs#L392), [`ui/dr-ui/src/library_ui.rs:535`](../ui/dr-ui/src/library_ui.rs#L535), [`ui/dr-ui/src/library_ui.rs:5791`](../ui/dr-ui/src/library_ui.rs#L5791), [`ui/dr-ui/src/settings_ui.rs:540`](../ui/dr-ui/src/settings_ui.rs#L540), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/src/xmp_sync.rs:250`](../ui/dr-ui/src/xmp_sync.rs#L250), [`ui/dr-ui/src/xmp_sync.rs:287`](../ui/dr-ui/src/xmp_sync.rs#L287), [`ui/dr-ui/src/xmp_sync.rs:324`](../ui/dr-ui/src/xmp_sync.rs#L324), [`ui/dr-ui/ui/app.slint:852`](../ui/dr-ui/ui/app.slint#L852), [`ui/dr-ui/ui/settings.slint:1020`](../ui/dr-ui/ui/settings.slint#L1020), [`ui/dr-ui/ui/settings.slint:189`](../ui/dr-ui/ui/settings.slint#L189) | -| FR-CAT-15 | [`core/dr-catalog/src/schema.rs:1003`](../core/dr-catalog/src/schema.rs#L1003), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:507`](../core/dr-sync-nextcloud/src/lib.rs#L507), [`core/dr-sync/src/lib.rs:135`](../core/dr-sync/src/lib.rs#L135), [`core/dr-sync/src/scan.rs:618`](../core/dr-sync/src/scan.rs#L618), [`core/dr-sync/src/scan.rs:93`](../core/dr-sync/src/scan.rs#L93), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`core/dr-types/src/place.rs:91`](../core/dr-types/src/place.rs#L91), [`ui/dr-ui/src/collections_ui.rs:1435`](../ui/dr-ui/src/collections_ui.rs#L1435), [`ui/dr-ui/src/collections_ui.rs:2341`](../ui/dr-ui/src/collections_ui.rs#L2341), [`ui/dr-ui/src/library.rs:183`](../ui/dr-ui/src/library.rs#L183), [`ui/dr-ui/src/library.rs:200`](../ui/dr-ui/src/library.rs#L200), [`ui/dr-ui/src/library.rs:249`](../ui/dr-ui/src/library.rs#L249), [`ui/dr-ui/src/library.rs:5275`](../ui/dr-ui/src/library.rs#L5275), [`ui/dr-ui/src/library.rs:5309`](../ui/dr-ui/src/library.rs#L5309), [`ui/dr-ui/src/library_ui.rs:238`](../ui/dr-ui/src/library_ui.rs#L238), [`ui/dr-ui/src/library_ui.rs:912`](../ui/dr-ui/src/library_ui.rs#L912), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1), [`ui/dr-ui/ui/collections.slint:745`](../ui/dr-ui/ui/collections.slint#L745) | +| FR-CAT-13 | [`core/dr-catalog/src/rating.rs:278`](../core/dr-catalog/src/rating.rs#L278), [`core/dr-catalog/src/schema.rs:718`](../core/dr-catalog/src/schema.rs#L718), [`core/dr-sync/src/scan.rs:40`](../core/dr-sync/src/scan.rs#L40), [`core/dr-sync/src/scan.rs:944`](../core/dr-sync/src/scan.rs#L944), [`core/dr-types/src/settings.rs:92`](../core/dr-types/src/settings.rs#L92), [`core/dr-xmp/src/lib.rs:1`](../core/dr-xmp/src/lib.rs#L1), [`core/dr-xmp/src/lib.rs:331`](../core/dr-xmp/src/lib.rs#L331), [`core/dr-xmp/src/lib.rs:442`](../core/dr-xmp/src/lib.rs#L442), [`core/dr-xmp/src/lib.rs:535`](../core/dr-xmp/src/lib.rs#L535), [`core/dr-xmp/src/lib.rs:733`](../core/dr-xmp/src/lib.rs#L733), [`core/dr-xmp/src/lib.rs:746`](../core/dr-xmp/src/lib.rs#L746), [`core/dr-xmp/src/read.rs:1`](../core/dr-xmp/src/read.rs#L1), [`core/dr-xmp/src/write.rs:1`](../core/dr-xmp/src/write.rs#L1), [`core/dr-xmp/tests/round_trip.rs:1`](../core/dr-xmp/tests/round_trip.rs#L1), [`ui/dr-ui/src/library.rs:1564`](../ui/dr-ui/src/library.rs#L1564), [`ui/dr-ui/src/library.rs:1627`](../ui/dr-ui/src/library.rs#L1627), [`ui/dr-ui/src/library.rs:1643`](../ui/dr-ui/src/library.rs#L1643), [`ui/dr-ui/src/library.rs:1750`](../ui/dr-ui/src/library.rs#L1750), [`ui/dr-ui/src/library_ui.rs:1327`](../ui/dr-ui/src/library_ui.rs#L1327), [`ui/dr-ui/src/library_ui.rs:301`](../ui/dr-ui/src/library_ui.rs#L301), [`ui/dr-ui/src/library_ui.rs:3453`](../ui/dr-ui/src/library_ui.rs#L3453), [`ui/dr-ui/src/library_ui.rs:3509`](../ui/dr-ui/src/library_ui.rs#L3509), [`ui/dr-ui/src/library_ui.rs:3607`](../ui/dr-ui/src/library_ui.rs#L3607), [`ui/dr-ui/src/library_ui.rs:392`](../ui/dr-ui/src/library_ui.rs#L392), [`ui/dr-ui/src/library_ui.rs:535`](../ui/dr-ui/src/library_ui.rs#L535), [`ui/dr-ui/src/library_ui.rs:5792`](../ui/dr-ui/src/library_ui.rs#L5792), [`ui/dr-ui/src/settings_ui.rs:540`](../ui/dr-ui/src/settings_ui.rs#L540), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/src/xmp_sync.rs:250`](../ui/dr-ui/src/xmp_sync.rs#L250), [`ui/dr-ui/src/xmp_sync.rs:287`](../ui/dr-ui/src/xmp_sync.rs#L287), [`ui/dr-ui/src/xmp_sync.rs:324`](../ui/dr-ui/src/xmp_sync.rs#L324), [`ui/dr-ui/ui/app.slint:856`](../ui/dr-ui/ui/app.slint#L856), [`ui/dr-ui/ui/settings.slint:1020`](../ui/dr-ui/ui/settings.slint#L1020), [`ui/dr-ui/ui/settings.slint:189`](../ui/dr-ui/ui/settings.slint#L189) | +| FR-CAT-15 | [`core/dr-catalog/src/schema.rs:1018`](../core/dr-catalog/src/schema.rs#L1018), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:507`](../core/dr-sync-nextcloud/src/lib.rs#L507), [`core/dr-sync/src/lib.rs:135`](../core/dr-sync/src/lib.rs#L135), [`core/dr-sync/src/scan.rs:618`](../core/dr-sync/src/scan.rs#L618), [`core/dr-sync/src/scan.rs:93`](../core/dr-sync/src/scan.rs#L93), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`core/dr-types/src/place.rs:91`](../core/dr-types/src/place.rs#L91), [`ui/dr-ui/src/collections_ui.rs:1435`](../ui/dr-ui/src/collections_ui.rs#L1435), [`ui/dr-ui/src/collections_ui.rs:2341`](../ui/dr-ui/src/collections_ui.rs#L2341), [`ui/dr-ui/src/library.rs:183`](../ui/dr-ui/src/library.rs#L183), [`ui/dr-ui/src/library.rs:200`](../ui/dr-ui/src/library.rs#L200), [`ui/dr-ui/src/library.rs:249`](../ui/dr-ui/src/library.rs#L249), [`ui/dr-ui/src/library.rs:5427`](../ui/dr-ui/src/library.rs#L5427), [`ui/dr-ui/src/library.rs:5461`](../ui/dr-ui/src/library.rs#L5461), [`ui/dr-ui/src/library_ui.rs:238`](../ui/dr-ui/src/library_ui.rs#L238), [`ui/dr-ui/src/library_ui.rs:912`](../ui/dr-ui/src/library_ui.rs#L912), [`ui/dr-ui/src/trash.rs:1`](../ui/dr-ui/src/trash.rs#L1), [`ui/dr-ui/ui/collections.slint:745`](../ui/dr-ui/ui/collections.slint#L745) | | FR-CAT-1a | [`core/dr-catalog/src/walk.rs:1`](../core/dr-catalog/src/walk.rs#L1), [`core/dr-types/src/lib.rs:56`](../core/dr-types/src/lib.rs#L56), [`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) | -| 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:105`](../core/dr-sync/src/scan.rs#L105), [`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:3796`](../ui/dr-ui/src/library.rs#L3796), [`ui/dr-ui/src/library.rs:4708`](../ui/dr-ui/src/library.rs#L4708), [`ui/dr-ui/src/library_ui.rs:177`](../ui/dr-ui/src/library_ui.rs#L177), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/src/library_ui.rs:6052`](../ui/dr-ui/src/library_ui.rs#L6052), [`ui/dr-ui/ui/app.slint:383`](../ui/dr-ui/ui/app.slint#L383), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425), [`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:434`](../core/dr-catalog/src/schema.rs#L434), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:230`](../ui/dr-ui/src/library.rs#L230), [`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:1475`](../core/dr-catalog/src/schema.rs#L1475), [`core/dr-catalog/src/schema.rs:918`](../core/dr-catalog/src/schema.rs#L918), [`core/dr-decode/src/lib.rs:285`](../core/dr-decode/src/lib.rs#L285), [`core/dr-decode/src/lib.rs:408`](../core/dr-decode/src/lib.rs#L408), [`core/dr-pipeline/src/sidecar.rs:156`](../core/dr-pipeline/src/sidecar.rs#L156), [`ui/dr-ui/src/collections_ui.rs:1731`](../ui/dr-ui/src/collections_ui.rs#L1731), [`ui/dr-ui/src/collections_ui.rs:1837`](../ui/dr-ui/src/collections_ui.rs#L1837), [`ui/dr-ui/src/collections_ui.rs:1886`](../ui/dr-ui/src/collections_ui.rs#L1886), [`ui/dr-ui/src/collections_ui.rs:275`](../ui/dr-ui/src/collections_ui.rs#L275), [`ui/dr-ui/src/collections_ui.rs:484`](../ui/dr-ui/src/collections_ui.rs#L484), [`ui/dr-ui/src/collections_ui.rs:87`](../ui/dr-ui/src/collections_ui.rs#L87), [`ui/dr-ui/src/library.rs:5323`](../ui/dr-ui/src/library.rs#L5323), [`ui/dr-ui/src/library_ui.rs:787`](../ui/dr-ui/src/library_ui.rs#L787), [`ui/dr-ui/src/library_ui.rs:8044`](../ui/dr-ui/src/library_ui.rs#L8044), [`ui/dr-ui/src/library_ui.rs:8055`](../ui/dr-ui/src/library_ui.rs#L8055), [`ui/dr-ui/src/library_ui.rs:8068`](../ui/dr-ui/src/library_ui.rs#L8068), [`ui/dr-ui/src/library_ui.rs:8083`](../ui/dr-ui/src/library_ui.rs#L8083), [`ui/dr-ui/src/library_ui.rs:8092`](../ui/dr-ui/src/library_ui.rs#L8092), [`ui/dr-ui/ui/app.slint:304`](../ui/dr-ui/ui/app.slint#L304), [`ui/dr-ui/ui/app.slint:569`](../ui/dr-ui/ui/app.slint#L569), [`ui/dr-ui/ui/library.slint:1360`](../ui/dr-ui/ui/library.slint#L1360), [`ui/dr-ui/ui/library.slint:1384`](../ui/dr-ui/ui/library.slint#L1384), [`ui/dr-ui/ui/library.slint:1437`](../ui/dr-ui/ui/library.slint#L1437), [`ui/dr-ui/ui/library.slint:19`](../ui/dr-ui/ui/library.slint#L19), [`ui/dr-ui/ui/library.slint:4201`](../ui/dr-ui/ui/library.slint#L4201) | -| 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:918`](../core/dr-catalog/src/schema.rs#L918), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:64`](../core/dr-types/src/settings.rs#L64), [`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:254`](../ui/dr-ui/src/library.rs#L254), [`ui/dr-ui/src/library.rs:5799`](../ui/dr-ui/src/library.rs#L5799), [`ui/dr-ui/src/library_ui.rs:396`](../ui/dr-ui/src/library_ui.rs#L396), [`ui/dr-ui/src/library_ui.rs:503`](../ui/dr-ui/src/library_ui.rs#L503), [`ui/dr-ui/src/library_ui.rs:6774`](../ui/dr-ui/src/library_ui.rs#L6774), [`ui/dr-ui/src/library_ui.rs:6827`](../ui/dr-ui/src/library_ui.rs#L6827), [`ui/dr-ui/src/library_ui.rs:8184`](../ui/dr-ui/src/library_ui.rs#L8184), [`ui/dr-ui/ui/app.slint:316`](../ui/dr-ui/ui/app.slint#L316), [`ui/dr-ui/ui/app.slint:569`](../ui/dr-ui/ui/app.slint#L569), [`ui/dr-ui/ui/app.slint:848`](../ui/dr-ui/ui/app.slint#L848), [`ui/dr-ui/ui/library.slint:111`](../ui/dr-ui/ui/library.slint#L111), [`ui/dr-ui/ui/library.slint:1547`](../ui/dr-ui/ui/library.slint#L1547), [`ui/dr-ui/ui/library.slint:4201`](../ui/dr-ui/ui/library.slint#L4201), [`ui/dr-ui/ui/settings.slint:181`](../ui/dr-ui/ui/settings.slint#L181) | -| 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:1117`](../ui/dr-ui/src/collections_ui.rs#L1117), [`ui/dr-ui/src/collections_ui.rs:117`](../ui/dr-ui/src/collections_ui.rs#L117), [`ui/dr-ui/src/collections_ui.rs:1225`](../ui/dr-ui/src/collections_ui.rs#L1225), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1750`](../ui/dr-ui/src/collections_ui.rs#L1750), [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/collections_ui.rs:2000`](../ui/dr-ui/src/collections_ui.rs#L2000), [`ui/dr-ui/src/collections_ui.rs:2065`](../ui/dr-ui/src/collections_ui.rs#L2065), [`ui/dr-ui/src/collections_ui.rs:2125`](../ui/dr-ui/src/collections_ui.rs#L2125), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:2755`](../ui/dr-ui/src/collections_ui.rs#L2755), [`ui/dr-ui/src/collections_ui.rs:2801`](../ui/dr-ui/src/collections_ui.rs#L2801), [`ui/dr-ui/src/collections_ui.rs:2903`](../ui/dr-ui/src/collections_ui.rs#L2903), [`ui/dr-ui/src/collections_ui.rs:2959`](../ui/dr-ui/src/collections_ui.rs#L2959), [`ui/dr-ui/src/collections_ui.rs:3120`](../ui/dr-ui/src/collections_ui.rs#L3120), [`ui/dr-ui/src/collections_ui.rs:3142`](../ui/dr-ui/src/collections_ui.rs#L3142), [`ui/dr-ui/src/collections_ui.rs:3208`](../ui/dr-ui/src/collections_ui.rs#L3208), [`ui/dr-ui/src/collections_ui.rs:329`](../ui/dr-ui/src/collections_ui.rs#L329), [`ui/dr-ui/src/collections_ui.rs:3328`](../ui/dr-ui/src/collections_ui.rs#L3328), [`ui/dr-ui/src/collections_ui.rs:339`](../ui/dr-ui/src/collections_ui.rs#L339), [`ui/dr-ui/src/collections_ui.rs:362`](../ui/dr-ui/src/collections_ui.rs#L362), [`ui/dr-ui/src/collections_ui.rs:3633`](../ui/dr-ui/src/collections_ui.rs#L3633), [`ui/dr-ui/src/collections_ui.rs:383`](../ui/dr-ui/src/collections_ui.rs#L383), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:718`](../ui/dr-ui/src/collections_ui.rs#L718), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library.rs:5604`](../ui/dr-ui/src/library.rs#L5604), [`ui/dr-ui/src/library.rs:5630`](../ui/dr-ui/src/library.rs#L5630), [`ui/dr-ui/src/library.rs:5685`](../ui/dr-ui/src/library.rs#L5685), [`ui/dr-ui/src/library_ui.rs:2779`](../ui/dr-ui/src/library_ui.rs#L2779), [`ui/dr-ui/src/library_ui.rs:4395`](../ui/dr-ui/src/library_ui.rs#L4395), [`ui/dr-ui/src/library_ui.rs:5154`](../ui/dr-ui/src/library_ui.rs#L5154), [`ui/dr-ui/ui/app.slint:307`](../ui/dr-ui/ui/app.slint#L307), [`ui/dr-ui/ui/app.slint:3123`](../ui/dr-ui/ui/app.slint#L3123), [`ui/dr-ui/ui/app.slint:564`](../ui/dr-ui/ui/app.slint#L564), [`ui/dr-ui/ui/app.slint:593`](../ui/dr-ui/ui/app.slint#L593), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:587`](../ui/dr-ui/ui/collections.slint#L587), [`ui/dr-ui/ui/library.slint:1327`](../ui/dr-ui/ui/library.slint#L1327), [`ui/dr-ui/ui/library.slint:2902`](../ui/dr-ui/ui/library.slint#L2902), [`ui/dr-ui/ui/library.slint:4179`](../ui/dr-ui/ui/library.slint#L4179), [`ui/dr-ui/ui/library.slint:4257`](../ui/dr-ui/ui/library.slint#L4257), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998) | -| FR-CAT-8 | [`core/dr-catalog/src/schema.rs:610`](../core/dr-catalog/src/schema.rs#L610), [`core/dr-pipeline/src/coverage.rs:1`](../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/graph.rs:587`](../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:640`](../core/dr-pipeline/src/graph.rs#L640), [`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:1373`](../core/dr-pipeline/src/sidecar.rs#L1373), [`core/dr-pipeline/src/sidecar.rs:2205`](../core/dr-pipeline/src/sidecar.rs#L2205), [`core/dr-pipeline/src/sidecar.rs:96`](../core/dr-pipeline/src/sidecar.rs#L96), [`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), [`core/dr-sync/src/scan.rs:31`](../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../core/dr-sync/src/scan.rs#L926), [`ui/dr-ui/src/develop.rs:2155`](../ui/dr-ui/src/develop.rs#L2155), [`ui/dr-ui/src/develop.rs:5421`](../ui/dr-ui/src/develop.rs#L5421), [`ui/dr-ui/src/develop.rs:5450`](../ui/dr-ui/src/develop.rs#L5450), [`ui/dr-ui/src/develop.rs:6824`](../ui/dr-ui/src/develop.rs#L6824), [`ui/dr-ui/src/develop.rs:6878`](../ui/dr-ui/src/develop.rs#L6878), [`ui/dr-ui/src/develop.rs:6980`](../ui/dr-ui/src/develop.rs#L6980), [`ui/dr-ui/src/export.rs:799`](../ui/dr-ui/src/export.rs#L799), [`ui/dr-ui/src/lib.rs:1298`](../ui/dr-ui/src/lib.rs#L1298), [`ui/dr-ui/src/lib.rs:1827`](../ui/dr-ui/src/lib.rs#L1827), [`ui/dr-ui/src/lib.rs:2396`](../ui/dr-ui/src/lib.rs#L2396), [`ui/dr-ui/src/lib.rs:2543`](../ui/dr-ui/src/lib.rs#L2543), [`ui/dr-ui/src/lib.rs:751`](../ui/dr-ui/src/lib.rs#L751), [`ui/dr-ui/src/library.rs:1391`](../ui/dr-ui/src/library.rs#L1391), [`ui/dr-ui/src/library.rs:1426`](../ui/dr-ui/src/library.rs#L1426), [`ui/dr-ui/src/library.rs:2427`](../ui/dr-ui/src/library.rs#L2427), [`ui/dr-ui/src/library.rs:500`](../ui/dr-ui/src/library.rs#L500), [`ui/dr-ui/src/library.rs:552`](../ui/dr-ui/src/library.rs#L552), [`ui/dr-ui/src/library.rs:589`](../ui/dr-ui/src/library.rs#L589), [`ui/dr-ui/src/library.rs:73`](../ui/dr-ui/src/library.rs#L73), [`ui/dr-ui/src/library.rs:8100`](../ui/dr-ui/src/library.rs#L8100), [`ui/dr-ui/src/library.rs:862`](../ui/dr-ui/src/library.rs#L862), [`ui/dr-ui/src/library_ui.rs:1344`](../ui/dr-ui/src/library_ui.rs#L1344), [`ui/dr-ui/src/library_ui.rs:6375`](../ui/dr-ui/src/library_ui.rs#L6375), [`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:975`](../core/dr-catalog/src/schema.rs#L975), [`core/dr-catalog/src/walk.rs:1022`](../core/dr-catalog/src/walk.rs#L1022), [`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:728`](../core/dr-catalog/src/walk.rs#L728), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`core/dr-sync/src/error.rs:113`](../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/reachability.rs:1`](../core/dr-sync/src/reachability.rs#L1), [`core/dr-sync/src/scan.rs:211`](../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../core/dr-sync/src/scan.rs#L519), [`core/dr-types/src/lib.rs:122`](../core/dr-types/src/lib.rs#L122), [`ui/dr-ui/src/develop.rs:4710`](../ui/dr-ui/src/develop.rs#L4710), [`ui/dr-ui/src/develop.rs:4753`](../ui/dr-ui/src/develop.rs#L4753), [`ui/dr-ui/src/library.rs:1291`](../ui/dr-ui/src/library.rs#L1291), [`ui/dr-ui/src/library.rs:1344`](../ui/dr-ui/src/library.rs#L1344), [`ui/dr-ui/src/library.rs:1375`](../ui/dr-ui/src/library.rs#L1375), [`ui/dr-ui/src/library.rs:1426`](../ui/dr-ui/src/library.rs#L1426), [`ui/dr-ui/src/library.rs:169`](../ui/dr-ui/src/library.rs#L169), [`ui/dr-ui/src/library.rs:1955`](../ui/dr-ui/src/library.rs#L1955), [`ui/dr-ui/src/library.rs:2407`](../ui/dr-ui/src/library.rs#L2407), [`ui/dr-ui/src/library.rs:2463`](../ui/dr-ui/src/library.rs#L2463), [`ui/dr-ui/src/library.rs:274`](../ui/dr-ui/src/library.rs#L274), [`ui/dr-ui/src/library.rs:589`](../ui/dr-ui/src/library.rs#L589), [`ui/dr-ui/src/library.rs:5907`](../ui/dr-ui/src/library.rs#L5907), [`ui/dr-ui/src/library.rs:846`](../ui/dr-ui/src/library.rs#L846), [`ui/dr-ui/src/library.rs:862`](../ui/dr-ui/src/library.rs#L862), [`ui/dr-ui/src/library.rs:916`](../ui/dr-ui/src/library.rs#L916), [`ui/dr-ui/src/library_ui.rs:1411`](../ui/dr-ui/src/library_ui.rs#L1411), [`ui/dr-ui/src/library_ui.rs:2002`](../ui/dr-ui/src/library_ui.rs#L2002), [`ui/dr-ui/src/library_ui.rs:2046`](../ui/dr-ui/src/library_ui.rs#L2046), [`ui/dr-ui/src/library_ui.rs:2062`](../ui/dr-ui/src/library_ui.rs#L2062), [`ui/dr-ui/src/library_ui.rs:2156`](../ui/dr-ui/src/library_ui.rs#L2156), [`ui/dr-ui/src/library_ui.rs:284`](../ui/dr-ui/src/library_ui.rs#L284), [`ui/dr-ui/src/library_ui.rs:3019`](../ui/dr-ui/src/library_ui.rs#L3019), [`ui/dr-ui/src/library_ui.rs:320`](../ui/dr-ui/src/library_ui.rs#L320), [`ui/dr-ui/src/library_ui.rs:328`](../ui/dr-ui/src/library_ui.rs#L328), [`ui/dr-ui/src/library_ui.rs:3642`](../ui/dr-ui/src/library_ui.rs#L3642), [`ui/dr-ui/src/library_ui.rs:3864`](../ui/dr-ui/src/library_ui.rs#L3864), [`ui/dr-ui/src/library_ui.rs:4142`](../ui/dr-ui/src/library_ui.rs#L4142), [`ui/dr-ui/src/library_ui.rs:4258`](../ui/dr-ui/src/library_ui.rs#L4258), [`ui/dr-ui/src/library_ui.rs:4446`](../ui/dr-ui/src/library_ui.rs#L4446), [`ui/dr-ui/src/library_ui.rs:4568`](../ui/dr-ui/src/library_ui.rs#L4568), [`ui/dr-ui/src/library_ui.rs:571`](../ui/dr-ui/src/library_ui.rs#L571), [`ui/dr-ui/src/library_ui.rs:660`](../ui/dr-ui/src/library_ui.rs#L660), [`ui/dr-ui/src/library_ui.rs:6872`](../ui/dr-ui/src/library_ui.rs#L6872), [`ui/dr-ui/src/library_ui.rs:6954`](../ui/dr-ui/src/library_ui.rs#L6954), [`ui/dr-ui/src/presets.rs:486`](../ui/dr-ui/src/presets.rs#L486), [`ui/dr-ui/src/presets.rs:498`](../ui/dr-ui/src/presets.rs#L498), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | +| 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:105`](../core/dr-sync/src/scan.rs#L105), [`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:3860`](../ui/dr-ui/src/library.rs#L3860), [`ui/dr-ui/src/library.rs:4798`](../ui/dr-ui/src/library.rs#L4798), [`ui/dr-ui/src/library_ui.rs:177`](../ui/dr-ui/src/library_ui.rs#L177), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/src/library_ui.rs:6053`](../ui/dr-ui/src/library_ui.rs#L6053), [`ui/dr-ui/ui/app.slint:383`](../ui/dr-ui/ui/app.slint#L383), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425), [`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:446`](../core/dr-catalog/src/schema.rs#L446), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:230`](../ui/dr-ui/src/library.rs#L230), [`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:1490`](../core/dr-catalog/src/schema.rs#L1490), [`core/dr-catalog/src/schema.rs:933`](../core/dr-catalog/src/schema.rs#L933), [`core/dr-decode/src/lib.rs:285`](../core/dr-decode/src/lib.rs#L285), [`core/dr-decode/src/lib.rs:408`](../core/dr-decode/src/lib.rs#L408), [`core/dr-pipeline/src/sidecar.rs:156`](../core/dr-pipeline/src/sidecar.rs#L156), [`ui/dr-ui/src/collections_ui.rs:1731`](../ui/dr-ui/src/collections_ui.rs#L1731), [`ui/dr-ui/src/collections_ui.rs:1837`](../ui/dr-ui/src/collections_ui.rs#L1837), [`ui/dr-ui/src/collections_ui.rs:1886`](../ui/dr-ui/src/collections_ui.rs#L1886), [`ui/dr-ui/src/collections_ui.rs:275`](../ui/dr-ui/src/collections_ui.rs#L275), [`ui/dr-ui/src/collections_ui.rs:484`](../ui/dr-ui/src/collections_ui.rs#L484), [`ui/dr-ui/src/collections_ui.rs:87`](../ui/dr-ui/src/collections_ui.rs#L87), [`ui/dr-ui/src/library.rs:5475`](../ui/dr-ui/src/library.rs#L5475), [`ui/dr-ui/src/library_ui.rs:787`](../ui/dr-ui/src/library_ui.rs#L787), [`ui/dr-ui/src/library_ui.rs:8075`](../ui/dr-ui/src/library_ui.rs#L8075), [`ui/dr-ui/src/library_ui.rs:8086`](../ui/dr-ui/src/library_ui.rs#L8086), [`ui/dr-ui/src/library_ui.rs:8099`](../ui/dr-ui/src/library_ui.rs#L8099), [`ui/dr-ui/src/library_ui.rs:8114`](../ui/dr-ui/src/library_ui.rs#L8114), [`ui/dr-ui/src/library_ui.rs:8123`](../ui/dr-ui/src/library_ui.rs#L8123), [`ui/dr-ui/ui/app.slint:304`](../ui/dr-ui/ui/app.slint#L304), [`ui/dr-ui/ui/app.slint:569`](../ui/dr-ui/ui/app.slint#L569), [`ui/dr-ui/ui/library.slint:1360`](../ui/dr-ui/ui/library.slint#L1360), [`ui/dr-ui/ui/library.slint:1384`](../ui/dr-ui/ui/library.slint#L1384), [`ui/dr-ui/ui/library.slint:1437`](../ui/dr-ui/ui/library.slint#L1437), [`ui/dr-ui/ui/library.slint:19`](../ui/dr-ui/ui/library.slint#L19), [`ui/dr-ui/ui/library.slint:4231`](../ui/dr-ui/ui/library.slint#L4231) | +| 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:933`](../core/dr-catalog/src/schema.rs#L933), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`core/dr-types/src/selector.rs:1`](../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:64`](../core/dr-types/src/settings.rs#L64), [`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:254`](../ui/dr-ui/src/library.rs#L254), [`ui/dr-ui/src/library.rs:5951`](../ui/dr-ui/src/library.rs#L5951), [`ui/dr-ui/src/library_ui.rs:396`](../ui/dr-ui/src/library_ui.rs#L396), [`ui/dr-ui/src/library_ui.rs:503`](../ui/dr-ui/src/library_ui.rs#L503), [`ui/dr-ui/src/library_ui.rs:6792`](../ui/dr-ui/src/library_ui.rs#L6792), [`ui/dr-ui/src/library_ui.rs:6845`](../ui/dr-ui/src/library_ui.rs#L6845), [`ui/dr-ui/src/library_ui.rs:8215`](../ui/dr-ui/src/library_ui.rs#L8215), [`ui/dr-ui/ui/app.slint:316`](../ui/dr-ui/ui/app.slint#L316), [`ui/dr-ui/ui/app.slint:569`](../ui/dr-ui/ui/app.slint#L569), [`ui/dr-ui/ui/app.slint:852`](../ui/dr-ui/ui/app.slint#L852), [`ui/dr-ui/ui/library.slint:111`](../ui/dr-ui/ui/library.slint#L111), [`ui/dr-ui/ui/library.slint:1552`](../ui/dr-ui/ui/library.slint#L1552), [`ui/dr-ui/ui/library.slint:4231`](../ui/dr-ui/ui/library.slint#L4231), [`ui/dr-ui/ui/settings.slint:181`](../ui/dr-ui/ui/settings.slint#L181) | +| 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:1117`](../ui/dr-ui/src/collections_ui.rs#L1117), [`ui/dr-ui/src/collections_ui.rs:117`](../ui/dr-ui/src/collections_ui.rs#L117), [`ui/dr-ui/src/collections_ui.rs:1225`](../ui/dr-ui/src/collections_ui.rs#L1225), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1750`](../ui/dr-ui/src/collections_ui.rs#L1750), [`ui/dr-ui/src/collections_ui.rs:1`](../ui/dr-ui/src/collections_ui.rs#L1), [`ui/dr-ui/src/collections_ui.rs:2000`](../ui/dr-ui/src/collections_ui.rs#L2000), [`ui/dr-ui/src/collections_ui.rs:2065`](../ui/dr-ui/src/collections_ui.rs#L2065), [`ui/dr-ui/src/collections_ui.rs:2125`](../ui/dr-ui/src/collections_ui.rs#L2125), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:2755`](../ui/dr-ui/src/collections_ui.rs#L2755), [`ui/dr-ui/src/collections_ui.rs:2801`](../ui/dr-ui/src/collections_ui.rs#L2801), [`ui/dr-ui/src/collections_ui.rs:2903`](../ui/dr-ui/src/collections_ui.rs#L2903), [`ui/dr-ui/src/collections_ui.rs:2959`](../ui/dr-ui/src/collections_ui.rs#L2959), [`ui/dr-ui/src/collections_ui.rs:3120`](../ui/dr-ui/src/collections_ui.rs#L3120), [`ui/dr-ui/src/collections_ui.rs:3142`](../ui/dr-ui/src/collections_ui.rs#L3142), [`ui/dr-ui/src/collections_ui.rs:3208`](../ui/dr-ui/src/collections_ui.rs#L3208), [`ui/dr-ui/src/collections_ui.rs:329`](../ui/dr-ui/src/collections_ui.rs#L329), [`ui/dr-ui/src/collections_ui.rs:3328`](../ui/dr-ui/src/collections_ui.rs#L3328), [`ui/dr-ui/src/collections_ui.rs:339`](../ui/dr-ui/src/collections_ui.rs#L339), [`ui/dr-ui/src/collections_ui.rs:362`](../ui/dr-ui/src/collections_ui.rs#L362), [`ui/dr-ui/src/collections_ui.rs:3633`](../ui/dr-ui/src/collections_ui.rs#L3633), [`ui/dr-ui/src/collections_ui.rs:383`](../ui/dr-ui/src/collections_ui.rs#L383), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:718`](../ui/dr-ui/src/collections_ui.rs#L718), [`ui/dr-ui/src/derived_sync.rs:1`](../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library.rs:5756`](../ui/dr-ui/src/library.rs#L5756), [`ui/dr-ui/src/library.rs:5782`](../ui/dr-ui/src/library.rs#L5782), [`ui/dr-ui/src/library.rs:5837`](../ui/dr-ui/src/library.rs#L5837), [`ui/dr-ui/src/library_ui.rs:2779`](../ui/dr-ui/src/library_ui.rs#L2779), [`ui/dr-ui/src/library_ui.rs:4395`](../ui/dr-ui/src/library_ui.rs#L4395), [`ui/dr-ui/src/library_ui.rs:5154`](../ui/dr-ui/src/library_ui.rs#L5154), [`ui/dr-ui/ui/app.slint:307`](../ui/dr-ui/ui/app.slint#L307), [`ui/dr-ui/ui/app.slint:3129`](../ui/dr-ui/ui/app.slint#L3129), [`ui/dr-ui/ui/app.slint:564`](../ui/dr-ui/ui/app.slint#L564), [`ui/dr-ui/ui/app.slint:593`](../ui/dr-ui/ui/app.slint#L593), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:587`](../ui/dr-ui/ui/collections.slint#L587), [`ui/dr-ui/ui/library.slint:1327`](../ui/dr-ui/ui/library.slint#L1327), [`ui/dr-ui/ui/library.slint:2932`](../ui/dr-ui/ui/library.slint#L2932), [`ui/dr-ui/ui/library.slint:4209`](../ui/dr-ui/ui/library.slint#L4209), [`ui/dr-ui/ui/library.slint:4287`](../ui/dr-ui/ui/library.slint#L4287), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998) | +| FR-CAT-8 | [`core/dr-catalog/src/schema.rs:622`](../core/dr-catalog/src/schema.rs#L622), [`core/dr-pipeline/src/coverage.rs:1`](../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/graph.rs:587`](../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:640`](../core/dr-pipeline/src/graph.rs#L640), [`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:1373`](../core/dr-pipeline/src/sidecar.rs#L1373), [`core/dr-pipeline/src/sidecar.rs:2205`](../core/dr-pipeline/src/sidecar.rs#L2205), [`core/dr-pipeline/src/sidecar.rs:96`](../core/dr-pipeline/src/sidecar.rs#L96), [`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), [`core/dr-sync/src/scan.rs:31`](../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../core/dr-sync/src/scan.rs#L926), [`ui/dr-ui/src/develop.rs:2155`](../ui/dr-ui/src/develop.rs#L2155), [`ui/dr-ui/src/develop.rs:5421`](../ui/dr-ui/src/develop.rs#L5421), [`ui/dr-ui/src/develop.rs:5450`](../ui/dr-ui/src/develop.rs#L5450), [`ui/dr-ui/src/develop.rs:6824`](../ui/dr-ui/src/develop.rs#L6824), [`ui/dr-ui/src/develop.rs:6878`](../ui/dr-ui/src/develop.rs#L6878), [`ui/dr-ui/src/develop.rs:6980`](../ui/dr-ui/src/develop.rs#L6980), [`ui/dr-ui/src/export.rs:799`](../ui/dr-ui/src/export.rs#L799), [`ui/dr-ui/src/lib.rs:1299`](../ui/dr-ui/src/lib.rs#L1299), [`ui/dr-ui/src/lib.rs:1828`](../ui/dr-ui/src/lib.rs#L1828), [`ui/dr-ui/src/lib.rs:2397`](../ui/dr-ui/src/lib.rs#L2397), [`ui/dr-ui/src/lib.rs:2544`](../ui/dr-ui/src/lib.rs#L2544), [`ui/dr-ui/src/lib.rs:752`](../ui/dr-ui/src/lib.rs#L752), [`ui/dr-ui/src/library.rs:1455`](../ui/dr-ui/src/library.rs#L1455), [`ui/dr-ui/src/library.rs:1490`](../ui/dr-ui/src/library.rs#L1490), [`ui/dr-ui/src/library.rs:2491`](../ui/dr-ui/src/library.rs#L2491), [`ui/dr-ui/src/library.rs:564`](../ui/dr-ui/src/library.rs#L564), [`ui/dr-ui/src/library.rs:616`](../ui/dr-ui/src/library.rs#L616), [`ui/dr-ui/src/library.rs:653`](../ui/dr-ui/src/library.rs#L653), [`ui/dr-ui/src/library.rs:73`](../ui/dr-ui/src/library.rs#L73), [`ui/dr-ui/src/library.rs:8480`](../ui/dr-ui/src/library.rs#L8480), [`ui/dr-ui/src/library.rs:926`](../ui/dr-ui/src/library.rs#L926), [`ui/dr-ui/src/library_ui.rs:1344`](../ui/dr-ui/src/library_ui.rs#L1344), [`ui/dr-ui/src/library_ui.rs:6376`](../ui/dr-ui/src/library_ui.rs#L6376), [`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:990`](../core/dr-catalog/src/schema.rs#L990), [`core/dr-catalog/src/walk.rs:1022`](../core/dr-catalog/src/walk.rs#L1022), [`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:728`](../core/dr-catalog/src/walk.rs#L728), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`core/dr-sync/src/error.rs:113`](../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/reachability.rs:1`](../core/dr-sync/src/reachability.rs#L1), [`core/dr-sync/src/scan.rs:211`](../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../core/dr-sync/src/scan.rs#L519), [`core/dr-types/src/lib.rs:122`](../core/dr-types/src/lib.rs#L122), [`ui/dr-ui/src/develop.rs:4710`](../ui/dr-ui/src/develop.rs#L4710), [`ui/dr-ui/src/develop.rs:4753`](../ui/dr-ui/src/develop.rs#L4753), [`ui/dr-ui/src/library.rs:1355`](../ui/dr-ui/src/library.rs#L1355), [`ui/dr-ui/src/library.rs:1408`](../ui/dr-ui/src/library.rs#L1408), [`ui/dr-ui/src/library.rs:1439`](../ui/dr-ui/src/library.rs#L1439), [`ui/dr-ui/src/library.rs:1490`](../ui/dr-ui/src/library.rs#L1490), [`ui/dr-ui/src/library.rs:169`](../ui/dr-ui/src/library.rs#L169), [`ui/dr-ui/src/library.rs:2019`](../ui/dr-ui/src/library.rs#L2019), [`ui/dr-ui/src/library.rs:2471`](../ui/dr-ui/src/library.rs#L2471), [`ui/dr-ui/src/library.rs:2527`](../ui/dr-ui/src/library.rs#L2527), [`ui/dr-ui/src/library.rs:274`](../ui/dr-ui/src/library.rs#L274), [`ui/dr-ui/src/library.rs:6059`](../ui/dr-ui/src/library.rs#L6059), [`ui/dr-ui/src/library.rs:653`](../ui/dr-ui/src/library.rs#L653), [`ui/dr-ui/src/library.rs:910`](../ui/dr-ui/src/library.rs#L910), [`ui/dr-ui/src/library.rs:926`](../ui/dr-ui/src/library.rs#L926), [`ui/dr-ui/src/library.rs:980`](../ui/dr-ui/src/library.rs#L980), [`ui/dr-ui/src/library_ui.rs:1411`](../ui/dr-ui/src/library_ui.rs#L1411), [`ui/dr-ui/src/library_ui.rs:2002`](../ui/dr-ui/src/library_ui.rs#L2002), [`ui/dr-ui/src/library_ui.rs:2046`](../ui/dr-ui/src/library_ui.rs#L2046), [`ui/dr-ui/src/library_ui.rs:2062`](../ui/dr-ui/src/library_ui.rs#L2062), [`ui/dr-ui/src/library_ui.rs:2156`](../ui/dr-ui/src/library_ui.rs#L2156), [`ui/dr-ui/src/library_ui.rs:284`](../ui/dr-ui/src/library_ui.rs#L284), [`ui/dr-ui/src/library_ui.rs:3019`](../ui/dr-ui/src/library_ui.rs#L3019), [`ui/dr-ui/src/library_ui.rs:320`](../ui/dr-ui/src/library_ui.rs#L320), [`ui/dr-ui/src/library_ui.rs:328`](../ui/dr-ui/src/library_ui.rs#L328), [`ui/dr-ui/src/library_ui.rs:3642`](../ui/dr-ui/src/library_ui.rs#L3642), [`ui/dr-ui/src/library_ui.rs:3864`](../ui/dr-ui/src/library_ui.rs#L3864), [`ui/dr-ui/src/library_ui.rs:4142`](../ui/dr-ui/src/library_ui.rs#L4142), [`ui/dr-ui/src/library_ui.rs:4258`](../ui/dr-ui/src/library_ui.rs#L4258), [`ui/dr-ui/src/library_ui.rs:4446`](../ui/dr-ui/src/library_ui.rs#L4446), [`ui/dr-ui/src/library_ui.rs:4568`](../ui/dr-ui/src/library_ui.rs#L4568), [`ui/dr-ui/src/library_ui.rs:571`](../ui/dr-ui/src/library_ui.rs#L571), [`ui/dr-ui/src/library_ui.rs:660`](../ui/dr-ui/src/library_ui.rs#L660), [`ui/dr-ui/src/library_ui.rs:6890`](../ui/dr-ui/src/library_ui.rs#L6890), [`ui/dr-ui/src/library_ui.rs:6972`](../ui/dr-ui/src/library_ui.rs#L6972), [`ui/dr-ui/src/presets.rs:486`](../ui/dr-ui/src/presets.rs#L486), [`ui/dr-ui/src/presets.rs:498`](../ui/dr-ui/src/presets.rs#L498), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../ui/dr-ui/tests/export_ignores_the_viewport.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:473`](../core/dr-catalog/src/schema.rs#L473), [`core/dr-catalog/src/schema.rs:651`](../core/dr-catalog/src/schema.rs#L651), [`core/dr-catalog/src/schema.rs:804`](../core/dr-catalog/src/schema.rs#L804), [`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), [`core/dr-types/src/settings.rs:129`](../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/develop.rs:121`](../ui/dr-ui/src/develop.rs#L121), [`ui/dr-ui/src/develop.rs:130`](../ui/dr-ui/src/develop.rs#L130), [`ui/dr-ui/src/develop.rs:196`](../ui/dr-ui/src/develop.rs#L196), [`ui/dr-ui/src/develop.rs:2416`](../ui/dr-ui/src/develop.rs#L2416), [`ui/dr-ui/src/develop.rs:715`](../ui/dr-ui/src/develop.rs#L715), [`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:2515`](../ui/dr-ui/src/lib.rs#L2515), [`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:804`](../core/dr-catalog/src/schema.rs#L804), [`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:295`](../ui/dr-ui/src/library.rs#L295), [`ui/dr-ui/src/library.rs:325`](../ui/dr-ui/src/library.rs#L325), [`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:473`](../core/dr-catalog/src/schema.rs#L473), [`core/dr-catalog/src/schema.rs:804`](../core/dr-catalog/src/schema.rs#L804), [`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-13 | [`core/dr-catalog/src/faces.rs:124`](../core/dr-catalog/src/faces.rs#L124), [`core/dr-face/src/classify.rs:1`](../core/dr-face/src/classify.rs#L1), [`core/dr-face/src/eyes.rs:1`](../core/dr-face/src/eyes.rs#L1), [`core/dr-face/src/landmarks.rs:1`](../core/dr-face/src/landmarks.rs#L1) | +| FR-CULL-10 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:485`](../core/dr-catalog/src/schema.rs#L485), [`core/dr-catalog/src/schema.rs:663`](../core/dr-catalog/src/schema.rs#L663), [`core/dr-catalog/src/schema.rs:819`](../core/dr-catalog/src/schema.rs#L819), [`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), [`core/dr-types/src/settings.rs:129`](../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/develop.rs:121`](../ui/dr-ui/src/develop.rs#L121), [`ui/dr-ui/src/develop.rs:130`](../ui/dr-ui/src/develop.rs#L130), [`ui/dr-ui/src/develop.rs:196`](../ui/dr-ui/src/develop.rs#L196), [`ui/dr-ui/src/develop.rs:2416`](../ui/dr-ui/src/develop.rs#L2416), [`ui/dr-ui/src/develop.rs:715`](../ui/dr-ui/src/develop.rs#L715), [`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:2516`](../ui/dr-ui/src/lib.rs#L2516), [`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:819`](../core/dr-catalog/src/schema.rs#L819), [`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:295`](../ui/dr-ui/src/library.rs#L295), [`ui/dr-ui/src/library.rs:345`](../ui/dr-ui/src/library.rs#L345), [`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:485`](../core/dr-catalog/src/schema.rs#L485), [`core/dr-catalog/src/schema.rs:819`](../core/dr-catalog/src/schema.rs#L819), [`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-13 | [`core/dr-catalog/src/faces.rs:124`](../core/dr-catalog/src/faces.rs#L124), [`core/dr-face/src/classify.rs:1`](../core/dr-face/src/classify.rs#L1), [`core/dr-face/src/eyes.rs:1`](../core/dr-face/src/eyes.rs#L1), [`core/dr-face/src/landmarks.rs:1`](../core/dr-face/src/landmarks.rs#L1), [`core/dr-types/src/place.rs:129`](../core/dr-types/src/place.rs#L129), [`ui/dr-ui/src/faces.rs:160`](../ui/dr-ui/src/faces.rs#L160), [`ui/dr-ui/src/faces.rs:1702`](../ui/dr-ui/src/faces.rs#L1702), [`ui/dr-ui/src/faces.rs:275`](../ui/dr-ui/src/faces.rs#L275), [`ui/dr-ui/src/identity.rs:104`](../ui/dr-ui/src/identity.rs#L104), [`ui/dr-ui/src/library.rs:321`](../ui/dr-ui/src/library.rs#L321), [`ui/dr-ui/src/library.rs:8313`](../ui/dr-ui/src/library.rs#L8313), [`ui/dr-ui/src/library.rs:8356`](../ui/dr-ui/src/library.rs#L8356), [`ui/dr-ui/src/library.rs:8394`](../ui/dr-ui/src/library.rs#L8394), [`ui/dr-ui/ui/app.slint:701`](../ui/dr-ui/ui/app.slint#L701), [`ui/dr-ui/ui/identity.slint:63`](../ui/dr-ui/ui/identity.slint#L63), [`ui/dr-ui/ui/library.slint:1512`](../ui/dr-ui/ui/library.slint#L1512) | | 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/raw_histogram.rs:129`](../core/dr-gpu/src/raw_histogram.rs#L129), [`core/dr-gpu/src/raw_histogram.rs:1`](../core/dr-gpu/src/raw_histogram.rs#L1), [`core/dr-gpu/src/raw_histogram.rs:272`](../core/dr-gpu/src/raw_histogram.rs#L272), [`core/dr-gpu/src/raw_histogram.rs:407`](../core/dr-gpu/src/raw_histogram.rs#L407), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`core/dr-gpu/src/shaders/raw_histogram.wgsl:1`](../core/dr-gpu/src/shaders/raw_histogram.wgsl#L1), [`ui/dr-ui/src/develop.rs:4137`](../ui/dr-ui/src/develop.rs#L4137), [`ui/dr-ui/src/develop.rs:4150`](../ui/dr-ui/src/develop.rs#L4150), [`ui/dr-ui/src/develop.rs:4195`](../ui/dr-ui/src/develop.rs#L4195), [`ui/dr-ui/src/develop.rs:4206`](../ui/dr-ui/src/develop.rs#L4206), [`ui/dr-ui/src/develop.rs:4212`](../ui/dr-ui/src/develop.rs#L4212), [`ui/dr-ui/src/develop.rs:4229`](../ui/dr-ui/src/develop.rs#L4229), [`ui/dr-ui/src/develop.rs:810`](../ui/dr-ui/src/develop.rs#L810), [`ui/dr-ui/src/develop.rs:830`](../ui/dr-ui/src/develop.rs#L830), [`ui/dr-ui/src/develop.rs:836`](../ui/dr-ui/src/develop.rs#L836), [`ui/dr-ui/src/develop.rs:8734`](../ui/dr-ui/src/develop.rs#L8734), [`ui/dr-ui/src/develop.rs:8798`](../ui/dr-ui/src/develop.rs#L8798), [`ui/dr-ui/src/develop.rs:8821`](../ui/dr-ui/src/develop.rs#L8821), [`ui/dr-ui/src/histogram.rs:1`](../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/histogram.rs:208`](../ui/dr-ui/src/histogram.rs#L208), [`ui/dr-ui/src/histogram.rs:228`](../ui/dr-ui/src/histogram.rs#L228), [`ui/dr-ui/src/histogram.rs:272`](../ui/dr-ui/src/histogram.rs#L272), [`ui/dr-ui/src/histogram.rs:544`](../ui/dr-ui/src/histogram.rs#L544), [`ui/dr-ui/src/histogram.rs:565`](../ui/dr-ui/src/histogram.rs#L565), [`ui/dr-ui/src/histogram.rs:593`](../ui/dr-ui/src/histogram.rs#L593), [`ui/dr-ui/src/histogram.rs:621`](../ui/dr-ui/src/histogram.rs#L621), [`ui/dr-ui/src/histogram.rs:658`](../ui/dr-ui/src/histogram.rs#L658), [`ui/dr-ui/src/lib.rs:1871`](../ui/dr-ui/src/lib.rs#L1871), [`ui/dr-ui/src/lib.rs:1979`](../ui/dr-ui/src/lib.rs#L1979), [`ui/dr-ui/src/lib.rs:2092`](../ui/dr-ui/src/lib.rs#L2092), [`ui/dr-ui/src/lib.rs:2133`](../ui/dr-ui/src/lib.rs#L2133), [`ui/dr-ui/src/lib.rs:3626`](../ui/dr-ui/src/lib.rs#L3626), [`ui/dr-ui/src/lib.rs:436`](../ui/dr-ui/src/lib.rs#L436), [`ui/dr-ui/src/peaking.rs:1`](../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:1938`](../ui/dr-ui/ui/app.slint#L1938), [`ui/dr-ui/ui/app.slint:2945`](../ui/dr-ui/ui/app.slint#L2945), [`ui/dr-ui/ui/app.slint:87`](../ui/dr-ui/ui/app.slint#L87), [`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), [`ui/dr-ui/ui/peaking.slint:91`](../ui/dr-ui/ui/peaking.slint#L91) | -| FR-CULL-4 | [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-pipeline/src/sidecar.rs:156`](../core/dr-pipeline/src/sidecar.rs#L156), [`core/dr-xmp/src/lib.rs:442`](../core/dr-xmp/src/lib.rs#L442), [`ui/dr-ui/src/library.rs:254`](../ui/dr-ui/src/library.rs#L254), [`ui/dr-ui/src/library.rs:500`](../ui/dr-ui/src/library.rs#L500) | -| FR-CULL-5 | [`core/dr-catalog/src/bursts.rs:1`](../core/dr-catalog/src/bursts.rs#L1), [`core/dr-catalog/src/schema.rs:516`](../core/dr-catalog/src/schema.rs#L516), [`ui/dr-ui/src/bursts.rs:1`](../ui/dr-ui/src/bursts.rs#L1), [`ui/dr-ui/src/library.rs:210`](../ui/dr-ui/src/library.rs#L210), [`ui/dr-ui/src/library.rs:6688`](../ui/dr-ui/src/library.rs#L6688) | -| 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:584`](../core/dr-catalog/src/schema.rs#L584), [`core/dr-catalog/src/schema.rs:763`](../core/dr-catalog/src/schema.rs#L763), [`core/dr-catalog/src/schema.rs:804`](../core/dr-catalog/src/schema.rs#L804), [`core/dr-face/src/align.rs:296`](../core/dr-face/src/align.rs#L296), [`core/dr-types/src/settings.rs:176`](../core/dr-types/src/settings.rs#L176), [`ui/dr-ui/examples/face_detectors.rs:1`](../ui/dr-ui/examples/face_detectors.rs#L1), [`ui/dr-ui/examples/face_native.rs:1`](../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/derived_sync.rs:124`](../ui/dr-ui/src/derived_sync.rs#L124), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/faces.rs:334`](../ui/dr-ui/src/faces.rs#L334), [`ui/dr-ui/src/faces.rs:350`](../ui/dr-ui/src/faces.rs#L350), [`ui/dr-ui/src/faces.rs:457`](../ui/dr-ui/src/faces.rs#L457), [`ui/dr-ui/src/identity_ui.rs:548`](../ui/dr-ui/src/identity_ui.rs#L548), [`ui/dr-ui/src/lib.rs:1479`](../ui/dr-ui/src/lib.rs#L1479), [`ui/dr-ui/src/lib.rs:3881`](../ui/dr-ui/src/lib.rs#L3881), [`ui/dr-ui/src/library.rs:3531`](../ui/dr-ui/src/library.rs#L3531), [`ui/dr-ui/src/library.rs:3797`](../ui/dr-ui/src/library.rs#L3797), [`ui/dr-ui/src/library.rs:4052`](../ui/dr-ui/src/library.rs#L4052), [`ui/dr-ui/src/library.rs:4333`](../ui/dr-ui/src/library.rs#L4333), [`ui/dr-ui/src/library.rs:4522`](../ui/dr-ui/src/library.rs#L4522), [`ui/dr-ui/src/library.rs:4558`](../ui/dr-ui/src/library.rs#L4558), [`ui/dr-ui/src/library.rs:4638`](../ui/dr-ui/src/library.rs#L4638), [`ui/dr-ui/src/library.rs:6855`](../ui/dr-ui/src/library.rs#L6855), [`ui/dr-ui/src/library_ui.rs:406`](../ui/dr-ui/src/library_ui.rs#L406), [`ui/dr-ui/src/library_ui.rs:491`](../ui/dr-ui/src/library_ui.rs#L491), [`ui/dr-ui/src/settings_ui.rs:210`](../ui/dr-ui/src/settings_ui.rs#L210), [`ui/dr-ui/src/settings_ui.rs:552`](../ui/dr-ui/src/settings_ui.rs#L552), [`ui/dr-ui/ui/app.slint:898`](../ui/dr-ui/ui/app.slint#L898), [`ui/dr-ui/ui/settings.slint:457`](../ui/dr-ui/ui/settings.slint#L457), [`ui/dr-ui/ui/settings.slint:82`](../ui/dr-ui/ui/settings.slint#L82), [`ui/dr-ui/ui/settings.slint:94`](../ui/dr-ui/ui/settings.slint#L94) | -| FR-CULL-9 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:651`](../core/dr-catalog/src/schema.rs#L651), [`core/dr-catalog/src/schema.rs:804`](../core/dr-catalog/src/schema.rs#L804), [`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), [`core/dr-types/src/settings.rs:129`](../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/faces.rs:457`](../ui/dr-ui/src/faces.rs#L457), [`ui/dr-ui/src/identity_ui.rs:1`](../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/library.rs:3904`](../ui/dr-ui/src/library.rs#L3904), [`ui/dr-ui/src/library.rs:4638`](../ui/dr-ui/src/library.rs#L4638), [`ui/dr-ui/ui/identity.slint:314`](../ui/dr-ui/ui/identity.slint#L314) | +| 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/raw_histogram.rs:129`](../core/dr-gpu/src/raw_histogram.rs#L129), [`core/dr-gpu/src/raw_histogram.rs:1`](../core/dr-gpu/src/raw_histogram.rs#L1), [`core/dr-gpu/src/raw_histogram.rs:272`](../core/dr-gpu/src/raw_histogram.rs#L272), [`core/dr-gpu/src/raw_histogram.rs:407`](../core/dr-gpu/src/raw_histogram.rs#L407), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`core/dr-gpu/src/shaders/raw_histogram.wgsl:1`](../core/dr-gpu/src/shaders/raw_histogram.wgsl#L1), [`ui/dr-ui/src/develop.rs:4137`](../ui/dr-ui/src/develop.rs#L4137), [`ui/dr-ui/src/develop.rs:4150`](../ui/dr-ui/src/develop.rs#L4150), [`ui/dr-ui/src/develop.rs:4195`](../ui/dr-ui/src/develop.rs#L4195), [`ui/dr-ui/src/develop.rs:4206`](../ui/dr-ui/src/develop.rs#L4206), [`ui/dr-ui/src/develop.rs:4212`](../ui/dr-ui/src/develop.rs#L4212), [`ui/dr-ui/src/develop.rs:4229`](../ui/dr-ui/src/develop.rs#L4229), [`ui/dr-ui/src/develop.rs:810`](../ui/dr-ui/src/develop.rs#L810), [`ui/dr-ui/src/develop.rs:830`](../ui/dr-ui/src/develop.rs#L830), [`ui/dr-ui/src/develop.rs:836`](../ui/dr-ui/src/develop.rs#L836), [`ui/dr-ui/src/develop.rs:8734`](../ui/dr-ui/src/develop.rs#L8734), [`ui/dr-ui/src/develop.rs:8798`](../ui/dr-ui/src/develop.rs#L8798), [`ui/dr-ui/src/develop.rs:8821`](../ui/dr-ui/src/develop.rs#L8821), [`ui/dr-ui/src/histogram.rs:1`](../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/histogram.rs:208`](../ui/dr-ui/src/histogram.rs#L208), [`ui/dr-ui/src/histogram.rs:228`](../ui/dr-ui/src/histogram.rs#L228), [`ui/dr-ui/src/histogram.rs:272`](../ui/dr-ui/src/histogram.rs#L272), [`ui/dr-ui/src/histogram.rs:544`](../ui/dr-ui/src/histogram.rs#L544), [`ui/dr-ui/src/histogram.rs:565`](../ui/dr-ui/src/histogram.rs#L565), [`ui/dr-ui/src/histogram.rs:593`](../ui/dr-ui/src/histogram.rs#L593), [`ui/dr-ui/src/histogram.rs:621`](../ui/dr-ui/src/histogram.rs#L621), [`ui/dr-ui/src/histogram.rs:658`](../ui/dr-ui/src/histogram.rs#L658), [`ui/dr-ui/src/lib.rs:1872`](../ui/dr-ui/src/lib.rs#L1872), [`ui/dr-ui/src/lib.rs:1980`](../ui/dr-ui/src/lib.rs#L1980), [`ui/dr-ui/src/lib.rs:2093`](../ui/dr-ui/src/lib.rs#L2093), [`ui/dr-ui/src/lib.rs:2134`](../ui/dr-ui/src/lib.rs#L2134), [`ui/dr-ui/src/lib.rs:3627`](../ui/dr-ui/src/lib.rs#L3627), [`ui/dr-ui/src/lib.rs:437`](../ui/dr-ui/src/lib.rs#L437), [`ui/dr-ui/src/peaking.rs:1`](../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:1944`](../ui/dr-ui/ui/app.slint#L1944), [`ui/dr-ui/ui/app.slint:2951`](../ui/dr-ui/ui/app.slint#L2951), [`ui/dr-ui/ui/app.slint:87`](../ui/dr-ui/ui/app.slint#L87), [`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), [`ui/dr-ui/ui/peaking.slint:91`](../ui/dr-ui/ui/peaking.slint#L91) | +| FR-CULL-4 | [`core/dr-catalog/src/rating.rs:1`](../core/dr-catalog/src/rating.rs#L1), [`core/dr-pipeline/src/sidecar.rs:156`](../core/dr-pipeline/src/sidecar.rs#L156), [`core/dr-xmp/src/lib.rs:442`](../core/dr-xmp/src/lib.rs#L442), [`ui/dr-ui/src/library.rs:254`](../ui/dr-ui/src/library.rs#L254), [`ui/dr-ui/src/library.rs:564`](../ui/dr-ui/src/library.rs#L564) | +| FR-CULL-5 | [`core/dr-catalog/src/bursts.rs:1`](../core/dr-catalog/src/bursts.rs#L1), [`core/dr-catalog/src/schema.rs:528`](../core/dr-catalog/src/schema.rs#L528), [`ui/dr-ui/src/bursts.rs:1`](../ui/dr-ui/src/bursts.rs#L1), [`ui/dr-ui/src/library.rs:210`](../ui/dr-ui/src/library.rs#L210), [`ui/dr-ui/src/library.rs:6840`](../ui/dr-ui/src/library.rs#L6840) | +| 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:596`](../core/dr-catalog/src/schema.rs#L596), [`core/dr-catalog/src/schema.rs:778`](../core/dr-catalog/src/schema.rs#L778), [`core/dr-catalog/src/schema.rs:819`](../core/dr-catalog/src/schema.rs#L819), [`core/dr-face/src/align.rs:296`](../core/dr-face/src/align.rs#L296), [`core/dr-types/src/settings.rs:176`](../core/dr-types/src/settings.rs#L176), [`ui/dr-ui/examples/face_detectors.rs:1`](../ui/dr-ui/examples/face_detectors.rs#L1), [`ui/dr-ui/examples/face_native.rs:1`](../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/derived_sync.rs:124`](../ui/dr-ui/src/derived_sync.rs#L124), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/faces.rs:403`](../ui/dr-ui/src/faces.rs#L403), [`ui/dr-ui/src/faces.rs:419`](../ui/dr-ui/src/faces.rs#L419), [`ui/dr-ui/src/faces.rs:539`](../ui/dr-ui/src/faces.rs#L539), [`ui/dr-ui/src/identity_ui.rs:555`](../ui/dr-ui/src/identity_ui.rs#L555), [`ui/dr-ui/src/lib.rs:1480`](../ui/dr-ui/src/lib.rs#L1480), [`ui/dr-ui/src/lib.rs:3882`](../ui/dr-ui/src/lib.rs#L3882), [`ui/dr-ui/src/library.rs:3595`](../ui/dr-ui/src/library.rs#L3595), [`ui/dr-ui/src/library.rs:3861`](../ui/dr-ui/src/library.rs#L3861), [`ui/dr-ui/src/library.rs:4123`](../ui/dr-ui/src/library.rs#L4123), [`ui/dr-ui/src/library.rs:4406`](../ui/dr-ui/src/library.rs#L4406), [`ui/dr-ui/src/library.rs:4603`](../ui/dr-ui/src/library.rs#L4603), [`ui/dr-ui/src/library.rs:4639`](../ui/dr-ui/src/library.rs#L4639), [`ui/dr-ui/src/library.rs:4721`](../ui/dr-ui/src/library.rs#L4721), [`ui/dr-ui/src/library.rs:7009`](../ui/dr-ui/src/library.rs#L7009), [`ui/dr-ui/src/library_ui.rs:406`](../ui/dr-ui/src/library_ui.rs#L406), [`ui/dr-ui/src/library_ui.rs:491`](../ui/dr-ui/src/library_ui.rs#L491), [`ui/dr-ui/src/settings_ui.rs:210`](../ui/dr-ui/src/settings_ui.rs#L210), [`ui/dr-ui/src/settings_ui.rs:552`](../ui/dr-ui/src/settings_ui.rs#L552), [`ui/dr-ui/ui/app.slint:902`](../ui/dr-ui/ui/app.slint#L902), [`ui/dr-ui/ui/settings.slint:457`](../ui/dr-ui/ui/settings.slint#L457), [`ui/dr-ui/ui/settings.slint:82`](../ui/dr-ui/ui/settings.slint#L82), [`ui/dr-ui/ui/settings.slint:94`](../ui/dr-ui/ui/settings.slint#L94) | +| FR-CULL-9 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:663`](../core/dr-catalog/src/schema.rs#L663), [`core/dr-catalog/src/schema.rs:819`](../core/dr-catalog/src/schema.rs#L819), [`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), [`core/dr-types/src/settings.rs:129`](../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/faces.rs:1`](../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/faces.rs:539`](../ui/dr-ui/src/faces.rs#L539), [`ui/dr-ui/src/identity_ui.rs:1`](../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/library.rs:3968`](../ui/dr-ui/src/library.rs#L3968), [`ui/dr-ui/src/library.rs:4721`](../ui/dr-ui/src/library.rs#L4721), [`ui/dr-ui/ui/identity.slint:341`](../ui/dr-ui/ui/identity.slint#L341) | | 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-10 | [`core/dr-gpu/src/mask.rs:1027`](../core/dr-gpu/src/mask.rs#L1027), [`core/dr-gpu/src/mask.rs:1251`](../core/dr-gpu/src/mask.rs#L1251), [`core/dr-gpu/src/mask.rs:1509`](../core/dr-gpu/src/mask.rs#L1509), [`core/dr-gpu/src/mask.rs:421`](../core/dr-gpu/src/mask.rs#L421), [`core/dr-gpu/src/mask.rs:463`](../core/dr-gpu/src/mask.rs#L463), [`core/dr-gpu/src/mask.rs:58`](../core/dr-gpu/src/mask.rs#L58), [`core/dr-gpu/src/mask.rs:60`](../core/dr-gpu/src/mask.rs#L60), [`core/dr-gpu/src/mask.rs:834`](../core/dr-gpu/src/mask.rs#L834), [`core/dr-gpu/src/mask.rs:85`](../core/dr-gpu/src/mask.rs#L85), [`core/dr-gpu/src/mask.rs:913`](../core/dr-gpu/src/mask.rs#L913), [`core/dr-gpu/src/shaders/mask.wgsl:117`](../core/dr-gpu/src/shaders/mask.wgsl#L117), [`core/dr-gpu/src/shaders/mask.wgsl:59`](../core/dr-gpu/src/shaders/mask.wgsl#L59), [`core/dr-gpu/tests/range_masks.rs:119`](../core/dr-gpu/tests/range_masks.rs#L119), [`core/dr-gpu/tests/range_masks.rs:147`](../core/dr-gpu/tests/range_masks.rs#L147), [`core/dr-gpu/tests/range_masks.rs:175`](../core/dr-gpu/tests/range_masks.rs#L175), [`core/dr-gpu/tests/range_masks.rs:1`](../core/dr-gpu/tests/range_masks.rs#L1), [`core/dr-gpu/tests/range_masks.rs:94`](../core/dr-gpu/tests/range_masks.rs#L94), [`core/dr-pipeline/src/mask.rs:125`](../core/dr-pipeline/src/mask.rs#L125), [`core/dr-pipeline/src/mask.rs:2845`](../core/dr-pipeline/src/mask.rs#L2845), [`core/dr-pipeline/src/mask.rs:2858`](../core/dr-pipeline/src/mask.rs#L2858), [`core/dr-pipeline/src/mask.rs:2877`](../core/dr-pipeline/src/mask.rs#L2877), [`core/dr-pipeline/src/mask.rs:2891`](../core/dr-pipeline/src/mask.rs#L2891), [`core/dr-pipeline/src/mask.rs:2901`](../core/dr-pipeline/src/mask.rs#L2901), [`core/dr-pipeline/src/mask.rs:710`](../core/dr-pipeline/src/mask.rs#L710), [`core/dr-pipeline/src/mask.rs:749`](../core/dr-pipeline/src/mask.rs#L749), [`core/dr-pipeline/src/mask.rs:809`](../core/dr-pipeline/src/mask.rs#L809), [`core/dr-pipeline/src/mask.rs:828`](../core/dr-pipeline/src/mask.rs#L828), [`core/dr-pipeline/src/mask.rs:852`](../core/dr-pipeline/src/mask.rs#L852), [`core/dr-pipeline/src/mask.rs:864`](../core/dr-pipeline/src/mask.rs#L864), [`core/dr-pipeline/src/mask.rs:876`](../core/dr-pipeline/src/mask.rs#L876), [`core/dr-pipeline/src/sidecar.rs:1309`](../core/dr-pipeline/src/sidecar.rs#L1309), [`core/dr-pipeline/src/sidecar.rs:1488`](../core/dr-pipeline/src/sidecar.rs#L1488), [`core/dr-pipeline/src/sidecar.rs:1577`](../core/dr-pipeline/src/sidecar.rs#L1577), [`core/dr-pipeline/src/sidecar.rs:1681`](../core/dr-pipeline/src/sidecar.rs#L1681), [`core/dr-pipeline/src/sidecar.rs:1889`](../core/dr-pipeline/src/sidecar.rs#L1889), [`core/dr-pipeline/tests/mask_sidecar.rs:1157`](../core/dr-pipeline/tests/mask_sidecar.rs#L1157), [`core/dr-pipeline/tests/mask_sidecar.rs:1186`](../core/dr-pipeline/tests/mask_sidecar.rs#L1186), [`core/dr-pipeline/tests/mask_sidecar.rs:1204`](../core/dr-pipeline/tests/mask_sidecar.rs#L1204), [`core/dr-pipeline/tests/mask_sidecar.rs:1234`](../core/dr-pipeline/tests/mask_sidecar.rs#L1234), [`ui/dr-ui/src/develop.rs:2318`](../ui/dr-ui/src/develop.rs#L2318), [`ui/dr-ui/src/develop.rs:3657`](../ui/dr-ui/src/develop.rs#L3657), [`ui/dr-ui/src/develop.rs:3684`](../ui/dr-ui/src/develop.rs#L3684), [`ui/dr-ui/src/develop.rs:3716`](../ui/dr-ui/src/develop.rs#L3716), [`ui/dr-ui/src/develop.rs:3740`](../ui/dr-ui/src/develop.rs#L3740), [`ui/dr-ui/src/develop.rs:3746`](../ui/dr-ui/src/develop.rs#L3746), [`ui/dr-ui/src/develop.rs:3753`](../ui/dr-ui/src/develop.rs#L3753), [`ui/dr-ui/src/develop.rs:3773`](../ui/dr-ui/src/develop.rs#L3773), [`ui/dr-ui/src/labels.rs:63`](../ui/dr-ui/src/labels.rs#L63), [`ui/dr-ui/src/masks_ui.rs:1150`](../ui/dr-ui/src/masks_ui.rs#L1150), [`ui/dr-ui/src/masks_ui.rs:748`](../ui/dr-ui/src/masks_ui.rs#L748) | | FR-DEV-12 | [`core/dr-pipeline/ops/colour_grading.yaml:1`](../core/dr-pipeline/ops/colour_grading.yaml#L1) | -| FR-DEV-16 | [`ui/dr-ui/src/lib.rs:418`](../ui/dr-ui/src/lib.rs#L418), [`ui/dr-ui/src/masks_ui.rs:670`](../ui/dr-ui/src/masks_ui.rs#L670), [`ui/dr-ui/ui/adjust.slint:998`](../ui/dr-ui/ui/adjust.slint#L998), [`ui/dr-ui/ui/app.slint:2530`](../ui/dr-ui/ui/app.slint#L2530), [`ui/dr-ui/ui/app.slint:2543`](../ui/dr-ui/ui/app.slint#L2543), [`ui/dr-ui/ui/masks.slint:824`](../ui/dr-ui/ui/masks.slint#L824) | +| FR-DEV-16 | [`ui/dr-ui/src/lib.rs:419`](../ui/dr-ui/src/lib.rs#L419), [`ui/dr-ui/src/masks_ui.rs:670`](../ui/dr-ui/src/masks_ui.rs#L670), [`ui/dr-ui/ui/adjust.slint:998`](../ui/dr-ui/ui/adjust.slint#L998), [`ui/dr-ui/ui/app.slint:2536`](../ui/dr-ui/ui/app.slint#L2536), [`ui/dr-ui/ui/app.slint:2549`](../ui/dr-ui/ui/app.slint#L2549), [`ui/dr-ui/ui/masks.slint:824`](../ui/dr-ui/ui/masks.slint#L824) | | FR-DEV-18 | [`core/dr-pipeline/src/ops/dehaze.rs:1`](../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:221`](../core/dr-pipeline/src/ops/dehaze.rs#L221) | | FR-DEV-19 | [`core/dr-pipeline/src/mask.rs:1307`](../core/dr-pipeline/src/mask.rs#L1307) | | FR-DEV-19a | [`core/dr-gpu/src/mask.rs:761`](../core/dr-gpu/src/mask.rs#L761), [`core/dr-pipeline/src/mask.rs:1588`](../core/dr-pipeline/src/mask.rs#L1588), [`core/dr-pipeline/src/mask.rs:2919`](../core/dr-pipeline/src/mask.rs#L2919), [`core/dr-pipeline/src/mask.rs:988`](../core/dr-pipeline/src/mask.rs#L988), [`core/dr-pipeline/src/sidecar.rs:1199`](../core/dr-pipeline/src/sidecar.rs#L1199), [`core/dr-pipeline/tests/mask_sidecar.rs:1347`](../core/dr-pipeline/tests/mask_sidecar.rs#L1347), [`core/dr-pipeline/tests/mask_sidecar.rs:1373`](../core/dr-pipeline/tests/mask_sidecar.rs#L1373), [`ui/dr-ui/src/develop.rs:2921`](../ui/dr-ui/src/develop.rs#L2921), [`ui/dr-ui/src/develop.rs:2982`](../ui/dr-ui/src/develop.rs#L2982), [`ui/dr-ui/src/develop.rs:3001`](../ui/dr-ui/src/develop.rs#L3001), [`ui/dr-ui/src/develop.rs:880`](../ui/dr-ui/src/develop.rs#L880), [`ui/dr-ui/src/labels.rs:73`](../ui/dr-ui/src/labels.rs#L73), [`ui/dr-ui/src/masks_ui.rs:1017`](../ui/dr-ui/src/masks_ui.rs#L1017), [`ui/dr-ui/src/masks_ui.rs:1089`](../ui/dr-ui/src/masks_ui.rs#L1089), [`ui/dr-ui/src/masks_ui.rs:1448`](../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:270`](../ui/dr-ui/src/masks_ui.rs#L270), [`ui/dr-ui/ui/masks.slint:150`](../ui/dr-ui/ui/masks.slint#L150), [`ui/dr-ui/ui/masks.slint:175`](../ui/dr-ui/ui/masks.slint#L175), [`ui/dr-ui/ui/masks.slint:337`](../ui/dr-ui/ui/masks.slint#L337), [`ui/dr-ui/ui/masks.slint:406`](../ui/dr-ui/ui/masks.slint#L406), [`ui/dr-ui/ui/masks.slint:762`](../ui/dr-ui/ui/masks.slint#L762), [`ui/dr-ui/ui/masks.slint:847`](../ui/dr-ui/ui/masks.slint#L847) | -| FR-DEV-19b | [`ui/dr-ui/src/develop.rs:3082`](../ui/dr-ui/src/develop.rs#L3082), [`ui/dr-ui/src/develop.rs:3625`](../ui/dr-ui/src/develop.rs#L3625), [`ui/dr-ui/src/develop.rs:889`](../ui/dr-ui/src/develop.rs#L889), [`ui/dr-ui/src/develop.rs:896`](../ui/dr-ui/src/develop.rs#L896), [`ui/dr-ui/src/labels.rs:67`](../ui/dr-ui/src/labels.rs#L67), [`ui/dr-ui/src/masks_ui.rs:1122`](../ui/dr-ui/src/masks_ui.rs#L1122), [`ui/dr-ui/src/masks_ui.rs:1341`](../ui/dr-ui/src/masks_ui.rs#L1341), [`ui/dr-ui/src/masks_ui.rs:1369`](../ui/dr-ui/src/masks_ui.rs#L1369), [`ui/dr-ui/src/masks_ui.rs:1712`](../ui/dr-ui/src/masks_ui.rs#L1712), [`ui/dr-ui/src/masks_ui.rs:858`](../ui/dr-ui/src/masks_ui.rs#L858), [`ui/dr-ui/ui/app.slint:1008`](../ui/dr-ui/ui/app.slint#L1008), [`ui/dr-ui/ui/app.slint:2170`](../ui/dr-ui/ui/app.slint#L2170), [`ui/dr-ui/ui/masks.slint:1118`](../ui/dr-ui/ui/masks.slint#L1118), [`ui/dr-ui/ui/masks.slint:453`](../ui/dr-ui/ui/masks.slint#L453), [`ui/dr-ui/ui/masks.slint:766`](../ui/dr-ui/ui/masks.slint#L766), [`ui/dr-ui/ui/masks.slint:840`](../ui/dr-ui/ui/masks.slint#L840), [`ui/dr-ui/ui/masks.slint:856`](../ui/dr-ui/ui/masks.slint#L856) | +| FR-DEV-19b | [`ui/dr-ui/src/develop.rs:3082`](../ui/dr-ui/src/develop.rs#L3082), [`ui/dr-ui/src/develop.rs:3625`](../ui/dr-ui/src/develop.rs#L3625), [`ui/dr-ui/src/develop.rs:889`](../ui/dr-ui/src/develop.rs#L889), [`ui/dr-ui/src/develop.rs:896`](../ui/dr-ui/src/develop.rs#L896), [`ui/dr-ui/src/labels.rs:67`](../ui/dr-ui/src/labels.rs#L67), [`ui/dr-ui/src/masks_ui.rs:1122`](../ui/dr-ui/src/masks_ui.rs#L1122), [`ui/dr-ui/src/masks_ui.rs:1341`](../ui/dr-ui/src/masks_ui.rs#L1341), [`ui/dr-ui/src/masks_ui.rs:1369`](../ui/dr-ui/src/masks_ui.rs#L1369), [`ui/dr-ui/src/masks_ui.rs:1712`](../ui/dr-ui/src/masks_ui.rs#L1712), [`ui/dr-ui/src/masks_ui.rs:858`](../ui/dr-ui/src/masks_ui.rs#L858), [`ui/dr-ui/ui/app.slint:1012`](../ui/dr-ui/ui/app.slint#L1012), [`ui/dr-ui/ui/app.slint:2176`](../ui/dr-ui/ui/app.slint#L2176), [`ui/dr-ui/ui/masks.slint:1118`](../ui/dr-ui/ui/masks.slint#L1118), [`ui/dr-ui/ui/masks.slint:453`](../ui/dr-ui/ui/masks.slint#L453), [`ui/dr-ui/ui/masks.slint:766`](../ui/dr-ui/ui/masks.slint#L766), [`ui/dr-ui/ui/masks.slint:840`](../ui/dr-ui/ui/masks.slint#L840), [`ui/dr-ui/ui/masks.slint:856`](../ui/dr-ui/ui/masks.slint#L856) | | FR-DEV-19c | [`core/dr-gpu/src/mask.rs:715`](../core/dr-gpu/src/mask.rs#L715), [`core/dr-gpu/tests/local_adjustments.rs:830`](../core/dr-gpu/tests/local_adjustments.rs#L830), [`core/dr-gpu/tests/local_adjustments.rs:887`](../core/dr-gpu/tests/local_adjustments.rs#L887), [`core/dr-gpu/tests/local_adjustments.rs:922`](../core/dr-gpu/tests/local_adjustments.rs#L922), [`core/dr-gpu/tests/local_adjustments.rs:967`](../core/dr-gpu/tests/local_adjustments.rs#L967), [`core/dr-pipeline/src/graph.rs:852`](../core/dr-pipeline/src/graph.rs#L852), [`core/dr-pipeline/src/mask.rs:1796`](../core/dr-pipeline/src/mask.rs#L1796), [`core/dr-pipeline/src/mask.rs:1822`](../core/dr-pipeline/src/mask.rs#L1822), [`core/dr-pipeline/src/mask.rs:1837`](../core/dr-pipeline/src/mask.rs#L1837), [`core/dr-pipeline/src/mask.rs:1957`](../core/dr-pipeline/src/mask.rs#L1957), [`core/dr-pipeline/src/mask.rs:2005`](../core/dr-pipeline/src/mask.rs#L2005), [`core/dr-pipeline/src/mask.rs:2149`](../core/dr-pipeline/src/mask.rs#L2149), [`core/dr-pipeline/src/mask.rs:2386`](../core/dr-pipeline/src/mask.rs#L2386), [`core/dr-pipeline/src/operation.rs:1600`](../core/dr-pipeline/src/operation.rs#L1600), [`core/dr-pipeline/src/operation.rs:558`](../core/dr-pipeline/src/operation.rs#L558), [`core/dr-pipeline/src/operation.rs:741`](../core/dr-pipeline/src/operation.rs#L741), [`ui/dr-ui/src/develop.rs:2035`](../ui/dr-ui/src/develop.rs#L2035), [`ui/dr-ui/src/develop.rs:2295`](../ui/dr-ui/src/develop.rs#L2295), [`ui/dr-ui/src/develop.rs:2542`](../ui/dr-ui/src/develop.rs#L2542), [`ui/dr-ui/src/develop.rs:2666`](../ui/dr-ui/src/develop.rs#L2666), [`ui/dr-ui/src/develop.rs:4059`](../ui/dr-ui/src/develop.rs#L4059), [`ui/dr-ui/src/develop.rs:686`](../ui/dr-ui/src/develop.rs#L686), [`ui/dr-ui/src/develop.rs:695`](../ui/dr-ui/src/develop.rs#L695), [`ui/dr-ui/src/develop.rs:6995`](../ui/dr-ui/src/develop.rs#L6995), [`ui/dr-ui/src/develop.rs:7031`](../ui/dr-ui/src/develop.rs#L7031), [`ui/dr-ui/src/develop.rs:915`](../ui/dr-ui/src/develop.rs#L915), [`ui/dr-ui/src/develop.rs:924`](../ui/dr-ui/src/develop.rs#L924), [`ui/dr-ui/src/masks_ui.rs:1341`](../ui/dr-ui/src/masks_ui.rs#L1341), [`ui/dr-ui/src/masks_ui.rs:152`](../ui/dr-ui/src/masks_ui.rs#L152), [`ui/dr-ui/src/masks_ui.rs:1712`](../ui/dr-ui/src/masks_ui.rs#L1712), [`ui/dr-ui/src/masks_ui.rs:291`](../ui/dr-ui/src/masks_ui.rs#L291), [`ui/dr-ui/src/masks_ui.rs:317`](../ui/dr-ui/src/masks_ui.rs#L317), [`ui/dr-ui/src/masks_ui.rs:634`](../ui/dr-ui/src/masks_ui.rs#L634), [`ui/dr-ui/src/masks_ui.rs:940`](../ui/dr-ui/src/masks_ui.rs#L940), [`ui/dr-ui/src/masks_ui.rs:968`](../ui/dr-ui/src/masks_ui.rs#L968), [`ui/dr-ui/ui/icons.slint:339`](../ui/dr-ui/ui/icons.slint#L339), [`ui/dr-ui/ui/masks.slint:1083`](../ui/dr-ui/ui/masks.slint#L1083), [`ui/dr-ui/ui/masks.slint:183`](../ui/dr-ui/ui/masks.slint#L183), [`ui/dr-ui/ui/masks.slint:292`](../ui/dr-ui/ui/masks.slint#L292), [`ui/dr-ui/ui/masks.slint:517`](../ui/dr-ui/ui/masks.slint#L517), [`ui/dr-ui/ui/masks.slint:70`](../ui/dr-ui/ui/masks.slint#L70), [`ui/dr-ui/ui/masks.slint:774`](../ui/dr-ui/ui/masks.slint#L774), [`ui/dr-ui/ui/masks.slint:842`](../ui/dr-ui/ui/masks.slint#L842), [`ui/dr-ui/ui/masks.slint:930`](../ui/dr-ui/ui/masks.slint#L930) | | FR-DEV-2 | [`core/dr-pipeline/src/operation.rs:403`](../core/dr-pipeline/src/operation.rs#L403) | -| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:2217`](../core/dr-gpu/src/adjust.rs#L2217), [`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/coverage.rs:122`](../core/dr-pipeline/src/coverage.rs#L122), [`core/dr-pipeline/src/coverage.rs:1`](../core/dr-pipeline/src/coverage.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:498`](../core/dr-pipeline/src/framing.rs#L498), [`core/dr-pipeline/src/framing.rs:753`](../core/dr-pipeline/src/framing.rs#L753), [`core/dr-pipeline/src/graph.rs:1307`](../core/dr-pipeline/src/graph.rs#L1307), [`core/dr-pipeline/src/graph.rs:1338`](../core/dr-pipeline/src/graph.rs#L1338), [`core/dr-pipeline/src/graph.rs:1361`](../core/dr-pipeline/src/graph.rs#L1361), [`core/dr-pipeline/src/graph.rs:1399`](../core/dr-pipeline/src/graph.rs#L1399), [`core/dr-pipeline/src/graph.rs:1430`](../core/dr-pipeline/src/graph.rs#L1430), [`core/dr-pipeline/src/graph.rs:225`](../core/dr-pipeline/src/graph.rs#L225), [`core/dr-pipeline/src/graph.rs:306`](../core/dr-pipeline/src/graph.rs#L306), [`core/dr-pipeline/src/graph.rs:344`](../core/dr-pipeline/src/graph.rs#L344), [`core/dr-pipeline/src/graph.rs:350`](../core/dr-pipeline/src/graph.rs#L350), [`core/dr-pipeline/src/graph.rs:911`](../core/dr-pipeline/src/graph.rs#L911), [`core/dr-pipeline/src/lens.rs:93`](../core/dr-pipeline/src/lens.rs#L93), [`core/dr-pipeline/src/mask.rs:205`](../core/dr-pipeline/src/mask.rs#L205), [`core/dr-pipeline/src/mask.rs:558`](../core/dr-pipeline/src/mask.rs#L558), [`core/dr-pipeline/src/neutral.rs:1`](../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:300`](../core/dr-pipeline/src/neutral.rs#L300), [`core/dr-pipeline/src/neutral.rs:316`](../core/dr-pipeline/src/neutral.rs#L316), [`core/dr-pipeline/src/neutral.rs:332`](../core/dr-pipeline/src/neutral.rs#L332), [`core/dr-pipeline/src/neutral.rs:354`](../core/dr-pipeline/src/neutral.rs#L354), [`core/dr-pipeline/src/neutral.rs:79`](../core/dr-pipeline/src/neutral.rs#L79), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:535`](../core/dr-pipeline/src/operation.rs#L535), [`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/preset.rs:751`](../core/dr-pipeline/src/preset.rs#L751), [`core/dr-pipeline/src/sidecar.rs:1373`](../core/dr-pipeline/src/sidecar.rs#L1373), [`core/dr-pipeline/src/sidecar.rs:177`](../core/dr-pipeline/src/sidecar.rs#L177), [`core/dr-pipeline/src/sidecar.rs:2205`](../core/dr-pipeline/src/sidecar.rs#L2205), [`core/dr-pipeline/src/sidecar.rs:2265`](../core/dr-pipeline/src/sidecar.rs#L2265), [`core/dr-pipeline/tests/tone_curve.rs:1`](../core/dr-pipeline/tests/tone_curve.rs#L1), [`core/dr-segment/src/refine.rs:937`](../core/dr-segment/src/refine.rs#L937), [`ui/dr-ui/src/develop.rs:103`](../ui/dr-ui/src/develop.rs#L103), [`ui/dr-ui/src/develop.rs:1318`](../ui/dr-ui/src/develop.rs#L1318), [`ui/dr-ui/src/develop.rs:1407`](../ui/dr-ui/src/develop.rs#L1407), [`ui/dr-ui/src/develop.rs:1443`](../ui/dr-ui/src/develop.rs#L1443), [`ui/dr-ui/src/develop.rs:165`](../ui/dr-ui/src/develop.rs#L165), [`ui/dr-ui/src/develop.rs:1714`](../ui/dr-ui/src/develop.rs#L1714), [`ui/dr-ui/src/develop.rs:2155`](../ui/dr-ui/src/develop.rs#L2155), [`ui/dr-ui/src/develop.rs:2398`](../ui/dr-ui/src/develop.rs#L2398), [`ui/dr-ui/src/develop.rs:2416`](../ui/dr-ui/src/develop.rs#L2416), [`ui/dr-ui/src/develop.rs:2430`](../ui/dr-ui/src/develop.rs#L2430), [`ui/dr-ui/src/develop.rs:2452`](../ui/dr-ui/src/develop.rs#L2452), [`ui/dr-ui/src/develop.rs:2752`](../ui/dr-ui/src/develop.rs#L2752), [`ui/dr-ui/src/develop.rs:2850`](../ui/dr-ui/src/develop.rs#L2850), [`ui/dr-ui/src/develop.rs:328`](../ui/dr-ui/src/develop.rs#L328), [`ui/dr-ui/src/develop.rs:365`](../ui/dr-ui/src/develop.rs#L365), [`ui/dr-ui/src/develop.rs:4400`](../ui/dr-ui/src/develop.rs#L4400), [`ui/dr-ui/src/develop.rs:4556`](../ui/dr-ui/src/develop.rs#L4556), [`ui/dr-ui/src/develop.rs:4616`](../ui/dr-ui/src/develop.rs#L4616), [`ui/dr-ui/src/develop.rs:5021`](../ui/dr-ui/src/develop.rs#L5021), [`ui/dr-ui/src/develop.rs:5051`](../ui/dr-ui/src/develop.rs#L5051), [`ui/dr-ui/src/develop.rs:5117`](../ui/dr-ui/src/develop.rs#L5117), [`ui/dr-ui/src/develop.rs:5131`](../ui/dr-ui/src/develop.rs#L5131), [`ui/dr-ui/src/develop.rs:5333`](../ui/dr-ui/src/develop.rs#L5333), [`ui/dr-ui/src/develop.rs:5421`](../ui/dr-ui/src/develop.rs#L5421), [`ui/dr-ui/src/develop.rs:588`](../ui/dr-ui/src/develop.rs#L588), [`ui/dr-ui/src/develop.rs:6367`](../ui/dr-ui/src/develop.rs#L6367), [`ui/dr-ui/src/develop.rs:6440`](../ui/dr-ui/src/develop.rs#L6440), [`ui/dr-ui/src/develop.rs:649`](../ui/dr-ui/src/develop.rs#L649), [`ui/dr-ui/src/develop.rs:6633`](../ui/dr-ui/src/develop.rs#L6633), [`ui/dr-ui/src/develop.rs:6824`](../ui/dr-ui/src/develop.rs#L6824), [`ui/dr-ui/src/develop.rs:6980`](../ui/dr-ui/src/develop.rs#L6980), [`ui/dr-ui/src/develop.rs:7136`](../ui/dr-ui/src/develop.rs#L7136), [`ui/dr-ui/src/develop.rs:7180`](../ui/dr-ui/src/develop.rs#L7180), [`ui/dr-ui/src/develop.rs:7230`](../ui/dr-ui/src/develop.rs#L7230), [`ui/dr-ui/src/develop.rs:7655`](../ui/dr-ui/src/develop.rs#L7655), [`ui/dr-ui/src/develop.rs:8383`](../ui/dr-ui/src/develop.rs#L8383), [`ui/dr-ui/src/develop.rs:850`](../ui/dr-ui/src/develop.rs#L850), [`ui/dr-ui/src/develop.rs:943`](../ui/dr-ui/src/develop.rs#L943), [`ui/dr-ui/src/develop.rs:972`](../ui/dr-ui/src/develop.rs#L972), [`ui/dr-ui/src/labels.rs:35`](../ui/dr-ui/src/labels.rs#L35), [`ui/dr-ui/src/lib.rs:1960`](../ui/dr-ui/src/lib.rs#L1960), [`ui/dr-ui/src/lib.rs:2840`](../ui/dr-ui/src/lib.rs#L2840), [`ui/dr-ui/src/lib.rs:3047`](../ui/dr-ui/src/lib.rs#L3047), [`ui/dr-ui/src/lib.rs:3180`](../ui/dr-ui/src/lib.rs#L3180), [`ui/dr-ui/src/lib.rs:3385`](../ui/dr-ui/src/lib.rs#L3385), [`ui/dr-ui/src/lib.rs:3449`](../ui/dr-ui/src/lib.rs#L3449), [`ui/dr-ui/src/lib.rs:3503`](../ui/dr-ui/src/lib.rs#L3503), [`ui/dr-ui/src/lib.rs:413`](../ui/dr-ui/src/lib.rs#L413), [`ui/dr-ui/src/lib.rs:442`](../ui/dr-ui/src/lib.rs#L442), [`ui/dr-ui/src/lib.rs:548`](../ui/dr-ui/src/lib.rs#L548), [`ui/dr-ui/src/lib.rs:572`](../ui/dr-ui/src/lib.rs#L572), [`ui/dr-ui/src/library.rs:552`](../ui/dr-ui/src/library.rs#L552), [`ui/dr-ui/src/masks_ui.rs:1471`](../ui/dr-ui/src/masks_ui.rs#L1471), [`ui/dr-ui/src/masks_ui.rs:1585`](../ui/dr-ui/src/masks_ui.rs#L1585), [`ui/dr-ui/src/masks_ui.rs:339`](../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/masks_ui.rs:44`](../ui/dr-ui/src/masks_ui.rs#L44), [`ui/dr-ui/src/presets.rs:414`](../ui/dr-ui/src/presets.rs#L414), [`ui/dr-ui/src/segmentation.rs:117`](../ui/dr-ui/src/segmentation.rs#L117), [`ui/dr-ui/src/segmentation.rs:353`](../ui/dr-ui/src/segmentation.rs#L353), [`ui/dr-ui/src/segmentation.rs:369`](../ui/dr-ui/src/segmentation.rs#L369), [`ui/dr-ui/src/segmentation.rs:499`](../ui/dr-ui/src/segmentation.rs#L499), [`ui/dr-ui/src/segmentation.rs:527`](../ui/dr-ui/src/segmentation.rs#L527), [`ui/dr-ui/ui/adjust.slint:1019`](../ui/dr-ui/ui/adjust.slint#L1019), [`ui/dr-ui/ui/adjust.slint:126`](../ui/dr-ui/ui/adjust.slint#L126), [`ui/dr-ui/ui/adjust.slint:1496`](../ui/dr-ui/ui/adjust.slint#L1496), [`ui/dr-ui/ui/adjust.slint:171`](../ui/dr-ui/ui/adjust.slint#L171), [`ui/dr-ui/ui/adjust.slint:46`](../ui/dr-ui/ui/adjust.slint#L46), [`ui/dr-ui/ui/adjust.slint:624`](../ui/dr-ui/ui/adjust.slint#L624), [`ui/dr-ui/ui/adjust.slint:650`](../ui/dr-ui/ui/adjust.slint#L650), [`ui/dr-ui/ui/adjust.slint:669`](../ui/dr-ui/ui/adjust.slint#L669), [`ui/dr-ui/ui/adjust.slint:790`](../ui/dr-ui/ui/adjust.slint#L790), [`ui/dr-ui/ui/adjust.slint:947`](../ui/dr-ui/ui/adjust.slint#L947), [`ui/dr-ui/ui/app.slint:146`](../ui/dr-ui/ui/app.slint#L146), [`ui/dr-ui/ui/app.slint:2235`](../ui/dr-ui/ui/app.slint#L2235), [`ui/dr-ui/ui/app.slint:2295`](../ui/dr-ui/ui/app.slint#L2295), [`ui/dr-ui/ui/develop.slint:223`](../ui/dr-ui/ui/develop.slint#L223), [`ui/dr-ui/ui/masks.slint:1208`](../ui/dr-ui/ui/masks.slint#L1208), [`ui/dr-ui/ui/masks.slint:745`](../ui/dr-ui/ui/masks.slint#L745), [`ui/dr-ui/ui/masks.slint:804`](../ui/dr-ui/ui/masks.slint#L804) | -| FR-DEV-3a | [`core/dr-pipeline/ops/exposure.yaml:1`](../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/descriptor.rs:212`](../core/dr-pipeline/src/descriptor.rs#L212), [`core/dr-pipeline/src/descriptor.rs:252`](../core/dr-pipeline/src/descriptor.rs#L252), [`core/dr-pipeline/src/descriptor.rs:276`](../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/descriptor.rs:331`](../core/dr-pipeline/src/descriptor.rs#L331), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-pipeline/src/graph.rs:25`](../core/dr-pipeline/src/graph.rs#L25), [`core/dr-pipeline/src/graph.rs:393`](../core/dr-pipeline/src/graph.rs#L393), [`core/dr-pipeline/src/graph.rs:47`](../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/graph.rs:534`](../core/dr-pipeline/src/graph.rs#L534), [`core/dr-pipeline/src/graph.rs:60`](../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/mask.rs:1699`](../core/dr-pipeline/src/mask.rs#L1699), [`core/dr-pipeline/src/neutral.rs:1`](../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:372`](../core/dr-pipeline/src/neutral.rs#L372), [`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:1330`](../ui/dr-ui/src/develop.rs#L1330), [`ui/dr-ui/src/develop.rs:1609`](../ui/dr-ui/src/develop.rs#L1609), [`ui/dr-ui/src/develop.rs:7655`](../ui/dr-ui/src/develop.rs#L7655), [`ui/dr-ui/src/develop.rs:7853`](../ui/dr-ui/src/develop.rs#L7853), [`ui/dr-ui/src/lib.rs:873`](../ui/dr-ui/src/lib.rs#L873), [`ui/dr-ui/tests/ui_names_no_operation.rs:1`](../ui/dr-ui/tests/ui_names_no_operation.rs#L1), [`ui/dr-ui/ui/app.slint:2479`](../ui/dr-ui/ui/app.slint#L2479) | -| FR-DEV-3b | [`core/dr-pipeline/src/descriptor.rs:276`](../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-pipeline/src/graph.rs:60`](../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/operation.rs:365`](../core/dr-pipeline/src/operation.rs#L365), [`ui/dr-ui/ui/app.slint:2690`](../ui/dr-ui/ui/app.slint#L2690) | +| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:2217`](../core/dr-gpu/src/adjust.rs#L2217), [`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/coverage.rs:122`](../core/dr-pipeline/src/coverage.rs#L122), [`core/dr-pipeline/src/coverage.rs:1`](../core/dr-pipeline/src/coverage.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:498`](../core/dr-pipeline/src/framing.rs#L498), [`core/dr-pipeline/src/framing.rs:753`](../core/dr-pipeline/src/framing.rs#L753), [`core/dr-pipeline/src/graph.rs:1307`](../core/dr-pipeline/src/graph.rs#L1307), [`core/dr-pipeline/src/graph.rs:1338`](../core/dr-pipeline/src/graph.rs#L1338), [`core/dr-pipeline/src/graph.rs:1361`](../core/dr-pipeline/src/graph.rs#L1361), [`core/dr-pipeline/src/graph.rs:1399`](../core/dr-pipeline/src/graph.rs#L1399), [`core/dr-pipeline/src/graph.rs:1430`](../core/dr-pipeline/src/graph.rs#L1430), [`core/dr-pipeline/src/graph.rs:225`](../core/dr-pipeline/src/graph.rs#L225), [`core/dr-pipeline/src/graph.rs:306`](../core/dr-pipeline/src/graph.rs#L306), [`core/dr-pipeline/src/graph.rs:344`](../core/dr-pipeline/src/graph.rs#L344), [`core/dr-pipeline/src/graph.rs:350`](../core/dr-pipeline/src/graph.rs#L350), [`core/dr-pipeline/src/graph.rs:911`](../core/dr-pipeline/src/graph.rs#L911), [`core/dr-pipeline/src/lens.rs:93`](../core/dr-pipeline/src/lens.rs#L93), [`core/dr-pipeline/src/mask.rs:205`](../core/dr-pipeline/src/mask.rs#L205), [`core/dr-pipeline/src/mask.rs:558`](../core/dr-pipeline/src/mask.rs#L558), [`core/dr-pipeline/src/neutral.rs:1`](../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:300`](../core/dr-pipeline/src/neutral.rs#L300), [`core/dr-pipeline/src/neutral.rs:316`](../core/dr-pipeline/src/neutral.rs#L316), [`core/dr-pipeline/src/neutral.rs:332`](../core/dr-pipeline/src/neutral.rs#L332), [`core/dr-pipeline/src/neutral.rs:354`](../core/dr-pipeline/src/neutral.rs#L354), [`core/dr-pipeline/src/neutral.rs:79`](../core/dr-pipeline/src/neutral.rs#L79), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:535`](../core/dr-pipeline/src/operation.rs#L535), [`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/preset.rs:751`](../core/dr-pipeline/src/preset.rs#L751), [`core/dr-pipeline/src/sidecar.rs:1373`](../core/dr-pipeline/src/sidecar.rs#L1373), [`core/dr-pipeline/src/sidecar.rs:177`](../core/dr-pipeline/src/sidecar.rs#L177), [`core/dr-pipeline/src/sidecar.rs:2205`](../core/dr-pipeline/src/sidecar.rs#L2205), [`core/dr-pipeline/src/sidecar.rs:2265`](../core/dr-pipeline/src/sidecar.rs#L2265), [`core/dr-pipeline/tests/tone_curve.rs:1`](../core/dr-pipeline/tests/tone_curve.rs#L1), [`core/dr-segment/src/refine.rs:937`](../core/dr-segment/src/refine.rs#L937), [`ui/dr-ui/src/develop.rs:103`](../ui/dr-ui/src/develop.rs#L103), [`ui/dr-ui/src/develop.rs:1318`](../ui/dr-ui/src/develop.rs#L1318), [`ui/dr-ui/src/develop.rs:1407`](../ui/dr-ui/src/develop.rs#L1407), [`ui/dr-ui/src/develop.rs:1443`](../ui/dr-ui/src/develop.rs#L1443), [`ui/dr-ui/src/develop.rs:165`](../ui/dr-ui/src/develop.rs#L165), [`ui/dr-ui/src/develop.rs:1714`](../ui/dr-ui/src/develop.rs#L1714), [`ui/dr-ui/src/develop.rs:2155`](../ui/dr-ui/src/develop.rs#L2155), [`ui/dr-ui/src/develop.rs:2398`](../ui/dr-ui/src/develop.rs#L2398), [`ui/dr-ui/src/develop.rs:2416`](../ui/dr-ui/src/develop.rs#L2416), [`ui/dr-ui/src/develop.rs:2430`](../ui/dr-ui/src/develop.rs#L2430), [`ui/dr-ui/src/develop.rs:2452`](../ui/dr-ui/src/develop.rs#L2452), [`ui/dr-ui/src/develop.rs:2752`](../ui/dr-ui/src/develop.rs#L2752), [`ui/dr-ui/src/develop.rs:2850`](../ui/dr-ui/src/develop.rs#L2850), [`ui/dr-ui/src/develop.rs:328`](../ui/dr-ui/src/develop.rs#L328), [`ui/dr-ui/src/develop.rs:365`](../ui/dr-ui/src/develop.rs#L365), [`ui/dr-ui/src/develop.rs:4400`](../ui/dr-ui/src/develop.rs#L4400), [`ui/dr-ui/src/develop.rs:4556`](../ui/dr-ui/src/develop.rs#L4556), [`ui/dr-ui/src/develop.rs:4616`](../ui/dr-ui/src/develop.rs#L4616), [`ui/dr-ui/src/develop.rs:5021`](../ui/dr-ui/src/develop.rs#L5021), [`ui/dr-ui/src/develop.rs:5051`](../ui/dr-ui/src/develop.rs#L5051), [`ui/dr-ui/src/develop.rs:5117`](../ui/dr-ui/src/develop.rs#L5117), [`ui/dr-ui/src/develop.rs:5131`](../ui/dr-ui/src/develop.rs#L5131), [`ui/dr-ui/src/develop.rs:5333`](../ui/dr-ui/src/develop.rs#L5333), [`ui/dr-ui/src/develop.rs:5421`](../ui/dr-ui/src/develop.rs#L5421), [`ui/dr-ui/src/develop.rs:588`](../ui/dr-ui/src/develop.rs#L588), [`ui/dr-ui/src/develop.rs:6367`](../ui/dr-ui/src/develop.rs#L6367), [`ui/dr-ui/src/develop.rs:6440`](../ui/dr-ui/src/develop.rs#L6440), [`ui/dr-ui/src/develop.rs:649`](../ui/dr-ui/src/develop.rs#L649), [`ui/dr-ui/src/develop.rs:6633`](../ui/dr-ui/src/develop.rs#L6633), [`ui/dr-ui/src/develop.rs:6824`](../ui/dr-ui/src/develop.rs#L6824), [`ui/dr-ui/src/develop.rs:6980`](../ui/dr-ui/src/develop.rs#L6980), [`ui/dr-ui/src/develop.rs:7136`](../ui/dr-ui/src/develop.rs#L7136), [`ui/dr-ui/src/develop.rs:7180`](../ui/dr-ui/src/develop.rs#L7180), [`ui/dr-ui/src/develop.rs:7230`](../ui/dr-ui/src/develop.rs#L7230), [`ui/dr-ui/src/develop.rs:7655`](../ui/dr-ui/src/develop.rs#L7655), [`ui/dr-ui/src/develop.rs:8383`](../ui/dr-ui/src/develop.rs#L8383), [`ui/dr-ui/src/develop.rs:850`](../ui/dr-ui/src/develop.rs#L850), [`ui/dr-ui/src/develop.rs:943`](../ui/dr-ui/src/develop.rs#L943), [`ui/dr-ui/src/develop.rs:972`](../ui/dr-ui/src/develop.rs#L972), [`ui/dr-ui/src/labels.rs:35`](../ui/dr-ui/src/labels.rs#L35), [`ui/dr-ui/src/lib.rs:1961`](../ui/dr-ui/src/lib.rs#L1961), [`ui/dr-ui/src/lib.rs:2841`](../ui/dr-ui/src/lib.rs#L2841), [`ui/dr-ui/src/lib.rs:3048`](../ui/dr-ui/src/lib.rs#L3048), [`ui/dr-ui/src/lib.rs:3181`](../ui/dr-ui/src/lib.rs#L3181), [`ui/dr-ui/src/lib.rs:3386`](../ui/dr-ui/src/lib.rs#L3386), [`ui/dr-ui/src/lib.rs:3450`](../ui/dr-ui/src/lib.rs#L3450), [`ui/dr-ui/src/lib.rs:3504`](../ui/dr-ui/src/lib.rs#L3504), [`ui/dr-ui/src/lib.rs:414`](../ui/dr-ui/src/lib.rs#L414), [`ui/dr-ui/src/lib.rs:443`](../ui/dr-ui/src/lib.rs#L443), [`ui/dr-ui/src/lib.rs:549`](../ui/dr-ui/src/lib.rs#L549), [`ui/dr-ui/src/lib.rs:573`](../ui/dr-ui/src/lib.rs#L573), [`ui/dr-ui/src/library.rs:616`](../ui/dr-ui/src/library.rs#L616), [`ui/dr-ui/src/masks_ui.rs:1471`](../ui/dr-ui/src/masks_ui.rs#L1471), [`ui/dr-ui/src/masks_ui.rs:1585`](../ui/dr-ui/src/masks_ui.rs#L1585), [`ui/dr-ui/src/masks_ui.rs:339`](../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/masks_ui.rs:44`](../ui/dr-ui/src/masks_ui.rs#L44), [`ui/dr-ui/src/presets.rs:414`](../ui/dr-ui/src/presets.rs#L414), [`ui/dr-ui/src/segmentation.rs:117`](../ui/dr-ui/src/segmentation.rs#L117), [`ui/dr-ui/src/segmentation.rs:353`](../ui/dr-ui/src/segmentation.rs#L353), [`ui/dr-ui/src/segmentation.rs:369`](../ui/dr-ui/src/segmentation.rs#L369), [`ui/dr-ui/src/segmentation.rs:499`](../ui/dr-ui/src/segmentation.rs#L499), [`ui/dr-ui/src/segmentation.rs:527`](../ui/dr-ui/src/segmentation.rs#L527), [`ui/dr-ui/ui/adjust.slint:1019`](../ui/dr-ui/ui/adjust.slint#L1019), [`ui/dr-ui/ui/adjust.slint:126`](../ui/dr-ui/ui/adjust.slint#L126), [`ui/dr-ui/ui/adjust.slint:1496`](../ui/dr-ui/ui/adjust.slint#L1496), [`ui/dr-ui/ui/adjust.slint:171`](../ui/dr-ui/ui/adjust.slint#L171), [`ui/dr-ui/ui/adjust.slint:46`](../ui/dr-ui/ui/adjust.slint#L46), [`ui/dr-ui/ui/adjust.slint:624`](../ui/dr-ui/ui/adjust.slint#L624), [`ui/dr-ui/ui/adjust.slint:650`](../ui/dr-ui/ui/adjust.slint#L650), [`ui/dr-ui/ui/adjust.slint:669`](../ui/dr-ui/ui/adjust.slint#L669), [`ui/dr-ui/ui/adjust.slint:790`](../ui/dr-ui/ui/adjust.slint#L790), [`ui/dr-ui/ui/adjust.slint:947`](../ui/dr-ui/ui/adjust.slint#L947), [`ui/dr-ui/ui/app.slint:146`](../ui/dr-ui/ui/app.slint#L146), [`ui/dr-ui/ui/app.slint:2241`](../ui/dr-ui/ui/app.slint#L2241), [`ui/dr-ui/ui/app.slint:2301`](../ui/dr-ui/ui/app.slint#L2301), [`ui/dr-ui/ui/develop.slint:223`](../ui/dr-ui/ui/develop.slint#L223), [`ui/dr-ui/ui/masks.slint:1208`](../ui/dr-ui/ui/masks.slint#L1208), [`ui/dr-ui/ui/masks.slint:745`](../ui/dr-ui/ui/masks.slint#L745), [`ui/dr-ui/ui/masks.slint:804`](../ui/dr-ui/ui/masks.slint#L804) | +| FR-DEV-3a | [`core/dr-pipeline/ops/exposure.yaml:1`](../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/descriptor.rs:212`](../core/dr-pipeline/src/descriptor.rs#L212), [`core/dr-pipeline/src/descriptor.rs:252`](../core/dr-pipeline/src/descriptor.rs#L252), [`core/dr-pipeline/src/descriptor.rs:276`](../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/descriptor.rs:331`](../core/dr-pipeline/src/descriptor.rs#L331), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-pipeline/src/graph.rs:25`](../core/dr-pipeline/src/graph.rs#L25), [`core/dr-pipeline/src/graph.rs:393`](../core/dr-pipeline/src/graph.rs#L393), [`core/dr-pipeline/src/graph.rs:47`](../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/graph.rs:534`](../core/dr-pipeline/src/graph.rs#L534), [`core/dr-pipeline/src/graph.rs:60`](../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/mask.rs:1699`](../core/dr-pipeline/src/mask.rs#L1699), [`core/dr-pipeline/src/neutral.rs:1`](../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:372`](../core/dr-pipeline/src/neutral.rs#L372), [`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:1330`](../ui/dr-ui/src/develop.rs#L1330), [`ui/dr-ui/src/develop.rs:1609`](../ui/dr-ui/src/develop.rs#L1609), [`ui/dr-ui/src/develop.rs:7655`](../ui/dr-ui/src/develop.rs#L7655), [`ui/dr-ui/src/develop.rs:7853`](../ui/dr-ui/src/develop.rs#L7853), [`ui/dr-ui/src/lib.rs:874`](../ui/dr-ui/src/lib.rs#L874), [`ui/dr-ui/tests/ui_names_no_operation.rs:1`](../ui/dr-ui/tests/ui_names_no_operation.rs#L1), [`ui/dr-ui/ui/app.slint:2485`](../ui/dr-ui/ui/app.slint#L2485) | +| FR-DEV-3b | [`core/dr-pipeline/src/descriptor.rs:276`](../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-pipeline/src/graph.rs:60`](../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/operation.rs:365`](../core/dr-pipeline/src/operation.rs#L365), [`ui/dr-ui/ui/app.slint:2696`](../ui/dr-ui/ui/app.slint#L2696) | | FR-DEV-3c | [`core/dr-pipeline/ops/exposure.yaml:1`](../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/graph.rs:393`](../core/dr-pipeline/src/graph.rs#L393), [`core/dr-pipeline/src/graph.rs:47`](../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/mask.rs:1699`](../core/dr-pipeline/src/mask.rs#L1699), [`core/dr-pipeline/src/preset.rs:751`](../core/dr-pipeline/src/preset.rs#L751), [`ui/dr-ui/src/develop.rs:7904`](../ui/dr-ui/src/develop.rs#L7904) | | FR-DEV-3d | [`core/dr-gpu/src/adjust.rs:104`](../core/dr-gpu/src/adjust.rs#L104), [`core/dr-gpu/src/adjust.rs:1079`](../core/dr-gpu/src/adjust.rs#L1079), [`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:950`](../core/dr-pipeline/src/graph.rs#L950), [`core/dr-pipeline/src/operation.rs:32`](../core/dr-pipeline/src/operation.rs#L32), [`core/dr-pipeline/src/operation.rs:403`](../core/dr-pipeline/src/operation.rs#L403), [`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:716`](../core/dr-decode/src/lib.rs#L716), [`core/dr-decode/src/lib.rs:756`](../core/dr-decode/src/lib.rs#L756), [`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:1837`](../core/dr-pipeline/src/operation.rs#L1837), [`core/dr-pipeline/src/operation.rs:1918`](../core/dr-pipeline/src/operation.rs#L1918), [`core/dr-pipeline/src/operation.rs:1943`](../core/dr-pipeline/src/operation.rs#L1943), [`core/dr-pipeline/src/operation.rs:1958`](../core/dr-pipeline/src/operation.rs#L1958), [`core/dr-pipeline/src/operation.rs:1982`](../core/dr-pipeline/src/operation.rs#L1982), [`core/dr-pipeline/src/operation.rs:310`](../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/operation.rs:454`](../core/dr-pipeline/src/operation.rs#L454), [`core/dr-pipeline/src/operation.rs:464`](../core/dr-pipeline/src/operation.rs#L464), [`core/dr-pipeline/src/operation.rs:647`](../core/dr-pipeline/src/operation.rs#L647) | -| 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:103`](../core/dr-pipeline/src/graph.rs#L103), [`core/dr-pipeline/src/graph.rs:168`](../core/dr-pipeline/src/graph.rs#L168), [`core/dr-pipeline/src/graph.rs:566`](../core/dr-pipeline/src/graph.rs#L566), [`core/dr-pipeline/src/operation.rs:1165`](../core/dr-pipeline/src/operation.rs#L1165), [`core/dr-pipeline/src/operation.rs:1193`](../core/dr-pipeline/src/operation.rs#L1193), [`core/dr-pipeline/src/operation.rs:1239`](../core/dr-pipeline/src/operation.rs#L1239), [`core/dr-pipeline/src/operation.rs:1837`](../core/dr-pipeline/src/operation.rs#L1837), [`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:102`](../core/dr-pipeline/src/ops/film_sim.rs#L102), [`core/dr-pipeline/src/ops/film_sim.rs:139`](../core/dr-pipeline/src/ops/film_sim.rs#L139), [`core/dr-pipeline/src/ops/film_sim.rs:163`](../core/dr-pipeline/src/ops/film_sim.rs#L163), [`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:341`](../core/dr-pipeline/src/ops/film_sim.rs#L341), [`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:97`](../core/dr-pipeline/src/ops/film_sim.rs#L97), [`core/dr-pipeline/src/sidecar.rs:1028`](../core/dr-pipeline/src/sidecar.rs#L1028), [`core/dr-pipeline/src/sidecar.rs:115`](../core/dr-pipeline/src/sidecar.rs#L115), [`core/dr-pipeline/src/sidecar.rs:188`](../core/dr-pipeline/src/sidecar.rs#L188), [`core/dr-pipeline/src/sidecar.rs:2634`](../core/dr-pipeline/src/sidecar.rs#L2634), [`core/dr-pipeline/src/sidecar.rs:2710`](../core/dr-pipeline/src/sidecar.rs#L2710), [`core/dr-pipeline/src/sidecar.rs:561`](../core/dr-pipeline/src/sidecar.rs#L561), [`core/dr-pipeline/src/sidecar.rs:854`](../core/dr-pipeline/src/sidecar.rs#L854), [`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:1170`](../ui/dr-ui/src/develop.rs#L1170), [`ui/dr-ui/src/develop.rs:4768`](../ui/dr-ui/src/develop.rs#L4768), [`ui/dr-ui/src/develop.rs:4785`](../ui/dr-ui/src/develop.rs#L4785), [`ui/dr-ui/src/develop.rs:4797`](../ui/dr-ui/src/develop.rs#L4797), [`ui/dr-ui/src/develop.rs:4835`](../ui/dr-ui/src/develop.rs#L4835), [`ui/dr-ui/src/develop.rs:4844`](../ui/dr-ui/src/develop.rs#L4844), [`ui/dr-ui/src/develop.rs:4947`](../ui/dr-ui/src/develop.rs#L4947), [`ui/dr-ui/src/develop.rs:5458`](../ui/dr-ui/src/develop.rs#L5458), [`ui/dr-ui/src/develop.rs:5629`](../ui/dr-ui/src/develop.rs#L5629), [`ui/dr-ui/src/develop.rs:8395`](../ui/dr-ui/src/develop.rs#L8395), [`ui/dr-ui/src/lib.rs:2812`](../ui/dr-ui/src/lib.rs#L2812), [`ui/dr-ui/src/lib.rs:799`](../ui/dr-ui/src/lib.rs#L799), [`ui/dr-ui/src/lib.rs:864`](../ui/dr-ui/src/lib.rs#L864), [`ui/dr-ui/src/library.rs:538`](../ui/dr-ui/src/library.rs#L538), [`ui/dr-ui/src/library.rs:806`](../ui/dr-ui/src/library.rs#L806), [`ui/dr-ui/src/presets.rs:422`](../ui/dr-ui/src/presets.rs#L422), [`ui/dr-ui/ui/adjust.slint:1040`](../ui/dr-ui/ui/adjust.slint#L1040), [`ui/dr-ui/ui/adjust.slint:1050`](../ui/dr-ui/ui/adjust.slint#L1050), [`ui/dr-ui/ui/adjust.slint:1268`](../ui/dr-ui/ui/adjust.slint#L1268) | +| 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:103`](../core/dr-pipeline/src/graph.rs#L103), [`core/dr-pipeline/src/graph.rs:168`](../core/dr-pipeline/src/graph.rs#L168), [`core/dr-pipeline/src/graph.rs:566`](../core/dr-pipeline/src/graph.rs#L566), [`core/dr-pipeline/src/operation.rs:1165`](../core/dr-pipeline/src/operation.rs#L1165), [`core/dr-pipeline/src/operation.rs:1193`](../core/dr-pipeline/src/operation.rs#L1193), [`core/dr-pipeline/src/operation.rs:1239`](../core/dr-pipeline/src/operation.rs#L1239), [`core/dr-pipeline/src/operation.rs:1837`](../core/dr-pipeline/src/operation.rs#L1837), [`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:102`](../core/dr-pipeline/src/ops/film_sim.rs#L102), [`core/dr-pipeline/src/ops/film_sim.rs:139`](../core/dr-pipeline/src/ops/film_sim.rs#L139), [`core/dr-pipeline/src/ops/film_sim.rs:163`](../core/dr-pipeline/src/ops/film_sim.rs#L163), [`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:341`](../core/dr-pipeline/src/ops/film_sim.rs#L341), [`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:97`](../core/dr-pipeline/src/ops/film_sim.rs#L97), [`core/dr-pipeline/src/sidecar.rs:1028`](../core/dr-pipeline/src/sidecar.rs#L1028), [`core/dr-pipeline/src/sidecar.rs:115`](../core/dr-pipeline/src/sidecar.rs#L115), [`core/dr-pipeline/src/sidecar.rs:188`](../core/dr-pipeline/src/sidecar.rs#L188), [`core/dr-pipeline/src/sidecar.rs:2634`](../core/dr-pipeline/src/sidecar.rs#L2634), [`core/dr-pipeline/src/sidecar.rs:2710`](../core/dr-pipeline/src/sidecar.rs#L2710), [`core/dr-pipeline/src/sidecar.rs:561`](../core/dr-pipeline/src/sidecar.rs#L561), [`core/dr-pipeline/src/sidecar.rs:854`](../core/dr-pipeline/src/sidecar.rs#L854), [`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:1170`](../ui/dr-ui/src/develop.rs#L1170), [`ui/dr-ui/src/develop.rs:4768`](../ui/dr-ui/src/develop.rs#L4768), [`ui/dr-ui/src/develop.rs:4785`](../ui/dr-ui/src/develop.rs#L4785), [`ui/dr-ui/src/develop.rs:4797`](../ui/dr-ui/src/develop.rs#L4797), [`ui/dr-ui/src/develop.rs:4835`](../ui/dr-ui/src/develop.rs#L4835), [`ui/dr-ui/src/develop.rs:4844`](../ui/dr-ui/src/develop.rs#L4844), [`ui/dr-ui/src/develop.rs:4947`](../ui/dr-ui/src/develop.rs#L4947), [`ui/dr-ui/src/develop.rs:5458`](../ui/dr-ui/src/develop.rs#L5458), [`ui/dr-ui/src/develop.rs:5629`](../ui/dr-ui/src/develop.rs#L5629), [`ui/dr-ui/src/develop.rs:8395`](../ui/dr-ui/src/develop.rs#L8395), [`ui/dr-ui/src/lib.rs:2813`](../ui/dr-ui/src/lib.rs#L2813), [`ui/dr-ui/src/lib.rs:800`](../ui/dr-ui/src/lib.rs#L800), [`ui/dr-ui/src/lib.rs:865`](../ui/dr-ui/src/lib.rs#L865), [`ui/dr-ui/src/library.rs:602`](../ui/dr-ui/src/library.rs#L602), [`ui/dr-ui/src/library.rs:870`](../ui/dr-ui/src/library.rs#L870), [`ui/dr-ui/src/presets.rs:422`](../ui/dr-ui/src/presets.rs#L422), [`ui/dr-ui/ui/adjust.slint:1040`](../ui/dr-ui/ui/adjust.slint#L1040), [`ui/dr-ui/ui/adjust.slint:1050`](../ui/dr-ui/ui/adjust.slint#L1050), [`ui/dr-ui/ui/adjust.slint:1268`](../ui/dr-ui/ui/adjust.slint#L1268) | | FR-DEV-3h | [`core/dr-decode/src/lib.rs:408`](../core/dr-decode/src/lib.rs#L408), [`core/dr-decode/src/preview.rs:29`](../core/dr-decode/src/preview.rs#L29), [`core/dr-pipeline/src/framing.rs:1067`](../core/dr-pipeline/src/framing.rs#L1067), [`core/dr-pipeline/src/framing.rs:328`](../core/dr-pipeline/src/framing.rs#L328), [`core/dr-pipeline/src/framing.rs:498`](../core/dr-pipeline/src/framing.rs#L498), [`core/dr-types/src/lib.rs:339`](../core/dr-types/src/lib.rs#L339), [`core/dr-types/src/lib.rs:447`](../core/dr-types/src/lib.rs#L447), [`core/dr-types/src/lib.rs:459`](../core/dr-types/src/lib.rs#L459), [`core/dr-types/src/lib.rs:475`](../core/dr-types/src/lib.rs#L475), [`ui/dr-ui/src/develop.rs:140`](../ui/dr-ui/src/develop.rs#L140), [`ui/dr-ui/src/develop.rs:2769`](../ui/dr-ui/src/develop.rs#L2769), [`ui/dr-ui/src/segmentation.rs:499`](../ui/dr-ui/src/segmentation.rs#L499) | | FR-DEV-3i | [`core/dr-pipeline/src/mask.rs:558`](../core/dr-pipeline/src/mask.rs#L558), [`core/dr-segment/src/lib.rs:1`](../core/dr-segment/src/lib.rs#L1), [`ui/dr-ui/src/segmentation.rs:1`](../ui/dr-ui/src/segmentation.rs#L1) | | FR-DEV-4 | [`core/dr-gpu/src/adjust.rs:770`](../core/dr-gpu/src/adjust.rs#L770), [`core/dr-gpu/src/lib.rs:366`](../core/dr-gpu/src/lib.rs#L366), [`ui/dr-ui/ui/crop.slint:1`](../ui/dr-ui/ui/crop.slint#L1) | -| FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:1399`](../core/dr-pipeline/src/graph.rs#L1399), [`core/dr-pipeline/src/graph.rs:587`](../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:640`](../core/dr-pipeline/src/graph.rs#L640), [`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/sidecar.rs:1018`](../core/dr-pipeline/src/sidecar.rs#L1018), [`core/dr-pipeline/src/sidecar.rs:129`](../core/dr-pipeline/src/sidecar.rs#L129), [`core/dr-pipeline/src/sidecar.rs:2425`](../core/dr-pipeline/src/sidecar.rs#L2425), [`core/dr-pipeline/src/sidecar.rs:2461`](../core/dr-pipeline/src/sidecar.rs#L2461), [`core/dr-pipeline/src/sidecar.rs:2473`](../core/dr-pipeline/src/sidecar.rs#L2473), [`core/dr-pipeline/src/sidecar.rs:288`](../core/dr-pipeline/src/sidecar.rs#L288), [`core/dr-pipeline/src/sidecar.rs:679`](../core/dr-pipeline/src/sidecar.rs#L679), [`core/dr-pipeline/src/sidecar.rs:695`](../core/dr-pipeline/src/sidecar.rs#L695), [`core/dr-pipeline/src/sidecar.rs:835`](../core/dr-pipeline/src/sidecar.rs#L835), [`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:4400`](../ui/dr-ui/src/develop.rs#L4400), [`ui/dr-ui/src/develop.rs:4797`](../ui/dr-ui/src/develop.rs#L4797), [`ui/dr-ui/src/develop.rs:5475`](../ui/dr-ui/src/develop.rs#L5475), [`ui/dr-ui/src/develop.rs:5493`](../ui/dr-ui/src/develop.rs#L5493), [`ui/dr-ui/src/develop.rs:5532`](../ui/dr-ui/src/develop.rs#L5532), [`ui/dr-ui/src/develop.rs:5546`](../ui/dr-ui/src/develop.rs#L5546), [`ui/dr-ui/src/develop.rs:5557`](../ui/dr-ui/src/develop.rs#L5557), [`ui/dr-ui/src/develop.rs:5616`](../ui/dr-ui/src/develop.rs#L5616), [`ui/dr-ui/src/develop.rs:5629`](../ui/dr-ui/src/develop.rs#L5629), [`ui/dr-ui/src/develop.rs:5659`](../ui/dr-ui/src/develop.rs#L5659), [`ui/dr-ui/src/develop.rs:5672`](../ui/dr-ui/src/develop.rs#L5672), [`ui/dr-ui/src/develop.rs:5684`](../ui/dr-ui/src/develop.rs#L5684), [`ui/dr-ui/src/develop.rs:5700`](../ui/dr-ui/src/develop.rs#L5700), [`ui/dr-ui/src/develop.rs:5732`](../ui/dr-ui/src/develop.rs#L5732), [`ui/dr-ui/src/develop.rs:5736`](../ui/dr-ui/src/develop.rs#L5736), [`ui/dr-ui/src/develop.rs:5755`](../ui/dr-ui/src/develop.rs#L5755), [`ui/dr-ui/src/develop.rs:5771`](../ui/dr-ui/src/develop.rs#L5771), [`ui/dr-ui/src/develop.rs:6613`](../ui/dr-ui/src/develop.rs#L6613), [`ui/dr-ui/src/develop.rs:6633`](../ui/dr-ui/src/develop.rs#L6633), [`ui/dr-ui/src/develop.rs:6664`](../ui/dr-ui/src/develop.rs#L6664), [`ui/dr-ui/src/develop.rs:6721`](../ui/dr-ui/src/develop.rs#L6721), [`ui/dr-ui/src/develop.rs:6781`](../ui/dr-ui/src/develop.rs#L6781), [`ui/dr-ui/src/develop.rs:772`](../ui/dr-ui/src/develop.rs#L772), [`ui/dr-ui/src/develop.rs:781`](../ui/dr-ui/src/develop.rs#L781), [`ui/dr-ui/src/labels.rs:12`](../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:278`](../ui/dr-ui/src/labels.rs#L278), [`ui/dr-ui/src/labels.rs:31`](../ui/dr-ui/src/labels.rs#L31), [`ui/dr-ui/src/lib.rs:1860`](../ui/dr-ui/src/lib.rs#L1860), [`ui/dr-ui/src/lib.rs:1865`](../ui/dr-ui/src/lib.rs#L1865), [`ui/dr-ui/src/lib.rs:1928`](../ui/dr-ui/src/lib.rs#L1928), [`ui/dr-ui/src/lib.rs:1937`](../ui/dr-ui/src/lib.rs#L1937), [`ui/dr-ui/src/lib.rs:1949`](../ui/dr-ui/src/lib.rs#L1949), [`ui/dr-ui/src/lib.rs:3080`](../ui/dr-ui/src/lib.rs#L3080), [`ui/dr-ui/src/lib.rs:3100`](../ui/dr-ui/src/lib.rs#L3100), [`ui/dr-ui/src/library.rs:547`](../ui/dr-ui/src/library.rs#L547), [`ui/dr-ui/src/library.rs:832`](../ui/dr-ui/src/library.rs#L832), [`ui/dr-ui/src/presets.rs:1678`](../ui/dr-ui/src/presets.rs#L1678), [`ui/dr-ui/src/presets.rs:373`](../ui/dr-ui/src/presets.rs#L373), [`ui/dr-ui/src/presets.rs:437`](../ui/dr-ui/src/presets.rs#L437), [`ui/dr-ui/src/presets.rs:557`](../ui/dr-ui/src/presets.rs#L557), [`ui/dr-ui/ui/history.slint:191`](../ui/dr-ui/ui/history.slint#L191), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:218`](../ui/dr-ui/ui/history.slint#L218), [`ui/dr-ui/ui/history.slint:303`](../ui/dr-ui/ui/history.slint#L303), [`ui/dr-ui/ui/history.slint:43`](../ui/dr-ui/ui/history.slint#L43), [`ui/dr-ui/ui/history.slint:53`](../ui/dr-ui/ui/history.slint#L53) | -| FR-DEV-6 | [`core/dr-pipeline/src/preset.rs:1`](../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:390`](../core/dr-pipeline/src/preset.rs#L390), [`core/dr-pipeline/src/preset.rs:423`](../core/dr-pipeline/src/preset.rs#L423), [`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:419`](../core/dr-types/src/settings.rs#L419), [`ui/dr-ui/src/develop.rs:5415`](../ui/dr-ui/src/develop.rs#L5415), [`ui/dr-ui/src/develop.rs:5436`](../ui/dr-ui/src/develop.rs#L5436), [`ui/dr-ui/src/lib.rs:1827`](../ui/dr-ui/src/lib.rs#L1827), [`ui/dr-ui/src/lib.rs:2613`](../ui/dr-ui/src/lib.rs#L2613), [`ui/dr-ui/src/lib.rs:2642`](../ui/dr-ui/src/lib.rs#L2642), [`ui/dr-ui/src/library.rs:2427`](../ui/dr-ui/src/library.rs#L2427), [`ui/dr-ui/src/library.rs:500`](../ui/dr-ui/src/library.rs#L500), [`ui/dr-ui/src/library.rs:528`](../ui/dr-ui/src/library.rs#L528), [`ui/dr-ui/src/library_ui.rs:3281`](../ui/dr-ui/src/library_ui.rs#L3281), [`ui/dr-ui/src/library_ui.rs:3864`](../ui/dr-ui/src/library_ui.rs#L3864), [`ui/dr-ui/src/library_ui.rs:628`](../ui/dr-ui/src/library_ui.rs#L628), [`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:707`](../ui/dr-ui/src/presets.rs#L707), [`ui/dr-ui/src/presets.rs:741`](../ui/dr-ui/src/presets.rs#L741), [`ui/dr-ui/ui/adjust.slint:853`](../ui/dr-ui/ui/adjust.slint#L853), [`ui/dr-ui/ui/adjust.slint:878`](../ui/dr-ui/ui/adjust.slint#L878), [`ui/dr-ui/ui/adjust.slint:889`](../ui/dr-ui/ui/adjust.slint#L889), [`ui/dr-ui/ui/adjust.slint:932`](../ui/dr-ui/ui/adjust.slint#L932), [`ui/dr-ui/ui/app.slint:1620`](../ui/dr-ui/ui/app.slint#L1620), [`ui/dr-ui/ui/app.slint:2448`](../ui/dr-ui/ui/app.slint#L2448), [`ui/dr-ui/ui/app.slint:3083`](../ui/dr-ui/ui/app.slint#L3083), [`ui/dr-ui/ui/app.slint:755`](../ui/dr-ui/ui/app.slint#L755), [`ui/dr-ui/ui/app.slint:766`](../ui/dr-ui/ui/app.slint#L766), [`ui/dr-ui/ui/library.slint:1574`](../ui/dr-ui/ui/library.slint#L1574), [`ui/dr-ui/ui/library.slint:1580`](../ui/dr-ui/ui/library.slint#L1580), [`ui/dr-ui/ui/library.slint:4217`](../ui/dr-ui/ui/library.slint#L4217), [`ui/dr-ui/ui/library.slint:4232`](../ui/dr-ui/ui/library.slint#L4232), [`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:113`](../ui/dr-ui/ui/settings.slint#L113), [`ui/dr-ui/ui/settings.slint:658`](../ui/dr-ui/ui/settings.slint#L658) | -| 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:4334`](../ui/dr-ui/src/develop.rs#L4334), [`ui/dr-ui/src/develop.rs:4375`](../ui/dr-ui/src/develop.rs#L4375), [`ui/dr-ui/src/develop.rs:5571`](../ui/dr-ui/src/develop.rs#L5571), [`ui/dr-ui/src/develop.rs:5588`](../ui/dr-ui/src/develop.rs#L5588), [`ui/dr-ui/src/develop.rs:5700`](../ui/dr-ui/src/develop.rs#L5700), [`ui/dr-ui/src/develop.rs:5732`](../ui/dr-ui/src/develop.rs#L5732), [`ui/dr-ui/src/develop.rs:6664`](../ui/dr-ui/src/develop.rs#L6664), [`ui/dr-ui/src/develop.rs:6781`](../ui/dr-ui/src/develop.rs#L6781), [`ui/dr-ui/src/develop.rs:797`](../ui/dr-ui/src/develop.rs#L797), [`ui/dr-ui/src/lib.rs:1937`](../ui/dr-ui/src/lib.rs#L1937), [`ui/dr-ui/src/lib.rs:2009`](../ui/dr-ui/src/lib.rs#L2009), [`ui/dr-ui/src/lib.rs:2023`](../ui/dr-ui/src/lib.rs#L2023), [`ui/dr-ui/src/lib.rs:3019`](../ui/dr-ui/src/lib.rs#L3019), [`ui/dr-ui/src/lib.rs:3080`](../ui/dr-ui/src/lib.rs#L3080), [`ui/dr-ui/src/lib.rs:3152`](../ui/dr-ui/src/lib.rs#L3152), [`ui/dr-ui/src/lib.rs:405`](../ui/dr-ui/src/lib.rs#L405), [`ui/dr-ui/ui/app.slint:128`](../ui/dr-ui/ui/app.slint#L128), [`ui/dr-ui/ui/app.slint:2355`](../ui/dr-ui/ui/app.slint#L2355), [`ui/dr-ui/ui/app.slint:2370`](../ui/dr-ui/ui/app.slint#L2370), [`ui/dr-ui/ui/app.slint:2690`](../ui/dr-ui/ui/app.slint#L2690), [`ui/dr-ui/ui/history.slint:102`](../ui/dr-ui/ui/history.slint#L102), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:226`](../ui/dr-ui/ui/history.slint#L226), [`ui/dr-ui/ui/history.slint:53`](../ui/dr-ui/ui/history.slint#L53), [`ui/dr-ui/ui/widgets.slint:71`](../ui/dr-ui/ui/widgets.slint#L71) | -| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:405`](../core/dr-gpu/src/detail.rs#L405), [`core/dr-gpu/src/detail.rs:623`](../core/dr-gpu/src/detail.rs#L623), [`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:1051`](../core/dr-pipeline/src/graph.rs#L1051), [`core/dr-pipeline/src/graph.rs:115`](../core/dr-pipeline/src/graph.rs#L115), [`core/dr-pipeline/src/graph.rs:247`](../core/dr-pipeline/src/graph.rs#L247), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:601`](../core/dr-pipeline/src/operation.rs#L601), [`core/dr-pipeline/src/sidecar.rs:1044`](../core/dr-pipeline/src/sidecar.rs#L1044), [`core/dr-pipeline/src/sidecar.rs:1098`](../core/dr-pipeline/src/sidecar.rs#L1098), [`core/dr-pipeline/src/sidecar.rs:1128`](../core/dr-pipeline/src/sidecar.rs#L1128), [`core/dr-pipeline/src/sidecar.rs:204`](../core/dr-pipeline/src/sidecar.rs#L204), [`core/dr-pipeline/src/sidecar.rs:380`](../core/dr-pipeline/src/sidecar.rs#L380), [`core/dr-pipeline/src/sidecar.rs:866`](../core/dr-pipeline/src/sidecar.rs#L866), [`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:3200`](../ui/dr-ui/src/develop.rs#L3200), [`ui/dr-ui/src/develop.rs:3238`](../ui/dr-ui/src/develop.rs#L3238), [`ui/dr-ui/src/develop.rs:3303`](../ui/dr-ui/src/develop.rs#L3303), [`ui/dr-ui/src/develop.rs:3386`](../ui/dr-ui/src/develop.rs#L3386), [`ui/dr-ui/src/develop.rs:3400`](../ui/dr-ui/src/develop.rs#L3400), [`ui/dr-ui/src/develop.rs:904`](../ui/dr-ui/src/develop.rs#L904), [`ui/dr-ui/src/labels.rs:80`](../ui/dr-ui/src/labels.rs#L80), [`ui/dr-ui/src/lib.rs:1967`](../ui/dr-ui/src/lib.rs#L1967), [`ui/dr-ui/src/lib.rs:3305`](../ui/dr-ui/src/lib.rs#L3305), [`ui/dr-ui/src/lib.rs:447`](../ui/dr-ui/src/lib.rs#L447), [`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/app.slint:2211`](../ui/dr-ui/ui/app.slint#L2211), [`ui/dr-ui/ui/app.slint:2413`](../ui/dr-ui/ui/app.slint#L2413), [`ui/dr-ui/ui/app.slint:2989`](../ui/dr-ui/ui/app.slint#L2989), [`ui/dr-ui/ui/icons.slint:366`](../ui/dr-ui/ui/icons.slint#L366), [`ui/dr-ui/ui/session.slint:102`](../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../ui/dr-ui/ui/spots.slint#L91) | -| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:2140`](../core/dr-gpu/src/adjust.rs#L2140), [`core/dr-gpu/src/adjust.rs:2217`](../core/dr-gpu/src/adjust.rs#L2217), [`core/dr-gpu/src/adjust.rs:2302`](../core/dr-gpu/src/adjust.rs#L2302), [`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:172`](../core/dr-gpu/src/lib.rs#L172), [`core/dr-gpu/src/lib.rs:192`](../core/dr-gpu/src/lib.rs#L192), [`core/dr-gpu/src/lib.rs:70`](../core/dr-gpu/src/lib.rs#L70), [`core/dr-gpu/src/lib.rs:93`](../core/dr-gpu/src/lib.rs#L93), [`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:881`](../core/dr-pipeline/src/graph.rs#L881), [`core/dr-pipeline/src/graph.rs:911`](../core/dr-pipeline/src/graph.rs#L911), [`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/dehaze.rs:1`](../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:592`](../core/dr-pipeline/src/ops/dehaze.rs#L592), [`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:4021`](../ui/dr-ui/src/develop.rs#L4021), [`ui/dr-ui/src/develop.rs:5283`](../ui/dr-ui/src/develop.rs#L5283), [`ui/dr-ui/src/develop.rs:6026`](../ui/dr-ui/src/develop.rs#L6026), [`ui/dr-ui/src/develop.rs:7354`](../ui/dr-ui/src/develop.rs#L7354), [`ui/dr-ui/src/develop.rs:7388`](../ui/dr-ui/src/develop.rs#L7388), [`ui/dr-ui/src/lib.rs:1020`](../ui/dr-ui/src/lib.rs#L1020), [`ui/dr-ui/src/lib.rs:1079`](../ui/dr-ui/src/lib.rs#L1079), [`ui/dr-ui/src/lib.rs:94`](../ui/dr-ui/src/lib.rs#L94) | +| FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:1399`](../core/dr-pipeline/src/graph.rs#L1399), [`core/dr-pipeline/src/graph.rs:587`](../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:640`](../core/dr-pipeline/src/graph.rs#L640), [`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/sidecar.rs:1018`](../core/dr-pipeline/src/sidecar.rs#L1018), [`core/dr-pipeline/src/sidecar.rs:129`](../core/dr-pipeline/src/sidecar.rs#L129), [`core/dr-pipeline/src/sidecar.rs:2425`](../core/dr-pipeline/src/sidecar.rs#L2425), [`core/dr-pipeline/src/sidecar.rs:2461`](../core/dr-pipeline/src/sidecar.rs#L2461), [`core/dr-pipeline/src/sidecar.rs:2473`](../core/dr-pipeline/src/sidecar.rs#L2473), [`core/dr-pipeline/src/sidecar.rs:288`](../core/dr-pipeline/src/sidecar.rs#L288), [`core/dr-pipeline/src/sidecar.rs:679`](../core/dr-pipeline/src/sidecar.rs#L679), [`core/dr-pipeline/src/sidecar.rs:695`](../core/dr-pipeline/src/sidecar.rs#L695), [`core/dr-pipeline/src/sidecar.rs:835`](../core/dr-pipeline/src/sidecar.rs#L835), [`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:4400`](../ui/dr-ui/src/develop.rs#L4400), [`ui/dr-ui/src/develop.rs:4797`](../ui/dr-ui/src/develop.rs#L4797), [`ui/dr-ui/src/develop.rs:5475`](../ui/dr-ui/src/develop.rs#L5475), [`ui/dr-ui/src/develop.rs:5493`](../ui/dr-ui/src/develop.rs#L5493), [`ui/dr-ui/src/develop.rs:5532`](../ui/dr-ui/src/develop.rs#L5532), [`ui/dr-ui/src/develop.rs:5546`](../ui/dr-ui/src/develop.rs#L5546), [`ui/dr-ui/src/develop.rs:5557`](../ui/dr-ui/src/develop.rs#L5557), [`ui/dr-ui/src/develop.rs:5616`](../ui/dr-ui/src/develop.rs#L5616), [`ui/dr-ui/src/develop.rs:5629`](../ui/dr-ui/src/develop.rs#L5629), [`ui/dr-ui/src/develop.rs:5659`](../ui/dr-ui/src/develop.rs#L5659), [`ui/dr-ui/src/develop.rs:5672`](../ui/dr-ui/src/develop.rs#L5672), [`ui/dr-ui/src/develop.rs:5684`](../ui/dr-ui/src/develop.rs#L5684), [`ui/dr-ui/src/develop.rs:5700`](../ui/dr-ui/src/develop.rs#L5700), [`ui/dr-ui/src/develop.rs:5732`](../ui/dr-ui/src/develop.rs#L5732), [`ui/dr-ui/src/develop.rs:5736`](../ui/dr-ui/src/develop.rs#L5736), [`ui/dr-ui/src/develop.rs:5755`](../ui/dr-ui/src/develop.rs#L5755), [`ui/dr-ui/src/develop.rs:5771`](../ui/dr-ui/src/develop.rs#L5771), [`ui/dr-ui/src/develop.rs:6613`](../ui/dr-ui/src/develop.rs#L6613), [`ui/dr-ui/src/develop.rs:6633`](../ui/dr-ui/src/develop.rs#L6633), [`ui/dr-ui/src/develop.rs:6664`](../ui/dr-ui/src/develop.rs#L6664), [`ui/dr-ui/src/develop.rs:6721`](../ui/dr-ui/src/develop.rs#L6721), [`ui/dr-ui/src/develop.rs:6781`](../ui/dr-ui/src/develop.rs#L6781), [`ui/dr-ui/src/develop.rs:772`](../ui/dr-ui/src/develop.rs#L772), [`ui/dr-ui/src/develop.rs:781`](../ui/dr-ui/src/develop.rs#L781), [`ui/dr-ui/src/labels.rs:12`](../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:278`](../ui/dr-ui/src/labels.rs#L278), [`ui/dr-ui/src/labels.rs:31`](../ui/dr-ui/src/labels.rs#L31), [`ui/dr-ui/src/lib.rs:1861`](../ui/dr-ui/src/lib.rs#L1861), [`ui/dr-ui/src/lib.rs:1866`](../ui/dr-ui/src/lib.rs#L1866), [`ui/dr-ui/src/lib.rs:1929`](../ui/dr-ui/src/lib.rs#L1929), [`ui/dr-ui/src/lib.rs:1938`](../ui/dr-ui/src/lib.rs#L1938), [`ui/dr-ui/src/lib.rs:1950`](../ui/dr-ui/src/lib.rs#L1950), [`ui/dr-ui/src/lib.rs:3081`](../ui/dr-ui/src/lib.rs#L3081), [`ui/dr-ui/src/lib.rs:3101`](../ui/dr-ui/src/lib.rs#L3101), [`ui/dr-ui/src/library.rs:611`](../ui/dr-ui/src/library.rs#L611), [`ui/dr-ui/src/library.rs:896`](../ui/dr-ui/src/library.rs#L896), [`ui/dr-ui/src/presets.rs:1678`](../ui/dr-ui/src/presets.rs#L1678), [`ui/dr-ui/src/presets.rs:373`](../ui/dr-ui/src/presets.rs#L373), [`ui/dr-ui/src/presets.rs:437`](../ui/dr-ui/src/presets.rs#L437), [`ui/dr-ui/src/presets.rs:557`](../ui/dr-ui/src/presets.rs#L557), [`ui/dr-ui/ui/history.slint:191`](../ui/dr-ui/ui/history.slint#L191), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:218`](../ui/dr-ui/ui/history.slint#L218), [`ui/dr-ui/ui/history.slint:303`](../ui/dr-ui/ui/history.slint#L303), [`ui/dr-ui/ui/history.slint:43`](../ui/dr-ui/ui/history.slint#L43), [`ui/dr-ui/ui/history.slint:53`](../ui/dr-ui/ui/history.slint#L53) | +| FR-DEV-6 | [`core/dr-pipeline/src/preset.rs:1`](../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:390`](../core/dr-pipeline/src/preset.rs#L390), [`core/dr-pipeline/src/preset.rs:423`](../core/dr-pipeline/src/preset.rs#L423), [`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:419`](../core/dr-types/src/settings.rs#L419), [`ui/dr-ui/src/develop.rs:5415`](../ui/dr-ui/src/develop.rs#L5415), [`ui/dr-ui/src/develop.rs:5436`](../ui/dr-ui/src/develop.rs#L5436), [`ui/dr-ui/src/lib.rs:1828`](../ui/dr-ui/src/lib.rs#L1828), [`ui/dr-ui/src/lib.rs:2614`](../ui/dr-ui/src/lib.rs#L2614), [`ui/dr-ui/src/lib.rs:2643`](../ui/dr-ui/src/lib.rs#L2643), [`ui/dr-ui/src/library.rs:2491`](../ui/dr-ui/src/library.rs#L2491), [`ui/dr-ui/src/library.rs:564`](../ui/dr-ui/src/library.rs#L564), [`ui/dr-ui/src/library.rs:592`](../ui/dr-ui/src/library.rs#L592), [`ui/dr-ui/src/library_ui.rs:3281`](../ui/dr-ui/src/library_ui.rs#L3281), [`ui/dr-ui/src/library_ui.rs:3864`](../ui/dr-ui/src/library_ui.rs#L3864), [`ui/dr-ui/src/library_ui.rs:628`](../ui/dr-ui/src/library_ui.rs#L628), [`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:707`](../ui/dr-ui/src/presets.rs#L707), [`ui/dr-ui/src/presets.rs:741`](../ui/dr-ui/src/presets.rs#L741), [`ui/dr-ui/ui/adjust.slint:853`](../ui/dr-ui/ui/adjust.slint#L853), [`ui/dr-ui/ui/adjust.slint:878`](../ui/dr-ui/ui/adjust.slint#L878), [`ui/dr-ui/ui/adjust.slint:889`](../ui/dr-ui/ui/adjust.slint#L889), [`ui/dr-ui/ui/adjust.slint:932`](../ui/dr-ui/ui/adjust.slint#L932), [`ui/dr-ui/ui/app.slint:1624`](../ui/dr-ui/ui/app.slint#L1624), [`ui/dr-ui/ui/app.slint:2454`](../ui/dr-ui/ui/app.slint#L2454), [`ui/dr-ui/ui/app.slint:3089`](../ui/dr-ui/ui/app.slint#L3089), [`ui/dr-ui/ui/app.slint:759`](../ui/dr-ui/ui/app.slint#L759), [`ui/dr-ui/ui/app.slint:770`](../ui/dr-ui/ui/app.slint#L770), [`ui/dr-ui/ui/library.slint:1579`](../ui/dr-ui/ui/library.slint#L1579), [`ui/dr-ui/ui/library.slint:1585`](../ui/dr-ui/ui/library.slint#L1585), [`ui/dr-ui/ui/library.slint:4247`](../ui/dr-ui/ui/library.slint#L4247), [`ui/dr-ui/ui/library.slint:4262`](../ui/dr-ui/ui/library.slint#L4262), [`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:113`](../ui/dr-ui/ui/settings.slint#L113), [`ui/dr-ui/ui/settings.slint:658`](../ui/dr-ui/ui/settings.slint#L658) | +| 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:4334`](../ui/dr-ui/src/develop.rs#L4334), [`ui/dr-ui/src/develop.rs:4375`](../ui/dr-ui/src/develop.rs#L4375), [`ui/dr-ui/src/develop.rs:5571`](../ui/dr-ui/src/develop.rs#L5571), [`ui/dr-ui/src/develop.rs:5588`](../ui/dr-ui/src/develop.rs#L5588), [`ui/dr-ui/src/develop.rs:5700`](../ui/dr-ui/src/develop.rs#L5700), [`ui/dr-ui/src/develop.rs:5732`](../ui/dr-ui/src/develop.rs#L5732), [`ui/dr-ui/src/develop.rs:6664`](../ui/dr-ui/src/develop.rs#L6664), [`ui/dr-ui/src/develop.rs:6781`](../ui/dr-ui/src/develop.rs#L6781), [`ui/dr-ui/src/develop.rs:797`](../ui/dr-ui/src/develop.rs#L797), [`ui/dr-ui/src/lib.rs:1938`](../ui/dr-ui/src/lib.rs#L1938), [`ui/dr-ui/src/lib.rs:2010`](../ui/dr-ui/src/lib.rs#L2010), [`ui/dr-ui/src/lib.rs:2024`](../ui/dr-ui/src/lib.rs#L2024), [`ui/dr-ui/src/lib.rs:3020`](../ui/dr-ui/src/lib.rs#L3020), [`ui/dr-ui/src/lib.rs:3081`](../ui/dr-ui/src/lib.rs#L3081), [`ui/dr-ui/src/lib.rs:3153`](../ui/dr-ui/src/lib.rs#L3153), [`ui/dr-ui/src/lib.rs:406`](../ui/dr-ui/src/lib.rs#L406), [`ui/dr-ui/ui/app.slint:128`](../ui/dr-ui/ui/app.slint#L128), [`ui/dr-ui/ui/app.slint:2361`](../ui/dr-ui/ui/app.slint#L2361), [`ui/dr-ui/ui/app.slint:2376`](../ui/dr-ui/ui/app.slint#L2376), [`ui/dr-ui/ui/app.slint:2696`](../ui/dr-ui/ui/app.slint#L2696), [`ui/dr-ui/ui/history.slint:102`](../ui/dr-ui/ui/history.slint#L102), [`ui/dr-ui/ui/history.slint:1`](../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:226`](../ui/dr-ui/ui/history.slint#L226), [`ui/dr-ui/ui/history.slint:53`](../ui/dr-ui/ui/history.slint#L53), [`ui/dr-ui/ui/widgets.slint:71`](../ui/dr-ui/ui/widgets.slint#L71) | +| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:405`](../core/dr-gpu/src/detail.rs#L405), [`core/dr-gpu/src/detail.rs:623`](../core/dr-gpu/src/detail.rs#L623), [`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:1051`](../core/dr-pipeline/src/graph.rs#L1051), [`core/dr-pipeline/src/graph.rs:115`](../core/dr-pipeline/src/graph.rs#L115), [`core/dr-pipeline/src/graph.rs:247`](../core/dr-pipeline/src/graph.rs#L247), [`core/dr-pipeline/src/operation.rs:330`](../core/dr-pipeline/src/operation.rs#L330), [`core/dr-pipeline/src/operation.rs:601`](../core/dr-pipeline/src/operation.rs#L601), [`core/dr-pipeline/src/sidecar.rs:1044`](../core/dr-pipeline/src/sidecar.rs#L1044), [`core/dr-pipeline/src/sidecar.rs:1098`](../core/dr-pipeline/src/sidecar.rs#L1098), [`core/dr-pipeline/src/sidecar.rs:1128`](../core/dr-pipeline/src/sidecar.rs#L1128), [`core/dr-pipeline/src/sidecar.rs:204`](../core/dr-pipeline/src/sidecar.rs#L204), [`core/dr-pipeline/src/sidecar.rs:380`](../core/dr-pipeline/src/sidecar.rs#L380), [`core/dr-pipeline/src/sidecar.rs:866`](../core/dr-pipeline/src/sidecar.rs#L866), [`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:3200`](../ui/dr-ui/src/develop.rs#L3200), [`ui/dr-ui/src/develop.rs:3238`](../ui/dr-ui/src/develop.rs#L3238), [`ui/dr-ui/src/develop.rs:3303`](../ui/dr-ui/src/develop.rs#L3303), [`ui/dr-ui/src/develop.rs:3386`](../ui/dr-ui/src/develop.rs#L3386), [`ui/dr-ui/src/develop.rs:3400`](../ui/dr-ui/src/develop.rs#L3400), [`ui/dr-ui/src/develop.rs:904`](../ui/dr-ui/src/develop.rs#L904), [`ui/dr-ui/src/labels.rs:80`](../ui/dr-ui/src/labels.rs#L80), [`ui/dr-ui/src/lib.rs:1968`](../ui/dr-ui/src/lib.rs#L1968), [`ui/dr-ui/src/lib.rs:3306`](../ui/dr-ui/src/lib.rs#L3306), [`ui/dr-ui/src/lib.rs:448`](../ui/dr-ui/src/lib.rs#L448), [`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/app.slint:2217`](../ui/dr-ui/ui/app.slint#L2217), [`ui/dr-ui/ui/app.slint:2419`](../ui/dr-ui/ui/app.slint#L2419), [`ui/dr-ui/ui/app.slint:2995`](../ui/dr-ui/ui/app.slint#L2995), [`ui/dr-ui/ui/icons.slint:366`](../ui/dr-ui/ui/icons.slint#L366), [`ui/dr-ui/ui/session.slint:102`](../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../ui/dr-ui/ui/spots.slint#L91) | +| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:2140`](../core/dr-gpu/src/adjust.rs#L2140), [`core/dr-gpu/src/adjust.rs:2217`](../core/dr-gpu/src/adjust.rs#L2217), [`core/dr-gpu/src/adjust.rs:2302`](../core/dr-gpu/src/adjust.rs#L2302), [`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:172`](../core/dr-gpu/src/lib.rs#L172), [`core/dr-gpu/src/lib.rs:192`](../core/dr-gpu/src/lib.rs#L192), [`core/dr-gpu/src/lib.rs:70`](../core/dr-gpu/src/lib.rs#L70), [`core/dr-gpu/src/lib.rs:93`](../core/dr-gpu/src/lib.rs#L93), [`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:881`](../core/dr-pipeline/src/graph.rs#L881), [`core/dr-pipeline/src/graph.rs:911`](../core/dr-pipeline/src/graph.rs#L911), [`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/dehaze.rs:1`](../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:592`](../core/dr-pipeline/src/ops/dehaze.rs#L592), [`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:4021`](../ui/dr-ui/src/develop.rs#L4021), [`ui/dr-ui/src/develop.rs:5283`](../ui/dr-ui/src/develop.rs#L5283), [`ui/dr-ui/src/develop.rs:6026`](../ui/dr-ui/src/develop.rs#L6026), [`ui/dr-ui/src/develop.rs:7354`](../ui/dr-ui/src/develop.rs#L7354), [`ui/dr-ui/src/develop.rs:7388`](../ui/dr-ui/src/develop.rs#L7388), [`ui/dr-ui/src/lib.rs:1021`](../ui/dr-ui/src/lib.rs#L1021), [`ui/dr-ui/src/lib.rs:1080`](../ui/dr-ui/src/lib.rs#L1080), [`ui/dr-ui/src/lib.rs:95`](../ui/dr-ui/src/lib.rs#L95) | | 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:497`](../core/dr-pipeline/src/operation.rs#L497), [`core/dr-types/src/colour.rs:1`](../core/dr-types/src/colour.rs#L1), [`ui/dr-ui/src/develop.rs:4051`](../ui/dr-ui/src/develop.rs#L4051), [`ui/dr-ui/src/develop.rs:8967`](../ui/dr-ui/src/develop.rs#L8967), [`ui/dr-ui/src/lib.rs:1913`](../ui/dr-ui/src/lib.rs#L1913), [`ui/dr-ui/src/lib.rs:3696`](../ui/dr-ui/src/lib.rs#L3696) | -| 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:4105`](../ui/dr-ui/src/develop.rs#L4105), [`ui/dr-ui/src/develop.rs:804`](../ui/dr-ui/src/develop.rs#L804), [`ui/dr-ui/src/develop.rs:8641`](../ui/dr-ui/src/develop.rs#L8641), [`ui/dr-ui/src/develop.rs:8673`](../ui/dr-ui/src/develop.rs#L8673), [`ui/dr-ui/src/histogram.rs:1`](../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/lib.rs:2047`](../ui/dr-ui/src/lib.rs#L2047), [`ui/dr-ui/src/lib.rs:424`](../ui/dr-ui/src/lib.rs#L424), [`ui/dr-ui/ui/histogram.slint:184`](../ui/dr-ui/ui/histogram.slint#L184), [`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:3997`](../ui/dr-ui/src/develop.rs#L3997), [`ui/dr-ui/src/develop.rs:4051`](../ui/dr-ui/src/develop.rs#L4051), [`ui/dr-ui/src/develop.rs:8967`](../ui/dr-ui/src/develop.rs#L8967), [`ui/dr-ui/src/develop.rs:9013`](../ui/dr-ui/src/develop.rs#L9013), [`ui/dr-ui/src/develop.rs:9032`](../ui/dr-ui/src/develop.rs#L9032), [`ui/dr-ui/src/develop.rs:957`](../ui/dr-ui/src/develop.rs#L957), [`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:1849`](../ui/dr-ui/src/lib.rs#L1849), [`ui/dr-ui/src/lib.rs:1913`](../ui/dr-ui/src/lib.rs#L1913), [`ui/dr-ui/src/lib.rs:3603`](../ui/dr-ui/src/lib.rs#L3603), [`ui/dr-ui/src/lib.rs:3696`](../ui/dr-ui/src/lib.rs#L3696), [`ui/dr-ui/ui/app.slint:1891`](../ui/dr-ui/ui/app.slint#L1891), [`ui/dr-ui/ui/app.slint:61`](../ui/dr-ui/ui/app.slint#L61), [`ui/dr-ui/ui/settings.slint:155`](../ui/dr-ui/ui/settings.slint#L155), [`ui/dr-ui/ui/settings.slint:895`](../ui/dr-ui/ui/settings.slint#L895) | +| FR-DSP-6 | [`core/dr-pipeline/src/operation.rs:497`](../core/dr-pipeline/src/operation.rs#L497), [`core/dr-types/src/colour.rs:1`](../core/dr-types/src/colour.rs#L1), [`ui/dr-ui/src/develop.rs:4051`](../ui/dr-ui/src/develop.rs#L4051), [`ui/dr-ui/src/develop.rs:8967`](../ui/dr-ui/src/develop.rs#L8967), [`ui/dr-ui/src/lib.rs:1914`](../ui/dr-ui/src/lib.rs#L1914), [`ui/dr-ui/src/lib.rs:3697`](../ui/dr-ui/src/lib.rs#L3697) | +| 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:4105`](../ui/dr-ui/src/develop.rs#L4105), [`ui/dr-ui/src/develop.rs:804`](../ui/dr-ui/src/develop.rs#L804), [`ui/dr-ui/src/develop.rs:8641`](../ui/dr-ui/src/develop.rs#L8641), [`ui/dr-ui/src/develop.rs:8673`](../ui/dr-ui/src/develop.rs#L8673), [`ui/dr-ui/src/histogram.rs:1`](../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/lib.rs:2048`](../ui/dr-ui/src/lib.rs#L2048), [`ui/dr-ui/src/lib.rs:425`](../ui/dr-ui/src/lib.rs#L425), [`ui/dr-ui/ui/histogram.slint:184`](../ui/dr-ui/ui/histogram.slint#L184), [`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:3997`](../ui/dr-ui/src/develop.rs#L3997), [`ui/dr-ui/src/develop.rs:4051`](../ui/dr-ui/src/develop.rs#L4051), [`ui/dr-ui/src/develop.rs:8967`](../ui/dr-ui/src/develop.rs#L8967), [`ui/dr-ui/src/develop.rs:9013`](../ui/dr-ui/src/develop.rs#L9013), [`ui/dr-ui/src/develop.rs:9032`](../ui/dr-ui/src/develop.rs#L9032), [`ui/dr-ui/src/develop.rs:957`](../ui/dr-ui/src/develop.rs#L957), [`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:1850`](../ui/dr-ui/src/lib.rs#L1850), [`ui/dr-ui/src/lib.rs:1914`](../ui/dr-ui/src/lib.rs#L1914), [`ui/dr-ui/src/lib.rs:3604`](../ui/dr-ui/src/lib.rs#L3604), [`ui/dr-ui/src/lib.rs:3697`](../ui/dr-ui/src/lib.rs#L3697), [`ui/dr-ui/ui/app.slint:1897`](../ui/dr-ui/ui/app.slint#L1897), [`ui/dr-ui/ui/app.slint:61`](../ui/dr-ui/ui/app.slint#L61), [`ui/dr-ui/ui/settings.slint:155`](../ui/dr-ui/ui/settings.slint#L155), [`ui/dr-ui/ui/settings.slint:895`](../ui/dr-ui/ui/settings.slint#L895) | | 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:2450`](../core/dr-gpu/src/adjust.rs#L2450), [`core/dr-pipeline/src/graph.rs:835`](../core/dr-pipeline/src/graph.rs#L835), [`core/dr-pipeline/src/graph.rs:925`](../core/dr-pipeline/src/graph.rs#L925), [`core/dr-pipeline/src/operation.rs:497`](../core/dr-pipeline/src/operation.rs#L497), [`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:934`](../core/dr-types/src/settings.rs#L934), [`ui/dr-ui/src/develop.rs:9032`](../ui/dr-ui/src/develop.rs#L9032), [`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:1003`](../core/dr-types/src/settings.rs#L1003), [`core/dr-types/src/settings.rs:1072`](../core/dr-types/src/settings.rs#L1072), [`core/dr-types/src/settings.rs:1100`](../core/dr-types/src/settings.rs#L1100), [`core/dr-types/src/settings.rs:1111`](../core/dr-types/src/settings.rs#L1111), [`core/dr-types/src/settings.rs:1117`](../core/dr-types/src/settings.rs#L1117), [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:979`](../core/dr-types/src/settings.rs#L979), [`core/dr-types/src/settings.rs:987`](../core/dr-types/src/settings.rs#L987), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:274`](../ui/dr-ui/src/settings_ui.rs#L274), [`ui/dr-ui/src/settings_ui.rs:287`](../ui/dr-ui/src/settings_ui.rs#L287), [`ui/dr-ui/src/settings_ui.rs:302`](../ui/dr-ui/src/settings_ui.rs#L302), [`ui/dr-ui/src/settings_ui.rs:701`](../ui/dr-ui/src/settings_ui.rs#L701), [`ui/dr-ui/ui/settings.slint:798`](../ui/dr-ui/ui/settings.slint#L798), [`ui/dr-ui/ui/settings.slint:808`](../ui/dr-ui/ui/settings.slint#L808) | | 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:601`](../ui/dr-ui/src/lib.rs#L601), [`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:815`](../ui/dr-ui/src/settings_ui.rs#L815) | -| 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:992`](../ui/dr-ui/src/export.rs#L992), [`ui/dr-ui/src/lib.rs:262`](../ui/dr-ui/src/lib.rs#L262), [`ui/dr-ui/src/lib.rs:2752`](../ui/dr-ui/src/lib.rs#L2752), [`ui/dr-ui/src/lib.rs:601`](../ui/dr-ui/src/lib.rs#L601), [`ui/dr-ui/src/lib.rs:647`](../ui/dr-ui/src/lib.rs#L647), [`ui/dr-ui/src/lib.rs:674`](../ui/dr-ui/src/lib.rs#L674), [`ui/dr-ui/src/library_ui.rs:4275`](../ui/dr-ui/src/library_ui.rs#L4275), [`ui/dr-ui/src/library_ui.rs:719`](../ui/dr-ui/src/library_ui.rs#L719), [`ui/dr-ui/src/library_ui.rs:8026`](../ui/dr-ui/src/library_ui.rs#L8026), [`ui/dr-ui/src/library_ui.rs:8103`](../ui/dr-ui/src/library_ui.rs#L8103), [`ui/dr-ui/src/library_ui.rs:8115`](../ui/dr-ui/src/library_ui.rs#L8115), [`ui/dr-ui/src/library_ui.rs:819`](../ui/dr-ui/src/library_ui.rs#L819), [`ui/dr-ui/src/library_ui.rs:876`](../ui/dr-ui/src/library_ui.rs#L876), [`ui/dr-ui/ui/app.slint:1091`](../ui/dr-ui/ui/app.slint#L1091), [`ui/dr-ui/ui/app.slint:1630`](../ui/dr-ui/ui/app.slint#L1630), [`ui/dr-ui/ui/library.slint:1583`](../ui/dr-ui/ui/library.slint#L1583), [`ui/dr-ui/ui/library.slint:4278`](../ui/dr-ui/ui/library.slint#L4278) | -| FR-EXP-8 | [`core/dr-decode/src/lib.rs:330`](../core/dr-decode/src/lib.rs#L330), [`core/dr-decode/src/lib.rs:354`](../core/dr-decode/src/lib.rs#L354), [`core/dr-decode/src/lib.rs:368`](../core/dr-decode/src/lib.rs#L368), [`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:655`](../core/dr-types/src/lib.rs#L655), [`core/dr-types/src/settings.rs:647`](../core/dr-types/src/settings.rs#L647), [`ui/dr-ui/src/develop.rs:4539`](../ui/dr-ui/src/develop.rs#L4539), [`ui/dr-ui/src/develop.rs:4651`](../ui/dr-ui/src/develop.rs#L4651), [`ui/dr-ui/src/develop.rs:729`](../ui/dr-ui/src/develop.rs#L729), [`ui/dr-ui/src/export.rs:467`](../ui/dr-ui/src/export.rs#L467), [`ui/dr-ui/src/export.rs:634`](../ui/dr-ui/src/export.rs#L634), [`ui/dr-ui/src/export.rs:680`](../ui/dr-ui/src/export.rs#L680), [`ui/dr-ui/src/export.rs:702`](../ui/dr-ui/src/export.rs#L702), [`ui/dr-ui/src/export.rs:826`](../ui/dr-ui/src/export.rs#L826), [`ui/dr-ui/src/export.rs:844`](../ui/dr-ui/src/export.rs#L844), [`ui/dr-ui/src/lib.rs:262`](../ui/dr-ui/src/lib.rs#L262), [`ui/dr-ui/src/lib.rs:285`](../ui/dr-ui/src/lib.rs#L285), [`ui/dr-ui/src/lib.rs:633`](../ui/dr-ui/src/lib.rs#L633), [`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:510`](../core/dr-decode/src/lib.rs#L510), [`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:1106`](../core/dr-gpu/src/adjust.rs#L1106), [`ui/dr-ui/examples/face_native.rs:1`](../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/develop.rs:4672`](../ui/dr-ui/src/develop.rs#L4672), [`ui/dr-ui/src/develop.rs:4710`](../ui/dr-ui/src/develop.rs#L4710), [`ui/dr-ui/src/develop.rs:6878`](../ui/dr-ui/src/develop.rs#L6878), [`ui/dr-ui/src/lib.rs:601`](../ui/dr-ui/src/lib.rs#L601), [`ui/dr-ui/src/library.rs:4052`](../ui/dr-ui/src/library.rs#L4052), [`ui/dr-ui/src/library.rs:4522`](../ui/dr-ui/src/library.rs#L4522), [`ui/dr-ui/src/library.rs:4558`](../ui/dr-ui/src/library.rs#L4558), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../ui/dr-ui/tests/export_ignores_the_viewport.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:602`](../ui/dr-ui/src/lib.rs#L602), [`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:815`](../ui/dr-ui/src/settings_ui.rs#L815) | +| 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:992`](../ui/dr-ui/src/export.rs#L992), [`ui/dr-ui/src/lib.rs:263`](../ui/dr-ui/src/lib.rs#L263), [`ui/dr-ui/src/lib.rs:2753`](../ui/dr-ui/src/lib.rs#L2753), [`ui/dr-ui/src/lib.rs:602`](../ui/dr-ui/src/lib.rs#L602), [`ui/dr-ui/src/lib.rs:648`](../ui/dr-ui/src/lib.rs#L648), [`ui/dr-ui/src/lib.rs:675`](../ui/dr-ui/src/lib.rs#L675), [`ui/dr-ui/src/library_ui.rs:4275`](../ui/dr-ui/src/library_ui.rs#L4275), [`ui/dr-ui/src/library_ui.rs:719`](../ui/dr-ui/src/library_ui.rs#L719), [`ui/dr-ui/src/library_ui.rs:8057`](../ui/dr-ui/src/library_ui.rs#L8057), [`ui/dr-ui/src/library_ui.rs:8134`](../ui/dr-ui/src/library_ui.rs#L8134), [`ui/dr-ui/src/library_ui.rs:8146`](../ui/dr-ui/src/library_ui.rs#L8146), [`ui/dr-ui/src/library_ui.rs:819`](../ui/dr-ui/src/library_ui.rs#L819), [`ui/dr-ui/src/library_ui.rs:876`](../ui/dr-ui/src/library_ui.rs#L876), [`ui/dr-ui/ui/app.slint:1095`](../ui/dr-ui/ui/app.slint#L1095), [`ui/dr-ui/ui/app.slint:1634`](../ui/dr-ui/ui/app.slint#L1634), [`ui/dr-ui/ui/library.slint:1588`](../ui/dr-ui/ui/library.slint#L1588), [`ui/dr-ui/ui/library.slint:4308`](../ui/dr-ui/ui/library.slint#L4308) | +| FR-EXP-8 | [`core/dr-decode/src/lib.rs:330`](../core/dr-decode/src/lib.rs#L330), [`core/dr-decode/src/lib.rs:354`](../core/dr-decode/src/lib.rs#L354), [`core/dr-decode/src/lib.rs:368`](../core/dr-decode/src/lib.rs#L368), [`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:655`](../core/dr-types/src/lib.rs#L655), [`core/dr-types/src/settings.rs:647`](../core/dr-types/src/settings.rs#L647), [`ui/dr-ui/src/develop.rs:4539`](../ui/dr-ui/src/develop.rs#L4539), [`ui/dr-ui/src/develop.rs:4651`](../ui/dr-ui/src/develop.rs#L4651), [`ui/dr-ui/src/develop.rs:729`](../ui/dr-ui/src/develop.rs#L729), [`ui/dr-ui/src/export.rs:467`](../ui/dr-ui/src/export.rs#L467), [`ui/dr-ui/src/export.rs:634`](../ui/dr-ui/src/export.rs#L634), [`ui/dr-ui/src/export.rs:680`](../ui/dr-ui/src/export.rs#L680), [`ui/dr-ui/src/export.rs:702`](../ui/dr-ui/src/export.rs#L702), [`ui/dr-ui/src/export.rs:826`](../ui/dr-ui/src/export.rs#L826), [`ui/dr-ui/src/export.rs:844`](../ui/dr-ui/src/export.rs#L844), [`ui/dr-ui/src/lib.rs:263`](../ui/dr-ui/src/lib.rs#L263), [`ui/dr-ui/src/lib.rs:286`](../ui/dr-ui/src/lib.rs#L286), [`ui/dr-ui/src/lib.rs:634`](../ui/dr-ui/src/lib.rs#L634), [`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:510`](../core/dr-decode/src/lib.rs#L510), [`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:1106`](../core/dr-gpu/src/adjust.rs#L1106), [`ui/dr-ui/examples/face_native.rs:1`](../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/develop.rs:4672`](../ui/dr-ui/src/develop.rs#L4672), [`ui/dr-ui/src/develop.rs:4710`](../ui/dr-ui/src/develop.rs#L4710), [`ui/dr-ui/src/develop.rs:6878`](../ui/dr-ui/src/develop.rs#L6878), [`ui/dr-ui/src/lib.rs:602`](../ui/dr-ui/src/lib.rs#L602), [`ui/dr-ui/src/library.rs:4123`](../ui/dr-ui/src/library.rs#L4123), [`ui/dr-ui/src/library.rs:4603`](../ui/dr-ui/src/library.rs#L4603), [`ui/dr-ui/src/library.rs:4639`](../ui/dr-ui/src/library.rs#L4639), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | | 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:361`](../core/dr-sync/src/account.rs#L361), [`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) | -| FR-NC-10 | [`core/dr-sync/src/account.rs:226`](../core/dr-sync/src/account.rs#L226), [`ui/dr-ui/src/export.rs:1`](../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/lib.rs:674`](../ui/dr-ui/src/lib.rs#L674), [`ui/dr-ui/src/library.rs:1170`](../ui/dr-ui/src/library.rs#L1170), [`ui/dr-ui/src/library.rs:2463`](../ui/dr-ui/src/library.rs#L2463), [`ui/dr-ui/src/library.rs:589`](../ui/dr-ui/src/library.rs#L589), [`ui/dr-ui/src/library.rs:916`](../ui/dr-ui/src/library.rs#L916), [`ui/dr-ui/src/library_ui.rs:2062`](../ui/dr-ui/src/library_ui.rs#L2062), [`ui/dr-ui/src/library_ui.rs:4275`](../ui/dr-ui/src/library_ui.rs#L4275), [`ui/dr-ui/src/library_ui.rs:660`](../ui/dr-ui/src/library_ui.rs#L660), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1) | +| FR-NC-10 | [`core/dr-sync/src/account.rs:226`](../core/dr-sync/src/account.rs#L226), [`ui/dr-ui/src/export.rs:1`](../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/lib.rs:675`](../ui/dr-ui/src/lib.rs#L675), [`ui/dr-ui/src/library.rs:1234`](../ui/dr-ui/src/library.rs#L1234), [`ui/dr-ui/src/library.rs:2527`](../ui/dr-ui/src/library.rs#L2527), [`ui/dr-ui/src/library.rs:653`](../ui/dr-ui/src/library.rs#L653), [`ui/dr-ui/src/library.rs:980`](../ui/dr-ui/src/library.rs#L980), [`ui/dr-ui/src/library_ui.rs:2062`](../ui/dr-ui/src/library_ui.rs#L2062), [`ui/dr-ui/src/library_ui.rs:4275`](../ui/dr-ui/src/library_ui.rs#L4275), [`ui/dr-ui/src/library_ui.rs:660`](../ui/dr-ui/src/library_ui.rs#L660), [`ui/dr-ui/src/sidecar_cache.rs:1`](../ui/dr-ui/src/sidecar_cache.rs#L1) | | 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:1022`](../core/dr-sync-nextcloud/src/lib.rs#L1022), [`core/dr-sync-nextcloud/src/lib.rs:40`](../core/dr-sync-nextcloud/src/lib.rs#L40), [`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:87`](../core/dr-sync/src/account.rs#L87), [`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:304`](../core/dr-sync/src/account.rs#L304), [`core/dr-sync/src/account.rs:361`](../core/dr-sync/src/account.rs#L361), [`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), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:3796`](../ui/dr-ui/src/library.rs#L3796), [`ui/dr-ui/src/library.rs:4708`](../ui/dr-ui/src/library.rs#L4708), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/src/library_ui.rs:6052`](../ui/dr-ui/src/library_ui.rs#L6052), [`ui/dr-ui/ui/app.slint:383`](../ui/dr-ui/ui/app.slint#L383), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425), [`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), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`ui/dr-ui/src/library.rs:1`](../ui/dr-ui/src/library.rs#L1), [`ui/dr-ui/src/library.rs:3860`](../ui/dr-ui/src/library.rs#L3860), [`ui/dr-ui/src/library.rs:4798`](../ui/dr-ui/src/library.rs#L4798), [`ui/dr-ui/src/library_ui.rs:1`](../ui/dr-ui/src/library_ui.rs#L1), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/src/library_ui.rs:6053`](../ui/dr-ui/src/library_ui.rs#L6053), [`ui/dr-ui/ui/app.slint:383`](../ui/dr-ui/ui/app.slint#L383), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425), [`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:129`](../core/dr-sync/src/scan.rs#L129), [`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:1430`](../core/dr-catalog/src/schema.rs#L1430), [`core/dr-catalog/src/schema.rs:975`](../core/dr-catalog/src/schema.rs#L975), [`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:2940`](../ui/dr-ui/src/collections_ui.rs#L2940), [`ui/dr-ui/src/collections_ui.rs:3182`](../ui/dr-ui/src/collections_ui.rs#L3182), [`ui/dr-ui/src/collections_ui.rs:4083`](../ui/dr-ui/src/collections_ui.rs#L4083), [`ui/dr-ui/src/collections_ui.rs:785`](../ui/dr-ui/src/collections_ui.rs#L785), [`ui/dr-ui/src/collections_ui.rs:856`](../ui/dr-ui/src/collections_ui.rs#L856), [`ui/dr-ui/src/lib.rs:1318`](../ui/dr-ui/src/lib.rs#L1318), [`ui/dr-ui/src/lib.rs:2426`](../ui/dr-ui/src/lib.rs#L2426), [`ui/dr-ui/src/lib.rs:2497`](../ui/dr-ui/src/lib.rs#L2497), [`ui/dr-ui/src/lib.rs:3793`](../ui/dr-ui/src/lib.rs#L3793), [`ui/dr-ui/src/lib.rs:3794`](../ui/dr-ui/src/lib.rs#L3794), [`ui/dr-ui/src/lib.rs:3833`](../ui/dr-ui/src/lib.rs#L3833), [`ui/dr-ui/src/library.rs:2109`](../ui/dr-ui/src/library.rs#L2109), [`ui/dr-ui/src/library.rs:2132`](../ui/dr-ui/src/library.rs#L2132), [`ui/dr-ui/src/library.rs:2407`](../ui/dr-ui/src/library.rs#L2407), [`ui/dr-ui/src/library.rs:2588`](../ui/dr-ui/src/library.rs#L2588), [`ui/dr-ui/src/library.rs:2725`](../ui/dr-ui/src/library.rs#L2725), [`ui/dr-ui/src/library.rs:2740`](../ui/dr-ui/src/library.rs#L2740), [`ui/dr-ui/src/library_ui.rs:1487`](../ui/dr-ui/src/library_ui.rs#L1487), [`ui/dr-ui/src/library_ui.rs:1560`](../ui/dr-ui/src/library_ui.rs#L1560), [`ui/dr-ui/src/library_ui.rs:1661`](../ui/dr-ui/src/library_ui.rs#L1661), [`ui/dr-ui/src/library_ui.rs:1716`](../ui/dr-ui/src/library_ui.rs#L1716), [`ui/dr-ui/src/library_ui.rs:1851`](../ui/dr-ui/src/library_ui.rs#L1851), [`ui/dr-ui/src/library_ui.rs:1969`](../ui/dr-ui/src/library_ui.rs#L1969), [`ui/dr-ui/src/library_ui.rs:2736`](../ui/dr-ui/src/library_ui.rs#L2736), [`ui/dr-ui/src/library_ui.rs:344`](../ui/dr-ui/src/library_ui.rs#L344), [`ui/dr-ui/src/library_ui.rs:355`](../ui/dr-ui/src/library_ui.rs#L355), [`ui/dr-ui/src/library_ui.rs:370`](../ui/dr-ui/src/library_ui.rs#L370), [`ui/dr-ui/src/library_ui.rs:379`](../ui/dr-ui/src/library_ui.rs#L379), [`ui/dr-ui/src/library_ui.rs:387`](../ui/dr-ui/src/library_ui.rs#L387), [`ui/dr-ui/src/library_ui.rs:515`](../ui/dr-ui/src/library_ui.rs#L515), [`ui/dr-ui/src/library_ui.rs:525`](../ui/dr-ui/src/library_ui.rs#L525), [`ui/dr-ui/src/library_ui.rs:540`](../ui/dr-ui/src/library_ui.rs#L540), [`ui/dr-ui/src/library_ui.rs:587`](../ui/dr-ui/src/library_ui.rs#L587), [`ui/dr-ui/src/library_ui.rs:602`](../ui/dr-ui/src/library_ui.rs#L602), [`ui/dr-ui/src/library_ui.rs:676`](../ui/dr-ui/src/library_ui.rs#L676), [`ui/dr-ui/src/library_ui.rs:6889`](../ui/dr-ui/src/library_ui.rs#L6889), [`ui/dr-ui/src/library_ui.rs:6907`](../ui/dr-ui/src/library_ui.rs#L6907), [`ui/dr-ui/src/library_ui.rs:707`](../ui/dr-ui/src/library_ui.rs#L707), [`ui/dr-ui/src/library_ui.rs:719`](../ui/dr-ui/src/library_ui.rs#L719), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1), [`ui/dr-ui/src/settings_ui.rs:157`](../ui/dr-ui/src/settings_ui.rs#L157), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:524`](../ui/dr-ui/src/settings_ui.rs#L524), [`ui/dr-ui/ui/app.slint:1524`](../ui/dr-ui/ui/app.slint#L1524), [`ui/dr-ui/ui/app.slint:3073`](../ui/dr-ui/ui/app.slint#L3073), [`ui/dr-ui/ui/app.slint:535`](../ui/dr-ui/ui/app.slint#L535), [`ui/dr-ui/ui/app.slint:543`](../ui/dr-ui/ui/app.slint#L543), [`ui/dr-ui/ui/app.slint:549`](../ui/dr-ui/ui/app.slint#L549), [`ui/dr-ui/ui/collections.slint:1037`](../ui/dr-ui/ui/collections.slint#L1037), [`ui/dr-ui/ui/collections.slint:1048`](../ui/dr-ui/ui/collections.slint#L1048), [`ui/dr-ui/ui/collections.slint:1127`](../ui/dr-ui/ui/collections.slint#L1127), [`ui/dr-ui/ui/collections.slint:272`](../ui/dr-ui/ui/collections.slint#L272), [`ui/dr-ui/ui/collections.slint:424`](../ui/dr-ui/ui/collections.slint#L424), [`ui/dr-ui/ui/collections.slint:433`](../ui/dr-ui/ui/collections.slint#L433), [`ui/dr-ui/ui/collections.slint:436`](../ui/dr-ui/ui/collections.slint#L436), [`ui/dr-ui/ui/collections.slint:482`](../ui/dr-ui/ui/collections.slint#L482), [`ui/dr-ui/ui/collections.slint:52`](../ui/dr-ui/ui/collections.slint#L52), [`ui/dr-ui/ui/collections.slint:720`](../ui/dr-ui/ui/collections.slint#L720), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/collections.slint:91`](../ui/dr-ui/ui/collections.slint#L91), [`ui/dr-ui/ui/icons.slint:262`](../ui/dr-ui/ui/icons.slint#L262), [`ui/dr-ui/ui/settings.slint:108`](../ui/dr-ui/ui/settings.slint#L108), [`ui/dr-ui/ui/settings.slint:603`](../ui/dr-ui/ui/settings.slint#L603) | +| 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:1445`](../core/dr-catalog/src/schema.rs#L1445), [`core/dr-catalog/src/schema.rs:990`](../core/dr-catalog/src/schema.rs#L990), [`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:2940`](../ui/dr-ui/src/collections_ui.rs#L2940), [`ui/dr-ui/src/collections_ui.rs:3182`](../ui/dr-ui/src/collections_ui.rs#L3182), [`ui/dr-ui/src/collections_ui.rs:4083`](../ui/dr-ui/src/collections_ui.rs#L4083), [`ui/dr-ui/src/collections_ui.rs:785`](../ui/dr-ui/src/collections_ui.rs#L785), [`ui/dr-ui/src/collections_ui.rs:856`](../ui/dr-ui/src/collections_ui.rs#L856), [`ui/dr-ui/src/lib.rs:1319`](../ui/dr-ui/src/lib.rs#L1319), [`ui/dr-ui/src/lib.rs:2427`](../ui/dr-ui/src/lib.rs#L2427), [`ui/dr-ui/src/lib.rs:2498`](../ui/dr-ui/src/lib.rs#L2498), [`ui/dr-ui/src/lib.rs:3794`](../ui/dr-ui/src/lib.rs#L3794), [`ui/dr-ui/src/lib.rs:3795`](../ui/dr-ui/src/lib.rs#L3795), [`ui/dr-ui/src/lib.rs:3834`](../ui/dr-ui/src/lib.rs#L3834), [`ui/dr-ui/src/library.rs:2173`](../ui/dr-ui/src/library.rs#L2173), [`ui/dr-ui/src/library.rs:2196`](../ui/dr-ui/src/library.rs#L2196), [`ui/dr-ui/src/library.rs:2471`](../ui/dr-ui/src/library.rs#L2471), [`ui/dr-ui/src/library.rs:2652`](../ui/dr-ui/src/library.rs#L2652), [`ui/dr-ui/src/library.rs:2789`](../ui/dr-ui/src/library.rs#L2789), [`ui/dr-ui/src/library.rs:2804`](../ui/dr-ui/src/library.rs#L2804), [`ui/dr-ui/src/library_ui.rs:1487`](../ui/dr-ui/src/library_ui.rs#L1487), [`ui/dr-ui/src/library_ui.rs:1560`](../ui/dr-ui/src/library_ui.rs#L1560), [`ui/dr-ui/src/library_ui.rs:1661`](../ui/dr-ui/src/library_ui.rs#L1661), [`ui/dr-ui/src/library_ui.rs:1716`](../ui/dr-ui/src/library_ui.rs#L1716), [`ui/dr-ui/src/library_ui.rs:1851`](../ui/dr-ui/src/library_ui.rs#L1851), [`ui/dr-ui/src/library_ui.rs:1969`](../ui/dr-ui/src/library_ui.rs#L1969), [`ui/dr-ui/src/library_ui.rs:2736`](../ui/dr-ui/src/library_ui.rs#L2736), [`ui/dr-ui/src/library_ui.rs:344`](../ui/dr-ui/src/library_ui.rs#L344), [`ui/dr-ui/src/library_ui.rs:355`](../ui/dr-ui/src/library_ui.rs#L355), [`ui/dr-ui/src/library_ui.rs:370`](../ui/dr-ui/src/library_ui.rs#L370), [`ui/dr-ui/src/library_ui.rs:379`](../ui/dr-ui/src/library_ui.rs#L379), [`ui/dr-ui/src/library_ui.rs:387`](../ui/dr-ui/src/library_ui.rs#L387), [`ui/dr-ui/src/library_ui.rs:515`](../ui/dr-ui/src/library_ui.rs#L515), [`ui/dr-ui/src/library_ui.rs:525`](../ui/dr-ui/src/library_ui.rs#L525), [`ui/dr-ui/src/library_ui.rs:540`](../ui/dr-ui/src/library_ui.rs#L540), [`ui/dr-ui/src/library_ui.rs:587`](../ui/dr-ui/src/library_ui.rs#L587), [`ui/dr-ui/src/library_ui.rs:602`](../ui/dr-ui/src/library_ui.rs#L602), [`ui/dr-ui/src/library_ui.rs:676`](../ui/dr-ui/src/library_ui.rs#L676), [`ui/dr-ui/src/library_ui.rs:6907`](../ui/dr-ui/src/library_ui.rs#L6907), [`ui/dr-ui/src/library_ui.rs:6925`](../ui/dr-ui/src/library_ui.rs#L6925), [`ui/dr-ui/src/library_ui.rs:707`](../ui/dr-ui/src/library_ui.rs#L707), [`ui/dr-ui/src/library_ui.rs:719`](../ui/dr-ui/src/library_ui.rs#L719), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1), [`ui/dr-ui/src/settings_ui.rs:157`](../ui/dr-ui/src/settings_ui.rs#L157), [`ui/dr-ui/src/settings_ui.rs:1`](../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:524`](../ui/dr-ui/src/settings_ui.rs#L524), [`ui/dr-ui/ui/app.slint:1528`](../ui/dr-ui/ui/app.slint#L1528), [`ui/dr-ui/ui/app.slint:3079`](../ui/dr-ui/ui/app.slint#L3079), [`ui/dr-ui/ui/app.slint:535`](../ui/dr-ui/ui/app.slint#L535), [`ui/dr-ui/ui/app.slint:543`](../ui/dr-ui/ui/app.slint#L543), [`ui/dr-ui/ui/app.slint:549`](../ui/dr-ui/ui/app.slint#L549), [`ui/dr-ui/ui/collections.slint:1037`](../ui/dr-ui/ui/collections.slint#L1037), [`ui/dr-ui/ui/collections.slint:1048`](../ui/dr-ui/ui/collections.slint#L1048), [`ui/dr-ui/ui/collections.slint:1127`](../ui/dr-ui/ui/collections.slint#L1127), [`ui/dr-ui/ui/collections.slint:272`](../ui/dr-ui/ui/collections.slint#L272), [`ui/dr-ui/ui/collections.slint:424`](../ui/dr-ui/ui/collections.slint#L424), [`ui/dr-ui/ui/collections.slint:433`](../ui/dr-ui/ui/collections.slint#L433), [`ui/dr-ui/ui/collections.slint:436`](../ui/dr-ui/ui/collections.slint#L436), [`ui/dr-ui/ui/collections.slint:482`](../ui/dr-ui/ui/collections.slint#L482), [`ui/dr-ui/ui/collections.slint:52`](../ui/dr-ui/ui/collections.slint#L52), [`ui/dr-ui/ui/collections.slint:720`](../ui/dr-ui/ui/collections.slint#L720), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/collections.slint:91`](../ui/dr-ui/ui/collections.slint#L91), [`ui/dr-ui/ui/icons.slint:262`](../ui/dr-ui/ui/icons.slint#L262), [`ui/dr-ui/ui/settings.slint:108`](../ui/dr-ui/ui/settings.slint#L108), [`ui/dr-ui/ui/settings.slint:603`](../ui/dr-ui/ui/settings.slint#L603) | | FR-NC-6b | [`ui/dr-ui/src/library_ui.rs:1716`](../ui/dr-ui/src/library_ui.rs#L1716), [`ui/dr-ui/src/memory.rs:1`](../ui/dr-ui/src/memory.rs#L1) | -| 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:818`](../core/dr-sync-folder/src/lib.rs#L818), [`core/dr-sync-folder/src/lib.rs:857`](../core/dr-sync-folder/src/lib.rs#L857), [`core/dr-sync-folder/src/vfs.rs:1`](../core/dr-sync-folder/src/vfs.rs#L1), [`core/dr-sync-nextcloud/src/desktop_client.rs:172`](../core/dr-sync-nextcloud/src/desktop_client.rs#L172), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`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:122`](../core/dr-types/src/lib.rs#L122), [`core/dr-types/src/lib.rs:204`](../core/dr-types/src/lib.rs#L204), [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1), [`ui/dr-ui/src/collections_ui.rs:4083`](../ui/dr-ui/src/collections_ui.rs#L4083), [`ui/dr-ui/src/collections_ui.rs:785`](../ui/dr-ui/src/collections_ui.rs#L785), [`ui/dr-ui/src/collections_ui.rs:856`](../ui/dr-ui/src/collections_ui.rs#L856), [`ui/dr-ui/src/derived_sync.rs:1031`](../ui/dr-ui/src/derived_sync.rs#L1031), [`ui/dr-ui/src/derived_sync.rs:631`](../ui/dr-ui/src/derived_sync.rs#L631), [`ui/dr-ui/src/library.rs:1020`](../ui/dr-ui/src/library.rs#L1020), [`ui/dr-ui/src/library.rs:2229`](../ui/dr-ui/src/library.rs#L2229), [`ui/dr-ui/src/library.rs:2319`](../ui/dr-ui/src/library.rs#L2319), [`ui/dr-ui/src/library.rs:4296`](../ui/dr-ui/src/library.rs#L4296), [`ui/dr-ui/src/library.rs:4828`](../ui/dr-ui/src/library.rs#L4828), [`ui/dr-ui/src/library_ui.rs:1487`](../ui/dr-ui/src/library_ui.rs#L1487), [`ui/dr-ui/src/library_ui.rs:1560`](../ui/dr-ui/src/library_ui.rs#L1560), [`ui/dr-ui/src/library_ui.rs:1759`](../ui/dr-ui/src/library_ui.rs#L1759), [`ui/dr-ui/src/remote.rs:40`](../ui/dr-ui/src/remote.rs#L40), [`ui/dr-ui/ui/collections.slint:272`](../ui/dr-ui/ui/collections.slint#L272), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/icons.slint:262`](../ui/dr-ui/ui/icons.slint#L262) | +| 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:818`](../core/dr-sync-folder/src/lib.rs#L818), [`core/dr-sync-folder/src/lib.rs:857`](../core/dr-sync-folder/src/lib.rs#L857), [`core/dr-sync-folder/src/vfs.rs:1`](../core/dr-sync-folder/src/vfs.rs#L1), [`core/dr-sync-nextcloud/src/desktop_client.rs:172`](../core/dr-sync-nextcloud/src/desktop_client.rs#L172), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`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:122`](../core/dr-types/src/lib.rs#L122), [`core/dr-types/src/lib.rs:204`](../core/dr-types/src/lib.rs#L204), [`ui/dr-ui/src/activity.rs:1`](../ui/dr-ui/src/activity.rs#L1), [`ui/dr-ui/src/collections_ui.rs:4083`](../ui/dr-ui/src/collections_ui.rs#L4083), [`ui/dr-ui/src/collections_ui.rs:785`](../ui/dr-ui/src/collections_ui.rs#L785), [`ui/dr-ui/src/collections_ui.rs:856`](../ui/dr-ui/src/collections_ui.rs#L856), [`ui/dr-ui/src/derived_sync.rs:1031`](../ui/dr-ui/src/derived_sync.rs#L1031), [`ui/dr-ui/src/derived_sync.rs:631`](../ui/dr-ui/src/derived_sync.rs#L631), [`ui/dr-ui/src/library.rs:1084`](../ui/dr-ui/src/library.rs#L1084), [`ui/dr-ui/src/library.rs:2293`](../ui/dr-ui/src/library.rs#L2293), [`ui/dr-ui/src/library.rs:2383`](../ui/dr-ui/src/library.rs#L2383), [`ui/dr-ui/src/library.rs:4369`](../ui/dr-ui/src/library.rs#L4369), [`ui/dr-ui/src/library.rs:4918`](../ui/dr-ui/src/library.rs#L4918), [`ui/dr-ui/src/library_ui.rs:1487`](../ui/dr-ui/src/library_ui.rs#L1487), [`ui/dr-ui/src/library_ui.rs:1560`](../ui/dr-ui/src/library_ui.rs#L1560), [`ui/dr-ui/src/library_ui.rs:1759`](../ui/dr-ui/src/library_ui.rs#L1759), [`ui/dr-ui/src/remote.rs:40`](../ui/dr-ui/src/remote.rs#L40), [`ui/dr-ui/ui/collections.slint:272`](../ui/dr-ui/ui/collections.slint#L272), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/icons.slint:262`](../ui/dr-ui/ui/icons.slint#L262) | | 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:4708`](../ui/dr-ui/src/library.rs#L4708), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425) | -| 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:353`](../core/dr-types/src/settings.rs#L353), [`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:1527`](../ui/dr-ui/src/lib.rs#L1527), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | -| FR-NC-7b | [`core/dr-ingest/src/lib.rs:733`](../core/dr-ingest/src/lib.rs#L733), [`core/dr-sync/src/upload.rs:1`](../core/dr-sync/src/upload.rs#L1), [`ui/dr-ui/src/import.rs:122`](../ui/dr-ui/src/import.rs#L122), [`ui/dr-ui/src/import.rs:336`](../ui/dr-ui/src/import.rs#L336), [`ui/dr-ui/src/import.rs:584`](../ui/dr-ui/src/import.rs#L584), [`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:1527`](../ui/dr-ui/src/lib.rs#L1527) | -| FR-NC-8 | [`core/dr-catalog/src/rating.rs:204`](../core/dr-catalog/src/rating.rs#L204), [`core/dr-catalog/src/rating.rs:66`](../core/dr-catalog/src/rating.rs#L66), [`core/dr-catalog/src/rating.rs:929`](../core/dr-catalog/src/rating.rs#L929), [`core/dr-catalog/src/schema.rs:202`](../core/dr-catalog/src/schema.rs#L202), [`core/dr-pipeline/src/sidecar.rs:122`](../core/dr-pipeline/src/sidecar.rs#L122), [`core/dr-pipeline/src/sidecar.rs:2944`](../core/dr-pipeline/src/sidecar.rs#L2944), [`core/dr-pipeline/src/sidecar.rs:645`](../core/dr-pipeline/src/sidecar.rs#L645), [`core/dr-pipeline/src/sidecar.rs:720`](../core/dr-pipeline/src/sidecar.rs#L720), [`core/dr-pipeline/src/sidecar.rs:96`](../core/dr-pipeline/src/sidecar.rs#L96), [`ui/dr-ui/src/lib.rs:2396`](../ui/dr-ui/src/lib.rs#L2396), [`ui/dr-ui/src/library.rs:1062`](../ui/dr-ui/src/library.rs#L1062), [`ui/dr-ui/src/library.rs:2518`](../ui/dr-ui/src/library.rs#L2518), [`ui/dr-ui/src/library.rs:500`](../ui/dr-ui/src/library.rs#L500), [`ui/dr-ui/src/library.rs:760`](../ui/dr-ui/src/library.rs#L760), [`ui/dr-ui/src/library.rs:8268`](../ui/dr-ui/src/library.rs#L8268), [`ui/dr-ui/src/library_ui.rs:628`](../ui/dr-ui/src/library_ui.rs#L628), [`ui/dr-ui/src/presets.rs:288`](../ui/dr-ui/src/presets.rs#L288), [`ui/dr-ui/src/presets.rs:336`](../ui/dr-ui/src/presets.rs#L336) | -| FR-NC-9 | [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/rating.rs:204`](../core/dr-catalog/src/rating.rs#L204), [`core/dr-catalog/src/rating.rs:66`](../core/dr-catalog/src/rating.rs#L66), [`core/dr-catalog/src/rating.rs:929`](../core/dr-catalog/src/rating.rs#L929), [`core/dr-catalog/src/schema.rs:202`](../core/dr-catalog/src/schema.rs#L202), [`core/dr-catalog/src/schema.rs:610`](../core/dr-catalog/src/schema.rs#L610), [`core/dr-catalog/src/schema.rs:918`](../core/dr-catalog/src/schema.rs#L918), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-pipeline/src/sidecar.rs:177`](../core/dr-pipeline/src/sidecar.rs#L177), [`core/dr-pipeline/src/sidecar.rs:204`](../core/dr-pipeline/src/sidecar.rs#L204), [`core/dr-pipeline/src/sidecar.rs:2473`](../core/dr-pipeline/src/sidecar.rs#L2473), [`core/dr-pipeline/src/sidecar.rs:2710`](../core/dr-pipeline/src/sidecar.rs#L2710), [`core/dr-pipeline/src/sidecar.rs:2944`](../core/dr-pipeline/src/sidecar.rs#L2944), [`core/dr-pipeline/src/sidecar.rs:380`](../core/dr-pipeline/src/sidecar.rs#L380), [`core/dr-pipeline/src/sidecar.rs:478`](../core/dr-pipeline/src/sidecar.rs#L478), [`core/dr-pipeline/src/sidecar.rs:645`](../core/dr-pipeline/src/sidecar.rs#L645), [`core/dr-pipeline/src/sidecar.rs:695`](../core/dr-pipeline/src/sidecar.rs#L695), [`core/dr-pipeline/src/sidecar.rs:720`](../core/dr-pipeline/src/sidecar.rs#L720), [`core/dr-pipeline/src/spot.rs:245`](../core/dr-pipeline/src/spot.rs#L245), [`core/dr-pipeline/tests/mask_sidecar.rs:1075`](../core/dr-pipeline/tests/mask_sidecar.rs#L1075), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:124`](../core/dr-sync-nextcloud/src/lib.rs#L124), [`core/dr-sync/src/scan.rs:31`](../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../core/dr-sync/src/scan.rs#L926), [`core/dr-xmp/src/lib.rs:733`](../core/dr-xmp/src/lib.rs#L733), [`core/dr-xmp/src/lib.rs:746`](../core/dr-xmp/src/lib.rs#L746), [`ui/dr-ui/src/derived_sync.rs:1059`](../ui/dr-ui/src/derived_sync.rs#L1059), [`ui/dr-ui/src/derived_sync.rs:602`](../ui/dr-ui/src/derived_sync.rs#L602), [`ui/dr-ui/src/derived_sync.rs:631`](../ui/dr-ui/src/derived_sync.rs#L631), [`ui/dr-ui/src/derived_sync.rs:664`](../ui/dr-ui/src/derived_sync.rs#L664), [`ui/dr-ui/src/derived_sync.rs:810`](../ui/dr-ui/src/derived_sync.rs#L810), [`ui/dr-ui/src/library.rs:1062`](../ui/dr-ui/src/library.rs#L1062), [`ui/dr-ui/src/library.rs:1082`](../ui/dr-ui/src/library.rs#L1082), [`ui/dr-ui/src/library.rs:1391`](../ui/dr-ui/src/library.rs#L1391), [`ui/dr-ui/src/library.rs:1426`](../ui/dr-ui/src/library.rs#L1426), [`ui/dr-ui/src/library.rs:2518`](../ui/dr-ui/src/library.rs#L2518), [`ui/dr-ui/src/library.rs:73`](../ui/dr-ui/src/library.rs#L73), [`ui/dr-ui/src/library.rs:760`](../ui/dr-ui/src/library.rs#L760), [`ui/dr-ui/src/library.rs:8100`](../ui/dr-ui/src/library.rs#L8100), [`ui/dr-ui/src/library.rs:8268`](../ui/dr-ui/src/library.rs#L8268), [`ui/dr-ui/src/library.rs:832`](../ui/dr-ui/src/library.rs#L832), [`ui/dr-ui/src/library.rs:916`](../ui/dr-ui/src/library.rs#L916), [`ui/dr-ui/src/library_ui.rs:1344`](../ui/dr-ui/src/library_ui.rs#L1344), [`ui/dr-ui/src/presets.rs:288`](../ui/dr-ui/src/presets.rs#L288), [`ui/dr-ui/src/presets.rs:336`](../ui/dr-ui/src/presets.rs#L336), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/src/xmp_sync.rs:287`](../ui/dr-ui/src/xmp_sync.rs#L287) | -| FR-PLAT-AND-2 | [`core/dr-catalog/src/walk.rs:1022`](../core/dr-catalog/src/walk.rs#L1022), [`core/dr-catalog/src/walk.rs:435`](../core/dr-catalog/src/walk.rs#L435), [`core/dr-sync-folder/src/lib.rs:242`](../core/dr-sync-folder/src/lib.rs#L242), [`core/dr-sync-folder/src/tests.rs:51`](../core/dr-sync-folder/src/tests.rs#L51), [`core/dr-sync/src/error.rs:113`](../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/error.rs:195`](../core/dr-sync/src/error.rs#L195), [`core/dr-sync/src/scan.rs:211`](../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../core/dr-sync/src/scan.rs#L519), [`core/dr-sync/src/scan.rs:545`](../core/dr-sync/src/scan.rs#L545), [`core/dr-sync/src/scan.rs:574`](../core/dr-sync/src/scan.rs#L574), [`ui/dr-ui/src/library.rs:1291`](../ui/dr-ui/src/library.rs#L1291), [`ui/dr-ui/src/library.rs:1344`](../ui/dr-ui/src/library.rs#L1344), [`ui/dr-ui/src/library.rs:1375`](../ui/dr-ui/src/library.rs#L1375), [`ui/dr-ui/src/library.rs:1955`](../ui/dr-ui/src/library.rs#L1955), [`ui/dr-ui/src/library_ui.rs:1315`](../ui/dr-ui/src/library_ui.rs#L1315), [`ui/dr-ui/src/library_ui.rs:1411`](../ui/dr-ui/src/library_ui.rs#L1411), [`ui/dr-ui/src/library_ui.rs:2010`](../ui/dr-ui/src/library_ui.rs#L2010), [`ui/dr-ui/src/library_ui.rs:328`](../ui/dr-ui/src/library_ui.rs#L328), [`ui/dr-ui/src/library_ui.rs:571`](../ui/dr-ui/src/library_ui.rs#L571) | +| 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:4798`](../ui/dr-ui/src/library.rs#L4798), [`ui/dr-ui/src/library_ui.rs:4541`](../ui/dr-ui/src/library_ui.rs#L4541), [`ui/dr-ui/ui/settings.slint:425`](../ui/dr-ui/ui/settings.slint#L425) | +| 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:353`](../core/dr-types/src/settings.rs#L353), [`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:1528`](../ui/dr-ui/src/lib.rs#L1528), [`ui/dr-ui/ui/import.slint:5`](../ui/dr-ui/ui/import.slint#L5) | +| FR-NC-7b | [`core/dr-ingest/src/lib.rs:733`](../core/dr-ingest/src/lib.rs#L733), [`core/dr-sync/src/upload.rs:1`](../core/dr-sync/src/upload.rs#L1), [`ui/dr-ui/src/import.rs:122`](../ui/dr-ui/src/import.rs#L122), [`ui/dr-ui/src/import.rs:336`](../ui/dr-ui/src/import.rs#L336), [`ui/dr-ui/src/import.rs:584`](../ui/dr-ui/src/import.rs#L584), [`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:1528`](../ui/dr-ui/src/lib.rs#L1528) | +| FR-NC-8 | [`core/dr-catalog/src/rating.rs:204`](../core/dr-catalog/src/rating.rs#L204), [`core/dr-catalog/src/rating.rs:66`](../core/dr-catalog/src/rating.rs#L66), [`core/dr-catalog/src/rating.rs:929`](../core/dr-catalog/src/rating.rs#L929), [`core/dr-catalog/src/schema.rs:210`](../core/dr-catalog/src/schema.rs#L210), [`core/dr-pipeline/src/sidecar.rs:122`](../core/dr-pipeline/src/sidecar.rs#L122), [`core/dr-pipeline/src/sidecar.rs:2944`](../core/dr-pipeline/src/sidecar.rs#L2944), [`core/dr-pipeline/src/sidecar.rs:645`](../core/dr-pipeline/src/sidecar.rs#L645), [`core/dr-pipeline/src/sidecar.rs:720`](../core/dr-pipeline/src/sidecar.rs#L720), [`core/dr-pipeline/src/sidecar.rs:96`](../core/dr-pipeline/src/sidecar.rs#L96), [`ui/dr-ui/src/lib.rs:2397`](../ui/dr-ui/src/lib.rs#L2397), [`ui/dr-ui/src/library.rs:1126`](../ui/dr-ui/src/library.rs#L1126), [`ui/dr-ui/src/library.rs:2582`](../ui/dr-ui/src/library.rs#L2582), [`ui/dr-ui/src/library.rs:564`](../ui/dr-ui/src/library.rs#L564), [`ui/dr-ui/src/library.rs:824`](../ui/dr-ui/src/library.rs#L824), [`ui/dr-ui/src/library.rs:8648`](../ui/dr-ui/src/library.rs#L8648), [`ui/dr-ui/src/library_ui.rs:628`](../ui/dr-ui/src/library_ui.rs#L628), [`ui/dr-ui/src/presets.rs:288`](../ui/dr-ui/src/presets.rs#L288), [`ui/dr-ui/src/presets.rs:336`](../ui/dr-ui/src/presets.rs#L336) | +| FR-NC-9 | [`core/dr-catalog/src/merge.rs:1`](../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/rating.rs:204`](../core/dr-catalog/src/rating.rs#L204), [`core/dr-catalog/src/rating.rs:66`](../core/dr-catalog/src/rating.rs#L66), [`core/dr-catalog/src/rating.rs:929`](../core/dr-catalog/src/rating.rs#L929), [`core/dr-catalog/src/schema.rs:210`](../core/dr-catalog/src/schema.rs#L210), [`core/dr-catalog/src/schema.rs:622`](../core/dr-catalog/src/schema.rs#L622), [`core/dr-catalog/src/schema.rs:933`](../core/dr-catalog/src/schema.rs#L933), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-pipeline/src/sidecar.rs:177`](../core/dr-pipeline/src/sidecar.rs#L177), [`core/dr-pipeline/src/sidecar.rs:204`](../core/dr-pipeline/src/sidecar.rs#L204), [`core/dr-pipeline/src/sidecar.rs:2473`](../core/dr-pipeline/src/sidecar.rs#L2473), [`core/dr-pipeline/src/sidecar.rs:2710`](../core/dr-pipeline/src/sidecar.rs#L2710), [`core/dr-pipeline/src/sidecar.rs:2944`](../core/dr-pipeline/src/sidecar.rs#L2944), [`core/dr-pipeline/src/sidecar.rs:380`](../core/dr-pipeline/src/sidecar.rs#L380), [`core/dr-pipeline/src/sidecar.rs:478`](../core/dr-pipeline/src/sidecar.rs#L478), [`core/dr-pipeline/src/sidecar.rs:645`](../core/dr-pipeline/src/sidecar.rs#L645), [`core/dr-pipeline/src/sidecar.rs:695`](../core/dr-pipeline/src/sidecar.rs#L695), [`core/dr-pipeline/src/sidecar.rs:720`](../core/dr-pipeline/src/sidecar.rs#L720), [`core/dr-pipeline/src/spot.rs:245`](../core/dr-pipeline/src/spot.rs#L245), [`core/dr-pipeline/tests/mask_sidecar.rs:1075`](../core/dr-pipeline/tests/mask_sidecar.rs#L1075), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-sync-nextcloud/src/lib.rs:124`](../core/dr-sync-nextcloud/src/lib.rs#L124), [`core/dr-sync/src/scan.rs:31`](../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../core/dr-sync/src/scan.rs#L926), [`core/dr-xmp/src/lib.rs:733`](../core/dr-xmp/src/lib.rs#L733), [`core/dr-xmp/src/lib.rs:746`](../core/dr-xmp/src/lib.rs#L746), [`ui/dr-ui/src/derived_sync.rs:1059`](../ui/dr-ui/src/derived_sync.rs#L1059), [`ui/dr-ui/src/derived_sync.rs:602`](../ui/dr-ui/src/derived_sync.rs#L602), [`ui/dr-ui/src/derived_sync.rs:631`](../ui/dr-ui/src/derived_sync.rs#L631), [`ui/dr-ui/src/derived_sync.rs:664`](../ui/dr-ui/src/derived_sync.rs#L664), [`ui/dr-ui/src/derived_sync.rs:810`](../ui/dr-ui/src/derived_sync.rs#L810), [`ui/dr-ui/src/library.rs:1126`](../ui/dr-ui/src/library.rs#L1126), [`ui/dr-ui/src/library.rs:1146`](../ui/dr-ui/src/library.rs#L1146), [`ui/dr-ui/src/library.rs:1455`](../ui/dr-ui/src/library.rs#L1455), [`ui/dr-ui/src/library.rs:1490`](../ui/dr-ui/src/library.rs#L1490), [`ui/dr-ui/src/library.rs:2582`](../ui/dr-ui/src/library.rs#L2582), [`ui/dr-ui/src/library.rs:73`](../ui/dr-ui/src/library.rs#L73), [`ui/dr-ui/src/library.rs:824`](../ui/dr-ui/src/library.rs#L824), [`ui/dr-ui/src/library.rs:8480`](../ui/dr-ui/src/library.rs#L8480), [`ui/dr-ui/src/library.rs:8648`](../ui/dr-ui/src/library.rs#L8648), [`ui/dr-ui/src/library.rs:896`](../ui/dr-ui/src/library.rs#L896), [`ui/dr-ui/src/library.rs:980`](../ui/dr-ui/src/library.rs#L980), [`ui/dr-ui/src/library_ui.rs:1344`](../ui/dr-ui/src/library_ui.rs#L1344), [`ui/dr-ui/src/presets.rs:288`](../ui/dr-ui/src/presets.rs#L288), [`ui/dr-ui/src/presets.rs:336`](../ui/dr-ui/src/presets.rs#L336), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/src/xmp_sync.rs:287`](../ui/dr-ui/src/xmp_sync.rs#L287) | +| FR-PLAT-AND-2 | [`core/dr-catalog/src/walk.rs:1022`](../core/dr-catalog/src/walk.rs#L1022), [`core/dr-catalog/src/walk.rs:435`](../core/dr-catalog/src/walk.rs#L435), [`core/dr-sync-folder/src/lib.rs:242`](../core/dr-sync-folder/src/lib.rs#L242), [`core/dr-sync-folder/src/tests.rs:51`](../core/dr-sync-folder/src/tests.rs#L51), [`core/dr-sync/src/error.rs:113`](../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/error.rs:195`](../core/dr-sync/src/error.rs#L195), [`core/dr-sync/src/scan.rs:211`](../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../core/dr-sync/src/scan.rs#L519), [`core/dr-sync/src/scan.rs:545`](../core/dr-sync/src/scan.rs#L545), [`core/dr-sync/src/scan.rs:574`](../core/dr-sync/src/scan.rs#L574), [`ui/dr-ui/src/library.rs:1355`](../ui/dr-ui/src/library.rs#L1355), [`ui/dr-ui/src/library.rs:1408`](../ui/dr-ui/src/library.rs#L1408), [`ui/dr-ui/src/library.rs:1439`](../ui/dr-ui/src/library.rs#L1439), [`ui/dr-ui/src/library.rs:2019`](../ui/dr-ui/src/library.rs#L2019), [`ui/dr-ui/src/library_ui.rs:1315`](../ui/dr-ui/src/library_ui.rs#L1315), [`ui/dr-ui/src/library_ui.rs:1411`](../ui/dr-ui/src/library_ui.rs#L1411), [`ui/dr-ui/src/library_ui.rs:2010`](../ui/dr-ui/src/library_ui.rs#L2010), [`ui/dr-ui/src/library_ui.rs:328`](../ui/dr-ui/src/library_ui.rs#L328), [`ui/dr-ui/src/library_ui.rs:571`](../ui/dr-ui/src/library_ui.rs#L571) | | FR-PLAT-AND-3 | [`core/dr-catalog/src/jobs.rs:1`](../core/dr-catalog/src/jobs.rs#L1), [`core/dr-catalog/src/runner.rs:1`](../core/dr-catalog/src/runner.rs#L1) | | FR-PLAT-AND-4 | [`core/dr-catalog/src/runner.rs:1`](../core/dr-catalog/src/runner.rs#L1) | -| FR-PLAT-AND-5 | [`apps/darkroom-android/src/lib.rs:166`](../apps/darkroom-android/src/lib.rs#L166), [`core/dr-gpu/src/adjust.rs:1029`](../core/dr-gpu/src/adjust.rs#L1029), [`core/dr-gpu/src/detail.rs:161`](../core/dr-gpu/src/detail.rs#L161), [`core/dr-gpu/src/detail.rs:547`](../core/dr-gpu/src/detail.rs#L547), [`core/dr-gpu/tests/detail_stage.rs:417`](../core/dr-gpu/tests/detail_stage.rs#L417), [`ui/dr-ui/src/develop.rs:4512`](../ui/dr-ui/src/develop.rs#L4512), [`ui/dr-ui/src/identity_ui.rs:125`](../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:1345`](../ui/dr-ui/src/lib.rs#L1345), [`ui/dr-ui/src/lib.rs:1801`](../ui/dr-ui/src/lib.rs#L1801), [`ui/dr-ui/src/memory.rs:163`](../ui/dr-ui/src/memory.rs#L163), [`ui/dr-ui/src/memory.rs:1`](../ui/dr-ui/src/memory.rs#L1) | -| FR-PLAT-AND-6 | [`apps/darkroom-android/src/lib.rs:397`](../apps/darkroom-android/src/lib.rs#L397) | -| FR-PLAT-LIN-1 | [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`platform/dr-plat/src/dirs.rs:1`](../platform/dr-plat/src/dirs.rs#L1), [`platform/dr-plat/src/storage.rs:344`](../platform/dr-plat/src/storage.rs#L344), [`ui/dr-ui/src/lib.rs:1160`](../ui/dr-ui/src/lib.rs#L1160), [`ui/dr-ui/src/preset_store.rs:1`](../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1) | +| FR-PLAT-AND-5 | [`apps/darkroom-android/src/lib.rs:166`](../apps/darkroom-android/src/lib.rs#L166), [`core/dr-gpu/src/adjust.rs:1029`](../core/dr-gpu/src/adjust.rs#L1029), [`core/dr-gpu/src/detail.rs:161`](../core/dr-gpu/src/detail.rs#L161), [`core/dr-gpu/src/detail.rs:547`](../core/dr-gpu/src/detail.rs#L547), [`core/dr-gpu/tests/detail_stage.rs:417`](../core/dr-gpu/tests/detail_stage.rs#L417), [`ui/dr-ui/src/develop.rs:4512`](../ui/dr-ui/src/develop.rs#L4512), [`ui/dr-ui/src/identity_ui.rs:125`](../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:1346`](../ui/dr-ui/src/lib.rs#L1346), [`ui/dr-ui/src/lib.rs:1802`](../ui/dr-ui/src/lib.rs#L1802), [`ui/dr-ui/src/memory.rs:163`](../ui/dr-ui/src/memory.rs#L163), [`ui/dr-ui/src/memory.rs:1`](../ui/dr-ui/src/memory.rs#L1) | +| FR-PLAT-AND-6 | [`apps/darkroom-android/src/lib.rs:405`](../apps/darkroom-android/src/lib.rs#L405) | +| FR-PLAT-LIN-1 | [`core/dr-types/src/settings.rs:1`](../core/dr-types/src/settings.rs#L1), [`platform/dr-plat/src/dirs.rs:1`](../platform/dr-plat/src/dirs.rs#L1), [`platform/dr-plat/src/storage.rs:344`](../platform/dr-plat/src/storage.rs#L344), [`ui/dr-ui/src/lib.rs:1161`](../ui/dr-ui/src/lib.rs#L1161), [`ui/dr-ui/src/preset_store.rs:1`](../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../ui/dr-ui/src/settings_store.rs#L1) | | FR-PLAT-LIN-2 | [`platform/dr-plat/src/display.rs:1`](../platform/dr-plat/src/display.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) | | FR-PLAT-WIN-1 | [`platform/dr-plat/src/dirs.rs:1`](../platform/dr-plat/src/dirs.rs#L1) | | FR-PLAT-WIN-2 | [`apps/darkroom-desktop/build.rs:1`](../apps/darkroom-desktop/build.rs#L1), [`apps/darkroom-desktop/src/main.rs:6`](../apps/darkroom-desktop/src/main.rs#L6), [`ui/dr-ui/src/launch_ui.rs:819`](../ui/dr-ui/src/launch_ui.rs#L819) | | FR-PLAT-WIN-3 | [`apps/darkroom-desktop/src/main.rs:19`](../apps/darkroom-desktop/src/main.rs#L19) | | FR-RAW-1 | [`core/dr-decode/src/lib.rs:243`](../core/dr-decode/src/lib.rs#L243), [`core/dr-types/src/lib.rs:132`](../core/dr-types/src/lib.rs#L132), [`core/dr-types/src/lib.rs:203`](../core/dr-types/src/lib.rs#L203) | | FR-RAW-3 | [`core/dr-decode/src/lib.rs:139`](../core/dr-decode/src/lib.rs#L139), [`core/dr-decode/src/lib.rs:510`](../core/dr-decode/src/lib.rs#L510), [`core/dr-decode/src/locate.rs:1366`](../core/dr-decode/src/locate.rs#L1366) | -| FR-RAW-4 | [`core/dr-decode/src/error.rs:1`](../core/dr-decode/src/error.rs#L1), [`core/dr-decode/src/error.rs:30`](../core/dr-decode/src/error.rs#L30), [`ui/dr-ui/src/lib.rs:262`](../ui/dr-ui/src/lib.rs#L262) | +| FR-RAW-4 | [`core/dr-decode/src/error.rs:1`](../core/dr-decode/src/error.rs#L1), [`core/dr-decode/src/error.rs:30`](../core/dr-decode/src/error.rs#L30), [`ui/dr-ui/src/lib.rs:263`](../ui/dr-ui/src/lib.rs#L263) | | 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 | [`core/dr-types/src/settings.rs:1348`](../core/dr-types/src/settings.rs#L1348), [`core/dr-types/src/settings.rs:468`](../core/dr-types/src/settings.rs#L468), [`core/dr-types/src/settings.rs:488`](../core/dr-types/src/settings.rs#L488), [`ui/dr-ui/src/lib.rs:102`](../ui/dr-ui/src/lib.rs#L102), [`ui/dr-ui/src/lib.rs:117`](../ui/dr-ui/src/lib.rs#L117), [`ui/dr-ui/src/lib.rs:139`](../ui/dr-ui/src/lib.rs#L139), [`ui/dr-ui/src/lib.rs:2650`](../ui/dr-ui/src/lib.rs#L2650), [`ui/dr-ui/src/lib.rs:3985`](../ui/dr-ui/src/lib.rs#L3985), [`ui/dr-ui/src/lib.rs:4004`](../ui/dr-ui/src/lib.rs#L4004), [`ui/dr-ui/src/lib.rs:4031`](../ui/dr-ui/src/lib.rs#L4031), [`ui/dr-ui/src/lib.rs:4082`](../ui/dr-ui/src/lib.rs#L4082), [`ui/dr-ui/src/lib.rs:4115`](../ui/dr-ui/src/lib.rs#L4115), [`ui/dr-ui/src/masks_ui.rs:1471`](../ui/dr-ui/src/masks_ui.rs#L1471), [`ui/dr-ui/src/settings_ui.rs:179`](../ui/dr-ui/src/settings_ui.rs#L179), [`ui/dr-ui/ui/adjust.slint:974`](../ui/dr-ui/ui/adjust.slint#L974), [`ui/dr-ui/ui/app.slint:2752`](../ui/dr-ui/ui/app.slint#L2752), [`ui/dr-ui/ui/app.slint:858`](../ui/dr-ui/ui/app.slint#L858), [`ui/dr-ui/ui/app.slint:962`](../ui/dr-ui/ui/app.slint#L962), [`ui/dr-ui/ui/identity.slint:219`](../ui/dr-ui/ui/identity.slint#L219), [`ui/dr-ui/ui/library.slint:1076`](../ui/dr-ui/ui/library.slint#L1076), [`ui/dr-ui/ui/settings.slint:116`](../ui/dr-ui/ui/settings.slint#L116), [`ui/dr-ui/ui/settings.slint:628`](../ui/dr-ui/ui/settings.slint#L628), [`ui/dr-ui/ui/toolrail.slint:156`](../ui/dr-ui/ui/toolrail.slint#L156), [`ui/dr-ui/ui/toolrail.slint:89`](../ui/dr-ui/ui/toolrail.slint#L89) | -| FR-UI-2 | [`ui/dr-ui/src/collections_ui.rs:116`](../ui/dr-ui/src/collections_ui.rs#L116), [`ui/dr-ui/src/collections_ui.rs:1197`](../ui/dr-ui/src/collections_ui.rs#L1197), [`ui/dr-ui/src/collections_ui.rs:1207`](../ui/dr-ui/src/collections_ui.rs#L1207), [`ui/dr-ui/src/collections_ui.rs:154`](../ui/dr-ui/src/collections_ui.rs#L154), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1721`](../ui/dr-ui/src/collections_ui.rs#L1721), [`ui/dr-ui/src/collections_ui.rs:1973`](../ui/dr-ui/src/collections_ui.rs#L1973), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:3596`](../ui/dr-ui/src/collections_ui.rs#L3596), [`ui/dr-ui/src/gestures.rs:1`](../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:102`](../ui/dr-ui/src/lib.rs#L102), [`ui/dr-ui/src/library_ui.rs:6774`](../ui/dr-ui/src/library_ui.rs#L6774), [`ui/dr-ui/src/library_ui.rs:8134`](../ui/dr-ui/src/library_ui.rs#L8134), [`ui/dr-ui/ui/app.slint:588`](../ui/dr-ui/ui/app.slint#L588), [`ui/dr-ui/ui/app.slint:602`](../ui/dr-ui/ui/app.slint#L602), [`ui/dr-ui/ui/app.slint:68`](../ui/dr-ui/ui/app.slint#L68), [`ui/dr-ui/ui/app.slint:946`](../ui/dr-ui/ui/app.slint#L946), [`ui/dr-ui/ui/controls.slint:626`](../ui/dr-ui/ui/controls.slint#L626), [`ui/dr-ui/ui/gestures.slint:1`](../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1287`](../ui/dr-ui/ui/library.slint#L1287), [`ui/dr-ui/ui/library.slint:1294`](../ui/dr-ui/ui/library.slint#L1294), [`ui/dr-ui/ui/library.slint:1391`](../ui/dr-ui/ui/library.slint#L1391), [`ui/dr-ui/ui/library.slint:2581`](../ui/dr-ui/ui/library.slint#L2581), [`ui/dr-ui/ui/library.slint:4316`](../ui/dr-ui/ui/library.slint#L4316), [`ui/dr-ui/ui/library.slint:965`](../ui/dr-ui/ui/library.slint#L965), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/settings.slint:130`](../ui/dr-ui/ui/settings.slint#L130) | -| FR-UI-3 | [`ui/dr-ui/src/collections_ui.rs:209`](../ui/dr-ui/src/collections_ui.rs#L209), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:414`](../ui/dr-ui/src/collections_ui.rs#L414), [`ui/dr-ui/src/collections_ui.rs:427`](../ui/dr-ui/src/collections_ui.rs#L427), [`ui/dr-ui/src/develop.rs:2850`](../ui/dr-ui/src/develop.rs#L2850), [`ui/dr-ui/src/develop.rs:3238`](../ui/dr-ui/src/develop.rs#L3238), [`ui/dr-ui/src/library_ui.rs:5803`](../ui/dr-ui/src/library_ui.rs#L5803), [`ui/dr-ui/src/masks_ui.rs:1563`](../ui/dr-ui/src/masks_ui.rs#L1563), [`ui/dr-ui/src/masks_ui.rs:1585`](../ui/dr-ui/src/masks_ui.rs#L1585), [`ui/dr-ui/src/masks_ui.rs:339`](../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:2295`](../ui/dr-ui/ui/app.slint#L2295), [`ui/dr-ui/ui/collections.slint:1127`](../ui/dr-ui/ui/collections.slint#L1127), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:75`](../ui/dr-ui/ui/collections.slint#L75), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/masks.slint:1208`](../ui/dr-ui/ui/masks.slint#L1208), [`ui/dr-ui/ui/widgets.slint:71`](../ui/dr-ui/ui/widgets.slint#L71) | -| FR-UI-4 | [`tools/traceability/src/gestures.rs:1`](../tools/traceability/src/gestures.rs#L1), [`ui/dr-ui/src/collections_ui.rs:116`](../ui/dr-ui/src/collections_ui.rs#L116), [`ui/dr-ui/src/collections_ui.rs:117`](../ui/dr-ui/src/collections_ui.rs#L117), [`ui/dr-ui/src/collections_ui.rs:1197`](../ui/dr-ui/src/collections_ui.rs#L1197), [`ui/dr-ui/src/collections_ui.rs:1207`](../ui/dr-ui/src/collections_ui.rs#L1207), [`ui/dr-ui/src/collections_ui.rs:126`](../ui/dr-ui/src/collections_ui.rs#L126), [`ui/dr-ui/src/collections_ui.rs:154`](../ui/dr-ui/src/collections_ui.rs#L154), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1721`](../ui/dr-ui/src/collections_ui.rs#L1721), [`ui/dr-ui/src/collections_ui.rs:1837`](../ui/dr-ui/src/collections_ui.rs#L1837), [`ui/dr-ui/src/collections_ui.rs:1973`](../ui/dr-ui/src/collections_ui.rs#L1973), [`ui/dr-ui/src/collections_ui.rs:2000`](../ui/dr-ui/src/collections_ui.rs#L2000), [`ui/dr-ui/src/collections_ui.rs:209`](../ui/dr-ui/src/collections_ui.rs#L209), [`ui/dr-ui/src/collections_ui.rs:2116`](../ui/dr-ui/src/collections_ui.rs#L2116), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:2755`](../ui/dr-ui/src/collections_ui.rs#L2755), [`ui/dr-ui/src/collections_ui.rs:3208`](../ui/dr-ui/src/collections_ui.rs#L3208), [`ui/dr-ui/src/collections_ui.rs:3596`](../ui/dr-ui/src/collections_ui.rs#L3596), [`ui/dr-ui/src/collections_ui.rs:3633`](../ui/dr-ui/src/collections_ui.rs#L3633), [`ui/dr-ui/src/collections_ui.rs:414`](../ui/dr-ui/src/collections_ui.rs#L414), [`ui/dr-ui/src/collections_ui.rs:427`](../ui/dr-ui/src/collections_ui.rs#L427), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:718`](../ui/dr-ui/src/collections_ui.rs#L718), [`ui/dr-ui/src/collections_ui.rs:738`](../ui/dr-ui/src/collections_ui.rs#L738), [`ui/dr-ui/src/develop.rs:5283`](../ui/dr-ui/src/develop.rs#L5283), [`ui/dr-ui/src/develop.rs:5308`](../ui/dr-ui/src/develop.rs#L5308), [`ui/dr-ui/src/develop.rs:5319`](../ui/dr-ui/src/develop.rs#L5319), [`ui/dr-ui/src/develop.rs:5333`](../ui/dr-ui/src/develop.rs#L5333), [`ui/dr-ui/src/develop.rs:6561`](../ui/dr-ui/src/develop.rs#L6561), [`ui/dr-ui/src/develop.rs:6592`](../ui/dr-ui/src/develop.rs#L6592), [`ui/dr-ui/src/develop.rs:6613`](../ui/dr-ui/src/develop.rs#L6613), [`ui/dr-ui/src/gesture_book.rs:3`](../ui/dr-ui/src/gesture_book.rs#L3), [`ui/dr-ui/src/gestures.rs:1`](../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:1318`](../ui/dr-ui/src/lib.rs#L1318), [`ui/dr-ui/src/lib.rs:1883`](../ui/dr-ui/src/lib.rs#L1883), [`ui/dr-ui/src/lib.rs:2307`](../ui/dr-ui/src/lib.rs#L2307), [`ui/dr-ui/src/lib.rs:2497`](../ui/dr-ui/src/lib.rs#L2497), [`ui/dr-ui/src/lib.rs:2557`](../ui/dr-ui/src/lib.rs#L2557), [`ui/dr-ui/src/lib.rs:3225`](../ui/dr-ui/src/lib.rs#L3225), [`ui/dr-ui/src/lib.rs:3794`](../ui/dr-ui/src/lib.rs#L3794), [`ui/dr-ui/src/lib.rs:4219`](../ui/dr-ui/src/lib.rs#L4219), [`ui/dr-ui/src/lib.rs:454`](../ui/dr-ui/src/lib.rs#L454), [`ui/dr-ui/src/lib.rs:483`](../ui/dr-ui/src/lib.rs#L483), [`ui/dr-ui/src/library.rs:2725`](../ui/dr-ui/src/library.rs#L2725), [`ui/dr-ui/src/library.rs:2740`](../ui/dr-ui/src/library.rs#L2740), [`ui/dr-ui/src/library_ui.rs:387`](../ui/dr-ui/src/library_ui.rs#L387), [`ui/dr-ui/src/library_ui.rs:525`](../ui/dr-ui/src/library_ui.rs#L525), [`ui/dr-ui/src/library_ui.rs:5803`](../ui/dr-ui/src/library_ui.rs#L5803), [`ui/dr-ui/src/library_ui.rs:5815`](../ui/dr-ui/src/library_ui.rs#L5815), [`ui/dr-ui/src/library_ui.rs:5885`](../ui/dr-ui/src/library_ui.rs#L5885), [`ui/dr-ui/src/library_ui.rs:5995`](../ui/dr-ui/src/library_ui.rs#L5995), [`ui/dr-ui/src/library_ui.rs:6023`](../ui/dr-ui/src/library_ui.rs#L6023), [`ui/dr-ui/src/library_ui.rs:602`](../ui/dr-ui/src/library_ui.rs#L602), [`ui/dr-ui/src/library_ui.rs:6907`](../ui/dr-ui/src/library_ui.rs#L6907), [`ui/dr-ui/src/settings_ui.rs:157`](../ui/dr-ui/src/settings_ui.rs#L157), [`ui/dr-ui/src/settings_ui.rs:524`](../ui/dr-ui/src/settings_ui.rs#L524), [`ui/dr-ui/ui/app.slint:168`](../ui/dr-ui/ui/app.slint#L168), [`ui/dr-ui/ui/app.slint:1990`](../ui/dr-ui/ui/app.slint#L1990), [`ui/dr-ui/ui/app.slint:2112`](../ui/dr-ui/ui/app.slint#L2112), [`ui/dr-ui/ui/app.slint:2519`](../ui/dr-ui/ui/app.slint#L2519), [`ui/dr-ui/ui/app.slint:2652`](../ui/dr-ui/ui/app.slint#L2652), [`ui/dr-ui/ui/app.slint:3123`](../ui/dr-ui/ui/app.slint#L3123), [`ui/dr-ui/ui/app.slint:564`](../ui/dr-ui/ui/app.slint#L564), [`ui/dr-ui/ui/app.slint:593`](../ui/dr-ui/ui/app.slint#L593), [`ui/dr-ui/ui/app.slint:602`](../ui/dr-ui/ui/app.slint#L602), [`ui/dr-ui/ui/app.slint:702`](../ui/dr-ui/ui/app.slint#L702), [`ui/dr-ui/ui/collections.slint:75`](../ui/dr-ui/ui/collections.slint#L75), [`ui/dr-ui/ui/gestures.slint:1`](../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1053`](../ui/dr-ui/ui/library.slint#L1053), [`ui/dr-ui/ui/library.slint:1262`](../ui/dr-ui/ui/library.slint#L1262), [`ui/dr-ui/ui/library.slint:1287`](../ui/dr-ui/ui/library.slint#L1287), [`ui/dr-ui/ui/library.slint:1294`](../ui/dr-ui/ui/library.slint#L1294), [`ui/dr-ui/ui/library.slint:1327`](../ui/dr-ui/ui/library.slint#L1327), [`ui/dr-ui/ui/library.slint:1384`](../ui/dr-ui/ui/library.slint#L1384), [`ui/dr-ui/ui/library.slint:1391`](../ui/dr-ui/ui/library.slint#L1391), [`ui/dr-ui/ui/library.slint:2581`](../ui/dr-ui/ui/library.slint#L2581), [`ui/dr-ui/ui/library.slint:4179`](../ui/dr-ui/ui/library.slint#L4179), [`ui/dr-ui/ui/library.slint:4257`](../ui/dr-ui/ui/library.slint#L4257), [`ui/dr-ui/ui/library.slint:4316`](../ui/dr-ui/ui/library.slint#L4316), [`ui/dr-ui/ui/library.slint:965`](../ui/dr-ui/ui/library.slint#L965), [`ui/dr-ui/ui/library.slint:992`](../ui/dr-ui/ui/library.slint#L992), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998), [`ui/dr-ui/ui/settings.slint:108`](../ui/dr-ui/ui/settings.slint#L108), [`ui/dr-ui/ui/settings.slint:603`](../ui/dr-ui/ui/settings.slint#L603) | -| 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:3270`](../ui/dr-ui/src/lib.rs#L3270), [`ui/dr-ui/src/lib.rs:4179`](../ui/dr-ui/src/lib.rs#L4179), [`ui/dr-ui/src/lib.rs:4370`](../ui/dr-ui/src/lib.rs#L4370), [`ui/dr-ui/src/masks_ui.rs:1518`](../ui/dr-ui/src/masks_ui.rs#L1518), [`ui/dr-ui/ui/app.slint:2479`](../ui/dr-ui/ui/app.slint#L2479), [`ui/dr-ui/ui/app.slint:2519`](../ui/dr-ui/ui/app.slint#L2519), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/session.slint:75`](../ui/dr-ui/ui/session.slint#L75) | +| FR-UI-1 | [`core/dr-types/src/settings.rs:1348`](../core/dr-types/src/settings.rs#L1348), [`core/dr-types/src/settings.rs:468`](../core/dr-types/src/settings.rs#L468), [`core/dr-types/src/settings.rs:488`](../core/dr-types/src/settings.rs#L488), [`ui/dr-ui/src/lib.rs:103`](../ui/dr-ui/src/lib.rs#L103), [`ui/dr-ui/src/lib.rs:118`](../ui/dr-ui/src/lib.rs#L118), [`ui/dr-ui/src/lib.rs:140`](../ui/dr-ui/src/lib.rs#L140), [`ui/dr-ui/src/lib.rs:2651`](../ui/dr-ui/src/lib.rs#L2651), [`ui/dr-ui/src/lib.rs:3985`](../ui/dr-ui/src/lib.rs#L3985), [`ui/dr-ui/src/lib.rs:4004`](../ui/dr-ui/src/lib.rs#L4004), [`ui/dr-ui/src/lib.rs:4031`](../ui/dr-ui/src/lib.rs#L4031), [`ui/dr-ui/src/lib.rs:4082`](../ui/dr-ui/src/lib.rs#L4082), [`ui/dr-ui/src/lib.rs:4115`](../ui/dr-ui/src/lib.rs#L4115), [`ui/dr-ui/src/masks_ui.rs:1471`](../ui/dr-ui/src/masks_ui.rs#L1471), [`ui/dr-ui/src/settings_ui.rs:179`](../ui/dr-ui/src/settings_ui.rs#L179), [`ui/dr-ui/ui/adjust.slint:974`](../ui/dr-ui/ui/adjust.slint#L974), [`ui/dr-ui/ui/app.slint:2758`](../ui/dr-ui/ui/app.slint#L2758), [`ui/dr-ui/ui/app.slint:862`](../ui/dr-ui/ui/app.slint#L862), [`ui/dr-ui/ui/app.slint:966`](../ui/dr-ui/ui/app.slint#L966), [`ui/dr-ui/ui/identity.slint:246`](../ui/dr-ui/ui/identity.slint#L246), [`ui/dr-ui/ui/library.slint:1076`](../ui/dr-ui/ui/library.slint#L1076), [`ui/dr-ui/ui/settings.slint:116`](../ui/dr-ui/ui/settings.slint#L116), [`ui/dr-ui/ui/settings.slint:628`](../ui/dr-ui/ui/settings.slint#L628), [`ui/dr-ui/ui/toolrail.slint:156`](../ui/dr-ui/ui/toolrail.slint#L156), [`ui/dr-ui/ui/toolrail.slint:89`](../ui/dr-ui/ui/toolrail.slint#L89) | +| FR-UI-2 | [`ui/dr-ui/src/collections_ui.rs:116`](../ui/dr-ui/src/collections_ui.rs#L116), [`ui/dr-ui/src/collections_ui.rs:1197`](../ui/dr-ui/src/collections_ui.rs#L1197), [`ui/dr-ui/src/collections_ui.rs:1207`](../ui/dr-ui/src/collections_ui.rs#L1207), [`ui/dr-ui/src/collections_ui.rs:154`](../ui/dr-ui/src/collections_ui.rs#L154), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1721`](../ui/dr-ui/src/collections_ui.rs#L1721), [`ui/dr-ui/src/collections_ui.rs:1973`](../ui/dr-ui/src/collections_ui.rs#L1973), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:3596`](../ui/dr-ui/src/collections_ui.rs#L3596), [`ui/dr-ui/src/gestures.rs:1`](../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:103`](../ui/dr-ui/src/lib.rs#L103), [`ui/dr-ui/src/library_ui.rs:6792`](../ui/dr-ui/src/library_ui.rs#L6792), [`ui/dr-ui/src/library_ui.rs:8165`](../ui/dr-ui/src/library_ui.rs#L8165), [`ui/dr-ui/ui/app.slint:588`](../ui/dr-ui/ui/app.slint#L588), [`ui/dr-ui/ui/app.slint:602`](../ui/dr-ui/ui/app.slint#L602), [`ui/dr-ui/ui/app.slint:68`](../ui/dr-ui/ui/app.slint#L68), [`ui/dr-ui/ui/app.slint:950`](../ui/dr-ui/ui/app.slint#L950), [`ui/dr-ui/ui/controls.slint:626`](../ui/dr-ui/ui/controls.slint#L626), [`ui/dr-ui/ui/gestures.slint:1`](../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1287`](../ui/dr-ui/ui/library.slint#L1287), [`ui/dr-ui/ui/library.slint:1294`](../ui/dr-ui/ui/library.slint#L1294), [`ui/dr-ui/ui/library.slint:1391`](../ui/dr-ui/ui/library.slint#L1391), [`ui/dr-ui/ui/library.slint:2611`](../ui/dr-ui/ui/library.slint#L2611), [`ui/dr-ui/ui/library.slint:4346`](../ui/dr-ui/ui/library.slint#L4346), [`ui/dr-ui/ui/library.slint:965`](../ui/dr-ui/ui/library.slint#L965), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998), [`ui/dr-ui/ui/presets.slint:19`](../ui/dr-ui/ui/presets.slint#L19), [`ui/dr-ui/ui/settings.slint:130`](../ui/dr-ui/ui/settings.slint#L130) | +| FR-UI-3 | [`ui/dr-ui/src/collections_ui.rs:209`](../ui/dr-ui/src/collections_ui.rs#L209), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:414`](../ui/dr-ui/src/collections_ui.rs#L414), [`ui/dr-ui/src/collections_ui.rs:427`](../ui/dr-ui/src/collections_ui.rs#L427), [`ui/dr-ui/src/develop.rs:2850`](../ui/dr-ui/src/develop.rs#L2850), [`ui/dr-ui/src/develop.rs:3238`](../ui/dr-ui/src/develop.rs#L3238), [`ui/dr-ui/src/library_ui.rs:5804`](../ui/dr-ui/src/library_ui.rs#L5804), [`ui/dr-ui/src/masks_ui.rs:1563`](../ui/dr-ui/src/masks_ui.rs#L1563), [`ui/dr-ui/src/masks_ui.rs:1585`](../ui/dr-ui/src/masks_ui.rs#L1585), [`ui/dr-ui/src/masks_ui.rs:339`](../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/spots_ui.rs:19`](../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:2301`](../ui/dr-ui/ui/app.slint#L2301), [`ui/dr-ui/ui/collections.slint:1127`](../ui/dr-ui/ui/collections.slint#L1127), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:75`](../ui/dr-ui/ui/collections.slint#L75), [`ui/dr-ui/ui/collections.slint:877`](../ui/dr-ui/ui/collections.slint#L877), [`ui/dr-ui/ui/masks.slint:1208`](../ui/dr-ui/ui/masks.slint#L1208), [`ui/dr-ui/ui/widgets.slint:71`](../ui/dr-ui/ui/widgets.slint#L71) | +| FR-UI-4 | [`tools/traceability/src/gestures.rs:1`](../tools/traceability/src/gestures.rs#L1), [`ui/dr-ui/src/collections_ui.rs:116`](../ui/dr-ui/src/collections_ui.rs#L116), [`ui/dr-ui/src/collections_ui.rs:117`](../ui/dr-ui/src/collections_ui.rs#L117), [`ui/dr-ui/src/collections_ui.rs:1197`](../ui/dr-ui/src/collections_ui.rs#L1197), [`ui/dr-ui/src/collections_ui.rs:1207`](../ui/dr-ui/src/collections_ui.rs#L1207), [`ui/dr-ui/src/collections_ui.rs:126`](../ui/dr-ui/src/collections_ui.rs#L126), [`ui/dr-ui/src/collections_ui.rs:154`](../ui/dr-ui/src/collections_ui.rs#L154), [`ui/dr-ui/src/collections_ui.rs:1704`](../ui/dr-ui/src/collections_ui.rs#L1704), [`ui/dr-ui/src/collections_ui.rs:1721`](../ui/dr-ui/src/collections_ui.rs#L1721), [`ui/dr-ui/src/collections_ui.rs:1837`](../ui/dr-ui/src/collections_ui.rs#L1837), [`ui/dr-ui/src/collections_ui.rs:1973`](../ui/dr-ui/src/collections_ui.rs#L1973), [`ui/dr-ui/src/collections_ui.rs:2000`](../ui/dr-ui/src/collections_ui.rs#L2000), [`ui/dr-ui/src/collections_ui.rs:209`](../ui/dr-ui/src/collections_ui.rs#L209), [`ui/dr-ui/src/collections_ui.rs:2116`](../ui/dr-ui/src/collections_ui.rs#L2116), [`ui/dr-ui/src/collections_ui.rs:2701`](../ui/dr-ui/src/collections_ui.rs#L2701), [`ui/dr-ui/src/collections_ui.rs:2755`](../ui/dr-ui/src/collections_ui.rs#L2755), [`ui/dr-ui/src/collections_ui.rs:3208`](../ui/dr-ui/src/collections_ui.rs#L3208), [`ui/dr-ui/src/collections_ui.rs:3596`](../ui/dr-ui/src/collections_ui.rs#L3596), [`ui/dr-ui/src/collections_ui.rs:3633`](../ui/dr-ui/src/collections_ui.rs#L3633), [`ui/dr-ui/src/collections_ui.rs:414`](../ui/dr-ui/src/collections_ui.rs#L414), [`ui/dr-ui/src/collections_ui.rs:427`](../ui/dr-ui/src/collections_ui.rs#L427), [`ui/dr-ui/src/collections_ui.rs:514`](../ui/dr-ui/src/collections_ui.rs#L514), [`ui/dr-ui/src/collections_ui.rs:718`](../ui/dr-ui/src/collections_ui.rs#L718), [`ui/dr-ui/src/collections_ui.rs:738`](../ui/dr-ui/src/collections_ui.rs#L738), [`ui/dr-ui/src/develop.rs:5283`](../ui/dr-ui/src/develop.rs#L5283), [`ui/dr-ui/src/develop.rs:5308`](../ui/dr-ui/src/develop.rs#L5308), [`ui/dr-ui/src/develop.rs:5319`](../ui/dr-ui/src/develop.rs#L5319), [`ui/dr-ui/src/develop.rs:5333`](../ui/dr-ui/src/develop.rs#L5333), [`ui/dr-ui/src/develop.rs:6561`](../ui/dr-ui/src/develop.rs#L6561), [`ui/dr-ui/src/develop.rs:6592`](../ui/dr-ui/src/develop.rs#L6592), [`ui/dr-ui/src/develop.rs:6613`](../ui/dr-ui/src/develop.rs#L6613), [`ui/dr-ui/src/gesture_book.rs:3`](../ui/dr-ui/src/gesture_book.rs#L3), [`ui/dr-ui/src/gestures.rs:1`](../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:1319`](../ui/dr-ui/src/lib.rs#L1319), [`ui/dr-ui/src/lib.rs:1884`](../ui/dr-ui/src/lib.rs#L1884), [`ui/dr-ui/src/lib.rs:2308`](../ui/dr-ui/src/lib.rs#L2308), [`ui/dr-ui/src/lib.rs:2498`](../ui/dr-ui/src/lib.rs#L2498), [`ui/dr-ui/src/lib.rs:2558`](../ui/dr-ui/src/lib.rs#L2558), [`ui/dr-ui/src/lib.rs:3226`](../ui/dr-ui/src/lib.rs#L3226), [`ui/dr-ui/src/lib.rs:3795`](../ui/dr-ui/src/lib.rs#L3795), [`ui/dr-ui/src/lib.rs:4219`](../ui/dr-ui/src/lib.rs#L4219), [`ui/dr-ui/src/lib.rs:455`](../ui/dr-ui/src/lib.rs#L455), [`ui/dr-ui/src/lib.rs:484`](../ui/dr-ui/src/lib.rs#L484), [`ui/dr-ui/src/library.rs:2789`](../ui/dr-ui/src/library.rs#L2789), [`ui/dr-ui/src/library.rs:2804`](../ui/dr-ui/src/library.rs#L2804), [`ui/dr-ui/src/library_ui.rs:387`](../ui/dr-ui/src/library_ui.rs#L387), [`ui/dr-ui/src/library_ui.rs:525`](../ui/dr-ui/src/library_ui.rs#L525), [`ui/dr-ui/src/library_ui.rs:5804`](../ui/dr-ui/src/library_ui.rs#L5804), [`ui/dr-ui/src/library_ui.rs:5816`](../ui/dr-ui/src/library_ui.rs#L5816), [`ui/dr-ui/src/library_ui.rs:5886`](../ui/dr-ui/src/library_ui.rs#L5886), [`ui/dr-ui/src/library_ui.rs:5996`](../ui/dr-ui/src/library_ui.rs#L5996), [`ui/dr-ui/src/library_ui.rs:6024`](../ui/dr-ui/src/library_ui.rs#L6024), [`ui/dr-ui/src/library_ui.rs:602`](../ui/dr-ui/src/library_ui.rs#L602), [`ui/dr-ui/src/library_ui.rs:6925`](../ui/dr-ui/src/library_ui.rs#L6925), [`ui/dr-ui/src/settings_ui.rs:157`](../ui/dr-ui/src/settings_ui.rs#L157), [`ui/dr-ui/src/settings_ui.rs:524`](../ui/dr-ui/src/settings_ui.rs#L524), [`ui/dr-ui/ui/app.slint:168`](../ui/dr-ui/ui/app.slint#L168), [`ui/dr-ui/ui/app.slint:1996`](../ui/dr-ui/ui/app.slint#L1996), [`ui/dr-ui/ui/app.slint:2118`](../ui/dr-ui/ui/app.slint#L2118), [`ui/dr-ui/ui/app.slint:2525`](../ui/dr-ui/ui/app.slint#L2525), [`ui/dr-ui/ui/app.slint:2658`](../ui/dr-ui/ui/app.slint#L2658), [`ui/dr-ui/ui/app.slint:3129`](../ui/dr-ui/ui/app.slint#L3129), [`ui/dr-ui/ui/app.slint:564`](../ui/dr-ui/ui/app.slint#L564), [`ui/dr-ui/ui/app.slint:593`](../ui/dr-ui/ui/app.slint#L593), [`ui/dr-ui/ui/app.slint:602`](../ui/dr-ui/ui/app.slint#L602), [`ui/dr-ui/ui/app.slint:706`](../ui/dr-ui/ui/app.slint#L706), [`ui/dr-ui/ui/collections.slint:75`](../ui/dr-ui/ui/collections.slint#L75), [`ui/dr-ui/ui/gestures.slint:1`](../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1053`](../ui/dr-ui/ui/library.slint#L1053), [`ui/dr-ui/ui/library.slint:1262`](../ui/dr-ui/ui/library.slint#L1262), [`ui/dr-ui/ui/library.slint:1287`](../ui/dr-ui/ui/library.slint#L1287), [`ui/dr-ui/ui/library.slint:1294`](../ui/dr-ui/ui/library.slint#L1294), [`ui/dr-ui/ui/library.slint:1327`](../ui/dr-ui/ui/library.slint#L1327), [`ui/dr-ui/ui/library.slint:1384`](../ui/dr-ui/ui/library.slint#L1384), [`ui/dr-ui/ui/library.slint:1391`](../ui/dr-ui/ui/library.slint#L1391), [`ui/dr-ui/ui/library.slint:2611`](../ui/dr-ui/ui/library.slint#L2611), [`ui/dr-ui/ui/library.slint:4209`](../ui/dr-ui/ui/library.slint#L4209), [`ui/dr-ui/ui/library.slint:4287`](../ui/dr-ui/ui/library.slint#L4287), [`ui/dr-ui/ui/library.slint:4346`](../ui/dr-ui/ui/library.slint#L4346), [`ui/dr-ui/ui/library.slint:965`](../ui/dr-ui/ui/library.slint#L965), [`ui/dr-ui/ui/library.slint:992`](../ui/dr-ui/ui/library.slint#L992), [`ui/dr-ui/ui/library.slint:998`](../ui/dr-ui/ui/library.slint#L998), [`ui/dr-ui/ui/settings.slint:108`](../ui/dr-ui/ui/settings.slint#L108), [`ui/dr-ui/ui/settings.slint:603`](../ui/dr-ui/ui/settings.slint#L603) | +| 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:3271`](../ui/dr-ui/src/lib.rs#L3271), [`ui/dr-ui/src/lib.rs:4179`](../ui/dr-ui/src/lib.rs#L4179), [`ui/dr-ui/src/lib.rs:4370`](../ui/dr-ui/src/lib.rs#L4370), [`ui/dr-ui/src/masks_ui.rs:1518`](../ui/dr-ui/src/masks_ui.rs#L1518), [`ui/dr-ui/ui/app.slint:2485`](../ui/dr-ui/ui/app.slint#L2485), [`ui/dr-ui/ui/app.slint:2525`](../ui/dr-ui/ui/app.slint#L2525), [`ui/dr-ui/ui/collections.slint:4`](../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/session.slint:75`](../ui/dr-ui/ui/session.slint#L75) | | 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:195`](../core/dr-pipeline/src/descriptor.rs#L195), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-types/src/settings.rs:468`](../core/dr-types/src/settings.rs#L468), [`ui/dr-ui/src/develop.rs:1330`](../ui/dr-ui/src/develop.rs#L1330), [`ui/dr-ui/src/lib.rs:4004`](../ui/dr-ui/src/lib.rs#L4004), [`ui/dr-ui/ui/adjust.slint:974`](../ui/dr-ui/ui/adjust.slint#L974), [`ui/dr-ui/ui/app.slint:2235`](../ui/dr-ui/ui/app.slint#L2235), [`ui/dr-ui/ui/settings.slint:628`](../ui/dr-ui/ui/settings.slint#L628), [`ui/dr-ui/ui/toolrail.slint:89`](../ui/dr-ui/ui/toolrail.slint#L89) | -| FR-UI-8 | [`core/dr-catalog/src/collections.rs:654`](../core/dr-catalog/src/collections.rs#L654), [`core/dr-catalog/src/collections.rs:675`](../core/dr-catalog/src/collections.rs#L675), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`ui/dr-ui/src/derived_sync.rs:216`](../ui/dr-ui/src/derived_sync.rs#L216), [`ui/dr-ui/src/derived_sync.rs:81`](../ui/dr-ui/src/derived_sync.rs#L81), [`ui/dr-ui/src/derived_sync.rs:883`](../ui/dr-ui/src/derived_sync.rs#L883), [`ui/dr-ui/src/derived_sync.rs:893`](../ui/dr-ui/src/derived_sync.rs#L893), [`ui/dr-ui/src/derived_sync.rs:975`](../ui/dr-ui/src/derived_sync.rs#L975), [`ui/dr-ui/src/library.rs:1123`](../ui/dr-ui/src/library.rs#L1123), [`ui/dr-ui/src/library.rs:5391`](../ui/dr-ui/src/library.rs#L5391), [`ui/dr-ui/src/library.rs:6109`](../ui/dr-ui/src/library.rs#L6109), [`ui/dr-ui/src/library.rs:6175`](../ui/dr-ui/src/library.rs#L6175), [`ui/dr-ui/src/library_ui.rs:1012`](../ui/dr-ui/src/library_ui.rs#L1012), [`ui/dr-ui/src/library_ui.rs:195`](../ui/dr-ui/src/library_ui.rs#L195), [`ui/dr-ui/src/library_ui.rs:2197`](../ui/dr-ui/src/library_ui.rs#L2197), [`ui/dr-ui/src/library_ui.rs:2386`](../ui/dr-ui/src/library_ui.rs#L2386), [`ui/dr-ui/src/library_ui.rs:2403`](../ui/dr-ui/src/library_ui.rs#L2403), [`ui/dr-ui/src/library_ui.rs:2501`](../ui/dr-ui/src/library_ui.rs#L2501), [`ui/dr-ui/src/library_ui.rs:5836`](../ui/dr-ui/src/library_ui.rs#L5836), [`ui/dr-ui/src/library_ui.rs:5876`](../ui/dr-ui/src/library_ui.rs#L5876), [`ui/dr-ui/src/library_ui.rs:5905`](../ui/dr-ui/src/library_ui.rs#L5905), [`ui/dr-ui/src/library_ui.rs:6168`](../ui/dr-ui/src/library_ui.rs#L6168), [`ui/dr-ui/src/library_ui.rs:6391`](../ui/dr-ui/src/library_ui.rs#L6391), [`ui/dr-ui/src/library_ui.rs:7115`](../ui/dr-ui/src/library_ui.rs#L7115), [`ui/dr-ui/src/library_ui.rs:933`](../ui/dr-ui/src/library_ui.rs#L933), [`ui/dr-ui/src/library_ui.rs:966`](../ui/dr-ui/src/library_ui.rs#L966), [`ui/dr-ui/src/place.rs:1`](../ui/dr-ui/src/place.rs#L1) | -| NFR-A11Y-2 | [`ui/dr-ui/tests/ui_controls_are_accessible.rs:1`](../ui/dr-ui/tests/ui_controls_are_accessible.rs#L1), [`ui/dr-ui/ui/adjust.slint:171`](../ui/dr-ui/ui/adjust.slint#L171), [`ui/dr-ui/ui/app.slint:2652`](../ui/dr-ui/ui/app.slint#L2652), [`ui/dr-ui/ui/app.slint:2690`](../ui/dr-ui/ui/app.slint#L2690) | +| FR-UI-7 | [`core/dr-pipeline/src/descriptor.rs:195`](../core/dr-pipeline/src/descriptor.rs#L195), [`core/dr-pipeline/src/framing.rs:395`](../core/dr-pipeline/src/framing.rs#L395), [`core/dr-types/src/settings.rs:468`](../core/dr-types/src/settings.rs#L468), [`ui/dr-ui/src/develop.rs:1330`](../ui/dr-ui/src/develop.rs#L1330), [`ui/dr-ui/src/lib.rs:4004`](../ui/dr-ui/src/lib.rs#L4004), [`ui/dr-ui/ui/adjust.slint:974`](../ui/dr-ui/ui/adjust.slint#L974), [`ui/dr-ui/ui/app.slint:2241`](../ui/dr-ui/ui/app.slint#L2241), [`ui/dr-ui/ui/settings.slint:628`](../ui/dr-ui/ui/settings.slint#L628), [`ui/dr-ui/ui/toolrail.slint:89`](../ui/dr-ui/ui/toolrail.slint#L89) | +| FR-UI-8 | [`core/dr-catalog/src/collections.rs:654`](../core/dr-catalog/src/collections.rs#L654), [`core/dr-catalog/src/collections.rs:675`](../core/dr-catalog/src/collections.rs#L675), [`core/dr-types/src/place.rs:1`](../core/dr-types/src/place.rs#L1), [`ui/dr-ui/src/derived_sync.rs:216`](../ui/dr-ui/src/derived_sync.rs#L216), [`ui/dr-ui/src/derived_sync.rs:81`](../ui/dr-ui/src/derived_sync.rs#L81), [`ui/dr-ui/src/derived_sync.rs:883`](../ui/dr-ui/src/derived_sync.rs#L883), [`ui/dr-ui/src/derived_sync.rs:893`](../ui/dr-ui/src/derived_sync.rs#L893), [`ui/dr-ui/src/derived_sync.rs:975`](../ui/dr-ui/src/derived_sync.rs#L975), [`ui/dr-ui/src/library.rs:1187`](../ui/dr-ui/src/library.rs#L1187), [`ui/dr-ui/src/library.rs:5543`](../ui/dr-ui/src/library.rs#L5543), [`ui/dr-ui/src/library.rs:6261`](../ui/dr-ui/src/library.rs#L6261), [`ui/dr-ui/src/library.rs:6327`](../ui/dr-ui/src/library.rs#L6327), [`ui/dr-ui/src/library_ui.rs:1012`](../ui/dr-ui/src/library_ui.rs#L1012), [`ui/dr-ui/src/library_ui.rs:195`](../ui/dr-ui/src/library_ui.rs#L195), [`ui/dr-ui/src/library_ui.rs:2197`](../ui/dr-ui/src/library_ui.rs#L2197), [`ui/dr-ui/src/library_ui.rs:2386`](../ui/dr-ui/src/library_ui.rs#L2386), [`ui/dr-ui/src/library_ui.rs:2403`](../ui/dr-ui/src/library_ui.rs#L2403), [`ui/dr-ui/src/library_ui.rs:2501`](../ui/dr-ui/src/library_ui.rs#L2501), [`ui/dr-ui/src/library_ui.rs:5837`](../ui/dr-ui/src/library_ui.rs#L5837), [`ui/dr-ui/src/library_ui.rs:5877`](../ui/dr-ui/src/library_ui.rs#L5877), [`ui/dr-ui/src/library_ui.rs:5906`](../ui/dr-ui/src/library_ui.rs#L5906), [`ui/dr-ui/src/library_ui.rs:6169`](../ui/dr-ui/src/library_ui.rs#L6169), [`ui/dr-ui/src/library_ui.rs:6392`](../ui/dr-ui/src/library_ui.rs#L6392), [`ui/dr-ui/src/library_ui.rs:7146`](../ui/dr-ui/src/library_ui.rs#L7146), [`ui/dr-ui/src/library_ui.rs:933`](../ui/dr-ui/src/library_ui.rs#L933), [`ui/dr-ui/src/library_ui.rs:966`](../ui/dr-ui/src/library_ui.rs#L966), [`ui/dr-ui/src/place.rs:1`](../ui/dr-ui/src/place.rs#L1) | +| NFR-A11Y-2 | [`ui/dr-ui/tests/ui_controls_are_accessible.rs:1`](../ui/dr-ui/tests/ui_controls_are_accessible.rs#L1), [`ui/dr-ui/ui/adjust.slint:171`](../ui/dr-ui/ui/adjust.slint#L171), [`ui/dr-ui/ui/app.slint:2658`](../ui/dr-ui/ui/app.slint#L2658), [`ui/dr-ui/ui/app.slint:2696`](../ui/dr-ui/ui/app.slint#L2696) | | NFR-A11Y-3 | [`ui/dr-ui/src/histogram.rs:356`](../ui/dr-ui/src/histogram.rs#L356), [`ui/dr-ui/ui/histogram.slint:137`](../ui/dr-ui/ui/histogram.slint#L137), [`ui/dr-ui/ui/library.slint:761`](../ui/dr-ui/ui/library.slint#L761), [`ui/dr-ui/ui/library.slint:909`](../ui/dr-ui/ui/library.slint#L909), [`ui/dr-ui/ui/peaking.slint:1`](../ui/dr-ui/ui/peaking.slint#L1) | -| 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:4052`](../ui/dr-ui/src/library.rs#L4052) | -| NFR-ARCH-3 | [`ui/dr-ui/src/export.rs:1809`](../ui/dr-ui/src/export.rs#L1809), [`ui/dr-ui/src/export.rs:1836`](../ui/dr-ui/src/export.rs#L1836), [`ui/dr-ui/src/export.rs:412`](../ui/dr-ui/src/export.rs#L412), [`ui/dr-ui/src/export.rs:438`](../ui/dr-ui/src/export.rs#L438), [`ui/dr-ui/src/lib.rs:2786`](../ui/dr-ui/src/lib.rs#L2786), [`ui/dr-ui/ui/app.slint:1102`](../ui/dr-ui/ui/app.slint#L1102), [`ui/dr-ui/ui/library.slint:4278`](../ui/dr-ui/ui/library.slint#L4278) | +| 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:4123`](../ui/dr-ui/src/library.rs#L4123) | +| NFR-ARCH-3 | [`ui/dr-ui/src/export.rs:1809`](../ui/dr-ui/src/export.rs#L1809), [`ui/dr-ui/src/export.rs:1836`](../ui/dr-ui/src/export.rs#L1836), [`ui/dr-ui/src/export.rs:412`](../ui/dr-ui/src/export.rs#L412), [`ui/dr-ui/src/export.rs:438`](../ui/dr-ui/src/export.rs#L438), [`ui/dr-ui/src/lib.rs:2787`](../ui/dr-ui/src/lib.rs#L2787), [`ui/dr-ui/ui/app.slint:1106`](../ui/dr-ui/ui/app.slint#L1106), [`ui/dr-ui/ui/library.slint:4308`](../ui/dr-ui/ui/library.slint#L4308) | | 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), [`core/dr-xmp/src/lib.rs:798`](../core/dr-xmp/src/lib.rs#L798), [`platform/dr-plat/src/storage.rs:148`](../platform/dr-plat/src/storage.rs#L148), [`ui/dr-ui/src/export.rs:514`](../ui/dr-ui/src/export.rs#L514) | | NFR-COMPAT-1 | [`core/dr-gpu/src/lib.rs:284`](../core/dr-gpu/src/lib.rs#L284) | -| NFR-OPS-1 | [`core/dr-gpu/src/lib.rs:337`](../core/dr-gpu/src/lib.rs#L337), [`platform/dr-plat/src/diagnostics.rs:1`](../platform/dr-plat/src/diagnostics.rs#L1), [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1), [`platform/dr-plat/src/state.rs:1`](../platform/dr-plat/src/state.rs#L1), [`ui/dr-ui/src/lib.rs:1209`](../ui/dr-ui/src/lib.rs#L1209), [`ui/dr-ui/ui/app.slint:1389`](../ui/dr-ui/ui/app.slint#L1389), [`ui/dr-ui/ui/app.slint:72`](../ui/dr-ui/ui/app.slint#L72), [`ui/dr-ui/ui/settings.slint:144`](../ui/dr-ui/ui/settings.slint#L144), [`ui/dr-ui/ui/settings.slint:942`](../ui/dr-ui/ui/settings.slint#L942) | +| NFR-OPS-1 | [`core/dr-gpu/src/lib.rs:337`](../core/dr-gpu/src/lib.rs#L337), [`platform/dr-plat/src/diagnostics.rs:1`](../platform/dr-plat/src/diagnostics.rs#L1), [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1), [`platform/dr-plat/src/state.rs:1`](../platform/dr-plat/src/state.rs#L1), [`ui/dr-ui/src/lib.rs:1210`](../ui/dr-ui/src/lib.rs#L1210), [`ui/dr-ui/ui/app.slint:1393`](../ui/dr-ui/ui/app.slint#L1393), [`ui/dr-ui/ui/app.slint:72`](../ui/dr-ui/ui/app.slint#L72), [`ui/dr-ui/ui/settings.slint:144`](../ui/dr-ui/ui/settings.slint#L144), [`ui/dr-ui/ui/settings.slint:942`](../ui/dr-ui/ui/settings.slint#L942) | | NFR-OPS-2 | [`platform/dr-plat/src/crash.rs:1`](../platform/dr-plat/src/crash.rs#L1) | | 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/bench/src/catalog_open.rs:1`](../tools/bench/src/catalog_open.rs#L1) | | 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:4229`](../ui/dr-ui/src/develop.rs#L4229), [`ui/dr-ui/src/lib.rs:2092`](../ui/dr-ui/src/lib.rs#L2092) | +| 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:4229`](../ui/dr-ui/src/develop.rs#L4229), [`ui/dr-ui/src/lib.rs:2093`](../ui/dr-ui/src/lib.rs#L2093) | | NFR-P3 | [`tools/bench/src/thumbnails.rs:1`](../tools/bench/src/thumbnails.rs#L1) | -| NFR-P5 | [`core/dr-catalog/src/schema.rs:434`](../core/dr-catalog/src/schema.rs#L434), [`ui/dr-ui/src/library.rs:5498`](../ui/dr-ui/src/library.rs#L5498), [`ui/dr-ui/src/library.rs:6611`](../ui/dr-ui/src/library.rs#L6611), [`ui/dr-ui/src/library_ui.rs:5031`](../ui/dr-ui/src/library_ui.rs#L5031), [`ui/dr-ui/src/library_ui.rs:64`](../ui/dr-ui/src/library_ui.rs#L64) | +| NFR-P5 | [`core/dr-catalog/src/schema.rs:446`](../core/dr-catalog/src/schema.rs#L446), [`ui/dr-ui/src/library.rs:5650`](../ui/dr-ui/src/library.rs#L5650), [`ui/dr-ui/src/library.rs:6763`](../ui/dr-ui/src/library.rs#L6763), [`ui/dr-ui/src/library_ui.rs:5031`](../ui/dr-ui/src/library_ui.rs#L5031), [`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:992`](../ui/dr-ui/src/export.rs#L992), [`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:272`](../core/dr-types/src/lib.rs#L272), [`core/dr-types/src/lib.rs:305`](../core/dr-types/src/lib.rs#L305), [`platform/dr-plat/src/dirs.rs:1`](../platform/dr-plat/src/dirs.rs#L1), [`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) | | NFR-PORT-3 | [`platform/dr-plat/src/storage.rs:1`](../platform/dr-plat/src/storage.rs#L1) | -| NFR-R1 | [`core/dr-catalog/src/schema.rs:236`](../core/dr-catalog/src/schema.rs#L236), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-gpu/src/lib.rs:192`](../core/dr-gpu/src/lib.rs#L192), [`core/dr-sync/src/account.rs:226`](../core/dr-sync/src/account.rs#L226), [`ui/dr-ui/src/library.rs:1170`](../ui/dr-ui/src/library.rs#L1170) | +| NFR-R1 | [`core/dr-catalog/src/schema.rs:244`](../core/dr-catalog/src/schema.rs#L244), [`core/dr-catalog/src/sync.rs:1`](../core/dr-catalog/src/sync.rs#L1), [`core/dr-gpu/src/lib.rs:192`](../core/dr-gpu/src/lib.rs#L192), [`core/dr-sync/src/account.rs:226`](../core/dr-sync/src/account.rs#L226), [`ui/dr-ui/src/library.rs:1234`](../ui/dr-ui/src/library.rs#L1234) | | NFR-R2 | [`core/dr-catalog/src/recovery.rs:1`](../core/dr-catalog/src/recovery.rs#L1), [`core/dr-catalog/src/recovery.rs:222`](../core/dr-catalog/src/recovery.rs#L222), [`core/dr-catalog/src/sync.rs:61`](../core/dr-catalog/src/sync.rs#L61), [`core/dr-catalog/src/trash.rs:1`](../core/dr-catalog/src/trash.rs#L1), [`ui/dr-ui/src/derived_sync.rs:602`](../ui/dr-ui/src/derived_sync.rs#L602), [`ui/dr-ui/src/derived_sync.rs:725`](../ui/dr-ui/src/derived_sync.rs#L725), [`ui/dr-ui/src/library_ui.rs:4200`](../ui/dr-ui/src/library_ui.rs#L4200), [`ui/dr-ui/src/library_ui.rs:4518`](../ui/dr-ui/src/library_ui.rs#L4518) | | NFR-R3 | [`core/dr-decode/src/error.rs:30`](../core/dr-decode/src/error.rs#L30) | -| NFR-R4 | [`core/dr-types/src/settings.rs:92`](../core/dr-types/src/settings.rs#L92), [`ui/dr-ui/src/library.rs:1563`](../ui/dr-ui/src/library.rs#L1563), [`ui/dr-ui/src/library.rs:1579`](../ui/dr-ui/src/library.rs#L1579), [`ui/dr-ui/src/library_ui.rs:3453`](../ui/dr-ui/src/library_ui.rs#L3453), [`ui/dr-ui/src/library_ui.rs:392`](../ui/dr-ui/src/library_ui.rs#L392), [`ui/dr-ui/src/library_ui.rs:535`](../ui/dr-ui/src/library_ui.rs#L535), [`ui/dr-ui/src/settings_ui.rs:540`](../ui/dr-ui/src/settings_ui.rs#L540), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/ui/settings.slint:1020`](../ui/dr-ui/ui/settings.slint#L1020), [`ui/dr-ui/ui/settings.slint:189`](../ui/dr-ui/ui/settings.slint#L189) | +| NFR-R4 | [`core/dr-types/src/settings.rs:92`](../core/dr-types/src/settings.rs#L92), [`ui/dr-ui/src/library.rs:1627`](../ui/dr-ui/src/library.rs#L1627), [`ui/dr-ui/src/library.rs:1643`](../ui/dr-ui/src/library.rs#L1643), [`ui/dr-ui/src/library_ui.rs:3453`](../ui/dr-ui/src/library_ui.rs#L3453), [`ui/dr-ui/src/library_ui.rs:392`](../ui/dr-ui/src/library_ui.rs#L392), [`ui/dr-ui/src/library_ui.rs:535`](../ui/dr-ui/src/library_ui.rs#L535), [`ui/dr-ui/src/settings_ui.rs:540`](../ui/dr-ui/src/settings_ui.rs#L540), [`ui/dr-ui/src/xmp_sync.rs:1`](../ui/dr-ui/src/xmp_sync.rs#L1), [`ui/dr-ui/ui/settings.slint:1020`](../ui/dr-ui/ui/settings.slint#L1020), [`ui/dr-ui/ui/settings.slint:189`](../ui/dr-ui/ui/settings.slint#L189) | | NFR-R5 | [`core/dr-catalog/src/collections.rs:1`](../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/error.rs:1`](../core/dr-catalog/src/error.rs#L1), [`core/dr-catalog/src/keywords.rs:1`](../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/schema.rs:1`](../core/dr-catalog/src/schema.rs#L1) | | NFR-R6 | [`core/dr-catalog/src/error.rs:1`](../core/dr-catalog/src/error.rs#L1), [`core/dr-catalog/src/lib.rs:255`](../core/dr-catalog/src/lib.rs#L255), [`core/dr-catalog/src/recovery.rs:1`](../core/dr-catalog/src/recovery.rs#L1) | | NFR-R7 | [`core/dr-gpu/src/error.rs:1`](../core/dr-gpu/src/error.rs#L1) | | NFR-R8 | [`core/dr-gpu/src/error.rs:1`](../core/dr-gpu/src/error.rs#L1) | -| NFR-RES-1 | [`core/dr-gpu/src/adjust.rs:1029`](../core/dr-gpu/src/adjust.rs#L1029), [`core/dr-pipeline/src/history.rs:86`](../core/dr-pipeline/src/history.rs#L86), [`ui/dr-ui/src/develop.rs:4512`](../ui/dr-ui/src/develop.rs#L4512), [`ui/dr-ui/src/identity_ui.rs:125`](../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:94`](../ui/dr-ui/src/lib.rs#L94), [`ui/dr-ui/src/memory.rs:1`](../ui/dr-ui/src/memory.rs#L1) | -| NFR-RES-2 | [`ui/dr-ui/src/faces.rs:350`](../ui/dr-ui/src/faces.rs#L350), [`ui/dr-ui/src/library.rs:3531`](../ui/dr-ui/src/library.rs#L3531), [`ui/dr-ui/src/library.rs:4052`](../ui/dr-ui/src/library.rs#L4052), [`ui/dr-ui/src/library.rs:4303`](../ui/dr-ui/src/library.rs#L4303), [`ui/dr-ui/src/library.rs:6855`](../ui/dr-ui/src/library.rs#L6855) | -| NFR-RES-4 | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/face_shard.rs:1`](../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-catalog/src/schema.rs:975`](../core/dr-catalog/src/schema.rs#L975), [`core/dr-gpu/src/lib.rs:93`](../core/dr-gpu/src/lib.rs#L93), [`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), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`ui/dr-ui/src/library.rs:3796`](../ui/dr-ui/src/library.rs#L3796) | +| NFR-RES-1 | [`core/dr-gpu/src/adjust.rs:1029`](../core/dr-gpu/src/adjust.rs#L1029), [`core/dr-pipeline/src/history.rs:86`](../core/dr-pipeline/src/history.rs#L86), [`ui/dr-ui/src/develop.rs:4512`](../ui/dr-ui/src/develop.rs#L4512), [`ui/dr-ui/src/identity_ui.rs:125`](../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:95`](../ui/dr-ui/src/lib.rs#L95), [`ui/dr-ui/src/memory.rs:1`](../ui/dr-ui/src/memory.rs#L1) | +| NFR-RES-2 | [`ui/dr-ui/src/faces.rs:419`](../ui/dr-ui/src/faces.rs#L419), [`ui/dr-ui/src/library.rs:3595`](../ui/dr-ui/src/library.rs#L3595), [`ui/dr-ui/src/library.rs:4123`](../ui/dr-ui/src/library.rs#L4123), [`ui/dr-ui/src/library.rs:4376`](../ui/dr-ui/src/library.rs#L4376), [`ui/dr-ui/src/library.rs:7009`](../ui/dr-ui/src/library.rs#L7009) | +| NFR-RES-4 | [`core/dr-catalog/src/cache.rs:1`](../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/face_shard.rs:1`](../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-catalog/src/schema.rs:990`](../core/dr-catalog/src/schema.rs#L990), [`core/dr-gpu/src/lib.rs:93`](../core/dr-gpu/src/lib.rs#L93), [`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), [`core/dr-thumbs/src/lib.rs:376`](../core/dr-thumbs/src/lib.rs#L376), [`ui/dr-ui/src/library.rs:3860`](../ui/dr-ui/src/library.rs#L3860) | | NFR-SEC-1 | [`core/dr-decode/src/error.rs:1`](../core/dr-decode/src/error.rs#L1), [`core/dr-decode/src/error.rs:30`](../core/dr-decode/src/error.rs#L30) | | NFR-SEC-2 | [`core/dr-sync/src/account.rs:304`](../core/dr-sync/src/account.rs#L304), [`platform/dr-plat/src/crash.rs:1`](../platform/dr-plat/src/crash.rs#L1), [`platform/dr-plat/src/diagnostics.rs:1`](../platform/dr-plat/src/diagnostics.rs#L1), [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1), [`platform/dr-plat/src/diagnostics/redact.rs:1`](../platform/dr-plat/src/diagnostics/redact.rs#L1), [`platform/dr-plat/src/secrets.rs:82`](../platform/dr-plat/src/secrets.rs#L82) | | NFR-SEC-3 | [`core/dr-sync-nextcloud/src/lib.rs:1`](../core/dr-sync-nextcloud/src/lib.rs#L1), [`core/dr-sync-nextcloud/src/provider.rs:1`](../core/dr-sync-nextcloud/src/provider.rs#L1) | | NFR-SEC-4 | [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1) | -| NFR-SEC-5 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:804`](../core/dr-catalog/src/schema.rs#L804), [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1), [`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/ui/identity.slint:1`](../ui/dr-ui/ui/identity.slint#L1) | +| NFR-SEC-5 | [`core/dr-catalog/src/faces.rs:1`](../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:819`](../core/dr-catalog/src/schema.rs#L819), [`platform/dr-plat/src/diagnostics/bundle.rs:1`](../platform/dr-plat/src/diagnostics/bundle.rs#L1), [`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/ui/identity.slint:1`](../ui/dr-ui/ui/identity.slint#L1) | | R3 | [`core/dr-export/src/lib.rs:1`](../core/dr-export/src/lib.rs#L1), [`core/dr-pipeline/src/lib.rs:1`](../core/dr-pipeline/src/lib.rs#L1) | | R4 | [`core/dr-gpu/src/lib.rs:366`](../core/dr-gpu/src/lib.rs#L366) | | R5 | [`core/dr-gpu/tests/zoom_resolution.rs:1`](../core/dr-gpu/tests/zoom_resolution.rs#L1) | diff --git a/ui/dr-ui/examples/face_index.rs b/ui/dr-ui/examples/face_index.rs index b4498d1..747ba20 100644 --- a/ui/dr-ui/examples/face_index.rs +++ b/ui/dr-ui/examples/face_index.rs @@ -60,7 +60,7 @@ fn main() { } }; - let audit = match faces::audit(&catalog, &store, MODEL_ID) { + let audit = match faces::audit(&catalog, &store, MODEL_ID, false) { Ok(a) => a, Err(e) => { eprintln!("coverage check failed: {e}"); @@ -183,8 +183,13 @@ fn main() { let rx = faces::spawn_store_face_sweep( catalog_path, store_dir, - PathBuf::from(detector), - PathBuf::from(embedder), + dr_ui::FaceModelPaths { + detector: PathBuf::from(detector), + embedder: PathBuf::from(embedder), + // A measurement tool for the detector and embedder; the eye + // models are the library pass's business. + eyes: None, + }, MODEL_ID.to_string(), dr_face::DetectOptions::default(), ); @@ -222,7 +227,7 @@ fn main() { } } - if let Ok(a) = faces::audit(&catalog, &store, MODEL_ID) { + if let Ok(a) = faces::audit(&catalog, &store, MODEL_ID, false) { println!("{}", a.summary()); } println!("\nrun again with --cluster to group these faces into people."); diff --git a/ui/dr-ui/examples/face_native.rs b/ui/dr-ui/examples/face_native.rs index 2ebe5c9..a3e5d0e 100644 --- a/ui/dr-ui/examples/face_native.rs +++ b/ui/dr-ui/examples/face_native.rs @@ -1,7 +1,7 @@ //! TRACES: FR-CULL-8 | FR-EXP-9 //! Measure what indexing at native resolution is actually worth. //! -//! cargo run -p dr-ui --example face_native -- DET.onnx EMB.onnx FILE [FILE…] +//! cargo run -p dr-ui --example face_native -- DET.onnx EMB.onnx [--export DIR] FILE [FILE…] //! //! Renders each file once at native resolution, then indexes it twice: the way //! FR-CULL-8 now specifies, and the way it used to be done — everything, both @@ -13,6 +13,10 @@ //! this is evidence about what the new code does, on the same photographs, with //! nothing between the two runs but the resolution. //! +//! `--export DIR` also writes each native render out as a JPEG, so the +//! model-free tooling in `dr-face`'s examples — `eyes` above all — can be +//! run over native pixels rather than proxies (docs/faces.md §17.4). +//! //! The models must have had their input dims frozen first; see //! `tools/fix-face-model-shapes.sh`. @@ -23,11 +27,18 @@ const MODEL_ID: &str = "w600k_mbf"; fn main() { env_logger::init(); - let args: Vec = std::env::args().skip(1).collect(); + let mut args: Vec = std::env::args().skip(1).collect(); + let export = args.iter().position(|a| a == "--export").map(|i| { + args.remove(i); + PathBuf::from(args.remove(i)) + }); if args.len() < 3 { - eprintln!("usage: face_native DETECTOR.onnx EMBEDDER.onnx FILE [FILE…]"); + eprintln!("usage: face_native DETECTOR.onnx EMBEDDER.onnx [--export DIR] FILE [FILE…]"); std::process::exit(2); } + if let Some(d) = &export { + std::fs::create_dir_all(d).expect("export dir"); + } let (detector_model, embedder_model) = (PathBuf::from(&args[0]), PathBuf::from(&args[1])); let Some(gpu) = pollster::block_on(dr_gpu::GpuContext::new_headless()).ok() else { @@ -76,10 +87,27 @@ fn main() { } }; let (w, h) = (frame.width as usize, frame.height as usize); - - let native = - dr_ui::faces::index_native(&mut detector, &mut embedder, &frame.rgba, w, h, &options) + if let Some(dir) = &export { + let stem = std::path::Path::new(path) + .file_stem() + .map(|s| s.to_string_lossy().into_owned()) .unwrap_or_default(); + match dr_thumbs::codec::encode_rgba(frame.width, frame.height, &frame.rgba) { + Ok(bytes) => std::fs::write(dir.join(format!("{stem}.jpg")), bytes).expect("write"), + Err(e) => println!("{path}: export: {e}"), + } + } + + let native = dr_ui::faces::index_native( + &mut detector, + &mut embedder, + None, + &frame.rgba, + w, + h, + &options, + ) + .unwrap_or_default(); // The old path, reproduced exactly: one buffer at 1024, used for both // detection and the crop. @@ -89,9 +117,10 @@ fn main() { rgba: frame.rgba.clone(), }; small.downscale_to(dr_thumbs::ThumbSize::Large.edge()); - let proxy = dr_ui::faces::index_preview(&mut detector, &mut embedder, &small, &options) - .map(|(f, _)| f) - .unwrap_or_default(); + let proxy = + dr_ui::faces::index_preview(&mut detector, &mut embedder, None, &small, &options) + .map(|(f, _)| f) + .unwrap_or_default(); let mean = |v: &[dr_catalog::faces::DetectedFace]| { if v.is_empty() { diff --git a/ui/dr-ui/src/faces.rs b/ui/dr-ui/src/faces.rs index ebd7951..59c6902 100644 --- a/ui/dr-ui/src/faces.rs +++ b/ui/dr-ui/src/faces.rs @@ -28,7 +28,10 @@ use std::sync::mpsc::{Receiver, Sender}; use dr_catalog::faces::{self, DetectedFace}; use dr_catalog::Catalog; -use dr_face::{align, Calibration, DetectOptions, Detection, Detector, Embedder, ModelId}; +use dr_face::{ + align, Calibration, DetectOptions, Detection, Detector, Embedder, EyeModels, EyeReading, + ModelId, +}; use dr_thumbs::{ThumbSize, ThumbStore}; use dr_types::settings::FaceSettings; use dr_types::ImageId; @@ -154,6 +157,14 @@ pub struct IndexAudit { /// Outstanding with no proxy on disk. Costs a range request, same as the /// ones above now do. pub awaiting_proxy: u64, + /// TRACES: FR-CULL-13 + /// Faces this model found that the measuring pass still has to read: + /// stored without their quality, or — on a device with the eye models — + /// without an eye reading. Work that is not visible in the coverage + /// figure, since every one of these images carries its run marker, and + /// that has to be counted here or the screen calls the library finished + /// and takes the button away that would finish it. + pub unmeasured: u64, } impl IndexAudit { @@ -188,8 +199,19 @@ impl IndexAudit { if outstanding > 0 { s.push_str(&format!("; {outstanding} to index")); } + if self.unmeasured > 0 { + s.push_str(&format!("; {} face(s) to measure", self.unmeasured)); + } s } + + /// Whether the sweep has nothing left to do — nothing to index *and* + /// nothing to measure. The screen hides the button on this, so it has to + /// be false while the measuring pass has work, or the eye readings of an + /// already-indexed library could never be filled in. + pub fn is_complete(&self) -> bool { + self.coverage.is_complete() && self.unmeasured == 0 + } } /// Check every library image for a face-detection run marker. @@ -197,13 +219,19 @@ impl IndexAudit { /// The batch pass that answers "has face recognition been over all of this", /// and the one to run before deciding whether to start a sweep. Cheap: two /// counts and one indexed scan, no decoding and no inference. +/// +/// `eyes` is whether this device has the eye models, and it decides whether +/// a face without an eye reading counts as work — see +/// `dr_catalog::faces::faces_unmeasured`. pub fn audit( catalog: &Catalog, store: &ThumbStore, model_id: &str, + eyes: bool, ) -> Result { let conn = catalog.connection(); let coverage = faces::coverage(conn, model_id)?; + let unmeasured = faces::faces_unmeasured(conn, model_id, eyes)?; // Split the outstanding set by whether a proxy exists. This is the query // `faces_outstanding` runs without the store filter, so the two cannot @@ -240,9 +268,40 @@ pub fn audit( coverage, ready, awaiting_proxy: awaiting, + unmeasured, }) } +/// TRACES: FR-CULL-13 +/// Read one face's eyes from the buffer its crop came from, if this device +/// can. +/// +/// From the same pixels the embedder saw the face in, so what the models +/// see is the eye at the resolution the crop had — and `dr_face::eyes`' +/// readability floors are judged against real pixels rather than a proxy's +/// idea of them. `bbox` is the detector's `(x0, y0, x1, y1)` and `landmarks` +/// its five points, both in this buffer's pixels. `None` on a device without +/// the models, which is the ordinary state of one that has not been given +/// them, and `None` — logged — where the models refuse: a face the embedder +/// could use is not lost for the want of an eye reading. +fn read_eyes( + models: Option<&mut EyeModels>, + px: dr_face::Pixels<'_>, + width: usize, + height: usize, + bbox: (f32, f32, f32, f32), + landmarks: &[(f32, f32); 5], +) -> Option { + let models = models?; + match models.read(px, width, height, bbox, landmarks) { + Ok(r) => r, + Err(e) => { + log::debug!("eye reading failed: {e}"); + None + } + } +} + /// Detect and embed every face in one decoded proxy. /// /// Coordinates come back **normalised to the long edge**, which is what the @@ -256,6 +315,7 @@ pub fn audit( pub fn index_proxy( detector: &mut Detector, embedder: &mut Embedder, + mut eye_models: Option<&mut EyeModels>, rgb: &[f32], width: usize, height: usize, @@ -310,6 +370,14 @@ pub fn index_proxy( } let embedded = embedder.embed(&aligned)?; + let eyes = read_eyes( + eye_models.as_deref_mut(), + dr_face::Pixels::RgbF32(rgb), + width, + height, + d.bbox, + &d.landmarks, + ); out.push(DetectedFace { x: d.bbox.0 / long_edge, @@ -321,6 +389,7 @@ pub fn index_proxy( embedding: embedded.to_f16_bytes(), crop_px: aligned.source_px(), quality: Some(embedded.quality), + eyes, model_id: embedder.model().as_str().to_string(), // Cut here, while the buffer is still in hand. This is the only // moment in the whole pipeline where the pixels are free. @@ -370,6 +439,7 @@ const DETECT_EDGE: usize = 1600; pub fn index_native( detector: &mut Detector, embedder: &mut Embedder, + mut eye_models: Option<&mut EyeModels>, rgba: &[u8], width: usize, height: usize, @@ -426,6 +496,17 @@ pub fn index_native( let embedded = embedder.embed(&aligned)?; let (bx, by) = (d.bbox.0 * sx, d.bbox.1 * sy); let (bw, bh) = (d.width() * sx, d.height() * sy); + // From the native buffer, box and landmarks scaled like the crop's + // — the eye is a fortieth of the face, and it is here that the + // native render pays for itself twice. + let eyes = read_eyes( + eye_models.as_deref_mut(), + native, + width, + height, + (bx, by, bx + bw, by + bh), + &landmarks, + ); out.push(DetectedFace { x: bx / long_edge, @@ -437,6 +518,7 @@ pub fn index_native( embedding: embedded.to_f16_bytes(), crop_px: aligned.source_px(), quality: Some(embedded.quality), + eyes, model_id: embedder.model().as_str().to_string(), crop: cut_crop_native(native, width, height, (bx, by, bw, bh)).unwrap_or_default(), }); @@ -469,8 +551,14 @@ pub struct Measured { /// established now is how much the model can make of each, which is the /// quality itself, and a face that would have failed a gate is precisely one /// that should come out short and stop vouching for anyone. +/// +/// The eyes are read on the same pass where the device has the models, for +/// the faces that have no reading yet (schema V16): the pixels are in hand, +/// and the eye is a window on the same landmarks. A face that already has +/// one keeps it. pub fn measure_native( embedder: &mut Embedder, + mut eye_models: Option<&mut EyeModels>, rgba: &[u8], width: usize, height: usize, @@ -494,10 +582,29 @@ pub fn measure_native( continue; }; let embedded = embedder.embed(&aligned)?; + let eyes = if f.eyes.is_some() { + None + } else { + let bbox = ( + f.x * long_edge, + f.y * long_edge, + (f.x + f.w) * long_edge, + (f.y + f.h) * long_edge, + ); + read_eyes( + eye_models.as_deref_mut(), + native, + width, + height, + bbox, + &landmarks, + ) + }; out.measured.push(faces::Measurement { face: f.id, embedding: embedded.to_f16_bytes(), quality: embedded.quality, + eyes, }); } Ok(out) @@ -658,8 +765,7 @@ fn normalise_landmarks(lm: &[(f32, f32); 5], long_edge: f32) -> [(f32, f32); 5] pub fn spawn_store_face_sweep( catalog_path: PathBuf, store_dir: PathBuf, - detector_model: PathBuf, - embedder_model: PathBuf, + models: crate::FaceModelPaths, model_id: String, options: DetectOptions, ) -> Receiver { @@ -696,7 +802,7 @@ pub fn spawn_store_face_sweep( // missing. This is also the path a library with face indexing enabled // but no model downloaded takes (docs/faces.md §2.2), so it must be a // quiet return rather than an error. - let mut detector = match Detector::from_path(&detector_model) { + let mut detector = match Detector::from_path(&models.detector) { Ok(d) => d, Err(e) => { log::warn!("face sweep: cannot load the detector: {e}"); @@ -705,7 +811,7 @@ pub fn spawn_store_face_sweep( } }; let mut embedder = - match Embedder::from_path(&embedder_model, ModelId::new(model_id.clone())) { + match Embedder::from_path(&models.embedder, ModelId::new(model_id.clone())) { Ok(e) => e, Err(e) => { log::warn!("face sweep: cannot load the embedder: {e}"); @@ -713,6 +819,7 @@ pub fn spawn_store_face_sweep( return; } }; + let mut eye_models = models.load_eyes(); // Nothing below this point can succeed, so do not pretend to try. // @@ -782,6 +889,7 @@ pub fn spawn_store_face_sweep( let faces = match index_proxy( &mut detector, &mut embedder, + eye_models.as_mut(), &rgb, w as usize, h as usize, @@ -1360,6 +1468,7 @@ fn cut_crop(rgb: &[f32], width: usize, height: usize, d: &Detection) -> Option, preview: &dr_decode::Preview, options: &DetectOptions, ) -> Result<(Vec, u32), dr_face::FaceError> { @@ -1367,6 +1476,7 @@ pub fn index_preview( let faces = index_proxy( detector, embedder, + eye_models, &rgb, preview.width as usize, preview.height as usize, @@ -1499,6 +1609,7 @@ mod tests { confidence: 0.9, crop_px: 280.0, quality: None, + eyes: None, model_id: "w600k_mbf".into(), person: None, probability: 0.0, @@ -1506,7 +1617,7 @@ mod tests { }; let stored_copy = stored.clone(); - let out = measure_native(&mut embedder, &rgba, w, h, &[stored]).expect("measure"); + let out = measure_native(&mut embedder, None, &rgba, w, h, &[stored]).expect("measure"); assert!(out.dropped.is_empty()); assert_eq!(out.measured.len(), 1); let m = &out.measured[0]; @@ -1526,7 +1637,7 @@ mod tests { landmarks: [(0.3, 0.3); 5], ..stored_copy }; - let out = measure_native(&mut embedder, &rgba, w, h, &[junk]).expect("measure"); + let out = measure_native(&mut embedder, None, &rgba, w, h, &[junk]).expect("measure"); assert!(out.measured.is_empty()); assert_eq!(out.dropped, vec![faces::FaceId(8)]); } @@ -1552,6 +1663,7 @@ mod tests { }, ready: 30, awaiting_proxy: 10, + unmeasured: 0, }; let s = a.summary(); assert!(s.contains("60/100"), "{s}"); @@ -1577,11 +1689,40 @@ mod tests { }, ready: 0, awaiting_proxy: 0, + unmeasured: 0, }; let s = a.summary(); assert!(!s.contains("ready"), "{s}"); assert!(!s.contains("awaiting"), "{s}"); + assert!(!s.contains("measure"), "{s}"); assert!(s.contains("10/10"), "{s}"); + assert!(a.is_complete()); + } + + /// TRACES: FR-CULL-13 + /// A fully indexed library whose faces have not been read is not + /// finished: the screen hides the button on `is_complete`, and this is + /// the only way the readings of an old library ever get filled in. + #[test] + fn faces_left_to_measure_keep_the_audit_incomplete() { + let a = IndexAudit { + coverage: faces::Coverage { + images: 10, + indexed: 10, + without_faces: 7, + faces: 4, + }, + ready: 0, + awaiting_proxy: 0, + unmeasured: 4, + }; + assert!(a.coverage.is_complete()); + assert!(!a.is_complete()); + assert!( + a.summary().contains("4 face(s) to measure"), + "{}", + a.summary() + ); } /// The figure the real library actually produced: 110 of 23,528 rounds to @@ -1597,6 +1738,7 @@ mod tests { }, ready: 69, awaiting_proxy: 23_349, + unmeasured: 0, }; let s = a.summary(); assert!(s.contains("0.5%"), "{s}"); @@ -1614,6 +1756,7 @@ mod tests { }, ready: 99_999, awaiting_proxy: 0, + unmeasured: 0, }; assert!(a.summary().contains("<0.1%"), "{}", a.summary()); } @@ -1663,6 +1806,7 @@ mod tests { confidence: 0.9, crop_px: 120.0, quality: None, + eyes: None, model_id: "w600k_mbf".into(), person: None, probability: 0.0, @@ -1781,6 +1925,7 @@ mod tests { embedding: embedding(identity, cosine), crop_px: 150.0, quality: None, + eyes: None, model_id: TEST_MODEL.to_string(), crop: Vec::new(), }; diff --git a/ui/dr-ui/src/gesture_book.rs b/ui/dr-ui/src/gesture_book.rs index e4ced81..34a0420 100644 --- a/ui/dr-ui/src/gesture_book.rs +++ b/ui/dr-ui/src/gesture_book.rs @@ -239,6 +239,13 @@ pub const GESTURES: &[Gesture] = &[ pointer: "Shift-click the last photograph of the run", keys: "", }, + Gesture { + title: "Take the blinks out of a burst", + section: "Library grid", + touch: "Narrow to a person, then tap \"Eyes open\" beside their name on the filter bar", + pointer: "Narrow to a person, then click \"Eyes open\" beside their name on the filter bar", + keys: "", + }, Gesture { title: "Find photographs with two people in them", section: "Library grid", diff --git a/ui/dr-ui/src/identity.rs b/ui/dr-ui/src/identity.rs index 07d9181..edf30ce 100644 --- a/ui/dr-ui/src/identity.rs +++ b/ui/dr-ui/src/identity.rs @@ -101,6 +101,9 @@ pub struct FaceCell { /// of its raw embedding (`dr_face::MIN_GALLERY_QUALITY`). `None` for a /// face indexed before it was kept. pub quality: Option, + /// TRACES: FR-CULL-13 + /// What the eyes are doing, where they were read. + pub eyes: Option, } impl FaceCell { @@ -144,6 +147,22 @@ impl FaceCell { pub fn in_gallery(&self) -> bool { dr_face::in_gallery(self.quality) } + + /// The eye state as a badge — "Eyes closed", "Sunglasses" or "Eyes + /// unclear" — or nothing. + /// + /// Nothing for open eyes and nothing for a face never read, on the rule + /// the confirmed marker follows: the common case carries no mark, so the + /// marks that appear mean something. The three that do appear are the + /// states the eyes-open filter treats differently from open — one it + /// drops, two it lets through — and a user asking why a frame is or is + /// not in the grid can read the answer off the face. + pub fn eyes_label(&self) -> &'static str { + match self.eyes.map(|e| e.state()) { + Some(dr_face::EyeState::Open) | None => "", + Some(state) => state.label(), + } + } } /// Put a grouping preview into words. @@ -284,6 +303,7 @@ pub fn load_faces( probability: f.probability, crop_px: f.crop_px, quality: f.quality, + eyes: f.eyes, }); } @@ -787,6 +807,7 @@ mod tests { embedding: vec![seed; 1024], crop_px: 180.0, quality: Some(f32::from(seed) + 10.0), + eyes: None, model_id: "w600k_mbf".into(), crop: Vec::new(), } @@ -835,6 +856,7 @@ mod tests { probability: 0.87, crop_px: 120.0, quality: Some(17.26), + eyes: None, }; assert_eq!(cell.confidence_label(), "87% likely"); @@ -858,6 +880,7 @@ mod tests { probability: 0.5, crop_px: 120.0, quality: Some(17.26), + eyes: None, }; assert_eq!(cell.quality_label(), "Quality 17.3"); assert!(cell.in_gallery()); @@ -880,6 +903,58 @@ mod tests { ); } + /// Only the two states the filter treats differently from open are + /// badged; open and unread carry no mark. + #[test] + fn the_eye_badge_names_a_blink_or_sunglasses_and_nothing_else() { + let eye = |open| dr_face::Eye { + open, + px: 40.0, + sharpness: 0.2, + }; + let reading = |right, left, sunglasses| { + Some(dr_face::EyeReading { + right: eye(right), + left: eye(left), + sunglasses, + }) + }; + let cell = FaceCell { + face: FaceId(1), + image: ImageId(1), + crop: None, + confirmed: false, + probability: 0.5, + crop_px: 120.0, + quality: Some(17.26), + eyes: None, + }; + assert_eq!(cell.eyes_label(), ""); + let open = FaceCell { + eyes: reading(0.9, 0.9, 0.0), + ..cell.clone() + }; + assert_eq!(open.eyes_label(), ""); + let blink = FaceCell { + eyes: reading(0.9, 0.2, 0.0), + ..cell.clone() + }; + assert_eq!(blink.eyes_label(), "Eyes closed"); + let shades = FaceCell { + eyes: reading(0.9, 0.2, 0.9), + ..cell.clone() + }; + assert_eq!(shades.eyes_label(), "Sunglasses"); + let mut soft = reading(0.1, 0.1, 0.0).unwrap(); + soft.right.sharpness = 0.0; + soft.left.sharpness = 0.0; + let unclear = FaceCell { + eyes: Some(soft), + ..cell + }; + assert_eq!(unclear.eyes_label(), "Eyes unclear"); + } + #[test] fn the_people_rail_reports_the_unassigned_pool() { let c = catalog(); diff --git a/ui/dr-ui/src/identity_ui.rs b/ui/dr-ui/src/identity_ui.rs index a393ddd..b1cafec 100644 --- a/ui/dr-ui/src/identity_ui.rs +++ b/ui/dr-ui/src/identity_ui.rs @@ -153,6 +153,7 @@ pub fn refresh( catalog: &Rc>>, store: Option>, model_id: &str, + eyes: bool, ) { let borrow = catalog.borrow(); let Some(cat) = borrow.as_ref() else { @@ -273,7 +274,7 @@ pub fn refresh( window.set_identity_picked(ctl.picked.borrow().len() as i32); drop(borrow); - refresh_coverage(window, catalog, store.as_deref(), model_id); + refresh_coverage(window, catalog, store.as_deref(), model_id, eyes); // Last, so a portrait cannot delay anything above it. if let Some(store) = store { @@ -380,23 +381,27 @@ fn fill_covers( /// /// Cheap enough to call on every open and after every sweep: two counts and one /// indexed scan, no decoding and no inference. +/// `eyes` is whether this device has the eye models: with them, faces with +/// no eye reading are work the sweep has left (`crate::faces::audit`). pub fn refresh_coverage( window: &AppWindow, catalog: &Rc>>, store: Option<&ThumbStore>, model_id: &str, + eyes: bool, ) { let borrow = catalog.borrow(); let (Some(cat), Some(store)) = (borrow.as_ref(), store) else { window.set_identity_coverage(Default::default()); return; }; - match crate::faces::audit(cat, store, model_id) { + match crate::faces::audit(cat, store, model_id, eyes) { Ok(a) => { window.set_identity_coverage(a.summary().into()); - // Complete means nothing left to index, not "every image has a - // face": most of a library has none, and that is a finding. - window.set_identity_coverage_complete(a.coverage.is_complete()); + // Complete means nothing left to index or measure, not "every + // image has a face": most of a library has none, and that is a + // finding. + window.set_identity_coverage_complete(a.is_complete()); } Err(e) => { log::warn!("identity: coverage check: {e}"); @@ -486,6 +491,7 @@ fn push_faces(window: &AppWindow, ctl: &IdentityController, cells: &[FaceCell]) crop_px: c.crop_px as i32, quality: c.quality_label().into(), in_gallery: c.in_gallery(), + eyes: c.eyes_label().into(), picked: picked.contains(&c.face), }) .collect(); @@ -512,8 +518,9 @@ fn to_slint_image(width: u32, height: u32, rgba: &[u8]) -> slint::Image { /// `library::spawn_face_sweep`). pub type SweepPaths = (dr_sync::Connection, std::path::PathBuf, std::path::PathBuf); -/// The detector and embedder files, when both are present. -pub type ModelPaths = (std::path::PathBuf, std::path::PathBuf); +/// The detector and embedder files, when both are present — and the eye +/// models beside them, when those are. +pub type ModelPaths = crate::library::FaceModelPaths; /// Put the grouping dials on the screen from the settings record. /// @@ -596,14 +603,32 @@ pub fn wire( // second-order effects — a merge empties a person, a split creates one, // a rejection changes two counts — and a model patched by hand would // drift from the catalog in exactly the cases that matter. + // Whether the eye models are on this machine, asked each time rather + // than once: it is two `is_file` checks, and a user who drops the files + // in while the app is open should see the faces become work to measure. + let eyes_available: Rc bool> = { + let models = models.clone(); + Rc::new(move || models().is_some_and(|m| m.eyes.is_some())) + }; + // The availability closure is an argument rather than named in the + // body: macro hygiene would bind the name to this scope's `Rc`, which the + // first `move` closure would then take with it. macro_rules! reload { - ($w:expr, $ctl:expr, $catalog:expr, $store:expr, $settings:expr) => { - refresh(&$w, &$ctl, &$catalog, $store(), &model_id(&$settings)) + ($w:expr, $ctl:expr, $catalog:expr, $store:expr, $settings:expr, $eyes:expr) => { + refresh( + &$w, + &$ctl, + &$catalog, + $store(), + &model_id(&$settings), + $eyes(), + ) }; } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -622,7 +647,7 @@ pub fn wire( // A fact about the filesystem, so it is re-checked on every open // rather than cached: the user may have just put the models there. w.set_identity_model_missing(models_present().is_none()); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } @@ -646,6 +671,7 @@ pub fn wire( { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -661,13 +687,14 @@ pub fn wire( // The offer was about the person being navigated away from. Left // up, its "Merge" would fold whoever is selected *now*. clear_merge_offer(&w, &ctl); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); reset_name_field(&w); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -706,7 +733,7 @@ pub fn wire( Err(e) => log::warn!("identity: looking for a namesake: {e}"), } } - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); // `rename` trims; the field should show what was actually stored // rather than the spacing the user happened to type. reset_name_field(&w); @@ -720,6 +747,7 @@ pub fn wire( // redirect behind so neither side of a sync resurrects what was merged. { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -743,7 +771,7 @@ pub fn wire( } } clear_merge_offer(&w, &ctl); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); reset_name_field(&w); }); } @@ -774,6 +802,7 @@ pub fn wire( { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -788,12 +817,13 @@ pub fn wire( log::warn!("identity: confirm: {e}"); } } - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -808,7 +838,7 @@ pub fn wire( log::warn!("identity: reject: {e}"); } } - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } @@ -836,6 +866,7 @@ pub fn wire( { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -851,12 +882,13 @@ pub fn wire( Err(e) => log::warn!("identity: confirm all: {e}"), } } - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -884,7 +916,7 @@ pub fn wire( } } ctl.clear_picks(); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } @@ -958,6 +990,7 @@ pub fn wire( let store = store.clone(); let paths = paths.clone(); let settings_for_regroup = settings.clone(); + let eyes_available = eyes_available.clone(); window.on_identity_recluster(move || { let Some(w) = weak.upgrade() else { return }; // One at a time. Two passes over the same faces would each create @@ -987,6 +1020,7 @@ pub fn wire( let catalog_tick = catalog.clone(); let store_tick = store.clone(); let settings_tick = settings_for_regroup.clone(); + let eyes_tick = eyes_available.clone(); timer.start( slint::TimerMode::Repeated, Duration::from_millis(100), @@ -1041,6 +1075,7 @@ pub fn wire( &catalog_tick, store_tick(), &model_id(&settings_tick), + eyes_tick(), ); } }, @@ -1058,12 +1093,13 @@ pub fn wire( let paths = paths.clone(); let gpu = gpu.clone(); let settings_for_sweep = settings.clone(); + let eyes_available = eyes_available.clone(); window.on_identity_index(move || { let Some(w) = weak.upgrade() else { return }; if ctl.sweep.borrow().is_some() { return; } - let Some((detector, embedder)) = models() else { + let Some(models) = models() else { w.set_identity_model_missing(true); return; }; @@ -1086,8 +1122,7 @@ pub fn wire( conn, catalog_path, store_dir, - detector, - embedder, + models, model_id(&settings_for_sweep), settings_for_sweep .snapshot() @@ -1114,6 +1149,7 @@ pub fn wire( let catalog_tick = catalog.clone(); let store_tick = store.clone(); let settings_tick = settings_for_sweep.clone(); + let eyes_tick = eyes_available.clone(); timer.start( slint::TimerMode::Repeated, Duration::from_millis(250), @@ -1202,6 +1238,7 @@ pub fn wire( &catalog_tick, store_tick(), &model_id(&settings_tick), + eyes_tick(), ); } }, @@ -1214,6 +1251,7 @@ pub fn wire( { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -1228,7 +1266,7 @@ pub fn wire( a.finish("stopped"); } w.set_identity_indexing(false); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } @@ -1237,14 +1275,22 @@ pub fn wire( let catalog = catalog.clone(); let store = store.clone(); let settings = settings.clone(); + let eyes_available = eyes_available.clone(); window.on_identity_check_coverage(move || { let Some(w) = weak.upgrade() else { return }; - refresh_coverage(&w, &catalog, store().as_deref(), &model_id(&settings)); + refresh_coverage( + &w, + &catalog, + store().as_deref(), + &model_id(&settings), + eyes_available(), + ); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -1265,12 +1311,13 @@ pub fn wire( ctl.selected.set(None); ctl.clear_picks(); } - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -1278,12 +1325,13 @@ pub fn wire( window.on_identity_toggle_show_ignored(move || { let Some(w) = weak.upgrade() else { return }; ctl.show_ignored.set(!ctl.show_ignored.get()); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } { let weak = window.as_weak(); + let eyes_available = eyes_available.clone(); let ctl = ctl.clone(); let catalog = catalog.clone(); let store = store.clone(); @@ -1299,7 +1347,7 @@ pub fn wire( ctl.selected.set(None); ctl.clear_picks(); ctl.covers.borrow_mut().clear(); - reload!(w, ctl, catalog, store, settings); + reload!(w, ctl, catalog, store, settings, eyes_available); }); } } diff --git a/ui/dr-ui/src/lib.rs b/ui/dr-ui/src/lib.rs index dce0308..e5bb5e0 100644 --- a/ui/dr-ui/src/lib.rs +++ b/ui/dr-ui/src/lib.rs @@ -76,6 +76,7 @@ pub use develop::DevelopSession; /// APK may carry a bundled copy and has to write it out before any store is /// opened — see `library::shared_face_models_dir`. pub use library::shared_face_models_dir; +pub use library::FaceModelPaths; /// The scene model's three files, wherever this device keeps them. /// @@ -3894,18 +3895,17 @@ fn refresh_face_status( let store = library .session() .and_then(|c| dr_thumbs::ThumbStore::open(&library::thumbs_dir(&c.account)).ok()); + let models = library + .session() + .and_then(|c| library::face_models(&c.account, detector)); identity_ui::refresh_coverage( window, &library.catalog(), store.as_ref(), detector.model_id(), + models.as_ref().is_some_and(|m| m.eyes.is_some()), ); - window.set_identity_model_missing( - library - .session() - .and_then(|c| library::face_models(&c.account, detector)) - .is_none(), - ); + window.set_identity_model_missing(models.is_none()); } fn describe_cache_usage(library: &Rc) -> String { diff --git a/ui/dr-ui/src/library.rs b/ui/dr-ui/src/library.rs index 6161356..092d35e 100644 --- a/ui/dr-ui/src/library.rs +++ b/ui/dr-ui/src/library.rs @@ -318,6 +318,26 @@ pub struct RatingFilter { pub people: Vec, /// Whether [`RatingFilter::people`] is a union or an intersection. pub people_mode: PeopleMode, + /// TRACES: FR-CULL-13 + /// Only photographs in which the chosen people are not caught blinking. + /// + /// A term *on* [`RatingFilter::people`]: Anna with her eyes open, whoever + /// else is in the frame. The bar offers it only while someone is chosen + /// and drops it when the last person goes, so the predicate below still + /// handles the empty case — every face in the frame — but nothing on the + /// screen reaches it. Either way the term drops a face only on a reading + /// that says **closed** from an eye that could be read — a face behind + /// sunglasses, one whose eyes were too small or soft to read, or one + /// never read, is left alone, because the filter's job is to take the + /// blinks out of a burst and not to insist on a verdict it does not + /// have. An old library with no readings at all therefore shows + /// everything under this chip rather than nothing, which is the honest + /// answer until the measuring pass has run. + /// + /// A filter and not a judgement: it narrows the grid the way a person or + /// a star count does, and nothing here rejects or rates a frame — the + /// line §3.9.1 draws. + pub eyes_open: bool, } /// How several people combine when the grid is narrowed by identity. @@ -351,6 +371,7 @@ impl RatingFilter { && self.captured_from.is_none() && self.captured_to.is_none() && self.people.is_empty() + && !self.eyes_open } /// Whether a date range is narrowing the grid. @@ -424,6 +445,41 @@ impl RatingFilter { ); } + // A face the eyes-open term drops: read, not behind sunglasses, and + // a *readable* eye under the threshold — one with enough pixels, + // sharp enough, and not the collapsed contour of a turned head's far + // eye. Constants from `dr_face`, formatted like the integers above; + // the rule is `dr_face::EyeReading::state`, and the thresholds live + // there so this and the People screen's label cannot disagree. + let readable = |eye: &str, other: &str| { + format!( + "(f.{eye}_px >= {px} AND f.{eye}_sharp >= {sharp} + AND f.{eye}_px >= f.{other}_px * {ratio})", + px = dr_face::MIN_EYE_PX, + sharp = dr_face::MIN_EYE_SHARPNESS, + ratio = dr_face::HIDDEN_EYE_RATIO, + ) + }; + let blink = format!( + "(f.eye_right IS NOT NULL AND f.eye_left IS NOT NULL + AND f.eye_right_px IS NOT NULL AND f.eye_left_px IS NOT NULL + AND f.eye_right_sharp IS NOT NULL AND f.eye_left_sharp IS NOT NULL + AND coalesce(f.sunglasses, 0) < {sg} + AND (({right_ok} AND f.eye_right < {open}) + OR ({left_ok} AND f.eye_left < {open})))", + sg = dr_face::SUNGLASSES_THRESHOLD, + open = dr_face::EYES_OPEN_THRESHOLD, + right_ok = readable("eye_right", "eye_left"), + left_ok = readable("eye_left", "eye_right"), + ); + // Appended to the face predicates below: with the chip on, a face + // counts only if it is not a blink. + let not_blinking = if self.eyes_open { + format!(" AND NOT {blink}") + } else { + String::new() + }; + if !self.people.is_empty() { // Integers this code owns, like every other term here — the ids // come from the catalog, never from typed text, so there is @@ -442,7 +498,7 @@ impl RatingFilter { PeopleMode::Any => format!( "EXISTS (SELECT 1 FROM faces f JOIN face_person fp ON fp.face_id = f.id - WHERE f.image_id = i.id AND fp.person_id IN ({ids}))" + WHERE f.image_id = i.id AND fp.person_id IN ({ids}){not_blinking})" ), // Counting *distinct* people rather than ANDing one EXISTS per // person: same result, one subquery instead of n, and it does @@ -452,10 +508,18 @@ impl RatingFilter { PeopleMode::All => format!( "(SELECT COUNT(DISTINCT fp.person_id) FROM faces f JOIN face_person fp ON fp.face_id = f.id - WHERE f.image_id = i.id AND fp.person_id IN ({ids})) = {}", + WHERE f.image_id = i.id AND fp.person_id IN ({ids}){not_blinking}) = {}", self.people.len() ), }); + } else if self.eyes_open { + // Nobody in particular: no face in the frame may be a blink. A + // photograph with no faces at all passes — there is no one in it + // to have blinked, and hiding the landscapes would make the chip + // read as "only people". + terms.push(format!( + "NOT EXISTS (SELECT 1 FROM faces f WHERE f.image_id = i.id AND {blink})" + )); } if let Some(flag) = self.flag { @@ -3915,9 +3979,15 @@ fn faces_without_proxy( /// there is no embedding without the pixels. What it saves is the detector, /// and — the part that matters — every suggestion and confirmation on those /// faces, which a re-detection would rebuild from box overlap. +/// +/// With `eyes` — this device has the eye models — the list also names every +/// image holding a face with no eye reading (schema V16), which the same +/// pass reads from the same render. Without them it does not, or a device +/// that cannot read eyes would fetch every original to do nothing to it. fn faces_unmeasured( catalog: &Catalog, model_id: &str, + eyes: bool, ) -> Result, dr_catalog::CatalogError> { let mut stmt = catalog.connection().prepare(&format!( "SELECT DISTINCT i.id, i.source_ref, r.file_id, i.file_size @@ -3925,9 +3995,10 @@ fn faces_unmeasured( JOIN remote r ON r.image_id = i.id JOIN faces f ON f.image_id = i.id WHERE r.file_id IS NOT NULL AND {VISIBLE} - AND {embedder} = ?1 AND f.quality IS NULL + AND {embedder} = ?1 AND {unmeasured} ORDER BY i.id", embedder = dr_catalog::faces::embedder_sql("f.model_id"), + unmeasured = dr_catalog::faces::unmeasured_sql("f.", eyes), ))?; let rows = stmt .query_map([dr_catalog::faces::embedder_of(model_id)], |r| { @@ -4095,8 +4166,7 @@ pub fn spawn_face_sweep( conn: Connection, catalog_path: PathBuf, store_dir: PathBuf, - detector_model: PathBuf, - embedder_model: PathBuf, + models: FaceModelPaths, model_id: String, supersedes: Vec, options: dr_face::DetectOptions, @@ -4144,7 +4214,7 @@ pub fn spawn_face_sweep( // listing twenty thousand images before discovering the weights are // missing helps nobody. A library with no model installed takes this // path, so it is a quiet return rather than an error. - let mut detector = match dr_face::Detector::from_path(&detector_model) { + let mut detector = match dr_face::Detector::from_path(&models.detector) { Ok(d) => d, Err(e) => { log::warn!("face sweep: cannot load the detector: {e}"); @@ -4153,7 +4223,7 @@ pub fn spawn_face_sweep( } }; let mut embedder = match dr_face::Embedder::from_path( - &embedder_model, + &models.embedder, dr_face::ModelId::new(model_id.clone()), ) { Ok(e) => e, @@ -4163,6 +4233,9 @@ pub fn spawn_face_sweep( return; } }; + // Optional, and loaded after the two that are not: a library + // without them indexes faces and simply has no eye readings. + let mut eye_models = models.load_eyes(); // **Repairs first, and the order is the whole point.** These are the // images the People screen is drawing *right now* and failing to, and @@ -4194,7 +4267,7 @@ pub fn spawn_face_sweep( // gets its quality from that, so it is not queued twice. let mut queued: std::collections::HashSet = wanted.iter().map(|(r, _)| r.image_id).collect(); - match faces_unmeasured(&catalog, &model_id) { + match faces_unmeasured(&catalog, &model_id, eye_models.is_some()) { Ok(measure) => { let fresh: Vec<_> = measure .into_iter() @@ -4373,6 +4446,7 @@ pub fn spawn_face_sweep( match measure_one_native( &gpu, &mut embedder, + eye_models.as_mut(), &catalog, image, &model_id, @@ -4398,7 +4472,14 @@ pub fn spawn_face_sweep( continue; } - match index_one_native(&gpu, &mut detector, &mut embedder, &bytes, &options) { + match index_one_native( + &gpu, + &mut detector, + &mut embedder, + eye_models.as_mut(), + &bytes, + &options, + ) { Ok((faces, edge, proxy)) => { // Before the detections, so a kill between the two // leaves a proxy with no faces recorded -- which @@ -4577,6 +4658,7 @@ fn index_one_native( gpu: &dr_gpu::GpuContext, detector: &mut dr_face::Detector, embedder: &mut dr_face::Embedder, + eye_models: Option<&mut dr_face::EyeModels>, bytes: &[u8], options: &dr_face::DetectOptions, ) -> Result< @@ -4594,6 +4676,7 @@ fn index_one_native( let faces = crate::faces::index_native( detector, embedder, + eye_models, &frame.rgba, frame.width as usize, frame.height as usize, @@ -4647,13 +4730,19 @@ fn index_one_native( fn measure_one_native( gpu: &dr_gpu::GpuContext, embedder: &mut dr_face::Embedder, + eye_models: Option<&mut dr_face::EyeModels>, catalog: &Catalog, image: dr_types::ImageId, model_id: &str, bytes: &[u8], ) -> Result { - let faces = dr_catalog::faces::unmeasured_on_image(catalog.connection(), image, model_id) - .map_err(|e| e.to_string())?; + let faces = dr_catalog::faces::unmeasured_on_image( + catalog.connection(), + image, + model_id, + eye_models.is_some(), + ) + .map_err(|e| e.to_string())?; if faces.is_empty() { return Ok(0); } @@ -4661,6 +4750,7 @@ fn measure_one_native( let edge = frame.width.max(frame.height); let measured = crate::faces::measure_native( embedder, + eye_models, &frame.rgba, frame.width as usize, frame.height as usize, @@ -5056,7 +5146,53 @@ pub fn shared_face_models_dir() -> PathBuf { data_root().join("models") } -/// The detector and embedder files, if both are present. +/// The names of the three eye-state models, as shipped in `models/face/`. +/// +/// The shape-fixed exports, like the face pair: `tools/fix-face-model-shapes.sh` +/// pins each one's batch dimension to 1 before tract will analyse it. +pub const LANDMARK_MODEL: &str = "2d106det_b1.onnx"; +pub const EYE_MODEL: &str = "ocec_s_b1.onnx"; +pub const SUNGLASSES_MODEL: &str = "sgc_l_48_b1.onnx"; + +/// Where the face models are on this machine. +/// +/// The detector and the embedder are required — see [`face_models`] — and +/// the eye pair is not: a library indexes people without it and simply has +/// no eye readings, which every reader treats as "unknown" rather than as a +/// verdict (`dr_face::eyes`). Found beside the pair, in the same directory, +/// so a hand-placed pair with no eye models beside it does not pick up the +/// package's eye models from a directory it otherwise outranks. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FaceModelPaths { + pub detector: PathBuf, + pub embedder: PathBuf, + /// `(landmarks, eyes, sunglasses)` — [`LANDMARK_MODEL`], [`EYE_MODEL`] + /// and [`SUNGLASSES_MODEL`] — where all three are present, or `None`. + /// All or none: a partial reading is not a reading + /// (`dr_face::classify::EyeModels`). + pub eyes: Option<(PathBuf, PathBuf, PathBuf)>, +} + +impl FaceModelPaths { + /// Load the eye models, if there are any. + /// + /// A pair that is present but refuses to load is logged and treated as + /// absent: a broken eye model must not stop the detector and embedder, + /// which are the ones the People screen cannot do without. + pub fn load_eyes(&self) -> Option { + let (landmarks, eyes, sunglasses) = self.eyes.as_ref()?; + match dr_face::EyeModels::from_paths(landmarks, eyes, sunglasses) { + Ok(m) => Some(m), + Err(e) => { + log::warn!("face models: eye models present but unusable, indexing without: {e}"); + None + } + } + } +} + +/// The detector and embedder files, if both are present — and the eye +/// models beside them, if those are. /// /// Both or neither: an embedder with no detector has nothing to embed, and a /// detector with no embedder finds faces it cannot tell apart. Reporting the @@ -5077,32 +5213,48 @@ pub fn shared_face_models_dir() -> PathBuf { /// 3. **The system directories.** Where a package installs them — the Arch /// package puts the pair in `/usr/share/darkroom/models`. Last, so anything /// the user placed themselves outranks what the package shipped. -pub fn face_models( - account: &Account, - detector: dr_types::FaceDetector, -) -> Option<(PathBuf, PathBuf)> { +pub fn face_models(account: &Account, detector: dr_types::FaceDetector) -> Option { let pair = |dir: &PathBuf| { - let detector = dir.join(detector.file_name()); + let det = dir.join(detector.file_name()); let embedder = dir.join("arcface_mbf_b1.onnx"); - (detector.is_file() && embedder.is_file()).then_some((detector, embedder)) + (det.is_file() && embedder.is_file()).then(|| { + let landmarks = dir.join(LANDMARK_MODEL); + let eyes = dir.join(EYE_MODEL); + let sunglasses = dir.join(SUNGLASSES_MODEL); + FaceModelPaths { + detector: det, + embedder, + eyes: (landmarks.is_file() && eyes.is_file() && sunglasses.is_file()) + .then_some((landmarks, eyes, sunglasses)), + } + }) }; let mut searched = vec![face_models_dir(account), shared_face_models_dir()]; searched.extend(system_face_models_dirs()); let found = searched.iter().find_map(pair); - if found.is_none() { - // The settings page can only say "not installed". This is the line - // that says where it looked, which is the whole of what a user with - // the files in the wrong place needs — and the first thing to read - // when a freshly installed package reports no model. - log::warn!( - "face models: no directory holds both {} and arcface_mbf_b1.onnx; searched {}", - detector.file_name(), - searched - .iter() - .map(|d| d.display().to_string()) - .collect::>() - .join(", ") - ); + match &found { + None => { + // The settings page can only say "not installed". This is the line + // that says where it looked, which is the whole of what a user with + // the files in the wrong place needs — and the first thing to read + // when a freshly installed package reports no model. + log::warn!( + "face models: no directory holds both {} and arcface_mbf_b1.onnx; searched {}", + detector.file_name(), + searched + .iter() + .map(|d| d.display().to_string()) + .collect::>() + .join(", ") + ); + } + Some(m) if m.eyes.is_none() => { + log::info!( + "face models: no {LANDMARK_MODEL}, {EYE_MODEL} and {SUNGLASSES_MODEL} beside {}; indexing without eye readings", + m.detector.display() + ); + } + Some(_) => {} } found } @@ -6773,6 +6925,7 @@ mod tests { embedding: vec![0u8; 1024], crop_px: 120.0, quality: None, + eyes: None, crop: Vec::new(), model_id: "w600k_mbf".into(), }; @@ -6823,6 +6976,7 @@ mod tests { embedding: vec![0u8; 1024], crop_px: 120.0, quality: None, + eyes: None, crop: Vec::new(), model_id: "w600k_mbf".into(), }; @@ -6979,6 +7133,7 @@ mod tests { embedding: vec![0u8; 1024], crop_px: 120.0, quality, + eyes: None, crop: Vec::new(), model_id: "w600k_mbf".into(), }; @@ -6996,7 +7151,7 @@ mod tests { // What V14 does to the first: the marker goes, the face stays. dr_catalog::faces::clear_index_marker(conn, ids[0], "w600k_mbf").unwrap(); - let measure = faces_unmeasured(&catalog, "w600k_mbf").unwrap(); + let measure = faces_unmeasured(&catalog, "w600k_mbf", false).unwrap(); assert_eq!(measure.len(), 1); assert_eq!(measure[0].image_id, ids[0].0 as i64); assert!(measure[0].full_resolution); @@ -7006,6 +7161,13 @@ mod tests { let detect = faces_unindexed(&catalog, "w600k_mbf").unwrap(); assert_eq!(detect.len(), 1); assert_eq!(detect[0].image_id, ids[2].0 as i64); + + // Neither face has an eye reading. A device that can read eyes has + // both images to measure; one that cannot still has only the first + // — it must not fetch an original to do nothing to it. + let with_eyes = faces_unmeasured(&catalog, "w600k_mbf", true).unwrap(); + assert_eq!(with_eyes.len(), 2); + assert_eq!(faces_unindexed(&catalog, "w600k_mbf").unwrap().len(), 1); } #[test] @@ -7968,6 +8130,7 @@ mod tests { embedding: vec![0u8; 1024], crop_px: 120.0, quality: None, + eyes: None, crop: Vec::new(), model_id: "w600k_mbf".into(), }; @@ -8095,6 +8258,223 @@ mod tests { assert!(f.is_unfiltered()); assert_eq!(total_images_scoped(&catalog, None, &f).unwrap(), 3); } + + // ── eyes open ───────────────────────────────────────────────────────── + + /// Write an eye reading onto every face of `person` on `image`: two + /// large, sharp eyes. + fn read_eyes( + catalog: &Catalog, + image: dr_types::ImageId, + person: dr_catalog::faces::PersonId, + (right, left, sunglasses): (f32, f32, f32), + ) { + read_eyes_full( + catalog, + image, + person, + [(right, 40.0, 0.2), (left, 40.0, 0.2)], + sunglasses, + ); + } + + /// The whole reading: per eye `(open, px, sharpness)`. + fn read_eyes_full( + catalog: &Catalog, + image: dr_types::ImageId, + person: dr_catalog::faces::PersonId, + eyes: [(f32, f32, f32); 2], + sunglasses: f32, + ) { + catalog + .connection() + .execute( + "UPDATE faces + SET eye_right = ?3, eye_right_px = ?4, eye_right_sharp = ?5, + eye_left = ?6, eye_left_px = ?7, eye_left_sharp = ?8, + sunglasses = ?9 + WHERE image_id = ?1 + AND id IN (SELECT face_id FROM face_person WHERE person_id = ?2)", + rusqlite::params![ + image.0 as i64, + person.0 as i64, + f64::from(eyes[0].0), + f64::from(eyes[0].1), + f64::from(eyes[0].2), + f64::from(eyes[1].0), + f64::from(eyes[1].1), + f64::from(eyes[1].2), + f64::from(sunglasses), + ], + ) + .unwrap(); + } + + /// TRACES: FR-CULL-13 + /// With a person chosen, the chip asks about *that* person's eyes: Anna + /// blinking hides the frame, and Bob blinking beside her does not. + #[test] + fn eyes_open_asks_about_the_chosen_persons_eyes() { + let catalog = with_images(5); + let ids = image_ids(&catalog); + let anna = dr_catalog::faces::create_person(catalog.connection(), "Anna").unwrap(); + let bob = dr_catalog::faces::create_person(catalog.connection(), "Bob").unwrap(); + assign(&catalog, anna, &[ids[0], ids[1], ids[2], ids[3]]); + assign(&catalog, bob, &[ids[1], ids[4]]); + + // 0: Anna open. 1: Anna open, Bob blinking. 2: Anna blinking. + // 3: Anna never read. 4: Bob alone, open. + read_eyes(&catalog, ids[0], anna, (0.9, 0.9, 0.0)); + read_eyes(&catalog, ids[1], anna, (0.9, 0.9, 0.0)); + read_eyes(&catalog, ids[1], bob, (0.1, 0.9, 0.0)); + read_eyes(&catalog, ids[2], anna, (0.2, 0.9, 0.0)); + read_eyes(&catalog, ids[4], bob, (0.9, 0.9, 0.0)); + + let count = |people: Vec, mode: PeopleMode, eyes_open: bool| { + let f = RatingFilter { + people, + people_mode: mode, + eyes_open, + ..Default::default() + }; + total_images_scoped(&catalog, None, &f).unwrap() + }; + + assert_eq!(count(vec![anna.0], PeopleMode::Any, false), 4); + // Drops only the frame where Anna herself is blinking; the unread + // one stays, and Bob's blink beside her is not her problem. + assert_eq!(count(vec![anna.0], PeopleMode::Any, true), 3); + // Bob: the frame he blinks in goes. + assert_eq!(count(vec![bob.0], PeopleMode::Any, true), 1); + // Both of them together: only frame 1, and Bob blinks in it. + assert_eq!(count(vec![anna.0, bob.0], PeopleMode::All, false), 1); + assert_eq!(count(vec![anna.0, bob.0], PeopleMode::All, true), 0); + // Either of them: 0, 1 (Anna's face is open there), 3, 4. + assert_eq!(count(vec![anna.0, bob.0], PeopleMode::Any, true), 4); + } + + /// TRACES: FR-CULL-13 + /// With nobody chosen the chip asks about every face, and a face behind + /// sunglasses is not a blink. + #[test] + fn eyes_open_alone_drops_any_frame_with_a_blink_in_it() { + let catalog = with_images(5); + let ids = image_ids(&catalog); + let anna = dr_catalog::faces::create_person(catalog.connection(), "Anna").unwrap(); + assign(&catalog, anna, &[ids[0], ids[1], ids[2], ids[3]]); + // 0: open. 1: a wink. 2: sunglasses over a reading that says closed. + // 3: never read. 4: no faces at all. + read_eyes(&catalog, ids[0], anna, (0.9, 0.9, 0.0)); + read_eyes(&catalog, ids[1], anna, (0.9, 0.3, 0.0)); + read_eyes(&catalog, ids[2], anna, (0.1, 0.1, 0.9)); + + let f = RatingFilter { + eyes_open: true, + ..Default::default() + }; + assert!(!f.is_unfiltered()); + assert_eq!(total_images_scoped(&catalog, None, &f).unwrap(), 4); + let shown: Vec = read_cells_scoped(&catalog, None, &f, 0, 10) + .unwrap() + .into_iter() + .map(|c| c.image_id) + .collect(); + assert!(!shown.contains(&(ids[1].0 as i64)), "the wink is hidden"); + assert!( + shown.contains(&(ids[2].0 as i64)), + "sunglasses are not a blink" + ); + assert!(shown.contains(&(ids[3].0 as i64)), "unread is not a blink"); + assert!( + shown.contains(&(ids[4].0 as i64)), + "a landscape has no one to blink" + ); + } + + /// TRACES: FR-CULL-13 + /// An eye that cannot be read is not a blink, in SQL as in + /// `dr_face::EyeReading::state` — the two must agree, or the badge on + /// the People screen would say one thing and the grid another. + #[test] + fn an_unreadable_eye_does_not_hide_the_frame() { + let catalog = with_images(5); + let ids = image_ids(&catalog); + let anna = dr_catalog::faces::create_person(catalog.connection(), "Anna").unwrap(); + assign(&catalog, anna, &[ids[0], ids[1], ids[2], ids[3], ids[4]]); + let (px, sharp) = (dr_face::MIN_EYE_PX, dr_face::MIN_EYE_SHARPNESS); + // 0: a profile — the far (right) eye's contour collapsed to a fifth + // of the near one and reads closed, the near eye open. Open. + // 1: a soft closed eye beside a sharp open one. Open. + // 2: both eyes too small to read. Unreadable — not a blink. + // 3: a large, sharp closed eye. A blink. + // 4: a small closed eye whose partner is just as small — not a + // hidden eye, but still under the pixel floor. Unreadable. + read_eyes_full( + &catalog, + ids[0], + anna, + [(0.05, 8.0, 0.3), (0.95, 40.0, 0.3)], + 0.0, + ); + read_eyes_full( + &catalog, + ids[1], + anna, + [(0.05, 40.0, sharp / 2.0), (0.95, 40.0, 0.3)], + 0.0, + ); + read_eyes_full( + &catalog, + ids[2], + anna, + [(0.05, px - 1.0, 0.3), (0.05, px - 1.0, 0.3)], + 0.0, + ); + read_eyes_full( + &catalog, + ids[3], + anna, + [(0.05, 40.0, 0.3), (0.95, 40.0, 0.3)], + 0.0, + ); + read_eyes_full( + &catalog, + ids[4], + anna, + [(0.05, 10.0, 0.3), (0.95, 10.0, 0.3)], + 0.0, + ); + + let f = RatingFilter { + eyes_open: true, + ..Default::default() + }; + let shown: Vec = read_cells_scoped(&catalog, None, &f, 0, 10) + .unwrap() + .into_iter() + .map(|c| c.image_id) + .collect(); + let want = [true, true, true, false, true]; + for (img, keep) in want.iter().enumerate() { + assert_eq!( + shown.contains(&(ids[img].0 as i64)), + *keep, + "image {img} in the grid" + ); + // And the same through the rule the badge uses. + let face = &dr_catalog::faces::for_image(catalog.connection(), ids[img]).unwrap()[0]; + assert_eq!( + face.eyes.map(|e| !e.is_blink()), + Some(*keep), + "image {img} by rule" + ); + } + let unclear = &dr_catalog::faces::for_image(catalog.connection(), ids[2]).unwrap()[0]; + assert_eq!( + unclear.eyes.map(|e| e.state()), + Some(dr_face::EyeState::Unreadable) + ); + } } /// TRACES: FR-CAT-8 | FR-NC-9 diff --git a/ui/dr-ui/src/library_ui.rs b/ui/dr-ui/src/library_ui.rs index 66c9cee..71bcd75 100644 --- a/ui/dr-ui/src/library_ui.rs +++ b/ui/dr-ui/src/library_ui.rs @@ -5671,6 +5671,7 @@ fn push_filter(window: &AppWindow, ctl: &Rc) { }); window.set_library_local_only(filter.local_only); ctl.local_only.set(filter.local_only); + window.set_library_filter_eyes_open(filter.eyes_open); push_people_chips(window, ctl); } @@ -6628,6 +6629,7 @@ pub fn wire( .borrow_mut() .people .retain(|p| *p != id.max(0) as u64); + drop_eyes_open_without_people(&w, &ctl); push_people_chips(&w, &ctl); refilter(&w, &ctl); }); @@ -6656,11 +6658,27 @@ pub fn wire( f.people.push(person); } } + drop_eyes_open_without_people(&w, &ctl); push_people_chips(&w, &ctl); refilter(&w, &ctl); }); } + { + let weak = window.as_weak(); + let ctl = ctl.clone(); + window.on_library_filter_eyes_open_toggled(move || { + let Some(w) = weak.upgrade() else { return }; + let on = { + let mut f = ctl.filter.borrow_mut(); + f.eyes_open = !f.eyes_open; + f.eyes_open + }; + w.set_library_filter_eyes_open(on); + refilter(&w, &ctl); + }); + } + { let weak = window.as_weak(); let ctl = ctl.clone(); @@ -6988,6 +7006,19 @@ pub fn wire( /// The label is the People screen's own wording, unnamed groups included, so /// the same group does not read one way on one screen and another way on the /// next. +/// Drop the eyes-open term when the last person leaves the filter. +/// +/// The chip lives beside the people chips and goes with them; a term that +/// stayed on after its chip had gone would narrow the grid with nothing on +/// the bar to say so, which is the one state a filter bar must never be in. +fn drop_eyes_open_without_people(window: &AppWindow, ctl: &Rc) { + let mut f = ctl.filter.borrow_mut(); + if f.people.is_empty() && f.eyes_open { + f.eyes_open = false; + window.set_library_filter_eyes_open(false); + } +} + fn push_people_chips(window: &AppWindow, ctl: &Rc) { let ids = ctl.filter.borrow().people.clone(); if ids.is_empty() { diff --git a/ui/dr-ui/src/place.rs b/ui/dr-ui/src/place.rs index a128df4..f58c52f 100644 --- a/ui/dr-ui/src/place.rs +++ b/ui/dr-ui/src/place.rs @@ -31,6 +31,7 @@ impl From<&RatingFilter> for StoredFilter { captured_to: f.captured_to, people: f.people.clone(), people_all: matches!(f.people_mode, PeopleMode::All), + eyes_open: f.eyes_open, } } } @@ -50,6 +51,7 @@ impl From<&StoredFilter> for RatingFilter { } else { PeopleMode::Any }, + eyes_open: s.eyes_open, } } } @@ -183,6 +185,7 @@ mod tests { captured_to: Some(2), people: vec![7, 9], people_all: true, + eyes_open: true, }, } } @@ -304,6 +307,7 @@ mod tests { captured_to: Some(20), people: vec![3, 5, 8], people_mode: PeopleMode::All, + eyes_open: true, }; let back: RatingFilter = (&StoredFilter::from(&original)).into(); assert_eq!(back, original); diff --git a/ui/dr-ui/ui/app.slint b/ui/dr-ui/ui/app.slint index 4435d91..3fe231c 100644 --- a/ui/dr-ui/ui/app.slint +++ b/ui/dr-ui/ui/app.slint @@ -698,6 +698,10 @@ export component AppWindow inherits Window { in property library-filter-people-all: false; callback library-filter-person-cleared(int); callback library-filter-people-mode-toggled(); + /// TRACES: FR-CULL-13 + /// Whether the grid is narrowed to photographs with nobody blinking. + in property library-filter-eyes-open: false; + callback library-filter-eyes-open-toggled(); /// Everyone the library knows, for the filter bar's people tray. /// TRACES: FR-UI-4 /// The gesture reference's rows, read from the generated table. @@ -1701,6 +1705,7 @@ in property panel-visible: true; filter-people: root.library-filter-people; filter-people-all: root.library-filter-people-all; + filter-eyes-open: root.library-filter-eyes-open; people: root.library-people; gestures: root.library-gestures; filter-min-rating: root.library-filter-min-rating; @@ -1739,6 +1744,7 @@ in property panel-visible: true; filter-flag-changed(f) => { root.library-filter-flag-changed(f); } filter-person-cleared(id) => { root.library-filter-person-cleared(id); } filter-people-mode-toggled() => { root.library-filter-people-mode-toggled(); } + filter-eyes-open-toggled() => { root.library-filter-eyes-open-toggled(); } people-listed() => { root.library-people-listed(); } filter-person-toggled(id) => { root.library-filter-person-toggled(id); } } diff --git a/ui/dr-ui/ui/identity.slint b/ui/dr-ui/ui/identity.slint index 4497d83..7fa536c 100644 --- a/ui/dr-ui/ui/identity.slint +++ b/ui/dr-ui/ui/identity.slint @@ -60,6 +60,12 @@ export struct IdentityFace { // group that has gathered none of a person's other photographs has an // explanation the user can only see if every member's label says it. in-gallery: bool, + // TRACES: FR-CULL-13 + // "Eyes closed", "Sunglasses" or "Eyes unclear", or empty — composed in + // Rust like the two above. Empty for open eyes and for a face never + // read, so the mark is only ever the reason a frame is or is not under + // the eyes-open chip. + eyes: string, // Part of the current multi-select — what a split would carry. picked: bool, } @@ -141,6 +147,27 @@ component FaceCell inherits Rectangle { } } + // The eye state, over the head of the crop, and only where it + // is a blink, sunglasses or eyes too soft to read: the readings + // the eyes-open filter treats differently from open. Open eyes + // carry no mark for the reason the confirmed marker below gives. + if face.eyes != "": Rectangle { + x: 0; + y: 0; + width: parent.width; + height: 16px; + background: Theme.ground.with-alpha(0.55); + Text { + text: face.eyes; + color: Theme.warn-ink; + font-size: Theme.text-sm; + horizontal-alignment: center; + vertical-alignment: center; + width: parent.width; + height: parent.height; + } + } + // A confirmed face carries a quiet marker rather than a badge: the // grid is mostly confirmed once the user has worked through it, and // a loud mark on the common case is just noise. diff --git a/ui/dr-ui/ui/library.slint b/ui/dr-ui/ui/library.slint index 5fc9c18..e39d863 100644 --- a/ui/dr-ui/ui/library.slint +++ b/ui/dr-ui/ui/library.slint @@ -1509,6 +1509,11 @@ export component LibraryGrid inherits Rectangle { in property filter-people-all: false; callback filter-person-cleared(int); callback filter-people-mode-toggled(); + /// TRACES: FR-CULL-13 + /// Only photographs in which the chosen people are not blinking. Shown + /// and meaningful only while `filter-people` holds someone. + in property filter-eyes-open: false; + callback filter-eyes-open-toggled(); callback filter-min-rating-changed(int); callback filter-unjudged-toggled(bool); callback filter-flag-changed(int); @@ -2028,7 +2033,8 @@ export component LibraryGrid inherits Rectangle { // Hidden while there is nothing to filter: an empty library offering // six rating buttons is chrome describing data that does not exist. if root.total > 0 || root.filter-min-rating > 0 || root.filter-unjudged - || root.filter-flag > 0 || root.filter-people.length > 0: Rectangle { + || root.filter-flag > 0 || root.filter-people.length > 0 + || root.filter-eyes-open: Rectangle { height: 34px; background: Theme.surface; @@ -2088,6 +2094,29 @@ export component LibraryGrid inherits Rectangle { clicked => { root.filter-people-mode-toggled(); } } + // Beside the people it applies to, and only with some chosen: + // "Anna, eyes open" is the question, and without a name in + // front of it the chip would be a judgement on everyone in + // the frame. A filter, never a verdict: it hides the blinks + // in a burst and rates nothing (FR-CULL-13). + // GESTURE: Take the blinks out of a burst + // where: Library grid + // touch: Narrow to a person, then tap "Eyes open" beside + // their name on the filter bar + // pointer: Narrow to a person, then click "Eyes open" beside + // their name on the filter bar + // why: Face indexing reads each face's eyes. The chip + // drops frames where the chosen people are caught + // blinking, and leaves sunglasses and eyes it could + // not read alone. + if root.filter-people.length > 0: FilterChip { + icon: "eye"; + label: "Eyes open"; + active: root.filter-eyes-open; + y: (parent.height - self.height) / 2; + clicked => { root.filter-eyes-open-toggled(); } + } + // The way in to the people tray, and the reason it exists. // // Narrowing to *two* people at once was already possible and @@ -2241,7 +2270,8 @@ export component LibraryGrid inherits Rectangle { // single most confusing state a filter can leave behind. Caption { text: (root.filter-min-rating > 0 || root.filter-unjudged - || root.filter-flag > 0 || root.local-only) + || root.filter-flag > 0 || root.local-only + || root.filter-eyes-open) ? "filtered" : ""; emphasised: true; vertical-alignment: center;