fix: explain gated Beamline tab clicks; drop login state POST
Two changes folded together because they touch the same status path: - Revert the login-default state POST: a state transition can move motors, and merely opening the GUI must never move hardware. The GUI now adopts whatever state the server reports. - A click on the pgroup-gated (disabled) Beamline tab used to be eaten silently by the tab bar. An event filter now pops the explanation: visitor-pgroup wording for staff, the staff-only message for users (same pattern as the Auxiliary-puck tab). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+33
-12
@@ -173,7 +173,6 @@ class MainWindow(QMainWindow):
|
||||
_default_dock_split_done: bool = False
|
||||
_pre_watch_dock_state: QByteArray | None = None
|
||||
_pre_watch_visibility: list[tuple[QWidget, bool]] | None = None
|
||||
_login_default_state_sent: bool = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -404,6 +403,10 @@ class MainWindow(QMainWindow):
|
||||
|
||||
self.left_column_tabs.addTab(beamline_page, "Beamline")
|
||||
self.left_column_tabs.addTab(experiment_page, "Experiment")
|
||||
# A click on the pgroup-gated (disabled) Beamline tab is otherwise
|
||||
# eaten silently by the tab bar — the filter pops the explanation
|
||||
# instead (same pattern as the Auxiliary-puck tab).
|
||||
self.left_column_tabs.tabBar().installEventFilter(self)
|
||||
|
||||
# Only the visible page counts toward the height — same trick as the
|
||||
# content stack below, else the taller page pads the other tab.
|
||||
@@ -1424,6 +1427,20 @@ class MainWindow(QMainWindow):
|
||||
"to configure the beamline.",
|
||||
)
|
||||
|
||||
def _show_beamline_tab_gated_popup(self) -> None:
|
||||
# The tab is only ever disabled by the pgroup gate; staff hitting it
|
||||
# are running a visitor's pgroup, users simply lack the rights.
|
||||
if self._decoded_token.staff:
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Beamline tab disabled",
|
||||
"The active pgroup is not one of yours, so the Beamline tab "
|
||||
"is disabled while running a visitor's experiment. Switch "
|
||||
"back to your own pgroup to configure the beamline.",
|
||||
)
|
||||
else:
|
||||
self._show_beamline_staff_only_popup()
|
||||
|
||||
@Slot()
|
||||
def _raise_reference_tools(self) -> None:
|
||||
if not self._decoded_token.staff:
|
||||
@@ -2643,17 +2660,9 @@ class MainWindow(QMainWindow):
|
||||
self._apply_session_gate(getattr(getattr(s, "session", None), "session", None))
|
||||
self._apply_pgroup_gate(getattr(getattr(s, "session", None), "current_pgroup", None))
|
||||
|
||||
# Login default: staff start in BeamLocation, users in SampleAlignment.
|
||||
# One-shot on the first status tick where this GUI owns the session and
|
||||
# the beamline is idle — a busy beamline or watch-only GUI must never
|
||||
# have its state yanked by someone merely logging in.
|
||||
if not self._login_default_state_sent and self._session_operations_enabled and not s.busy:
|
||||
self._login_default_state_sent = True
|
||||
if self._decoded_token.staff:
|
||||
if s.state != BeamlineStateEnum.BeamLocation:
|
||||
self.daq.beam_location()
|
||||
elif s.state != BeamlineStateEnum.SampleAlignment:
|
||||
self.daq.sample_alignment()
|
||||
# No login-default state: the GUI adopts whatever state the server
|
||||
# reports and never posts a transition on startup — a state POST can
|
||||
# move motors, and merely logging in must not move hardware.
|
||||
|
||||
# Default tab only on state TRANSITIONS — a manual tab choice
|
||||
# survives while the state stays put.
|
||||
@@ -3225,6 +3234,18 @@ class MainWindow(QMainWindow):
|
||||
if event.type() == QEvent.Type.MouseButtonPress and obj in self._locked_beamline_banners:
|
||||
self._show_beamline_staff_only_popup()
|
||||
return True
|
||||
# Click on the pgroup-gated (disabled) Beamline tab: tabAt() is
|
||||
# geometric, so it still sees the disabled tab under the cursor.
|
||||
left_tab_bar = self.left_column_tabs.tabBar()
|
||||
if (
|
||||
event.type() == QEvent.Type.MouseButtonPress
|
||||
and left_tab_bar is not None
|
||||
and obj is left_tab_bar
|
||||
and left_tab_bar.tabAt(event.position().toPoint()) == 0
|
||||
and not self.left_column_tabs.isTabEnabled(0)
|
||||
):
|
||||
self._show_beamline_tab_gated_popup()
|
||||
return True
|
||||
return super().eventFilter(obj, event)
|
||||
|
||||
def _start_remote_close_countdown(
|
||||
|
||||
Reference in New Issue
Block a user