feat: reference-tools position column and state-driven default sample tab
The reference table gets a display-only '#' column (like the Dewar list) with sort indices shifted around it; the sample dock switches to the Auxiliary puck tab on entering alignment/maintenance states and back to Dewar elsewhere, only on state transitions so a manual choice sticks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -593,6 +593,10 @@ class MainWindow(QMainWindow):
|
||||
# click is caught in eventFilter via the geometric tabAt() instead.
|
||||
self.sample_lists_tabs.tabBar().installEventFilter(self)
|
||||
|
||||
# Tracks beamline-state TRANSITIONS for the default sample-tab switch
|
||||
# (see _apply_default_sample_tab).
|
||||
self._last_beamline_state: BeamlineStateEnum | None = None
|
||||
|
||||
# Wrapper for the left inset: QTabWidget ignores its own contents
|
||||
# margins for the tab bar, so the padding lives one level up. Aligns
|
||||
# the panel's left edge with the left column above (Loop centering).
|
||||
@@ -2554,11 +2558,37 @@ class MainWindow(QMainWindow):
|
||||
for widget in hide_in_watch_mode + self.findChildren(QDockWidget):
|
||||
widget.hide()
|
||||
|
||||
# Alignment/maintenance states mount reference pins, so the sample dock
|
||||
# defaults to the Auxiliary puck there; every other state defaults back
|
||||
# to the Dewar list.
|
||||
_AUX_PUCK_STATES = frozenset(
|
||||
{
|
||||
BeamlineStateEnum.Maintenance,
|
||||
BeamlineStateEnum.BeamLocation,
|
||||
BeamlineStateEnum.BeamstopAlignment,
|
||||
BeamlineStateEnum.FluxMeasurement,
|
||||
}
|
||||
)
|
||||
|
||||
def _apply_default_sample_tab(self, state: BeamlineStateEnum | None) -> None:
|
||||
# Index 1 = Auxiliary puck; disabled for non-staff, never force it.
|
||||
if state in self._AUX_PUCK_STATES and self.sample_lists_tabs.isTabEnabled(1):
|
||||
self.sample_lists_tabs.setCurrentIndex(1)
|
||||
else:
|
||||
self.sample_lists_tabs.setCurrentIndex(0)
|
||||
|
||||
@Slot(DAQStatusModel)
|
||||
def update_daq_status(self, s: DAQStatusModel):
|
||||
self._latest_daq_status = s
|
||||
self._apply_session_gate(getattr(getattr(s, "session", None), "session", None))
|
||||
|
||||
# Default tab only on state TRANSITIONS — a manual tab choice
|
||||
# survives while the state stays put.
|
||||
new_beamline_state = getattr(s, "state", None)
|
||||
if new_beamline_state != self._last_beamline_state:
|
||||
self._last_beamline_state = new_beamline_state
|
||||
self._apply_default_sample_tab(new_beamline_state)
|
||||
|
||||
if self._is_automation_active():
|
||||
self._refresh_idle_activity(report_backend=False)
|
||||
|
||||
|
||||
@@ -40,7 +40,10 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
|
||||
self.samples: list[SampleShortInfo] = rows or []
|
||||
self.current_reference = current_reference
|
||||
# Column 0 is display-only: the row position ("#"), matching the
|
||||
# Dewar samples table; the vertical header is hidden in the panel.
|
||||
self.header = [
|
||||
"#",
|
||||
"Position",
|
||||
"Sample name",
|
||||
"Mount count",
|
||||
@@ -48,7 +51,7 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
"Rotation count",
|
||||
"Screening count",
|
||||
]
|
||||
self._sort_col = 0
|
||||
self._sort_col = 1
|
||||
self._sort_order = Qt.SortOrder.AscendingOrder
|
||||
self._sorted_samples: list[SampleShortInfo] = []
|
||||
if self.samples:
|
||||
@@ -70,7 +73,9 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
return None
|
||||
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
return get_entry(self._sorted_samples[index.row()], index.column())
|
||||
if index.column() == 0:
|
||||
return str(index.row() + 1)
|
||||
return get_entry(self._sorted_samples[index.row()], index.column() - 1)
|
||||
elif role == Qt.ItemDataRole.TextAlignmentRole:
|
||||
return Qt.AlignmentFlag.AlignCenter
|
||||
elif role == Qt.ItemDataRole.BackgroundRole:
|
||||
@@ -109,6 +114,9 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
self.endResetModel()
|
||||
|
||||
def sort(self, column, order):
|
||||
# The "#" column is display-only — nothing to sort by.
|
||||
if column == 0:
|
||||
return
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
self._sort_order = order
|
||||
self._sort_col = column
|
||||
@@ -121,14 +129,14 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
self._sorted_samples = []
|
||||
return
|
||||
|
||||
if self._sort_col == 0:
|
||||
if self._sort_col == 1:
|
||||
# Special sorting for location (Position column)
|
||||
self._sorted_samples = sorted(
|
||||
self.samples,
|
||||
key=lambda row: row.loc_str_sort(),
|
||||
reverse=(self._sort_order == Qt.SortOrder.DescendingOrder),
|
||||
)
|
||||
elif self._sort_col == 2:
|
||||
elif self._sort_col == 3:
|
||||
# Numeric sort for Mount count; place None last on ascending, first on descending
|
||||
none_sentinel = (
|
||||
float("inf") if self._sort_order == Qt.SortOrder.AscendingOrder else float("-inf")
|
||||
@@ -141,10 +149,11 @@ class ReferenceToolsModel(QAbstractTableModel):
|
||||
reverse=(self._sort_order == Qt.SortOrder.DescendingOrder),
|
||||
)
|
||||
else:
|
||||
# String sort with empty fallback
|
||||
# String sort with empty fallback (get_entry columns sit one left
|
||||
# of the view columns because of the display-only "#").
|
||||
self._sorted_samples = sorted(
|
||||
self.samples,
|
||||
key=lambda row: get_entry(row, self._sort_col) or "",
|
||||
key=lambda row: get_entry(row, self._sort_col - 1) or "",
|
||||
reverse=(self._sort_order == Qt.SortOrder.DescendingOrder),
|
||||
)
|
||||
|
||||
@@ -221,7 +230,9 @@ class ReferenceToolsPanel(QFrame):
|
||||
header.setStretchLastSection(True)
|
||||
# No bold column titles when cells are selected.
|
||||
header.setHighlightSections(False)
|
||||
self.table_view.verticalHeader().setVisible(True)
|
||||
# Row numbers live in the display-only "#" column (like the Dewar
|
||||
# table), not the vertical header.
|
||||
self.table_view.verticalHeader().setVisible(False)
|
||||
logger.debug("Setting up table view sorting")
|
||||
# Adopt the model's current order first — a second panel on a shared
|
||||
# model must not re-sort it on open.
|
||||
|
||||
Reference in New Issue
Block a user