Filter the grid to a person with their eyes open
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.
This commit is contained in:
@@ -698,6 +698,10 @@ export component AppWindow inherits Window {
|
||||
in property <bool> 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 <bool> 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 <bool> 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 <bool> 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); }
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1509,6 +1509,11 @@ export component LibraryGrid inherits Rectangle {
|
||||
in property <bool> 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 <bool> 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;
|
||||
|
||||
Reference in New Issue
Block a user