From 7e0a27f99233e39f245d6d3a40af3c49fb336ae7 Mon Sep 17 00:00:00 2001 From: appleb_m Date: Wed, 22 Apr 2026 16:05:37 +0200 Subject: [PATCH] GUI: added shortcuts and a helper --- src/aare/gui/main_window.py | 99 ++++++++++++++++++- src/aare/gui/panels/automation_panel.py | 14 +++ .../gui/tutorials/controls_help_dialog.py | 63 ++++++++++++ src/aare/gui/widgets/camera_image.py | 6 +- 4 files changed, 177 insertions(+), 5 deletions(-) diff --git a/src/aare/gui/main_window.py b/src/aare/gui/main_window.py index 5e2a0c86..bb37544a 100644 --- a/src/aare/gui/main_window.py +++ b/src/aare/gui/main_window.py @@ -3,7 +3,7 @@ import requests import jwt from PySide6.QtCore import Qt, Slot, Signal, QTimer, QSettings -from PySide6.QtGui import QAction, QPixmap +from PySide6.QtGui import QAction, QPixmap, QKeySequence from PySide6.QtWidgets import ( QMainWindow, QWidget, @@ -347,6 +347,7 @@ class MainWindow(QMainWindow): self.setWindowTitle("AareGUI") self.create_menu_bar() + self._setup_global_shortcuts() self._capture_default_window_state() self._restore_window_state() @@ -635,6 +636,69 @@ class MainWindow(QMainWindow): # Initial load QTimer.singleShot(1000, self.daq.workflow_load_queue) + def _setup_global_shortcuts(self) -> None: + self._shortcut_manual_sample = QAction("Raise Manual Sample Dock", self) + self._shortcut_manual_sample.setShortcut(QKeySequence("Ctrl+M")) + self._shortcut_manual_sample.triggered.connect( + lambda: (self.manual_sample_dock.setVisible(True), self.manual_sample_dock.raise_())) + self.addAction(self._shortcut_manual_sample) + + self._shortcut_raise_sample_list = QAction("Raise sample list", self) + self._shortcut_raise_sample_list.setShortcut(QKeySequence("Ctrl+L")) + self._shortcut_raise_sample_list.triggered.connect( + lambda: (self.tell_samples_dock.setVisible(True), self.tell_samples_dock.raise_()) + ) + self.addAction(self._shortcut_raise_sample_list) + + self._shortcut_raise_reference_tools_list = QAction("Raise reference tools", self) + self._shortcut_raise_reference_tools_list.setShortcut(QKeySequence("Ctrl+R")) + self._shortcut_raise_reference_tools_list.triggered.connect( + lambda: (self.ref_tools_dock.setVisible(True), self.ref_tools_dock.raise_()) + ) + self.addAction(self._shortcut_raise_reference_tools_list) + + self._shortcut_raise_job_list = QAction("Raise automation list", self) + self._shortcut_raise_job_list.setShortcut(QKeySequence("Ctrl+J")) + self._shortcut_raise_job_list.triggered.connect( + lambda: (self.job_list_dock.setVisible(True), self.job_list_dock.raise_()) + ) + self.addAction(self._shortcut_raise_job_list) + + self._shortcut_toggle_workflow = QAction("Toggle workflow panel", self) + self._shortcut_toggle_workflow.setShortcut(QKeySequence("Ctrl+W")) + self._shortcut_toggle_workflow.triggered.connect( + lambda: self.workflow_dock.setVisible(not self.workflow_dock.isVisible()) + ) + self.addAction(self._shortcut_toggle_workflow) + + self._shortcut_toggle_target_stability = QAction("Toggle target stability panel", self) + self._shortcut_toggle_target_stability.setShortcut(QKeySequence("Ctrl+Shift+T")) + self._shortcut_toggle_target_stability.triggered.connect( + lambda: self.target_stability_dock.setVisible(not self.target_stability_dock.isVisible()) + ) + self.addAction(self._shortcut_toggle_target_stability) + + self._shortcut_toggle_prediction_metrics = QAction("Toggle prediction metrics panel", self) + self._shortcut_toggle_prediction_metrics.setShortcut(QKeySequence("Ctrl+Shift+P")) + self._shortcut_toggle_prediction_metrics.triggered.connect( + lambda: self.prediction_metrics_dock.setVisible(not self.prediction_metrics_dock.isVisible()) + ) + self.addAction(self._shortcut_toggle_prediction_metrics) + + self._shortcut_toggle_smargon_trace = QAction("Toggle smargon trace panel", self) + self._shortcut_toggle_smargon_trace.setShortcut(QKeySequence("Ctrl+Shift+S")) + self._shortcut_toggle_smargon_trace.triggered.connect( + lambda: self.smargon_trace_dock.setVisible(not self.smargon_trace_dock.isVisible()) + ) + self.addAction(self._shortcut_toggle_smargon_trace) + + self._shortcut_console_log = QAction("Toggle Console Log", self) + self._shortcut_console_log.setShortcut(QKeySequence("Ctrl+Shift+L")) + self._shortcut_console_log.triggered.connect( + lambda: (self.log_dock.setVisible(True), self.log_dock.raise_()) + ) + self.addAction(self._shortcut_console_log) + def _restore_samcam_overlay_settings(self) -> None: settings = QSettings("PSI", "AareGUI") show_detections = settings.value("samcam/show_detections", True, type=bool) @@ -735,8 +799,9 @@ class MainWindow(QMainWindow): # File menu file_menu = menu_bar.addMenu("File") - quit_action = QAction("&Quit", self) # Action for 'Quit' - quit_action.triggered.connect(self.close) # Connect to window's `close` method + quit_action = QAction("&Quit", self) + quit_action.setShortcut(QKeySequence.StandardKey.Quit) + quit_action.triggered.connect(self.close) file_menu.addAction(quit_action) view_menu = menu_bar.addMenu("View") @@ -830,16 +895,40 @@ class MainWindow(QMainWindow): view_menu.addSeparator() + sample_camera_tab_action = QAction("Sample camera tab", self) + sample_camera_tab_action.setShortcut(QKeySequence("Ctrl+1")) + sample_camera_tab_action.triggered.connect(lambda: self.video_tab.setCurrentIndex(0)) + view_menu.addAction(sample_camera_tab_action) + + gonio_camera_tab_action = QAction("Gonio camera tab", self) + gonio_camera_tab_action.setShortcut(QKeySequence("Ctrl+2")) + gonio_camera_tab_action.triggered.connect(lambda: self.video_tab.setCurrentIndex(1)) + view_menu.addAction(gonio_camera_tab_action) + + beamline_view_tab_action = QAction("Beamline view tab", self) + beamline_view_tab_action.setShortcut(QKeySequence("Ctrl+3")) + beamline_view_tab_action.triggered.connect(lambda: self.video_tab.setCurrentIndex(2)) + view_menu.addAction(beamline_view_tab_action) + + beamline_combined_tab_action = QAction("Beamline combined view tab", self) + beamline_combined_tab_action.setShortcut(QKeySequence("Ctrl+4")) + beamline_combined_tab_action.triggered.connect(lambda: self.video_tab.setCurrentIndex(3)) + view_menu.addAction(beamline_combined_tab_action) + + view_menu.addSeparator() + restore_default_view_action = QAction("Restore Default View", self) + restore_default_view_action.setShortcut(QKeySequence("Ctrl+Shift+R")) restore_default_view_action.triggered.connect(self.restore_default_view) view_menu.addAction(restore_default_view_action) help_menu = menu_bar.addMenu("Help") - about_action = QAction("About", self) # Action for 'About' + about_action = QAction("About", self) about_action.triggered.connect(self.show_about_dialog) help_menu.addAction(about_action) controls_help_action = QAction("Mouse / Keyboard Controls", self) + controls_help_action.setShortcut(QKeySequence(Qt.Key.Key_F1)) controls_help_action.triggered.connect(self.show_controls_help) help_menu.addAction(controls_help_action) @@ -1188,11 +1277,13 @@ class MainWindow(QMainWindow): settings.endGroup() def _restore_window_state(self) -> None: + #TODO put all setting related handlign into state_manager self.state_manager.restore_window(self) self._restore_panel_visibility_settings() def closeEvent(self, event) -> None: try: + # TODO put all setting related handling into state_manager self.state_manager.save_window(self) self._save_samcam_overlay_settings() self._save_panel_visibility_settings() diff --git a/src/aare/gui/panels/automation_panel.py b/src/aare/gui/panels/automation_panel.py index 3fd82e5c..22490ce6 100644 --- a/src/aare/gui/panels/automation_panel.py +++ b/src/aare/gui/panels/automation_panel.py @@ -297,6 +297,7 @@ class WorkflowPanel(QWidget): self._automation_enabled = False self._was_paused_before_automation = False # Track pause state before automation self._setup_ui() + self._setup_shortcuts() def _setup_ui(self) -> None: layout = QVBoxLayout(self) @@ -436,6 +437,19 @@ class WorkflowPanel(QWidget): # Initial state self._update_button_states() + def _setup_shortcuts(self) -> None: + self._pause_resume_shortcut = QShortcut(QKeySequence(Qt.Key.Key_Space), self) + self._pause_resume_shortcut.setContext(Qt.ShortcutContext.WidgetWithChildrenShortcut) + self._pause_resume_shortcut.activated.connect(self._on_pause_resume) + + self._refresh_shortcut = QShortcut(QKeySequence("Ctrl+R"), self) + self._refresh_shortcut.setContext(Qt.ShortcutContext.WidgetWithChildrenShortcut) + self._refresh_shortcut.activated.connect(self.request_queue_refresh.emit) + + self._clear_shortcut = QShortcut(QKeySequence("Ctrl+Delete"), self) + self._clear_shortcut.setContext(Qt.ShortcutContext.WidgetWithChildrenShortcut) + self._clear_shortcut.activated.connect(self._on_clear_queue) + def _on_start_guided(self) -> None: """Start guided mode with the first pending sample.""" pending = [i for i in self._queue_items if i.status == QueueItemStatus.PENDING] diff --git a/src/aare/gui/tutorials/controls_help_dialog.py b/src/aare/gui/tutorials/controls_help_dialog.py index 88e8c731..82c47aad 100644 --- a/src/aare/gui/tutorials/controls_help_dialog.py +++ b/src/aare/gui/tutorials/controls_help_dialog.py @@ -36,6 +36,7 @@ class ControlsHelpDialog(QDialog): """ ), @@ -115,13 +120,46 @@ class ControlsHelpDialog(QDialog):

Sample Queue

+ +

Workflow Panel

+ + +

Sample / Reference Tables

+

Fluorescence Plot

+ +

Target Stability Panel

+ + +

Status Bar / Labels

+

General Widgets