Compare commits

...

3 Commits

Author SHA1 Message Date
Talley Lambert
f364e52706 Merge 4c5c0fbea2 into 9ca0bbf858 2024-05-04 21:09:16 -04:00
Talley Lambert
4c5c0fbea2 remove comment 2024-05-04 21:09:01 -04:00
Talley Lambert
ea93c046af merge in fixes 2024-05-04 17:05:55 -04:00
3 changed files with 50 additions and 22 deletions

View File

@@ -124,11 +124,27 @@ class _GenericRangeSlider(_GenericSlider):
"""
return tuple(float(i) for i in self._position)
def setSliderPosition(self, pos: Union[float, Sequence[float]], index=None) -> None:
def setSliderPosition( # type: ignore
self,
pos: Union[float, Sequence[float]],
index: int | None = None,
*,
reversed: bool = False,
) -> None:
"""Set current position of the handles with a sequence of integers.
If `pos` is a sequence, it must have the same length as `value()`.
If it is a scalar, index will be
Parameters
----------
pos : Union[float, Sequence[float]]
The new position of the slider handle(s). If a sequence, it must have the
same length as `value()`. If it is a scalar, index will be used to set the
position of the handle at that index.
index : int | None
The index of the handle to set the position of. If None, the "pressedIndex"
will be used.
reversed : bool
Order in which to set the positions. Can be useful when setting multiple
positions, to avoid intermediate overlapping values.
"""
if isinstance(pos, (list, tuple)):
val_len = len(self.value())
@@ -139,6 +155,9 @@ class _GenericRangeSlider(_GenericSlider):
else:
pairs = [(self._pressedIndex if index is None else index, pos)]
if reversed:
pairs = pairs[::-1]
for idx, position in pairs:
self._position[idx] = self._bound(position, idx)
@@ -222,7 +241,7 @@ class _GenericRangeSlider(_GenericSlider):
offset = self.maximum() - ref[-1]
elif ref[0] + offset < self.minimum():
offset = self.minimum() - ref[0]
self.setSliderPosition([i + offset for i in ref])
self.setSliderPosition([i + offset for i in ref], reversed=offset > 0)
def _fixStyleOption(self, option):
pass

View File

@@ -31,6 +31,7 @@ class LabelPosition(IntEnum):
LabelsBelow = auto()
LabelsRight = LabelsAbove
LabelsLeft = LabelsBelow
LabelsOnHandle = auto()
class EdgeLabelMode(IntFlag):
@@ -42,10 +43,10 @@ class EdgeLabelMode(IntFlag):
class _SliderProxy:
_slider: QSlider
def value(self) -> int:
def value(self) -> Any:
return self._slider.value()
def setValue(self, value: int) -> None:
def setValue(self, value: Any) -> None:
self._slider.setValue(value)
def sliderPosition(self) -> int:
@@ -157,6 +158,9 @@ def _handle_overloaded_slider_sig(
class QLabeledSlider(_SliderProxy, QAbstractSlider):
editingFinished = Signal()
_ivalueChanged = Signal(int)
_isliderMoved = Signal(int)
_irangeChanged = Signal(int, int)
_slider_class = QSlider
_slider: QSlider
@@ -276,8 +280,9 @@ class QLabeledSlider(_SliderProxy, QAbstractSlider):
self._slider.setValue(int(value))
def _rename_signals(self) -> None:
# for subclasses
pass
self.valueChanged = self._ivalueChanged
self.sliderMoved = self._isliderMoved
self.rangeChanged = self._irangeChanged
class QLabeledDoubleSlider(QLabeledSlider):
@@ -383,10 +388,10 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
"""Set where/whether labels are shown adjacent to slider handles."""
self._handle_label_position = opt
for lbl in self._handle_labels:
if not opt:
lbl.hide()
else:
lbl.show()
lbl.setVisible(bool(opt))
trans = opt == LabelPosition.LabelsOnHandle
# TODO: make double clickable to edit
lbl.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, trans)
self.setOrientation(self.orientation())
def edgeLabelMode(self) -> EdgeLabelMode:
@@ -430,6 +435,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
"""Set orientation, value will be 'horizontal' or 'vertical'."""
self._slider.setOrientation(orientation)
inverted = self._slider.invertedAppearance()
marg = (0, 0, 0, 0)
if orientation == Qt.Orientation.Vertical:
layout: QBoxLayout = QVBoxLayout()
layout.setSpacing(1)
@@ -437,9 +443,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
# TODO: set margins based on label width
if self._handle_label_position == LabelPosition.LabelsLeft:
marg = (30, 0, 0, 0)
elif self._handle_label_position == LabelPosition.NoLabel:
marg = (0, 0, 0, 0)
else:
elif self._handle_label_position == LabelPosition.LabelsRight:
marg = (0, 0, 20, 0)
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
else:
@@ -447,9 +451,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
layout.setSpacing(7)
if self._handle_label_position == LabelPosition.LabelsBelow:
marg = (0, 0, 0, 25)
elif self._handle_label_position == LabelPosition.NoLabel:
marg = (0, 0, 0, 0)
else:
elif self._handle_label_position == LabelPosition.LabelsAbove:
marg = (0, 25, 0, 0)
self._add_labels(layout, inverted=inverted)
@@ -490,6 +492,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
horizontal = self.orientation() == Qt.Orientation.Horizontal
labels_above = self._handle_label_position == LabelPosition.LabelsAbove
labels_on_handle = self._handle_label_position == LabelPosition.LabelsOnHandle
last_edge = None
labels: Iterable[tuple[int, SliderLabel]] = enumerate(self._handle_labels)
@@ -497,13 +500,16 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
labels = reversed(list(labels))
for i, label in labels:
rect = self._slider._handleRect(i)
dx = -label.width() / 2
dy = -label.height() / 2
if labels_above:
dx = (-label.width() / 2) + 1.5
dy = (-label.height() / 2) + 0.5
if labels_above: # or on the right
if horizontal:
dy *= 3
else:
dx *= -1
elif labels_on_handle:
if not horizontal:
dx *= -1
else:
if horizontal:
dy *= -1
@@ -520,6 +526,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
label.move(pos)
last_edge = pos
label.clearFocus()
label.raise_()
label.show()
self.update()

View File

@@ -2,6 +2,7 @@
from __future__ import annotations
from concurrent.futures import Future
from contextlib import suppress
from functools import wraps
from typing import TYPE_CHECKING, Any, Callable, ClassVar, overload
@@ -41,7 +42,8 @@ class CallCallable(QObject):
def call(self):
CallCallable.instances.remove(self)
res = self._callable(*self._args, **self._kwargs)
self.finished.emit(res)
with suppress(RuntimeError):
self.finished.emit(res)
# fmt: off