mirror of
https://github.com/pyapp-kit/superqt.git
synced 2025-12-16 03:00:05 +01:00
style: use ruff format instead of black, update pre-commit, restrict pyside6 tests (#235)
* style: use ruff format * fix import * disallow pyside 6.6.2 * pin in tests too * pyside6.4 on windows * fix greedy imports * double quote * run sliders last * try 6.6.1 again
This commit is contained in:
0
tests/zz_test_sliders/__init__.py
Normal file
0
tests/zz_test_sliders/__init__.py
Normal file
88
tests/zz_test_sliders/_testutil.py
Normal file
88
tests/zz_test_sliders/_testutil.py
Normal file
@@ -0,0 +1,88 @@
|
||||
from contextlib import suppress
|
||||
from platform import system
|
||||
|
||||
import pytest
|
||||
from qtpy import QT_VERSION
|
||||
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
||||
from qtpy.QtGui import QHoverEvent, QMouseEvent, QWheelEvent
|
||||
|
||||
QT_VERSION = tuple(int(x) for x in QT_VERSION.split("."))
|
||||
|
||||
SYS_DARWIN = system() == "Darwin"
|
||||
|
||||
skip_on_linux_qt6 = pytest.mark.skipif(
|
||||
system() == "Linux" and QT_VERSION >= (6, 0),
|
||||
reason="hover events not working on linux pyqt6",
|
||||
)
|
||||
|
||||
_PointF = QPointF()
|
||||
|
||||
|
||||
def _mouse_event(pos=_PointF, type_=QEvent.Type.MouseMove):
|
||||
"""Create a mouse event of `type_` at `pos`."""
|
||||
return QMouseEvent(
|
||||
type_,
|
||||
QPointF(pos), # localPos
|
||||
QPointF(), # windowPos / globalPos
|
||||
Qt.MouseButton.LeftButton, # button
|
||||
Qt.MouseButton.LeftButton, # buttons
|
||||
Qt.KeyboardModifier.NoModifier, # modifiers
|
||||
)
|
||||
|
||||
|
||||
def _wheel_event(arc):
|
||||
"""Create a wheel event with `arc`."""
|
||||
with suppress(TypeError):
|
||||
return QWheelEvent(
|
||||
QPointF(),
|
||||
QPointF(),
|
||||
QPoint(arc, arc),
|
||||
QPoint(arc, arc),
|
||||
Qt.MouseButton.NoButton,
|
||||
Qt.KeyboardModifier.NoModifier,
|
||||
Qt.ScrollPhase.ScrollBegin,
|
||||
False,
|
||||
Qt.MouseEventSource.MouseEventSynthesizedByQt,
|
||||
)
|
||||
with suppress(TypeError):
|
||||
return QWheelEvent(
|
||||
QPointF(),
|
||||
QPointF(),
|
||||
QPoint(-arc, -arc),
|
||||
QPoint(-arc, -arc),
|
||||
1,
|
||||
Qt.Orientation.Vertical,
|
||||
Qt.MouseButton.NoButton,
|
||||
Qt.KeyboardModifier.NoModifier,
|
||||
Qt.ScrollPhase.ScrollBegin,
|
||||
False,
|
||||
Qt.MouseEventSource.MouseEventSynthesizedByQt,
|
||||
)
|
||||
|
||||
return QWheelEvent(
|
||||
QPointF(),
|
||||
QPointF(),
|
||||
QPoint(arc, arc),
|
||||
QPoint(arc, arc),
|
||||
1,
|
||||
Qt.Orientation.Vertical,
|
||||
Qt.MouseButton.NoButton,
|
||||
Qt.KeyboardModifier.NoModifier,
|
||||
)
|
||||
|
||||
|
||||
def _hover_event(_type, position, old_position, widget=None):
|
||||
with suppress(TypeError):
|
||||
return QHoverEvent(
|
||||
_type,
|
||||
position,
|
||||
widget.mapToGlobal(position),
|
||||
old_position,
|
||||
)
|
||||
return QHoverEvent(_type, position, old_position)
|
||||
|
||||
|
||||
def _linspace(start: int, stop: int, n: int):
|
||||
h = (stop - start) / (n - 1)
|
||||
for i in range(n):
|
||||
yield start + h * i
|
||||
140
tests/zz_test_sliders/test_float.py
Normal file
140
tests/zz_test_sliders/test_float.py
Normal file
@@ -0,0 +1,140 @@
|
||||
import math
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from qtpy import API_NAME
|
||||
from qtpy.QtWidgets import QStyleOptionSlider
|
||||
|
||||
from superqt import (
|
||||
QDoubleRangeSlider,
|
||||
QDoubleSlider,
|
||||
QLabeledDoubleRangeSlider,
|
||||
QLabeledDoubleSlider,
|
||||
)
|
||||
|
||||
from ._testutil import _linspace
|
||||
|
||||
range_types = {QDoubleRangeSlider, QLabeledDoubleRangeSlider}
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
QDoubleSlider,
|
||||
QLabeledDoubleSlider,
|
||||
QDoubleRangeSlider,
|
||||
QLabeledDoubleRangeSlider,
|
||||
]
|
||||
)
|
||||
def ds(qtbot, request):
|
||||
# convenience fixture that converts value() and setValue()
|
||||
# to let us use setValue((a, b)) for both range and non-range sliders
|
||||
cls = request.param
|
||||
wdg = cls()
|
||||
qtbot.addWidget(wdg)
|
||||
|
||||
def assert_val_type():
|
||||
type_ = float
|
||||
if cls in range_types:
|
||||
assert all(isinstance(i, type_) for i in wdg.value()) # sourcery skip
|
||||
else:
|
||||
assert isinstance(wdg.value(), type_)
|
||||
|
||||
def assert_val_eq(val):
|
||||
assert wdg.value() == val if cls is QDoubleRangeSlider else val[0]
|
||||
|
||||
wdg.assert_val_type = assert_val_type
|
||||
wdg.assert_val_eq = assert_val_eq
|
||||
|
||||
if cls not in range_types:
|
||||
superset = wdg.setValue
|
||||
|
||||
def _safe_set(val):
|
||||
superset(val[0] if isinstance(val, tuple) else val)
|
||||
|
||||
wdg.setValue = _safe_set
|
||||
|
||||
return wdg
|
||||
|
||||
|
||||
def test_double_sliders(ds):
|
||||
ds.setMinimum(10)
|
||||
ds.setMaximum(99)
|
||||
ds.setValue((20, 40))
|
||||
ds.setSingleStep(1)
|
||||
assert ds.minimum() == 10
|
||||
assert ds.maximum() == 99
|
||||
ds.assert_val_eq((20, 40))
|
||||
assert ds.singleStep() == 1
|
||||
|
||||
ds.assert_val_eq((20, 40))
|
||||
ds.assert_val_type()
|
||||
|
||||
ds.setValue((20.23, 40.23))
|
||||
ds.assert_val_eq((20.23, 40.23))
|
||||
ds.assert_val_type()
|
||||
|
||||
assert ds.minimum() == 10
|
||||
assert ds.maximum() == 99
|
||||
assert ds.singleStep() == 1
|
||||
ds.assert_val_eq((20.23, 40.23))
|
||||
ds.setValue((20.2343, 40.2342))
|
||||
ds.assert_val_eq((20.2343, 40.2342))
|
||||
|
||||
ds.assert_val_eq((20.2343, 40.2342))
|
||||
assert ds.minimum() == 10
|
||||
assert ds.maximum() == 99
|
||||
assert ds.singleStep() == 1
|
||||
|
||||
ds.assert_val_eq((20.2343, 40.2342))
|
||||
assert ds.minimum() == 10
|
||||
assert ds.maximum() == 99
|
||||
assert ds.singleStep() == 1
|
||||
|
||||
|
||||
def test_double_sliders_small(ds):
|
||||
ds.setMaximum(1)
|
||||
ds.setValue((0.5, 0.9))
|
||||
assert ds.minimum() == 0
|
||||
assert ds.maximum() == 1
|
||||
ds.assert_val_eq((0.5, 0.9))
|
||||
|
||||
ds.setValue((0.122233, 0.72644353))
|
||||
ds.assert_val_eq((0.122233, 0.72644353))
|
||||
|
||||
|
||||
def test_double_sliders_big(ds):
|
||||
ds.setValue((20, 80))
|
||||
ds.setMaximum(5e14)
|
||||
assert ds.minimum() == 0
|
||||
assert ds.maximum() == 5e14
|
||||
ds.setValue((1.74e9, 1.432e10))
|
||||
ds.assert_val_eq((1.74e9, 1.432e10))
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.name == "nt" and API_NAME == "PyQt6", reason="Not ready for pyqt6"
|
||||
)
|
||||
def test_signals(ds, qtbot):
|
||||
with qtbot.waitSignal(ds.valueChanged):
|
||||
ds.setValue((10, 20))
|
||||
|
||||
with qtbot.waitSignal(ds.rangeChanged):
|
||||
ds.setMinimum(0.5)
|
||||
|
||||
with qtbot.waitSignal(ds.rangeChanged):
|
||||
ds.setMaximum(3.7)
|
||||
|
||||
with qtbot.waitSignal(ds.rangeChanged):
|
||||
ds.setRange(1.2, 3.3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mag", list(range(4, 37, 4)) + list(range(-4, -37, -4)))
|
||||
def test_slider_extremes(mag, qtbot):
|
||||
sld = QDoubleSlider()
|
||||
_mag = 10**mag
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setRange(-_mag, _mag)
|
||||
for i in _linspace(-_mag, _mag, 10):
|
||||
sld.setValue(i)
|
||||
assert math.isclose(sld.value(), i, rel_tol=1e-8)
|
||||
sld.initStyleOption(QStyleOptionSlider())
|
||||
187
tests/zz_test_sliders/test_generic_slider.py
Normal file
187
tests/zz_test_sliders/test_generic_slider.py
Normal file
@@ -0,0 +1,187 @@
|
||||
import math
|
||||
import platform
|
||||
|
||||
import pytest
|
||||
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
||||
from qtpy.QtWidgets import QStyle, QStyleOptionSlider
|
||||
|
||||
from superqt.sliders._generic_slider import _GenericSlider, _sliderValueFromPosition
|
||||
|
||||
from ._testutil import _hover_event, _mouse_event, _wheel_event, skip_on_linux_qt6
|
||||
|
||||
|
||||
@pytest.fixture(params=[Qt.Orientation.Horizontal, Qt.Orientation.Vertical])
|
||||
def gslider(qtbot, request):
|
||||
slider = _GenericSlider(request.param)
|
||||
qtbot.addWidget(slider)
|
||||
assert slider.value() == 0
|
||||
assert slider.minimum() == 0
|
||||
assert slider.maximum() == 99
|
||||
yield slider
|
||||
slider.initStyleOption(QStyleOptionSlider())
|
||||
|
||||
|
||||
def test_change_floatslider_range(gslider: _GenericSlider, qtbot):
|
||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
||||
gslider.setMinimum(10)
|
||||
|
||||
assert gslider.value() == 10 == gslider.minimum()
|
||||
assert gslider.maximum() == 99
|
||||
|
||||
with qtbot.waitSignal(gslider.rangeChanged):
|
||||
gslider.setMaximum(90)
|
||||
assert gslider.value() == 10 == gslider.minimum()
|
||||
assert gslider.maximum() == 90
|
||||
|
||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
||||
gslider.setRange(20, 40)
|
||||
assert gslider.value() == 20 == gslider.minimum()
|
||||
assert gslider.maximum() == 40
|
||||
|
||||
with qtbot.waitSignal(gslider.valueChanged):
|
||||
gslider.setValue(30)
|
||||
assert gslider.value() == 30
|
||||
|
||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
||||
gslider.setMaximum(25)
|
||||
assert gslider.value() == 25 == gslider.maximum()
|
||||
assert gslider.minimum() == 20
|
||||
|
||||
|
||||
def test_float_values(gslider: _GenericSlider, qtbot):
|
||||
with qtbot.waitSignal(gslider.rangeChanged):
|
||||
gslider.setRange(0.25, 0.75)
|
||||
assert gslider.minimum() == 0.25
|
||||
assert gslider.maximum() == 0.75
|
||||
|
||||
with qtbot.waitSignal(gslider.valueChanged):
|
||||
gslider.setValue(0.55)
|
||||
assert gslider.value() == 0.55
|
||||
|
||||
with qtbot.waitSignal(gslider.valueChanged):
|
||||
gslider.setValue(1.55)
|
||||
assert gslider.value() == 0.75 == gslider.maximum()
|
||||
|
||||
|
||||
def test_ticks(gslider: _GenericSlider, qtbot):
|
||||
gslider.setTickInterval(0.3)
|
||||
assert gslider.tickInterval() == 0.3
|
||||
gslider.setTickPosition(gslider.TickPosition.TicksAbove)
|
||||
gslider.show()
|
||||
|
||||
|
||||
def test_show(gslider, qtbot):
|
||||
gslider.show()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.system() != "Darwin", reason="cross-platform is tricky")
|
||||
def test_press_move_release(gslider: _GenericSlider, qtbot):
|
||||
# this fail on vertical came with pyside6.2 ... need to debug
|
||||
# still works in practice, but test fails to catch signals
|
||||
if gslider.orientation() == Qt.Orientation.Vertical:
|
||||
pytest.xfail()
|
||||
|
||||
assert gslider._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
opt = QStyleOptionSlider()
|
||||
gslider.initStyleOption(opt)
|
||||
style = gslider.style()
|
||||
hrect = style.subControlRect(
|
||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||
)
|
||||
handle_pos = gslider.mapToGlobal(hrect.center())
|
||||
|
||||
with qtbot.waitSignal(gslider.sliderPressed):
|
||||
qtbot.mousePress(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
assert gslider._pressedControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
with qtbot.waitSignals([gslider.sliderMoved, gslider.valueChanged]):
|
||||
shift = (
|
||||
QPoint(0, -8)
|
||||
if gslider.orientation() == Qt.Orientation.Vertical
|
||||
else QPoint(8, 0)
|
||||
)
|
||||
gslider.mouseMoveEvent(_mouse_event(handle_pos + shift))
|
||||
|
||||
with qtbot.waitSignal(gslider.sliderReleased):
|
||||
qtbot.mouseRelease(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
assert gslider._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
gslider.show()
|
||||
with qtbot.waitSignal(gslider.sliderPressed):
|
||||
qtbot.mousePress(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
|
||||
@skip_on_linux_qt6
|
||||
def test_hover(gslider: _GenericSlider):
|
||||
# stub
|
||||
opt = QStyleOptionSlider()
|
||||
gslider.initStyleOption(opt)
|
||||
style = gslider.style()
|
||||
hrect = style.subControlRect(
|
||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||
)
|
||||
handle_pos = QPointF(gslider.mapToGlobal(hrect.center()))
|
||||
|
||||
assert gslider._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
gslider.event(_hover_event(QEvent.Type.HoverEnter, handle_pos, QPointF(), gslider))
|
||||
assert gslider._hoverControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
gslider.event(
|
||||
_hover_event(QEvent.Type.HoverLeave, QPointF(-1000, -1000), handle_pos, gslider)
|
||||
)
|
||||
assert gslider._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
|
||||
def test_wheel(gslider: _GenericSlider, qtbot):
|
||||
with qtbot.waitSignal(gslider.valueChanged):
|
||||
gslider.wheelEvent(_wheel_event(120))
|
||||
|
||||
gslider.wheelEvent(_wheel_event(0))
|
||||
|
||||
|
||||
def test_position(gslider: _GenericSlider, qtbot):
|
||||
gslider.setSliderPosition(21.2)
|
||||
assert gslider.sliderPosition() == 21.2
|
||||
|
||||
|
||||
def test_steps(gslider: _GenericSlider, qtbot):
|
||||
gslider.setSingleStep(0.1)
|
||||
assert gslider.singleStep() == 0.1
|
||||
|
||||
gslider.setSingleStep(1.5e20)
|
||||
assert gslider.singleStep() == 1.5e20
|
||||
|
||||
gslider.setPageStep(0.2)
|
||||
assert gslider.pageStep() == 0.2
|
||||
|
||||
gslider.setPageStep(1.5e30)
|
||||
assert gslider.pageStep() == 1.5e30
|
||||
|
||||
|
||||
# args are (min: float, max: float, position: int, span: int, upsideDown: bool)
|
||||
@pytest.mark.parametrize(
|
||||
"args, result",
|
||||
[
|
||||
# (min, max, pos, span[, inverted]), expectation
|
||||
# data range (1, 2)
|
||||
((1, 2, 50, 100), 1.5),
|
||||
((1, 2, 70, 100), 1.7),
|
||||
((1, 2, 70, 100, True), 1.3), # inverted appearance
|
||||
((1, 2, 170, 100), 2),
|
||||
((1, 2, 100, 100), 2),
|
||||
((1, 2, -30, 100), 1),
|
||||
# data range (-2, 2)
|
||||
((-2, 2, 50, 100), 0),
|
||||
((-2, 2, 75, 100), 1),
|
||||
((-2, 2, 75, 100, True), -1), # inverted appearance
|
||||
((-2, 2, 170, 100), 2),
|
||||
((-2, 2, 100, 100), 2),
|
||||
((-2, 2, -30, 100), -2),
|
||||
],
|
||||
)
|
||||
def test_slider_value_from_position(args, result):
|
||||
assert math.isclose(_sliderValueFromPosition(*args), result)
|
||||
85
tests/zz_test_sliders/test_labeled_slider.py
Normal file
85
tests/zz_test_sliders/test_labeled_slider.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from typing import Any, Iterable
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from superqt import QLabeledDoubleSlider, QLabeledRangeSlider, QLabeledSlider
|
||||
|
||||
|
||||
def test_labeled_slider_api(qtbot):
|
||||
slider = QLabeledRangeSlider()
|
||||
qtbot.addWidget(slider)
|
||||
slider.hideBar()
|
||||
slider.showBar()
|
||||
slider.setBarVisible()
|
||||
slider.setBarMovesAllHandles()
|
||||
slider.setBarIsRigid()
|
||||
|
||||
|
||||
def test_slider_connect_works(qtbot):
|
||||
slider = QLabeledSlider()
|
||||
qtbot.addWidget(slider)
|
||||
|
||||
slider._label.editingFinished.emit()
|
||||
|
||||
|
||||
def _assert_types(args: Iterable[Any], type_: type):
|
||||
# sourcery skip: comprehension-to-generator
|
||||
assert all(isinstance(v, type_) for v in args), "invalid type"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls", [QLabeledDoubleSlider, QLabeledSlider])
|
||||
def test_labeled_signals(cls, qtbot):
|
||||
gslider = cls()
|
||||
qtbot.addWidget(gslider)
|
||||
|
||||
type_ = float if cls == QLabeledDoubleSlider else int
|
||||
|
||||
mock = Mock()
|
||||
gslider.valueChanged.connect(mock)
|
||||
with qtbot.waitSignal(gslider.valueChanged):
|
||||
gslider.setValue(10)
|
||||
mock.assert_called_once_with(10)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
mock = Mock()
|
||||
gslider.rangeChanged.connect(mock)
|
||||
with qtbot.waitSignal(gslider.rangeChanged):
|
||||
gslider.setMinimum(3)
|
||||
mock.assert_called_once_with(3, 99)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
mock.reset_mock()
|
||||
with qtbot.waitSignal(gslider.rangeChanged):
|
||||
gslider.setMaximum(15)
|
||||
mock.assert_called_once_with(3, 15)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
mock.reset_mock()
|
||||
with qtbot.waitSignal(gslider.rangeChanged):
|
||||
gslider.setRange(1, 2)
|
||||
mock.assert_called_once_with(1, 2)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"cls", [QLabeledDoubleSlider, QLabeledRangeSlider, QLabeledSlider]
|
||||
)
|
||||
def test_editing_finished_signal(cls, qtbot):
|
||||
mock = Mock()
|
||||
slider = cls()
|
||||
qtbot.addWidget(slider)
|
||||
slider.editingFinished.connect(mock)
|
||||
if hasattr(slider, "_label"):
|
||||
slider._label.editingFinished.emit()
|
||||
else:
|
||||
slider._min_label.editingFinished.emit()
|
||||
mock.assert_called_once()
|
||||
|
||||
|
||||
def test_editing_float(qtbot):
|
||||
slider = QLabeledDoubleSlider()
|
||||
qtbot.addWidget(slider)
|
||||
slider._label.setValue(0.5)
|
||||
slider._label.editingFinished.emit()
|
||||
assert slider.value() == 0.5
|
||||
255
tests/zz_test_sliders/test_range_slider.py
Normal file
255
tests/zz_test_sliders/test_range_slider.py
Normal file
@@ -0,0 +1,255 @@
|
||||
import math
|
||||
from itertools import product
|
||||
from typing import Any, Iterable
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
||||
from qtpy.QtWidgets import QStyle, QStyleOptionSlider
|
||||
|
||||
from superqt import QDoubleRangeSlider, QLabeledRangeSlider, QRangeSlider
|
||||
|
||||
from ._testutil import (
|
||||
_hover_event,
|
||||
_linspace,
|
||||
_mouse_event,
|
||||
_wheel_event,
|
||||
skip_on_linux_qt6,
|
||||
)
|
||||
|
||||
ALL_SLIDER_COMBOS = list(
|
||||
product(
|
||||
[QDoubleRangeSlider, QRangeSlider, QLabeledRangeSlider],
|
||||
[Qt.Orientation.Horizontal, Qt.Orientation.Vertical],
|
||||
)
|
||||
)
|
||||
FLOAT_SLIDERS = [c for c in ALL_SLIDER_COMBOS if c[0] == QDoubleRangeSlider]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_slider_init(qtbot, cls, orientation):
|
||||
slider = cls(orientation)
|
||||
assert slider.value() == (20, 80)
|
||||
assert slider.minimum() == 0
|
||||
assert slider.maximum() == 99
|
||||
slider.show()
|
||||
qtbot.addWidget(slider)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_change_floatslider_range(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
with qtbot.waitSignals([sld.rangeChanged, sld.valueChanged]):
|
||||
sld.setMinimum(30)
|
||||
|
||||
assert sld.value()[0] == 30 == sld.minimum()
|
||||
assert sld.maximum() == 99
|
||||
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setMaximum(70)
|
||||
assert sld.value()[0] == 30 == sld.minimum()
|
||||
assert sld.value()[1] == 70 == sld.maximum()
|
||||
|
||||
with qtbot.waitSignals([sld.rangeChanged, sld.valueChanged]):
|
||||
sld.setRange(40, 60)
|
||||
assert sld.value()[0] == 40 == sld.minimum()
|
||||
assert sld.maximum() == 60
|
||||
|
||||
with qtbot.waitSignal(sld.valueChanged):
|
||||
sld.setValue([40, 50])
|
||||
assert sld.value()[0] == 40 == sld.minimum()
|
||||
assert sld.value()[1] == 50
|
||||
|
||||
with qtbot.waitSignals([sld.rangeChanged, sld.valueChanged]):
|
||||
sld.setMaximum(45)
|
||||
assert sld.value()[0] == 40 == sld.minimum()
|
||||
assert sld.value()[1] == 45 == sld.maximum()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||
def test_float_values(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setRange(0.1, 0.9)
|
||||
assert sld.minimum() == 0.1
|
||||
assert sld.maximum() == 0.9
|
||||
|
||||
with qtbot.waitSignal(sld.valueChanged):
|
||||
sld.setValue([0.4, 0.6])
|
||||
assert sld.value() == (0.4, 0.6)
|
||||
|
||||
with qtbot.waitSignal(sld.valueChanged):
|
||||
sld.setValue([0, 1.9])
|
||||
assert sld.value()[0] == 0.1 == sld.minimum()
|
||||
assert sld.value()[1] == 0.9 == sld.maximum()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_position(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
sld.setSliderPosition([10, 80])
|
||||
assert sld.sliderPosition() == (10, 80)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_steps(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
sld.setSingleStep(0.1)
|
||||
assert sld.singleStep() == 0.1
|
||||
|
||||
sld.setSingleStep(1.5e20)
|
||||
assert sld.singleStep() == 1.5e20
|
||||
|
||||
sld.setPageStep(0.2)
|
||||
assert sld.pageStep() == 0.2
|
||||
|
||||
sld.setPageStep(1.5e30)
|
||||
assert sld.pageStep() == 1.5e30
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mag", list(range(4, 37, 4)) + list(range(-4, -37, -4)))
|
||||
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||
def test_slider_extremes(cls, orientation, qtbot, mag):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
_mag = 10**mag
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setRange(-_mag, _mag)
|
||||
for i in _linspace(-_mag, _mag, 10):
|
||||
sld.setValue((i, _mag))
|
||||
assert math.isclose(sld.value()[0], i, rel_tol=0.0001)
|
||||
sld.initStyleOption(QStyleOptionSlider())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_ticks(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
sld.setTickInterval(0.3)
|
||||
assert sld.tickInterval() == 0.3
|
||||
sld.setTickPosition(sld.TickPosition.TicksAbove)
|
||||
sld.show()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||
def test_press_move_release(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
# this fail on vertical came with pyside6.2 ... need to debug
|
||||
# still works in practice, but test fails to catch signals
|
||||
if sld.orientation() == Qt.Orientation.Vertical:
|
||||
pytest.xfail()
|
||||
|
||||
assert sld._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
opt = QStyleOptionSlider()
|
||||
sld.initStyleOption(opt)
|
||||
style = sld.style()
|
||||
hrect = style.subControlRect(
|
||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||
)
|
||||
handle_pos = sld.mapToGlobal(hrect.center())
|
||||
|
||||
with qtbot.waitSignal(sld.sliderPressed):
|
||||
qtbot.mousePress(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
assert sld._pressedControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
with qtbot.waitSignals([sld.sliderMoved, sld.valueChanged]):
|
||||
shift = (
|
||||
QPoint(0, -8)
|
||||
if sld.orientation() == Qt.Orientation.Vertical
|
||||
else QPoint(8, 0)
|
||||
)
|
||||
sld.mouseMoveEvent(_mouse_event(handle_pos + shift))
|
||||
|
||||
with qtbot.waitSignal(sld.sliderReleased):
|
||||
qtbot.mouseRelease(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
assert sld._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
sld.show()
|
||||
with qtbot.waitSignal(sld.sliderPressed):
|
||||
qtbot.mousePress(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
|
||||
@skip_on_linux_qt6
|
||||
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||
def test_hover(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
hrect = sld._handleRect(0)
|
||||
handle_pos = QPointF(sld.mapToGlobal(hrect.center()))
|
||||
|
||||
assert sld._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
sld.event(_hover_event(QEvent.Type.HoverEnter, handle_pos, QPointF(), sld))
|
||||
assert sld._hoverControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
sld.event(
|
||||
_hover_event(QEvent.Type.HoverLeave, QPointF(-1000, -1000), handle_pos, sld)
|
||||
)
|
||||
assert sld._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||
def test_wheel(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
with qtbot.waitSignal(sld.valueChanged):
|
||||
sld.wheelEvent(_wheel_event(120))
|
||||
|
||||
sld.wheelEvent(_wheel_event(0))
|
||||
|
||||
|
||||
def _assert_types(args: Iterable[Any], type_: type):
|
||||
# sourcery skip: comprehension-to-generator
|
||||
assert all(isinstance(v, type_) for v in args), "invalid type"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||
def test_rangeslider_signals(cls, orientation, qtbot):
|
||||
sld = cls(orientation)
|
||||
qtbot.addWidget(sld)
|
||||
|
||||
type_ = float if cls == QDoubleRangeSlider else int
|
||||
|
||||
mock = Mock()
|
||||
sld.valueChanged.connect(mock)
|
||||
with qtbot.waitSignal(sld.valueChanged):
|
||||
sld.setValue((20, 40))
|
||||
mock.assert_called_once_with((20, 40))
|
||||
_assert_types(mock.call_args.args, tuple)
|
||||
_assert_types(mock.call_args.args[0], type_)
|
||||
|
||||
mock = Mock()
|
||||
sld.rangeChanged.connect(mock)
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setMinimum(3)
|
||||
mock.assert_called_once_with(3, 99)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
mock.reset_mock()
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setMaximum(15)
|
||||
mock.assert_called_once_with(3, 15)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
|
||||
mock.reset_mock()
|
||||
with qtbot.waitSignal(sld.rangeChanged):
|
||||
sld.setRange(1, 2)
|
||||
mock.assert_called_once_with(1, 2)
|
||||
_assert_types(mock.call_args.args, type_)
|
||||
231
tests/zz_test_sliders/test_single_value_sliders.py
Normal file
231
tests/zz_test_sliders/test_single_value_sliders.py
Normal file
@@ -0,0 +1,231 @@
|
||||
import math
|
||||
import platform
|
||||
from contextlib import suppress
|
||||
|
||||
import pytest
|
||||
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
||||
from qtpy.QtWidgets import QSlider, QStyle, QStyleOptionSlider
|
||||
|
||||
from superqt import QDoubleSlider, QLabeledDoubleSlider, QLabeledSlider
|
||||
from superqt.sliders._generic_slider import _GenericSlider
|
||||
|
||||
from ._testutil import (
|
||||
QT_VERSION,
|
||||
_hover_event,
|
||||
_linspace,
|
||||
_mouse_event,
|
||||
_wheel_event,
|
||||
skip_on_linux_qt6,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[Qt.Orientation.Horizontal, Qt.Orientation.Vertical],
|
||||
ids=["horizontal", "vertical"],
|
||||
)
|
||||
def orientation(request):
|
||||
return request.param
|
||||
|
||||
|
||||
START_MI_MAX_VAL = (0, 99, 0)
|
||||
TEST_SLIDERS = [QDoubleSlider, QLabeledSlider, QLabeledDoubleSlider]
|
||||
|
||||
|
||||
def _assert_value_in_range(sld):
|
||||
val = sld.value()
|
||||
if isinstance(val, (int, float)):
|
||||
val = (val,)
|
||||
assert all(sld.minimum() <= v <= sld.maximum() for v in val)
|
||||
|
||||
|
||||
@pytest.fixture(params=TEST_SLIDERS)
|
||||
def sld(request, qtbot, orientation):
|
||||
Cls = request.param
|
||||
slider = Cls(orientation)
|
||||
slider.setRange(*START_MI_MAX_VAL[:2])
|
||||
slider.setValue(START_MI_MAX_VAL[2])
|
||||
qtbot.addWidget(slider)
|
||||
assert (slider.minimum(), slider.maximum(), slider.value()) == START_MI_MAX_VAL
|
||||
_assert_value_in_range(slider)
|
||||
yield slider
|
||||
_assert_value_in_range(slider)
|
||||
with suppress(AttributeError):
|
||||
slider.initStyleOption(QStyleOptionSlider())
|
||||
|
||||
|
||||
def called_with(*expected_result):
|
||||
"""Use in check_params_cbs to assert that a callback is called as expected.
|
||||
|
||||
e.g. `called_with(20, 50)` returns a callback that checks that the callback
|
||||
is called with the arguments (20, 50)
|
||||
"""
|
||||
|
||||
def check_emitted_values(*values):
|
||||
return values == expected_result
|
||||
|
||||
return check_emitted_values
|
||||
|
||||
|
||||
def test_change_floatslider_range(sld: _GenericSlider, qtbot):
|
||||
BOTH = [sld.rangeChanged, sld.valueChanged]
|
||||
|
||||
for signals, checks, funcname, args in [
|
||||
(BOTH, [called_with(10, 99), called_with(10)], "setMinimum", (10,)),
|
||||
([sld.rangeChanged], [called_with(10, 90)], "setMaximum", (90,)),
|
||||
(BOTH, [called_with(20, 40), called_with(20)], "setRange", (20, 40)),
|
||||
([sld.valueChanged], [called_with(30)], "setValue", (30,)),
|
||||
(BOTH, [called_with(20, 25), called_with(25)], "setMaximum", (25,)),
|
||||
([sld.valueChanged], [called_with(23)], "setValue", (23,)),
|
||||
]:
|
||||
with qtbot.waitSignals(signals, check_params_cbs=checks, timeout=500):
|
||||
getattr(sld, funcname)(*args)
|
||||
_assert_value_in_range(sld)
|
||||
|
||||
|
||||
def test_float_values(sld: _GenericSlider, qtbot):
|
||||
if type(sld) is QLabeledSlider:
|
||||
pytest.skip()
|
||||
for signals, checks, funcname, args in [
|
||||
(sld.rangeChanged, called_with(0.1, 0.9), "setRange", (0.1, 0.9)),
|
||||
(sld.valueChanged, called_with(0.4), "setValue", (0.4,)),
|
||||
(sld.valueChanged, called_with(0.1), "setValue", (0,)),
|
||||
(sld.valueChanged, called_with(0.9), "setValue", (1.9,)),
|
||||
]:
|
||||
with qtbot.waitSignal(signals, check_params_cb=checks, timeout=400):
|
||||
getattr(sld, funcname)(*args)
|
||||
_assert_value_in_range(sld)
|
||||
|
||||
|
||||
def test_ticks(sld: _GenericSlider, qtbot):
|
||||
sld.setTickInterval(3)
|
||||
assert sld.tickInterval() == 3
|
||||
sld.setTickPosition(QSlider.TickPosition.TicksAbove)
|
||||
sld.show()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.system() != "Darwin", reason="cross-platform is tricky")
|
||||
def test_press_move_release(sld: _GenericSlider, qtbot):
|
||||
if hasattr(sld, "_slider") and sld._slider.orientation() == Qt.Orientation.Vertical:
|
||||
pytest.xfail("test failing for vertical at the moment")
|
||||
# this fail on vertical came with pyside6.2 ... need to debug
|
||||
# still works in practice, but test fails to catch signals
|
||||
if sld.orientation() == Qt.Orientation.Vertical:
|
||||
pytest.xfail()
|
||||
|
||||
_real_sld = getattr(sld, "_slider", sld)
|
||||
|
||||
with suppress(AttributeError): # for QSlider
|
||||
assert _real_sld._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
opt = QStyleOptionSlider()
|
||||
_real_sld.initStyleOption(opt)
|
||||
style = _real_sld.style()
|
||||
hrect = style.subControlRect(
|
||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||
)
|
||||
handle_pos = _real_sld.mapToGlobal(hrect.center())
|
||||
|
||||
with qtbot.waitSignal(_real_sld.sliderPressed, timeout=300):
|
||||
qtbot.mousePress(_real_sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
with suppress(AttributeError):
|
||||
assert sld._pressedControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
with qtbot.waitSignals(
|
||||
[_real_sld.sliderMoved, _real_sld.valueChanged], timeout=300
|
||||
):
|
||||
shift = (
|
||||
QPoint(0, -8)
|
||||
if _real_sld.orientation() == Qt.Orientation.Vertical
|
||||
else QPoint(8, 0)
|
||||
)
|
||||
_real_sld.mouseMoveEvent(_mouse_event(handle_pos + shift))
|
||||
|
||||
with qtbot.waitSignal(_real_sld.sliderReleased, timeout=300):
|
||||
qtbot.mouseRelease(_real_sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
with suppress(AttributeError):
|
||||
assert _real_sld._pressedControl == QStyle.SubControl.SC_None
|
||||
|
||||
sld.show()
|
||||
with qtbot.waitSignal(_real_sld.sliderPressed, timeout=300):
|
||||
qtbot.mousePress(_real_sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||
|
||||
|
||||
@skip_on_linux_qt6
|
||||
def test_hover(sld: _GenericSlider):
|
||||
_real_sld = getattr(sld, "_slider", sld)
|
||||
|
||||
opt = QStyleOptionSlider()
|
||||
_real_sld.initStyleOption(opt)
|
||||
hrect = _real_sld.style().subControlRect(
|
||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||
)
|
||||
handle_pos = QPointF(sld.mapToGlobal(hrect.center()))
|
||||
|
||||
with suppress(AttributeError): # for QSlider
|
||||
assert _real_sld._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
_real_sld.event(_hover_event(QEvent.Type.HoverEnter, handle_pos, QPointF(), sld))
|
||||
with suppress(AttributeError): # for QSlider
|
||||
assert _real_sld._hoverControl == QStyle.SubControl.SC_SliderHandle
|
||||
|
||||
_real_sld.event(
|
||||
_hover_event(QEvent.Type.HoverLeave, QPointF(-1000, -1000), handle_pos, sld)
|
||||
)
|
||||
with suppress(AttributeError): # for QSlider
|
||||
assert _real_sld._hoverControl == QStyle.SubControl.SC_None
|
||||
|
||||
|
||||
def test_wheel(sld: _GenericSlider, qtbot):
|
||||
if type(sld) is QLabeledSlider and QT_VERSION < (5, 12):
|
||||
pytest.skip()
|
||||
|
||||
_real_sld = getattr(sld, "_slider", sld)
|
||||
with qtbot.waitSignal(sld.valueChanged, timeout=400):
|
||||
_real_sld.wheelEvent(_wheel_event(120))
|
||||
|
||||
_real_sld.wheelEvent(_wheel_event(0))
|
||||
|
||||
|
||||
def test_position(sld: _GenericSlider, qtbot):
|
||||
sld.setSliderPosition(21)
|
||||
assert sld.sliderPosition() == 21
|
||||
|
||||
if type(sld) is not QLabeledSlider:
|
||||
sld.setSliderPosition(21.5)
|
||||
assert sld.sliderPosition() == 21.5
|
||||
|
||||
|
||||
def test_steps(sld: _GenericSlider, qtbot):
|
||||
sld.setSingleStep(11)
|
||||
assert sld.singleStep() == 11
|
||||
|
||||
sld.setPageStep(16)
|
||||
assert sld.pageStep() == 16
|
||||
|
||||
if type(sld) is not QLabeledSlider:
|
||||
sld.setSingleStep(0.1)
|
||||
assert sld.singleStep() == 0.1
|
||||
|
||||
sld.setSingleStep(1.5e20)
|
||||
assert sld.singleStep() == 1.5e20
|
||||
|
||||
sld.setPageStep(0.2)
|
||||
assert sld.pageStep() == 0.2
|
||||
|
||||
sld.setPageStep(1.5e30)
|
||||
assert sld.pageStep() == 1.5e30
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mag", list(range(4, 37, 4)) + list(range(-4, -37, -4)))
|
||||
def test_slider_extremes(sld: _GenericSlider, mag, qtbot):
|
||||
if type(sld) is QLabeledSlider:
|
||||
pytest.skip()
|
||||
|
||||
_mag = 10**mag
|
||||
with qtbot.waitSignal(sld.rangeChanged, timeout=400):
|
||||
sld.setRange(-_mag, _mag)
|
||||
for i in _linspace(-_mag, _mag, 10):
|
||||
sld.setValue(i)
|
||||
assert math.isclose(sld.value(), i, rel_tol=1e-8)
|
||||
142
tests/zz_test_sliders/test_slider.py
Normal file
142
tests/zz_test_sliders/test_slider.py
Normal file
@@ -0,0 +1,142 @@
|
||||
import platform
|
||||
|
||||
import pytest
|
||||
from qtpy import API_NAME
|
||||
from qtpy.QtCore import Qt
|
||||
|
||||
from superqt import QRangeSlider
|
||||
from superqt.sliders._generic_range_slider import SC_BAR, SC_HANDLE, SC_NONE
|
||||
|
||||
LINUX = platform.system() == "Linux"
|
||||
NOT_PYQT6 = API_NAME != "PyQt6"
|
||||
|
||||
skipmouse = pytest.mark.skipif(LINUX or NOT_PYQT6, reason="mouse tests finicky")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("orientation", ["Horizontal", "Vertical"])
|
||||
def test_basic(qtbot, orientation):
|
||||
rs = QRangeSlider(getattr(Qt.Orientation, orientation))
|
||||
qtbot.addWidget(rs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("orientation", ["Horizontal", "Vertical"])
|
||||
def test_value(qtbot, orientation):
|
||||
rs = QRangeSlider(getattr(Qt.Orientation, orientation))
|
||||
qtbot.addWidget(rs)
|
||||
rs.setValue([10, 20])
|
||||
assert rs.value() == (10, 20)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("orientation", ["Horizontal", "Vertical"])
|
||||
def test_range(qtbot, orientation):
|
||||
rs = QRangeSlider(getattr(Qt.Orientation, orientation))
|
||||
qtbot.addWidget(rs)
|
||||
rs.setValue([10, 20])
|
||||
assert rs.value() == (10, 20)
|
||||
rs.setRange(15, 20)
|
||||
assert rs.value() == (15, 20)
|
||||
assert rs.minimum() == 15
|
||||
assert rs.maximum() == 20
|
||||
|
||||
|
||||
@skipmouse
|
||||
def test_drag_handles(qtbot):
|
||||
rs = QRangeSlider(Qt.Orientation.Horizontal)
|
||||
qtbot.addWidget(rs)
|
||||
rs.setRange(0, 99)
|
||||
rs.setValue((20, 80))
|
||||
rs.setMouseTracking(True)
|
||||
rs.show()
|
||||
|
||||
# press the left handle
|
||||
pos = rs._handleRect(0).center()
|
||||
with qtbot.waitSignal(rs.sliderPressed):
|
||||
qtbot.mousePress(rs, Qt.MouseButton.LeftButton, pos=pos)
|
||||
assert rs._pressedControl == SC_HANDLE
|
||||
assert rs._pressedIndex == 0
|
||||
|
||||
# drag the left handle
|
||||
with qtbot.waitSignals([rs.sliderMoved] * 13): # couple less signals
|
||||
for _ in range(15):
|
||||
pos.setX(pos.x() + 2)
|
||||
qtbot.mouseMove(rs, pos)
|
||||
|
||||
with qtbot.waitSignal(rs.sliderReleased):
|
||||
qtbot.mouseRelease(rs, Qt.MouseButton.LeftButton)
|
||||
|
||||
# check the values
|
||||
assert rs.value()[0] > 30
|
||||
assert rs._pressedControl == SC_NONE
|
||||
|
||||
# press the right handle
|
||||
pos = rs._handleRect(1).center()
|
||||
with qtbot.waitSignal(rs.sliderPressed):
|
||||
qtbot.mousePress(rs, Qt.MouseButton.LeftButton, pos=pos)
|
||||
assert rs._pressedControl == SC_HANDLE
|
||||
assert rs._pressedIndex == 1
|
||||
|
||||
# drag the right handle
|
||||
with qtbot.waitSignals([rs.sliderMoved] * 13): # couple less signals
|
||||
for _ in range(15):
|
||||
pos.setX(pos.x() - 2)
|
||||
qtbot.mouseMove(rs, pos)
|
||||
with qtbot.waitSignal(rs.sliderReleased):
|
||||
qtbot.mouseRelease(rs, Qt.MouseButton.LeftButton)
|
||||
|
||||
# check the values
|
||||
assert rs.value()[1] < 70
|
||||
assert rs._pressedControl == SC_NONE
|
||||
|
||||
|
||||
@skipmouse
|
||||
def test_drag_handles_beyond_edge(qtbot):
|
||||
rs = QRangeSlider(Qt.Orientation.Horizontal)
|
||||
qtbot.addWidget(rs)
|
||||
rs.setRange(0, 99)
|
||||
rs.setValue((20, 80))
|
||||
rs.setMouseTracking(True)
|
||||
rs.show()
|
||||
|
||||
# press the right handle
|
||||
pos = rs._handleRect(1).center()
|
||||
with qtbot.waitSignal(rs.sliderPressed):
|
||||
qtbot.mousePress(rs, Qt.MouseButton.LeftButton, pos=pos)
|
||||
assert rs._pressedControl == SC_HANDLE
|
||||
assert rs._pressedIndex == 1
|
||||
|
||||
# drag the handle off the right edge and make sure the value gets to the max
|
||||
for _ in range(7):
|
||||
pos.setX(pos.x() + 10)
|
||||
qtbot.mouseMove(rs, pos)
|
||||
|
||||
with qtbot.waitSignal(rs.sliderReleased):
|
||||
qtbot.mouseRelease(rs, Qt.MouseButton.LeftButton)
|
||||
|
||||
assert rs.value()[1] == 99
|
||||
|
||||
|
||||
@skipmouse
|
||||
def test_bar_drag_beyond_edge(qtbot):
|
||||
rs = QRangeSlider(Qt.Orientation.Horizontal)
|
||||
qtbot.addWidget(rs)
|
||||
rs.setRange(0, 99)
|
||||
rs.setValue((20, 80))
|
||||
rs.setMouseTracking(True)
|
||||
rs.show()
|
||||
|
||||
# press the right handle
|
||||
pos = rs.rect().center()
|
||||
with qtbot.waitSignal(rs.sliderPressed):
|
||||
qtbot.mousePress(rs, Qt.MouseButton.LeftButton, pos=pos)
|
||||
assert rs._pressedControl == SC_BAR
|
||||
assert rs._pressedIndex == 1
|
||||
|
||||
# drag the handle off the right edge and make sure the value gets to the max
|
||||
for _ in range(15):
|
||||
pos.setX(pos.x() + 10)
|
||||
qtbot.mouseMove(rs, pos)
|
||||
|
||||
with qtbot.waitSignal(rs.sliderReleased):
|
||||
qtbot.mouseRelease(rs, Qt.MouseButton.LeftButton)
|
||||
|
||||
assert rs.value()[1] == 99
|
||||
Reference in New Issue
Block a user