diff --git a/src/aare/gui/panels/beamline_recovery_panel.py b/src/aare/gui/panels/beamline_recovery_panel.py index 4891e9e0..3ce97a5d 100644 --- a/src/aare/gui/panels/beamline_recovery_panel.py +++ b/src/aare/gui/panels/beamline_recovery_panel.py @@ -193,11 +193,20 @@ class RecoveryPanel(QWidget): sample_mounted = self._sample_appears_mounted() tell_connected = bool(getattr(self._last_status, "tell_connected", False)) + tell_state_text = "—" + if getattr(self._last_status, "tell_state", None) is not None: + tell_state = self._last_status.tell_state + tell_state_text = tell_state.activity.value + tell_message = (tell_state.message or "").strip() + if tell_message: + tell_state_text = f"{tell_state_text} ({tell_message})" + return ( f"State: {state_name}\n" f"Busy: {busy}\n" f"Sample mounted: {sample_mounted}\n" - f"TELL connected: {tell_connected}" + f"TELL connected: {tell_connected}\n" + f"TELL state: {tell_state_text}" ) def _refresh_buttons(self) -> None: diff --git a/src/aare/gui/panels/beamline_state_panel.py b/src/aare/gui/panels/beamline_state_panel.py index 4f036609..32c426ec 100644 --- a/src/aare/gui/panels/beamline_state_panel.py +++ b/src/aare/gui/panels/beamline_state_panel.py @@ -164,6 +164,19 @@ class BeamlineStatePanel(QFrame): self.current_label.move(14, 58) self.current_label.adjustSize() + self.tell_label = QLabel("Tell: —", self) + self.tell_label.setStyleSheet(""" + QLabel { + color: rgb(55, 67, 87); + font-size: 13px; + font-weight: 600; + padding-left: 4px; + background: transparent; + } + """) + self.tell_label.move(14, 86) + self.tell_label.adjustSize() + self.view_toggle = QPushButton(self) self.view_toggle.setCheckable(False) self.view_toggle.setStyleSheet(""" @@ -529,6 +542,39 @@ class BeamlineStatePanel(QFrame): def update_daq_status(self, status: DAQStatusModel) -> None: self.set_current_state(status.state) + tell_text = "Tell: —" + tell_color = "rgb(55, 67, 87)" + if status.tell_state is not None: + tell_state = status.tell_state + tell_text = f"Tell: {tell_state.activity.display_name()}" + + tell_phase = tell_state.phase.display_name() if tell_state.phase is not None else "" + tell_message = (tell_state.message or "").strip() + + if tell_phase: + tell_text = f"{tell_text} ({tell_phase})" + elif tell_message: + tell_text = f"{tell_text} ({tell_message})" + + if tell_state.activity.value == "error": + tell_color = "red" + elif tell_state.activity.value in {"mounting", "unmounting", "drying", "cooling"}: + tell_color = "orange" + else: + tell_color = "green" + + self.tell_label.setText(tell_text) + self.tell_label.setStyleSheet(f""" + QLabel {{ + color: {tell_color}; + font-size: 13px; + font-weight: 600; + padding-left: 4px; + background: transparent; + }} + """) + self.tell_label.adjustSize() + def set_current_state(self, state: BeamlineStateEnum | None) -> None: self._current_state = state diff --git a/src/aare/gui/widgets/camera_image.py b/src/aare/gui/widgets/camera_image.py index 501be959..b7f570b8 100644 --- a/src/aare/gui/widgets/camera_image.py +++ b/src/aare/gui/widgets/camera_image.py @@ -76,6 +76,7 @@ class SampleCameraImageLabel(QGraphicsView): self.__camera_available = True self.__last_grid_update_ts = 0.0 self.__grid_update_min_interval_s = 1.0 / 25.0 + self.__tell_state = None self.__geom = geom self.__bookmarks: SmargonBookmarkList = SmargonBookmarkList() @@ -208,6 +209,19 @@ class SampleCameraImageLabel(QGraphicsView): self.__smoothed_target_point = None self.update() + def __busy_overlay_text(self) -> str: + tell_state = self.__tell_state + if tell_state is None: + return "BEAMLINE BUSY" + + activity_value = str(getattr(tell_state.activity, "value", "") or "").lower() + if activity_value not in {"mounting", "unmounting", "drying", "cooling"}: + return "BEAMLINE BUSY" + + activity_name = tell_state.activity.display_name() + + return f"TELL {activity_name}".upper() + def __draw_busy_overlay(self, painter: QPainter): if not self.__is_daq_busy: return @@ -223,7 +237,7 @@ class SampleCameraImageLabel(QGraphicsView): painter.setPen(QPen(QColor(255, 255, 255, 200), 2, Qt.PenStyle.SolidLine)) painter.setBrush(QColor(255, 0, 0, 150)) - text = "BEAMLINE BUSY" + text = self.__busy_overlay_text() font_metrics = QFontMetrics(font) text_rect = font_metrics.boundingRect(text) @@ -586,6 +600,7 @@ class SampleCameraImageLabel(QGraphicsView): self.__geom = s.geom self.__sam_cam = s.bl.sample_camera self.__bounding_box = s.box + self.__tell_state = s.tell_state new_session_state = s.session.session if hasattr(s, 'session') else None if new_session_state != self.__session_state: diff --git a/src/aare/gui/widgets/status_bar.py b/src/aare/gui/widgets/status_bar.py index a78ffbf6..7c34a50a 100644 --- a/src/aare/gui/widgets/status_bar.py +++ b/src/aare/gui/widgets/status_bar.py @@ -72,6 +72,8 @@ class StatusBar(QStatusBar): self.state_label = ClickableLabel(parent=self) self.state_label.clicked.connect(self.show_state_menu) + self.tell_state_label = QLabel("Tell: —", self) + self.busy_label = ClickableLabel(parent=self) self.session_label = ClickableLabel(parent=self) @@ -93,6 +95,7 @@ class StatusBar(QStatusBar): self.addPermanentWidget(self.exp_shutter_label) self.addPermanentWidget(self.pgroup_label) self.addPermanentWidget(self.state_label) + self.addPermanentWidget(self.tell_state_label) self.addPermanentWidget(self.busy_label) self.addPermanentWidget(self.session_label) @@ -173,6 +176,21 @@ class StatusBar(QStatusBar): self.state_label.setText(f"""State: {status.state.display_name()} """) + tell_text = "—" + tell_color = "rgb(55, 67, 87)" + if status.tell_state is not None: + tell_text = status.tell_state.activity.display_name() + + if status.tell_state.activity.value == "error": + tell_color = "red" + elif status.tell_state.activity.value in {"mounting", "unmounting", "drying", "cooling"}: + tell_color = "orange" + else: + tell_color = "green" + + self.tell_state_label.setText(f"Tell: {tell_text} ") + self.tell_state_label.setStyleSheet(f"color: {tell_color};") + if status.busy: busy_flag = """ Busy 🔒 """ else: