diff --git a/src/aare/gui/widgets/camera_image.py b/src/aare/gui/widgets/camera_image.py index dc3b42b2..93c820b9 100644 --- a/src/aare/gui/widgets/camera_image.py +++ b/src/aare/gui/widgets/camera_image.py @@ -139,6 +139,9 @@ class SampleCameraImageLabel(QGraphicsView): # toggle can still switch back to 1:1. self._autoscale = True self._show_coords = False + # Full-frame crosshair through the beam center; off by default so the + # default view stays as before, toggled from the right-click menu. + self._show_beam_crosshair = False self._helical_start = SmargonCoordinate() self._helical_end = SmargonCoordinate() self._raster_alpha = 127 @@ -682,6 +685,9 @@ class SampleCameraImageLabel(QGraphicsView): autofocus_action = menu.addAction("Auto-focus") beam_mark_action = menu.addAction("Mark beam center") + crosshair_action = menu.addAction("Show beam crosshair") + crosshair_action.setCheckable(True) + crosshair_action.setChecked(self._show_beam_crosshair) delete_action = None evaluate_action = None @@ -730,6 +736,8 @@ class SampleCameraImageLabel(QGraphicsView): elif action == beam_mark_action: c = self.mapToScene(event.pos()) self.update_beam_mark.emit(c.x(), c.y()) + elif action == crosshair_action: + self._show_beam_crosshair = not self._show_beam_crosshair self.update() def _screenshot_with_dialog(self, overlay: bool): @@ -1446,6 +1454,13 @@ class SampleCameraImageLabel(QGraphicsView): int(beam_size_pxl.y), ) ) + if self._show_beam_crosshair: + # Same pen as the box so the crosshair follows the beam state color. + r = self.sceneRect() + cx = int(self._geom.beam_location_pxl.x) + cy = int(self._geom.beam_location_pxl.y) + painter.drawLine(int(r.left()), cy, int(r.right()), cy) + painter.drawLine(cx, int(r.top()), cx, int(r.bottom())) @staticmethod def _draw_circle(painter, coord: Coordinate, color: QColor, radius=10): diff --git a/tests/unit/gui/test_camera_image.py b/tests/unit/gui/test_camera_image.py index 51ff331a..428129ba 100644 --- a/tests/unit/gui/test_camera_image.py +++ b/tests/unit/gui/test_camera_image.py @@ -334,3 +334,27 @@ def test_mounted_hud_ink_follows_theme(camera): assert camera._mounted_hud_ink() == (SHADOW, WHITE) camera.set_theme(THEME_SUNSET) assert camera._mounted_hud_ink() == (WHITE, SHADOW) + + +def test_beam_crosshair_toggle_draws(camera, monkeypatch): + from PySide6.QtWidgets import QMenu + + assert camera._show_beam_crosshair is False + # Pick the crosshair action out of the real menu instead of exec'ing it. + monkeypatch.setattr( + QMenu, + "exec_", + lambda self, *_: next(a for a in self.actions() if a.text() == "Show beam crosshair"), + ) + camera._camera_interaction_enabled = lambda: True + press = QMouseEvent( + QEvent.Type.MouseButtonPress, + QPointF(10, 10), + QPointF(camera.mapToGlobal(QPoint(10, 10))), + Qt.MouseButton.RightButton, + Qt.MouseButton.RightButton, + Qt.KeyboardModifier.NoModifier, + ) + camera._right_click_menu(press) + assert camera._show_beam_crosshair is True + camera.grab() # exercises the crosshair draw path