feat: fold expanded help cheatsheet when mouse leaves the box

Click is no longer the only way back to the "?" badge: moving the
pointer off the expanded box, or out of the widget entirely, folds it.
Checked before the interaction gate so it works in viewing mode too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 19:54:50 +02:00
co-authored by Claude Fable 5
parent 47f2939d47
commit 64058ae6c8
2 changed files with 41 additions and 0 deletions
+18
View File
@@ -585,6 +585,11 @@ class SampleCameraImageLabel(QGraphicsView):
if self._hover_pos is not None:
self._hover_pos = None
self.update()
if self._help_expanded:
# Pointer left the widget with the cheatsheet open — fold it,
# same as wandering off the box below.
self._help_expanded = False
self.update()
super().leaveEvent(event)
def mouseMoveEvent(self, event):
@@ -593,6 +598,19 @@ class SampleCameraImageLabel(QGraphicsView):
self._hover_pos = self.mapToScene(event.pos())
self.update()
# Expanded help folds when the pointer wanders off the box — click
# is not the only way back to the "?" badge. Before the gate: the
# badge is a pure UI affordance, live even in viewing mode.
if (
self._help_expanded
and self._help_hit_rect is not None
and not self._help_hit_rect.contains(
QPointF(self.viewport().mapFrom(self, event.pos()))
)
):
self._help_expanded = False
self.update()
# Badge hover feedback must run BEFORE the interaction gate: the
# badge is visible precisely when interaction is disabled.
hovered = self._session_badge_rect is not None and self._session_badge_rect.contains(
+23
View File
@@ -114,6 +114,29 @@ def test_help_badge_click_toggles_cheatsheet(camera, qtbot):
assert not camera._help_expanded
def test_help_overlay_folds_when_mouse_leaves_box(camera, qtbot):
camera.grab() # paint records the collapsed "?" badge hit rect
badge = camera._help_hit_rect
qtbot.mouseClick(camera.viewport(), Qt.MouseButton.LeftButton, pos=badge.center().toPoint())
assert camera._help_expanded
camera.grab() # expanded paint records the full box rect
box = camera._help_hit_rect
_mouse_move(camera, box.center().toPoint()) # inside the box: stays open
assert camera._help_expanded
_mouse_move(camera, QPoint(int(box.left()) - 40, int(box.bottom()) + 40))
assert not camera._help_expanded, "moving off the box must fold it back to the badge"
# Leaving the widget entirely folds it too.
camera.grab()
badge = camera._help_hit_rect
qtbot.mouseClick(camera.viewport(), Qt.MouseButton.LeftButton, pos=badge.center().toPoint())
assert camera._help_expanded
camera.leaveEvent(QEvent(QEvent.Type.Leave))
assert not camera._help_expanded
def test_camera_error_message_rewords_and_draws(camera):
camera.set_camera_available(False)
camera.set_camera_error_message("Sample camera feed unavailable: cable unplugged")