mirror of
https://github.com/pyapp-kit/superqt.git
synced 2026-01-04 19:31:24 +01:00
fix: Fix TypeError on slider rangeChanged signal (#121)
* fix: fix sliders type signals * test: more tests * fix for pyside2 * skip type check on py37
This commit is contained in:
@@ -44,9 +44,9 @@ QOVERFLOW = 2**31 - 1
|
|||||||
|
|
||||||
|
|
||||||
class _GenericSlider(QSlider, Generic[_T]):
|
class _GenericSlider(QSlider, Generic[_T]):
|
||||||
_fvalueChanged = Signal(float)
|
_fvalueChanged = Signal(int)
|
||||||
_fsliderMoved = Signal(float)
|
_fsliderMoved = Signal(int)
|
||||||
_frangeChanged = Signal(float, float)
|
_frangeChanged = Signal(int, int)
|
||||||
|
|
||||||
MAX_DISPLAY = 5000
|
MAX_DISPLAY = 5000
|
||||||
|
|
||||||
@@ -134,8 +134,8 @@ class _GenericSlider(QSlider, Generic[_T]):
|
|||||||
self.setRange(min(self._minimum, max), max)
|
self.setRange(min(self._minimum, max), max)
|
||||||
|
|
||||||
def setRange(self, min: float, max_: float) -> None:
|
def setRange(self, min: float, max_: float) -> None:
|
||||||
oldMin, self._minimum = self._minimum, float(min)
|
oldMin, self._minimum = self._minimum, self._type_cast(min)
|
||||||
oldMax, self._maximum = self._maximum, float(max(min, max_))
|
oldMax, self._maximum = self._maximum, self._type_cast(max(min, max_))
|
||||||
|
|
||||||
if oldMin != self._minimum or oldMax != self._maximum:
|
if oldMin != self._minimum or oldMax != self._maximum:
|
||||||
self.sliderChange(self.SliderChange.SliderRangeChange)
|
self.sliderChange(self.SliderChange.SliderRangeChange)
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class _IntMixin:
|
|||||||
|
|
||||||
|
|
||||||
class _FloatMixin:
|
class _FloatMixin:
|
||||||
|
_fvalueChanged = Signal(float)
|
||||||
|
_fsliderMoved = Signal(float)
|
||||||
|
_frangeChanged = Signal(float, float)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._singleStep = 0.01
|
self._singleStep = 0.01
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ def _hover_event(_type, position, old_position, widget=None):
|
|||||||
return QHoverEvent(_type, position, old_position)
|
return QHoverEvent(_type, position, old_position)
|
||||||
|
|
||||||
|
|
||||||
def _linspace(start, stop, n):
|
def _linspace(start: int, stop: int, n: int):
|
||||||
h = (stop - start) / (n - 1)
|
h = (stop - start) / (n - 1)
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
yield start + h * i
|
yield start + h * i
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import math
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from qtpy import API_NAME
|
from qtpy import API_NAME
|
||||||
|
from qtpy.QtWidgets import QStyleOptionSlider
|
||||||
|
|
||||||
from superqt import (
|
from superqt import (
|
||||||
QDoubleRangeSlider,
|
QDoubleRangeSlider,
|
||||||
@@ -10,6 +12,8 @@ from superqt import (
|
|||||||
QLabeledDoubleSlider,
|
QLabeledDoubleSlider,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ._testutil import _linspace
|
||||||
|
|
||||||
range_types = {QDoubleRangeSlider, QLabeledDoubleRangeSlider}
|
range_types = {QDoubleRangeSlider, QLabeledDoubleRangeSlider}
|
||||||
|
|
||||||
|
|
||||||
@@ -122,3 +126,15 @@ def test_signals(ds, qtbot):
|
|||||||
|
|
||||||
with qtbot.waitSignal(ds.rangeChanged):
|
with qtbot.waitSignal(ds.rangeChanged):
|
||||||
ds.setRange(1.2, 3.3)
|
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())
|
||||||
|
|||||||
@@ -7,13 +7,7 @@ from qtpy.QtWidgets import QStyle, QStyleOptionSlider
|
|||||||
|
|
||||||
from superqt.sliders._generic_slider import _GenericSlider, _sliderValueFromPosition
|
from superqt.sliders._generic_slider import _GenericSlider, _sliderValueFromPosition
|
||||||
|
|
||||||
from ._testutil import (
|
from ._testutil import _hover_event, _mouse_event, _wheel_event, skip_on_linux_qt6
|
||||||
_hover_event,
|
|
||||||
_linspace,
|
|
||||||
_mouse_event,
|
|
||||||
_wheel_event,
|
|
||||||
skip_on_linux_qt6,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=[Qt.Orientation.Horizontal, Qt.Orientation.Vertical])
|
@pytest.fixture(params=[Qt.Orientation.Horizontal, Qt.Orientation.Vertical])
|
||||||
@@ -169,17 +163,6 @@ def test_steps(gslider: _GenericSlider, qtbot):
|
|||||||
assert gslider.pageStep() == 1.5e30
|
assert gslider.pageStep() == 1.5e30
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mag", list(range(4, 37, 4)) + list(range(-4, -37, -4)))
|
|
||||||
def test_slider_extremes(gslider: _GenericSlider, mag, qtbot):
|
|
||||||
_mag = 10**mag
|
|
||||||
with qtbot.waitSignal(gslider.rangeChanged):
|
|
||||||
gslider.setRange(-_mag, _mag)
|
|
||||||
for i in _linspace(-_mag, _mag, 10):
|
|
||||||
gslider.setValue(i)
|
|
||||||
assert math.isclose(gslider.value(), i, rel_tol=1e-8)
|
|
||||||
gslider.initStyleOption(QStyleOptionSlider())
|
|
||||||
|
|
||||||
|
|
||||||
# args are (min: float, max: float, position: int, span: int, upsideDown: bool)
|
# args are (min: float, max: float, position: int, span: int, upsideDown: bool)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"args, result",
|
"args, result",
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
from superqt import QLabeledRangeSlider, QLabeledSlider
|
import sys
|
||||||
|
from typing import Any, Iterable
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from superqt import QLabeledDoubleSlider, QLabeledRangeSlider, QLabeledSlider
|
||||||
|
|
||||||
|
|
||||||
def test_labeled_slider_api(qtbot):
|
def test_labeled_slider_api(qtbot):
|
||||||
@@ -16,3 +22,43 @@ def test_slider_connect_works(qtbot):
|
|||||||
qtbot.addWidget(slider)
|
qtbot.addWidget(slider)
|
||||||
|
|
||||||
slider._label.editingFinished.emit()
|
slider._label.editingFinished.emit()
|
||||||
|
|
||||||
|
|
||||||
|
def _assert_types(args: Iterable[Any], type_: type):
|
||||||
|
# sourcery skip: comprehension-to-generator
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
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_)
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import math
|
import math
|
||||||
|
import sys
|
||||||
|
from itertools import product
|
||||||
|
from typing import Any, Iterable
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
from qtpy.QtCore import QEvent, QPoint, QPointF, Qt
|
||||||
from qtpy.QtWidgets import QStyle, QStyleOptionSlider
|
from qtpy.QtWidgets import QStyle, QStyleOptionSlider
|
||||||
|
|
||||||
from superqt import QDoubleRangeSlider, QRangeSlider
|
from superqt import QDoubleRangeSlider, QLabeledRangeSlider, QRangeSlider
|
||||||
|
|
||||||
from ._testutil import (
|
from ._testutil import (
|
||||||
_hover_event,
|
_hover_event,
|
||||||
@@ -14,161 +18,240 @@ from ._testutil import (
|
|||||||
skip_on_linux_qt6,
|
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.fixture(params=[Qt.Orientation.Horizontal, Qt.Orientation.Vertical])
|
|
||||||
def gslider(qtbot, request):
|
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||||
slider = QDoubleRangeSlider(request.param)
|
def test_slider_init(qtbot, cls, orientation):
|
||||||
qtbot.addWidget(slider)
|
slider = cls(orientation)
|
||||||
assert slider.value() == (20, 80)
|
assert slider.value() == (20, 80)
|
||||||
assert slider.minimum() == 0
|
assert slider.minimum() == 0
|
||||||
assert slider.maximum() == 99
|
assert slider.maximum() == 99
|
||||||
yield slider
|
slider.show()
|
||||||
slider.initStyleOption(QStyleOptionSlider())
|
qtbot.addWidget(slider)
|
||||||
|
|
||||||
|
|
||||||
def test_change_floatslider_range(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
def test_change_floatslider_range(cls, orientation, qtbot):
|
||||||
gslider.setMinimum(30)
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
assert gslider.value()[0] == 30 == gslider.minimum()
|
with qtbot.waitSignals([sld.rangeChanged, sld.valueChanged]):
|
||||||
assert gslider.maximum() == 99
|
sld.setMinimum(30)
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.rangeChanged):
|
assert sld.value()[0] == 30 == sld.minimum()
|
||||||
gslider.setMaximum(70)
|
assert sld.maximum() == 99
|
||||||
assert gslider.value()[0] == 30 == gslider.minimum()
|
|
||||||
assert gslider.value()[1] == 70 == gslider.maximum()
|
|
||||||
|
|
||||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
with qtbot.waitSignal(sld.rangeChanged):
|
||||||
gslider.setRange(40, 60)
|
sld.setMaximum(70)
|
||||||
assert gslider.value()[0] == 40 == gslider.minimum()
|
assert sld.value()[0] == 30 == sld.minimum()
|
||||||
assert gslider.maximum() == 60
|
assert sld.value()[1] == 70 == sld.maximum()
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.valueChanged):
|
with qtbot.waitSignals([sld.rangeChanged, sld.valueChanged]):
|
||||||
gslider.setValue([40, 50])
|
sld.setRange(40, 60)
|
||||||
assert gslider.value()[0] == 40 == gslider.minimum()
|
assert sld.value()[0] == 40 == sld.minimum()
|
||||||
assert gslider.value()[1] == 50
|
assert sld.maximum() == 60
|
||||||
|
|
||||||
with qtbot.waitSignals([gslider.rangeChanged, gslider.valueChanged]):
|
with qtbot.waitSignal(sld.valueChanged):
|
||||||
gslider.setMaximum(45)
|
sld.setValue([40, 50])
|
||||||
assert gslider.value()[0] == 40 == gslider.minimum()
|
assert sld.value()[0] == 40 == sld.minimum()
|
||||||
assert gslider.value()[1] == 45 == gslider.maximum()
|
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()
|
||||||
|
|
||||||
|
|
||||||
def test_float_values(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||||
with qtbot.waitSignal(gslider.rangeChanged):
|
def test_float_values(cls, orientation, qtbot):
|
||||||
gslider.setRange(0.1, 0.9)
|
sld = cls(orientation)
|
||||||
assert gslider.minimum() == 0.1
|
qtbot.addWidget(sld)
|
||||||
assert gslider.maximum() == 0.9
|
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.valueChanged):
|
with qtbot.waitSignal(sld.rangeChanged):
|
||||||
gslider.setValue([0.4, 0.6])
|
sld.setRange(0.1, 0.9)
|
||||||
assert gslider.value() == (0.4, 0.6)
|
assert sld.minimum() == 0.1
|
||||||
|
assert sld.maximum() == 0.9
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.valueChanged):
|
with qtbot.waitSignal(sld.valueChanged):
|
||||||
gslider.setValue([0, 1.9])
|
sld.setValue([0.4, 0.6])
|
||||||
assert gslider.value()[0] == 0.1 == gslider.minimum()
|
assert sld.value() == (0.4, 0.6)
|
||||||
assert gslider.value()[1] == 0.9 == gslider.maximum()
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
def test_position(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||||
gslider.setSliderPosition([10, 80])
|
def test_position(cls, orientation, qtbot):
|
||||||
assert gslider.sliderPosition() == (10, 80)
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
|
sld.setSliderPosition([10, 80])
|
||||||
|
assert sld.sliderPosition() == (10, 80)
|
||||||
|
|
||||||
|
|
||||||
def test_steps(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||||
gslider.setSingleStep(0.1)
|
def test_steps(cls, orientation, qtbot):
|
||||||
assert gslider.singleStep() == 0.1
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
gslider.setSingleStep(1.5e20)
|
sld.setSingleStep(0.1)
|
||||||
assert gslider.singleStep() == 1.5e20
|
assert sld.singleStep() == 0.1
|
||||||
|
|
||||||
gslider.setPageStep(0.2)
|
sld.setSingleStep(1.5e20)
|
||||||
assert gslider.pageStep() == 0.2
|
assert sld.singleStep() == 1.5e20
|
||||||
|
|
||||||
gslider.setPageStep(1.5e30)
|
sld.setPageStep(0.2)
|
||||||
assert gslider.pageStep() == 1.5e30
|
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("mag", list(range(4, 37, 4)) + list(range(-4, -37, -4)))
|
||||||
def test_slider_extremes(gslider: QRangeSlider, mag, qtbot):
|
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||||
|
def test_slider_extremes(cls, orientation, qtbot, mag):
|
||||||
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
_mag = 10**mag
|
_mag = 10**mag
|
||||||
with qtbot.waitSignal(gslider.rangeChanged):
|
with qtbot.waitSignal(sld.rangeChanged):
|
||||||
gslider.setRange(-_mag, _mag)
|
sld.setRange(-_mag, _mag)
|
||||||
for i in _linspace(-_mag, _mag, 10):
|
for i in _linspace(-_mag, _mag, 10):
|
||||||
gslider.setValue((i, _mag))
|
sld.setValue((i, _mag))
|
||||||
assert math.isclose(gslider.value()[0], i, rel_tol=1e-8)
|
assert math.isclose(sld.value()[0], i, rel_tol=0.0001)
|
||||||
gslider.initStyleOption(QStyleOptionSlider())
|
sld.initStyleOption(QStyleOptionSlider())
|
||||||
|
|
||||||
|
|
||||||
def test_ticks(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", ALL_SLIDER_COMBOS)
|
||||||
gslider.setTickInterval(0.3)
|
def test_ticks(cls, orientation, qtbot):
|
||||||
assert gslider.tickInterval() == 0.3
|
sld = cls(orientation)
|
||||||
gslider.setTickPosition(gslider.TickPosition.TicksAbove)
|
qtbot.addWidget(sld)
|
||||||
gslider.show()
|
|
||||||
|
sld.setTickInterval(0.3)
|
||||||
|
assert sld.tickInterval() == 0.3
|
||||||
|
sld.setTickPosition(sld.TickPosition.TicksAbove)
|
||||||
|
sld.show()
|
||||||
|
|
||||||
|
|
||||||
def test_show(gslider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||||
gslider.show()
|
def test_press_move_release(cls, orientation, qtbot):
|
||||||
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
|
|
||||||
def test_press_move_release(gslider: QRangeSlider, qtbot):
|
|
||||||
# this fail on vertical came with pyside6.2 ... need to debug
|
# this fail on vertical came with pyside6.2 ... need to debug
|
||||||
# still works in practice, but test fails to catch signals
|
# still works in practice, but test fails to catch signals
|
||||||
if gslider.orientation() == Qt.Orientation.Vertical:
|
if sld.orientation() == Qt.Orientation.Vertical:
|
||||||
pytest.xfail()
|
pytest.xfail()
|
||||||
|
|
||||||
assert gslider._pressedControl == QStyle.SubControl.SC_None
|
assert sld._pressedControl == QStyle.SubControl.SC_None
|
||||||
|
|
||||||
opt = QStyleOptionSlider()
|
opt = QStyleOptionSlider()
|
||||||
gslider.initStyleOption(opt)
|
sld.initStyleOption(opt)
|
||||||
style = gslider.style()
|
style = sld.style()
|
||||||
hrect = style.subControlRect(
|
hrect = style.subControlRect(
|
||||||
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
QStyle.ComplexControl.CC_Slider, opt, QStyle.SubControl.SC_SliderHandle
|
||||||
)
|
)
|
||||||
handle_pos = gslider.mapToGlobal(hrect.center())
|
handle_pos = sld.mapToGlobal(hrect.center())
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.sliderPressed):
|
with qtbot.waitSignal(sld.sliderPressed):
|
||||||
qtbot.mousePress(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
qtbot.mousePress(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||||
|
|
||||||
assert gslider._pressedControl == QStyle.SubControl.SC_SliderHandle
|
assert sld._pressedControl == QStyle.SubControl.SC_SliderHandle
|
||||||
|
|
||||||
with qtbot.waitSignals([gslider.sliderMoved, gslider.valueChanged]):
|
with qtbot.waitSignals([sld.sliderMoved, sld.valueChanged]):
|
||||||
shift = (
|
shift = (
|
||||||
QPoint(0, -8)
|
QPoint(0, -8)
|
||||||
if gslider.orientation() == Qt.Orientation.Vertical
|
if sld.orientation() == Qt.Orientation.Vertical
|
||||||
else QPoint(8, 0)
|
else QPoint(8, 0)
|
||||||
)
|
)
|
||||||
gslider.mouseMoveEvent(_mouse_event(handle_pos + shift))
|
sld.mouseMoveEvent(_mouse_event(handle_pos + shift))
|
||||||
|
|
||||||
with qtbot.waitSignal(gslider.sliderReleased):
|
with qtbot.waitSignal(sld.sliderReleased):
|
||||||
qtbot.mouseRelease(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
qtbot.mouseRelease(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||||
|
|
||||||
assert gslider._pressedControl == QStyle.SubControl.SC_None
|
assert sld._pressedControl == QStyle.SubControl.SC_None
|
||||||
|
|
||||||
gslider.show()
|
sld.show()
|
||||||
with qtbot.waitSignal(gslider.sliderPressed):
|
with qtbot.waitSignal(sld.sliderPressed):
|
||||||
qtbot.mousePress(gslider, Qt.MouseButton.LeftButton, pos=handle_pos)
|
qtbot.mousePress(sld, Qt.MouseButton.LeftButton, pos=handle_pos)
|
||||||
|
|
||||||
|
|
||||||
@skip_on_linux_qt6
|
@skip_on_linux_qt6
|
||||||
def test_hover(gslider: QRangeSlider):
|
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||||
|
def test_hover(cls, orientation, qtbot):
|
||||||
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
hrect = gslider._handleRect(0)
|
hrect = sld._handleRect(0)
|
||||||
handle_pos = QPointF(gslider.mapToGlobal(hrect.center()))
|
handle_pos = QPointF(sld.mapToGlobal(hrect.center()))
|
||||||
|
|
||||||
assert gslider._hoverControl == QStyle.SubControl.SC_None
|
assert sld._hoverControl == QStyle.SubControl.SC_None
|
||||||
|
|
||||||
gslider.event(_hover_event(QEvent.Type.HoverEnter, handle_pos, QPointF(), gslider))
|
sld.event(_hover_event(QEvent.Type.HoverEnter, handle_pos, QPointF(), sld))
|
||||||
assert gslider._hoverControl == QStyle.SubControl.SC_SliderHandle
|
assert sld._hoverControl == QStyle.SubControl.SC_SliderHandle
|
||||||
|
|
||||||
gslider.event(
|
sld.event(
|
||||||
_hover_event(QEvent.Type.HoverLeave, QPointF(-1000, -1000), handle_pos, gslider)
|
_hover_event(QEvent.Type.HoverLeave, QPointF(-1000, -1000), handle_pos, sld)
|
||||||
)
|
)
|
||||||
assert gslider._hoverControl == QStyle.SubControl.SC_None
|
assert sld._hoverControl == QStyle.SubControl.SC_None
|
||||||
|
|
||||||
|
|
||||||
def test_wheel(gslider: QRangeSlider, qtbot):
|
@pytest.mark.parametrize("cls, orientation", FLOAT_SLIDERS)
|
||||||
with qtbot.waitSignal(gslider.valueChanged):
|
def test_wheel(cls, orientation, qtbot):
|
||||||
gslider.wheelEvent(_wheel_event(120))
|
sld = cls(orientation)
|
||||||
|
qtbot.addWidget(sld)
|
||||||
|
|
||||||
gslider.wheelEvent(_wheel_event(0))
|
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
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
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_)
|
||||||
|
|||||||
Reference in New Issue
Block a user