From 344888dac072090fcf33a751dfb330bd2094bee1 Mon Sep 17 00:00:00 2001 From: Dawn Date: Mon, 17 Aug 2026 16:10:38 +0200 Subject: [PATCH] feat: Queued chip view shows the actual run order The queue engine keeps insertion order and Run pops its head, but the Queued view sorted by the dewar table's header sort - the top row was not what runs next. set_queued_ids now keeps the order it is fed (the queue model's order) and the Queued view displays exactly that; header clicks no longer reorder it. Co-Authored-By: Claude Fable 5 --- src/aare/gui/models/user_sample_model.py | 16 +++++++++++++++- tests/unit/gui/test_models.py | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/aare/gui/models/user_sample_model.py b/src/aare/gui/models/user_sample_model.py index 2890a43c..0d25a5ce 100644 --- a/src/aare/gui/models/user_sample_model.py +++ b/src/aare/gui/models/user_sample_model.py @@ -91,6 +91,9 @@ class UserSampleSpreadsheet(QAbstractTableModel): # as the queue view). Fed from outside; the queue itself stays in the # SampleQueueSpreadsheet. self.queued_ids: set[int] = set() + # Queue order as the engine holds it (Run pops its head): the Queued + # chip view displays THIS order, not the header sort. + self.queued_order: list[int] = [] self.flagged_ids: set[int] = set() # None = All; otherwise "queued" | "flagged" | "measured" | # "unmeasured" (chip row). @@ -170,7 +173,10 @@ class UserSampleSpreadsheet(QAbstractTableModel): return isinstance(sample.rotation_count, (int, float)) and sample.rotation_count >= 1 def set_queued_ids(self, db_ids) -> None: - self.queued_ids = set(db_ids) + # Callers pass the ids in queue order (main_window feeds them straight + # from the queue model) — keep it for the Queued view's row order. + self.queued_order = list(db_ids) + self.queued_ids = set(self.queued_order) self._status_sets_changed() def set_flagged(self, db_id: int, flagged: bool) -> None: @@ -238,6 +244,14 @@ class UserSampleSpreadsheet(QAbstractTableModel): def _sort(self): filtered = self._apply_filter(self.samples) + if self.status_filter == "queued": + # The Queued view is the run order — row 1 runs next. Header + # clicks still move the indicator but must not reorder it. + position = {db_id: i for i, db_id in enumerate(self.queued_order)} + self._sorted_samples = sorted( + filtered, key=lambda row: position.get(row.db_id, len(position)) + ) + return if self._sort_col == 4: # Location self._sorted_samples = sorted( filtered, diff --git a/tests/unit/gui/test_models.py b/tests/unit/gui/test_models.py index 4daa177a..95c634bc 100644 --- a/tests/unit/gui/test_models.py +++ b/tests/unit/gui/test_models.py @@ -208,6 +208,20 @@ def test_status_filter_selects_rows(status_model): assert model.rowCount() == 4 +def test_queued_view_shows_queue_order(status_model): + model = status_model + # Queue order deliberately different from location/db order. + model.set_queued_ids([3, 1, 2]) + model.set_status_filter("queued") + assert [model.get_id(r).db_id for r in range(model.rowCount())] == [3, 1, 2] + # Header sorts must not reorder the queue view — row 1 runs next. + model.sort(1, Qt.SortOrder.AscendingOrder) + assert [model.get_id(r).db_id for r in range(model.rowCount())] == [3, 1, 2] + # Other views keep the normal header sort. + model.set_status_filter(None) + assert [model.get_id(r).db_id for r in range(model.rowCount())] != [3, 1, 2] + + def test_status_tints_are_context_dependent(status_model): from aare.gui.styles import SAMPLE_STATUS_FLAGGED_BG, SAMPLE_STATUS_QUEUED_BG