From 4175cb8edfa6b732260d9a4f2c3f339216e9ba04 Mon Sep 17 00:00:00 2001 From: Dawn Date: Mon, 17 Aug 2026 14:02:16 +0200 Subject: [PATCH] feat: add Unmeasured filter chip to the sample table Complement of Measured (rotation count <= 1): one click shows everything still to be done, so it can be selected wholesale and queued. Plain chip like All - unmeasured rows carry no tint, so there is no legend color to wear; cross-status marks (queued/ flagged) show like in the Measured view. Co-Authored-By: Claude Fable 5 --- src/aare/gui/models/user_sample_model.py | 8 ++++++-- src/aare/gui/panels/tell_sample_panel.py | 6 ++++++ tests/unit/gui/test_models.py | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/aare/gui/models/user_sample_model.py b/src/aare/gui/models/user_sample_model.py index 8d8fc512..5e1bc4de 100644 --- a/src/aare/gui/models/user_sample_model.py +++ b/src/aare/gui/models/user_sample_model.py @@ -92,7 +92,8 @@ class UserSampleSpreadsheet(QAbstractTableModel): # SampleQueueSpreadsheet. self.queued_ids: set[int] = set() self.flagged_ids: set[int] = set() - # None = All; otherwise "queued" | "flagged" | "measured" (chip row). + # None = All; otherwise "queued" | "flagged" | "measured" | + # "unmeasured" (chip row). self.status_filter: str | None = None self._sort() @@ -150,7 +151,7 @@ class UserSampleSpreadsheet(QAbstractTableModel): return SAMPLE_STATUS_FLAGGED_BG if flagged else None if self.status_filter == "flagged": return SAMPLE_STATUS_QUEUED_BG if queued else None - if self.status_filter == "measured": + if self.status_filter in ("measured", "unmeasured"): if queued: return SAMPLE_STATUS_QUEUED_BG return SAMPLE_STATUS_FLAGGED_BG if flagged else None @@ -263,6 +264,9 @@ class UserSampleSpreadsheet(QAbstractTableModel): rows = [r for r in rows if r.db_id in self.flagged_ids] elif self.status_filter == "measured": rows = [r for r in rows if self._measured(r)] + elif self.status_filter == "unmeasured": + # Everything still to be done — the view to select-all and queue. + rows = [r for r in rows if not self._measured(r)] # Default filter by User using current p-group if no explicit filter set filters: dict[int, str] = { diff --git a/src/aare/gui/panels/tell_sample_panel.py b/src/aare/gui/panels/tell_sample_panel.py index 637c73d8..26a4ee8a 100644 --- a/src/aare/gui/panels/tell_sample_panel.py +++ b/src/aare/gui/panels/tell_sample_panel.py @@ -158,6 +158,7 @@ class TellSamplePanel(QFrame): ("Queued", "queued"), ("Flagged", "flagged"), ("Measured", "measured"), + ("Unmeasured", "unmeasured"), ): if key == "queued": chip = QueueDropChip(label, self) @@ -175,6 +176,11 @@ class TellSamplePanel(QFrame): chip = QPushButton(label, self) if key == "measured": chip.setToolTip("Filter measured samples (automatic: rotation count > 1)") + elif key == "unmeasured": + chip.setToolTip( + "Filter samples not yet measured — select all here to queue" + " everything still to be done" + ) chip.setCheckable(True) chip.setChecked(key is None) chip.setProperty("status_key", key) diff --git a/tests/unit/gui/test_models.py b/tests/unit/gui/test_models.py index 034374cc..6459d835 100644 --- a/tests/unit/gui/test_models.py +++ b/tests/unit/gui/test_models.py @@ -200,6 +200,9 @@ def test_status_filter_selects_rows(status_model): assert {model.get_id(r).db_id for r in range(model.rowCount())} == {3} model.set_status_filter("measured") assert {model.get_id(r).db_id for r in range(model.rowCount())} == {4} + # Unmeasured is the complement: everything still to be done. + model.set_status_filter("unmeasured") + assert {model.get_id(r).db_id for r in range(model.rowCount())} == {1, 2, 3} model.set_status_filter(None) assert model.rowCount() == 4