diff --git a/src/aare/gui/panels/sample_queue_panel.py b/src/aare/gui/panels/sample_queue_panel.py index ce46a850..629c4cc5 100644 --- a/src/aare/gui/panels/sample_queue_panel.py +++ b/src/aare/gui/panels/sample_queue_panel.py @@ -268,6 +268,20 @@ class SampleQueuePanel(QFrame): def run(self): self.__recovery_timer.stop() + + # Pausing must ALWAYS be possible, regardless of beamline state, busy + # flag, baton or maintenance. Only starting/resuming is gated on + # conditions, so handle the pause toggle first and return immediately. + if not self.__pause: + self.__set_to_pause = True + self.__pause = True + self.table_model.set_running(False) + self.play_button.setText("▶ Run") + self._emit_samples_in_queue_changed() + self.automation_running_changed.emit(False) + return + + # --- Starting/resuming: require the beamline to be in a good state. --- checks_enabled = self._checks_enabled() if checks_enabled: if self.__warning_msg_box: @@ -282,82 +296,74 @@ class SampleQueuePanel(QFrame): ) return - if self.__pause: - if self.__busy: - logger.error(f"Cannot run automation while beamline is busy. Busy flag = {self.__busy}") - self.show_error_dialog( - title="Beamline is busy", - msg="Cannot run automation while beamline is busy", - info="Please wait until beamline is idle " - "or contact your local contact for support", - ) - return + if self.__busy: + logger.error(f"Cannot run automation while beamline is busy. Busy flag = {self.__busy}") + self.show_error_dialog( + title="Beamline is busy", + msg="Cannot run automation while beamline is busy", + info="Please wait until beamline is idle " + "or contact your local contact for support", + ) + return - if self.__baton_holder is SessionsStateEnum.Vacant: - self.show_error_dialog( - title="Session is vacant", - msg="Starting automation while session is vacant is not currently implemented", - info="Please grab the baton before continuing " - "or contact your local contact for support", - ) - return + if self.__baton_holder is SessionsStateEnum.Vacant: + self.show_error_dialog( + title="Session is vacant", + msg="Starting automation while session is vacant is not currently implemented", + info="Please grab the baton before continuing " + "or contact your local contact for support", + ) + return - elif self.__baton_holder is not SessionsStateEnum.OwnedByYou: - self.show_error_dialog( - title="You do not hold the baton", - msg="You do not hold the baton.", - info="Please request the baton if it is your shift." - "If your baton request is denied and it should be the start of your shift," - "please contact your local contact for support", - ) - return + elif self.__baton_holder is not SessionsStateEnum.OwnedByYou: + self.show_error_dialog( + title="You do not hold the baton", + msg="You do not hold the baton.", + info="Please request the baton if it is your shift." + "If your baton request is denied and it should be the start of your shift," + "please contact your local contact for support", + ) + return - if self.__beamline_state is BeamlineStateEnum.Maintenance: - self.show_error_dialog( - title="Maintenance mode", - msg="Cannot run automation while beamline is in maintenance mode", - info=("Change to safe state such as Sample Exchange before trying to continue. " - "If this issue persists please contact your local contact for support."), - ) - return + if self.__beamline_state is BeamlineStateEnum.Maintenance: + self.show_error_dialog( + title="Maintenance mode", + msg="Cannot run automation while beamline is in maintenance mode", + info=("Change to safe state such as Sample Exchange before trying to continue. " + "If this issue persists please contact your local contact for support."), + ) + return - if len(self.table_model.samples) > 0: - if checks_enabled: - bad = self._bad_conditions() - if bad: - logger.warning(f"Cannot start automation; beamline not ready: {bad}") - self.show_error_dialog( - title="Beamline not ready", - msg="Cannot start automation:\n- " + "\n- ".join(bad), - info="Fix the above, or untick 'Pause on bad conditions' for testing.", - ) - return + if len(self.table_model.samples) > 0: + if checks_enabled: + bad = self._bad_conditions() + if bad: + logger.warning(f"Cannot start automation; beamline not ready: {bad}") + self.show_error_dialog( + title="Beamline not ready", + msg="Cannot start automation:\n- " + "\n- ".join(bad), + info="Fix the above, or untick 'Pause on bad conditions' for testing.", + ) + return - self.table_model.set_running(True) - self.__set_to_pause = False - self.__pause = False - self.play_button.setText("⏸ Pause") - current = self.table_model.samples[0] - self._current_db_id = current.db_id - self._emit_samples_in_queue_changed() - self.automation_running_changed.emit(True) - self.auto_scan.emit(current) - self.viewer_track_online.emit() - else: - logger.debug("No samples in queue, skipping") - self.show_error_dialog( - title="No Samples in Queue", - msg="Cannot run automation as there are no samples in the queue.", - info="Please add samples to the queue.", - ) - return - else: - self.__set_to_pause = True - self.__pause = True - self.table_model.set_running(False) - self.play_button.setText("▶ Run") + self.table_model.set_running(True) + self.__set_to_pause = False + self.__pause = False + self.play_button.setText("⏸ Pause") + current = self.table_model.samples[0] + self._current_db_id = current.db_id self._emit_samples_in_queue_changed() - self.automation_running_changed.emit(False) + self.automation_running_changed.emit(True) + self.auto_scan.emit(current) + self.viewer_track_online.emit() + else: + logger.debug("No samples in queue, skipping") + self.show_error_dialog( + title="No Samples in Queue", + msg="Cannot run automation as there are no samples in the queue.", + info="Please add samples to the queue.", + ) + return def clear(self): self.table_model.clearSamples()