fix(gui): add "Show beam crosshair" toggle to the camera right-click menu #236

Merged
duan_j merged 3 commits from feat/gui-statusbar-pin-right into main 2026-09-18 16:39:09 +02:00
2 changed files with 48 additions and 7 deletions
+21 -4
View File
@@ -56,6 +56,7 @@ from aare.gui.styles import (
SCALE_BAR_GREY,
SHADOW,
TARGET_COLORS,
TEXT,
THEME_SUNSET,
TOOLTIP_TEXT,
WHITE,
@@ -139,6 +140,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 +686,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 +737,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):
@@ -1278,10 +1287,11 @@ class SampleCameraImageLabel(QGraphicsView):
return bar_um, label
def _mounted_hud_ink(self) -> tuple[str, str]:
"""(text, shadow) for the mounted-sample HUD: black on a white halo in
the light themes, white on black in Sunset. The camera image behind
is arbitrary, so the pair follows the theme rather than the pixels."""
return (WHITE, SHADOW) if self._dark_theme else (SHADOW, WHITE)
"""(text, shadow) for the mounted-sample HUD: theme text ink on a white
halo in the light themes (pure black read too harsh over the camera),
white on black in Sunset. The camera image behind is arbitrary, so
the pair follows the theme rather than the pixels."""
return (WHITE, SHADOW) if self._dark_theme else (TEXT, WHITE)
def _draw_mounted_sample(self, painter: QPainter):
# Top-left HUD line (legend sits bottom-left, scale bar bottom-right):
@@ -1446,6 +1456,13 @@ class SampleCameraImageLabel(QGraphicsView):
int(beam_size_pxl.y),
)
)
if self._show_beam_crosshair:
# Anuschka and Katherine really want a crosshair at 10s
arm = 33
cx = int(self._geom.beam_location_pxl.x)
cy = int(self._geom.beam_location_pxl.y)
painter.drawLine(cx - arm, cy, cx + arm, cy)
painter.drawLine(cx, cy - arm, cx, cy + arm)
@staticmethod
def _draw_circle(painter, coord: Coordinate, color: QColor, radius=10):
+27 -3
View File
@@ -327,10 +327,34 @@ def test_mounted_sample_hud_follows_status(camera):
def test_mounted_hud_ink_follows_theme(camera):
"""Mounted-sample HUD: dark ink + white halo on light themes, inverted on Sunset."""
from aare.gui.styles import SHADOW, THEME_SUNRISE, THEME_SUNSET, WHITE
"""Mounted-sample HUD: theme text ink + white halo on light themes, inverted on Sunset."""
from aare.gui.styles import SHADOW, TEXT, THEME_SUNRISE, THEME_SUNSET, WHITE
camera.set_theme(THEME_SUNRISE)
assert camera._mounted_hud_ink() == (SHADOW, WHITE)
assert camera._mounted_hud_ink() == (TEXT, 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