Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
jborbely committed Mar 10, 2020
2 parents b2e4508 + 5799b92 commit b45f3e1
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
19 changes: 13 additions & 6 deletions msl/qt/widgets/spinboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,15 @@ def validate(self, text, position):
"""Overrides :meth:`QtWidgets.QAbstractSpinBox.validate`."""
if self._validator is None:
return super(DoubleSpinBox, self).validate(text, position)
# don't pass self.cleanText() to the validator, use rstrip()
return self._validator.validate(text.rstrip(self.suffix()), position)
# Don't pass self.cleanText() to the validator because it does not always return
# what is expected. For example, if `text`='0.12f3' then self.cleanText() returns
# '0.12f' (which has removed the 3 at the end) and this causes the validator to
# return Acceptable and the displayed text in the DoubleSpinBox then becomes
# '0.12f3' which is Invalid and one can no longer edit the value in the
# DoubleSpinBox. It is okay to use self.cleanText() in the methods self.fixup(),
# self.valueFromText() and self.stepBy()
text = text.rstrip(self.suffix()).lstrip(self.prefix())
return self._validator.validate(text, position - len(self.prefix()))

def fixup(self, text):
"""Overrides :meth:`QtWidgets.QAbstractSpinBox.fixup`."""
Expand All @@ -162,8 +169,8 @@ def setValue(self, value):
if self._validator is None:
super(DoubleSpinBox, self).setValue(value)
else:
truncated = max(min(si_to_number(str(value)), self.maximum()), self.minimum())
self.lineEdit().setText(self.textFromValue(truncated))
coerced = max(min(si_to_number(str(value)), self.maximum()), self.minimum())
self.lineEdit().setText(self.textFromValue(coerced))

def stepBy(self, steps):
"""Overrides :meth:`QtWidgets.QAbstractSpinBox.stepBy`.
Expand All @@ -179,8 +186,8 @@ def stepBy(self, steps):
super(DoubleSpinBox, self).stepBy(steps)
else:
number = si_to_number(self.cleanText())
truncated = max(min(number, self.maximum()), self.minimum())
_, si_prefix = number_to_si(truncated)
coerced = max(min(number, self.maximum()), self.minimum())
_, si_prefix = number_to_si(coerced)
value = number + si_to_number(str(steps * self.singleStep()) + si_prefix)
self.setValue(value)
self.editingFinished.emit()
Expand Down
32 changes: 31 additions & 1 deletion tests/test_spinboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ def test_si_prefix_validator():
assert validator.validate('-1.2 n', 6) is Acceptable
assert validator.fixup('-1.2 n') == '-1.2 n'

assert validator.validate('0.12f3', 6) is Invalid


def test_doublespinbox():
dsb = spinboxes.DoubleSpinBox()
Expand Down Expand Up @@ -154,6 +156,22 @@ def test_doublespinbox():
assert dsb.minimum() == -0.105
assert dsb.maximum() == 0.105
assert isinstance(dsb._validator, spinboxes._SIPrefixValidator)
dsb.setValue('12n')
assert dsb.value() == pytest.approx(12e-9)
dsb.setValue(0.012)
assert dsb.value() == 0.012
for value in [-1e2, -math.inf, '-1e5', '-1P', -1.1e30]:
dsb.setValue(value)
assert dsb.value() == -0.105
for steps in [-1, int(-1e30)]:
dsb.stepBy(steps)
assert dsb.value() == -0.105
for value in [1e2, math.inf, '1e5', '1P', 1.1e30]:
dsb.setValue(value)
assert dsb.value() == 0.105
for steps in [1, int(1e30)]:
dsb.stepBy(steps)
assert dsb.value() == 0.105

dsb = spinboxes.DoubleSpinBox(minimum=-math.inf, maximum=math.inf, use_si_prefix=True)
dsb.setValue('12n')
Expand All @@ -167,8 +185,20 @@ def test_doublespinbox():
dsb.setValue(3.4e21)
assert dsb.value() == pytest.approx(3.4e21)
dsb.setValue('-1000.00 Y')
assert dsb.value() == pytest.approx(-1e27)
dsb.stepBy(10)
assert dsb.value() == pytest.approx(-9.9e+26)
dsb.setValue('1000.00 Y')
dsb.setValue('1000Y')
assert dsb.value() == pytest.approx(1e27)
dsb.stepBy(-10)
assert dsb.value() == pytest.approx(9.9e+26)
dsb.setValue(0.0)
assert dsb.value() == 0.0
dsb.stepBy(100)
assert dsb.value() == 100.0
dsb.stepBy(-1000)
assert dsb.value() == -900.0
dsb.setValue('1E')
assert dsb.value() == pytest.approx(1e18)
dsb.setValue('1E0')
assert dsb.value() == pytest.approx(1.0)

0 comments on commit b45f3e1

Please sign in to comment.