CI / lint (pull_request) Successful in 1m9s
CI / test (3.12) (pull_request) Successful in 1m3s
CI / test (3.14) (pull_request) Successful in 1m11s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m14s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m16s
CI / test-with-coverage (pull_request) Successful in 1m40s
CI / coverage-analysis (pull_request) Successful in 3s
CI / test (3.13) (pull_request) Successful in 58s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m14s
Docs build and publish / docker (push) Successful in 14s
CI / lint (push) Successful in 35s
CI / test (3.12) (push) Canceled after 42s
CI / test (3.13) (push) Canceled after 37s
CI / test (3.14) (push) Canceled after 37s
CI / test-with-beamline-plugins (pxi_bec) (push) Canceled after 32s
CI / test-with-beamline-plugins (pxii_bec) (push) Canceled after 32s
CI / test-with-beamline-plugins (pxiii_bec) (push) Canceled after 27s
CI / test-with-coverage (push) Canceled after 27s
CI / coverage-analysis (push) Canceled after 0s
Build and Publish / release (push) Successful in 26s
CI (3.12, PR 232) failed test_font_zoom_keeps_frozen_column_aligned_and_reautosizes with a pytest-qt CALL ERROR: PySide 6.9 handed both app-level filters a QWidgetItem instead of a QEvent during layout teardown, and event.type() raised. The wheel guard now keys on isinstance(event, QWheelEvent) and returns False itself instead of super().eventFilter() (which type-checks its arguments and would raise the same way); the cursor filter ignores anything that is not a QEvent. Regression test for each. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
"""The wheel guard is motor protection: a bare wheel over a value widget must
|
|
never change the value (it scrolls the page instead); adjusting requires the
|
|
deliberate right-button + wheel gesture."""
|
|
|
|
import pytest
|
|
from PySide6.QtCore import QPoint, QPointF, Qt
|
|
from PySide6.QtGui import QWheelEvent
|
|
from PySide6.QtWidgets import (
|
|
QApplication,
|
|
QScrollArea,
|
|
QSlider,
|
|
QSpinBox,
|
|
QVBoxLayout,
|
|
QWidget,
|
|
QWidgetItem,
|
|
)
|
|
|
|
from aare.gui.widgets.wheel_value_guard import WheelValueGuard
|
|
|
|
|
|
@pytest.fixture
|
|
def guard(qapp):
|
|
guard = WheelValueGuard()
|
|
qapp.installEventFilter(guard)
|
|
yield guard
|
|
qapp.removeEventFilter(guard)
|
|
|
|
|
|
def _wheel(buttons):
|
|
return QWheelEvent(
|
|
QPointF(5, 5),
|
|
QPointF(5, 5),
|
|
QPoint(0, 0),
|
|
QPoint(0, 120),
|
|
buttons,
|
|
Qt.KeyboardModifier.NoModifier,
|
|
Qt.ScrollPhase.NoScrollPhase,
|
|
False,
|
|
)
|
|
|
|
|
|
def test_bare_wheel_does_not_adjust(guard, qtbot):
|
|
slider = QSlider(Qt.Orientation.Horizontal)
|
|
qtbot.addWidget(slider)
|
|
slider.setRange(0, 100)
|
|
slider.setValue(50)
|
|
QApplication.sendEvent(slider, _wheel(Qt.MouseButton.NoButton))
|
|
assert slider.value() == 50
|
|
|
|
|
|
def test_right_button_wheel_adjusts(guard, qtbot):
|
|
slider = QSlider(Qt.Orientation.Horizontal)
|
|
qtbot.addWidget(slider)
|
|
slider.setRange(0, 100)
|
|
slider.setValue(50)
|
|
QApplication.sendEvent(slider, _wheel(Qt.MouseButton.RightButton))
|
|
assert slider.value() != 50
|
|
|
|
|
|
def test_bare_wheel_scrolls_the_enclosing_area(guard, qtbot):
|
|
area = QScrollArea()
|
|
qtbot.addWidget(area)
|
|
content = QWidget()
|
|
layout = QVBoxLayout(content)
|
|
spin = QSpinBox()
|
|
spin.setRange(0, 100)
|
|
spin.setValue(50)
|
|
layout.addWidget(spin)
|
|
# Tall filler so the area has something to scroll.
|
|
filler = QWidget()
|
|
filler.setFixedHeight(2000)
|
|
layout.addWidget(filler)
|
|
area.setWidget(content)
|
|
area.resize(200, 200)
|
|
area.show()
|
|
bar = area.verticalScrollBar()
|
|
bar.setValue(bar.maximum() // 2)
|
|
before = bar.value()
|
|
|
|
QApplication.sendEvent(spin, _wheel(Qt.MouseButton.NoButton))
|
|
assert spin.value() == 50
|
|
assert bar.value() != before
|
|
|
|
|
|
def test_a_non_event_argument_is_ignored(guard, qtbot):
|
|
# PySide 6.9 can hand an app-level filter a QWidgetItem instead of a
|
|
# QEvent during layout teardown; raising there fails a random test.
|
|
widget = QWidget()
|
|
qtbot.addWidget(widget)
|
|
assert guard.eventFilter(widget, QWidgetItem(widget)) is False
|