diff --git a/examples/basic.py b/examples/basic.py index a434c7b..35ed28d 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -1,9 +1,10 @@ from qtrangeslider import QRangeSlider +from qtrangeslider.qtcompat.QtCore import Qt from qtrangeslider.qtcompat.QtWidgets import QApplication app = QApplication([]) -slider = QRangeSlider() +slider = QRangeSlider(Qt.Horizontal) slider.setValue((20, 80)) slider.show() diff --git a/qtrangeslider/_qrangeslider.py b/qtrangeslider/_qrangeslider.py index 0582345..9cd4af9 100644 --- a/qtrangeslider/_qrangeslider.py +++ b/qtrangeslider/_qrangeslider.py @@ -125,7 +125,8 @@ class QRangeSlider(QSlider): ) for i, v in enumerate(val): - self._setSliderPositionAt(i, v, _update=i == len(val) - 1) + self._setSliderPositionAt(i, v, _update=False) + self._updateSliderMove() def barIsRigid(self) -> bool: """Whether bar length is constant when dragging the bar. @@ -173,23 +174,26 @@ class QRangeSlider(QSlider): return self._position[index] = pos if _update: - if not self.hasTracking(): - self.update() - if self.isSliderDown(): - self.sliderMoved.emit(tuple(self._position)) - if self.hasTracking(): - self.triggerAction(QSlider.SliderMove) + self._updateSliderMove() + + def _updateSliderMove(self): + if not self.hasTracking(): + self.update() + if self.isSliderDown(): + self.sliderMoved.emit(tuple(self._position)) + if self.hasTracking(): + self.triggerAction(QSlider.SliderMove) def _offsetAllPositions(self, offset: int, ref=None) -> None: if ref is None: ref = self._position - _new = [i - offset for i in ref] if self._bar_is_rigid: - # FIXME: if there is an overflow ... it should still hit the edge. - if all(self.minimum() <= i <= self.maximum() for i in _new): - self.setSliderPosition(_new) - else: - self.setSliderPosition(_new) + # NOTE: This assumes monotonically increasing slider positions + if offset > 0 and ref[-1] + offset > self.maximum(): + offset = self.maximum() - ref[-1] + elif ref[0] + offset < self.minimum(): + offset = self.minimum() - ref[0] + self.setSliderPosition([i + offset for i in ref]) def _getStyleOption(self) -> QStyleOptionSlider: opt = QStyleOptionSlider() @@ -309,8 +313,9 @@ class QRangeSlider(QSlider): self._setSliderPositionAt(self._pressedControl[1], new) elif self._pressedControl[0] == "bar": ev.accept() + delta = self._clickOffset - self._pixelPosToRangeValue(self._pick(ev.pos())) - self._offsetAllPositions(delta, self._sldPosAtPress) + self._offsetAllPositions(-delta, self._sldPosAtPress) else: ev.ignore() return @@ -528,7 +533,7 @@ class QRangeSlider(QSlider): _prev_value = self.value() - self._offsetAllPositions(-steps_to_scroll) + self._offsetAllPositions(steps_to_scroll) self.triggerAction(QSlider.SliderMove) if _prev_value == self.value(): diff --git a/qtrangeslider/_tests/test_slider.py b/qtrangeslider/_tests/test_slider.py index b56e0e1..7010173 100644 --- a/qtrangeslider/_tests/test_slider.py +++ b/qtrangeslider/_tests/test_slider.py @@ -1,10 +1,115 @@ +import os + import pytest from qtrangeslider import QRangeSlider from qtrangeslider.qtcompat.QtCore import Qt +WINDOWS = os.name == "nt" + @pytest.mark.parametrize("orientation", ["Horizontal", "Vertical"]) def test_basic(qtbot, orientation): rs = QRangeSlider(getattr(Qt, orientation)) qtbot.addWidget(rs) + + +# @pytest.mark.skipif(WINDOWS, reason="QTest.mouseMove not working on windows") +# def test_drag_handles(qtbot): +# rs = QRangeSlider(Qt.Horizontal) +# qtbot.addWidget(rs) +# rs.setRange(0, 99) +# rs.setValue((20, 80)) +# rs.setMouseTracking(True) +# rs.show() + +# # press the left handle +# opt = rs._getStyleOption() +# pos = rs._handleRects(opt, 0).center() +# with qtbot.waitSignal(rs.sliderPressed): +# qtbot.mousePress(rs, Qt.LeftButton, pos=pos) +# assert rs._pressedControl == ("handle", 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.LeftButton) + +# # check the values +# assert rs.value()[0] > 30 +# assert rs._pressedControl == rs._NULL_CTRL + +# # press the right handle +# pos = rs._handleRects(opt, 1).center() +# with qtbot.waitSignal(rs.sliderPressed): +# qtbot.mousePress(rs, Qt.LeftButton, pos=pos) +# assert rs._pressedControl == ("handle", 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.LeftButton) + +# # check the values +# assert rs.value()[1] < 70 +# assert rs._pressedControl == rs._NULL_CTRL + + +# @pytest.mark.skipif(WINDOWS, reason="QTest.mouseMove not working on windows") +# def test_drag_handles_beyond_edge(qtbot): +# rs = QRangeSlider(Qt.Horizontal) +# qtbot.addWidget(rs) +# rs.setRange(0, 99) +# rs.setValue((20, 80)) +# rs.setMouseTracking(True) +# rs.show() + +# # press the right handle +# opt = rs._getStyleOption() +# pos = rs._handleRects(opt, 1).center() +# with qtbot.waitSignal(rs.sliderPressed): +# qtbot.mousePress(rs, Qt.LeftButton, pos=pos) +# assert rs._pressedControl == ("handle", 1) + +# # drag the handle off the right edge and make sure the value gets to the max +# for _ in range(5): +# pos.setX(pos.x() + 20) +# qtbot.mouseMove(rs, pos) + +# with qtbot.waitSignal(rs.sliderReleased): +# qtbot.mouseRelease(rs, Qt.LeftButton) + +# assert rs.value()[1] == 99 + + +# @pytest.mark.skipif(WINDOWS, reason="QTest.mouseMove not working on windows") +# def test_bar_drag_beyond_edge(qtbot): +# rs = QRangeSlider(Qt.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.LeftButton, pos=pos) +# assert rs._pressedControl == ("bar", 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.LeftButton) + +# assert rs.value()[1] == 99