aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/templates/qtquicktemplates2plugin.cpp1
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp77
-rw-r--r--src/quicktemplates2/qquickspinbox_p.h5
-rw-r--r--tests/auto/controls/data/tst_spinbox.qml32
4 files changed, 91 insertions, 24 deletions
diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp
index a03229a4..e16a0e45 100644
--- a/src/imports/templates/qtquicktemplates2plugin.cpp
+++ b/src/imports/templates/qtquicktemplates2plugin.cpp
@@ -265,6 +265,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterType<QQuickScrollBar, 3>(uri, 2, 3, "ScrollBar");
qmlRegisterType<QQuickScrollIndicator, 3>(uri, 2, 3, "ScrollIndicator");
qmlRegisterType<QQuickSlider, 3>(uri, 2, 3, "Slider");
+ qmlRegisterType<QQuickSpinBox, 3>(uri, 2, 3, "SpinBox");
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index b6e99609..b6da0c9f 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -108,6 +108,7 @@ class QQuickSpinBoxPrivate : public QQuickControlPrivate
public:
QQuickSpinBoxPrivate()
: editable(false),
+ wrap(false),
from(0),
to(99),
value(0),
@@ -121,9 +122,10 @@ public:
{
}
- int boundValue(int value) const;
+ int boundValue(int value, bool wrap) const;
void updateValue();
- bool setValue(int value);
+ bool setValue(int value, bool wrap);
+ bool stepBy(int steps);
int effectiveStepSize() const;
@@ -143,6 +145,7 @@ public:
void handleUngrab() override;
bool editable;
+ bool wrap;
int from;
int to;
int value;
@@ -157,9 +160,20 @@ public:
Qt::InputMethodHints inputMethodHints;
};
-int QQuickSpinBoxPrivate::boundValue(int value) const
+int QQuickSpinBoxPrivate::boundValue(int value, bool wrap) const
{
- return from > to ? qBound(to, value, from) : qBound(from, value, to);
+ bool inverted = from > to;
+ if (!wrap)
+ return inverted ? qBound(to, value, from) : qBound(from, value, to);
+
+ int f = inverted ? to : from;
+ int t = inverted ? from : to;
+ if (value < f)
+ value = t;
+ else if (value > t)
+ value = f;
+
+ return value;
}
void QQuickSpinBoxPrivate::updateValue()
@@ -174,7 +188,7 @@ void QQuickSpinBoxPrivate::updateValue()
QJSValue loc(v4, QQmlLocale::wrap(v4, locale));
QJSValue val = q->valueFromText().call(QJSValueList() << text.toString() << loc);
const int oldValue = value;
- q->setValue(val.toInt());
+ setValue(val.toInt(), /* allowWrap = */ false);
if (oldValue != value)
emit q->valueModified();
}
@@ -182,11 +196,11 @@ void QQuickSpinBoxPrivate::updateValue()
}
}
-bool QQuickSpinBoxPrivate::setValue(int newValue)
+bool QQuickSpinBoxPrivate::setValue(int newValue, bool allowWrap)
{
Q_Q(QQuickSpinBox);
if (q->isComponentComplete())
- newValue = boundValue(newValue);
+ newValue = boundValue(newValue, allowWrap);
if (value == newValue)
return false;
@@ -200,6 +214,11 @@ bool QQuickSpinBoxPrivate::setValue(int newValue)
return true;
}
+bool QQuickSpinBoxPrivate::stepBy(int steps)
+{
+ return setValue(value + steps, wrap);
+}
+
int QQuickSpinBoxPrivate::effectiveStepSize() const
{
return from > to ? -1 * stepSize : stepSize;
@@ -217,7 +236,7 @@ void QQuickSpinBoxPrivate::updateUpEnabled()
if (!upIndicator)
return;
- upIndicator->setEnabled(from < to ? value < to : value > to);
+ upIndicator->setEnabled(wrap || (from < to ? value < to : value > to));
}
bool QQuickSpinBoxPrivate::downEnabled() const
@@ -232,7 +251,7 @@ void QQuickSpinBoxPrivate::updateDownEnabled()
if (!downIndicator)
return;
- downIndicator->setEnabled(from < to ? value > from : value < from);
+ downIndicator->setEnabled(wrap || (from < to ? value > from : value < from));
}
void QQuickSpinBoxPrivate::updateHover(const QPointF &pos)
@@ -373,7 +392,7 @@ void QQuickSpinBox::setFrom(int from)
d->from = from;
emit fromChanged();
if (isComponentComplete()) {
- if (!d->setValue(d->value)) {
+ if (!d->setValue(d->value, /* allowWrap = */ false)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
@@ -402,7 +421,7 @@ void QQuickSpinBox::setTo(int to)
d->to = to;
emit toChanged();
if (isComponentComplete()) {
- if (!d->setValue(d->value)) {
+ if (!d->setValue(d->value, /* allowWrap = */false)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
@@ -423,7 +442,7 @@ int QQuickSpinBox::value() const
void QQuickSpinBox::setValue(int value)
{
Q_D(QQuickSpinBox);
- d->setValue(value);
+ d->setValue(value, /* allowWrap = */ false);
}
/*!
@@ -694,6 +713,34 @@ bool QQuickSpinBox::isInputMethodComposing() const
}
/*!
+ \since QtQuick.Controls 2.3
+ \qmlproperty bool QtQuick.Controls::SpinBox::wrap
+
+ This property holds whether the spinbox wraps. The default value is \c false.
+
+ If wrap is \c true, stepping past \l to changes the value to \l from and vice versa.
+*/
+bool QQuickSpinBox::wrap() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->wrap;
+}
+
+void QQuickSpinBox::setWrap(bool wrap)
+{
+ Q_D(QQuickSpinBox);
+ if (d->wrap == wrap)
+ return;
+
+ d->wrap = wrap;
+ if (d->value == d->from || d->value == d->to) {
+ d->updateUpEnabled();
+ d->updateDownEnabled();
+ }
+ emit wrapChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::SpinBox::increase()
Increases the value by \l stepSize, or \c 1 if stepSize is not defined.
@@ -703,7 +750,7 @@ bool QQuickSpinBox::isInputMethodComposing() const
void QQuickSpinBox::increase()
{
Q_D(QQuickSpinBox);
- setValue(d->value + d->effectiveStepSize());
+ d->stepBy(d->effectiveStepSize());
}
/*!
@@ -716,7 +763,7 @@ void QQuickSpinBox::increase()
void QQuickSpinBox::decrease()
{
Q_D(QQuickSpinBox);
- setValue(d->value - d->effectiveStepSize());
+ d->stepBy(-d->effectiveStepSize());
}
void QQuickSpinBox::hoverEnterEvent(QHoverEvent *event)
@@ -809,7 +856,7 @@ void QQuickSpinBox::wheelEvent(QWheelEvent *event)
const int oldValue = d->value;
const QPointF angle = event->angleDelta();
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : angle.y()) / QWheelEvent::DefaultDeltasPerStep;
- setValue(oldValue + qRound(d->effectiveStepSize() * delta));
+ d->stepBy(qRound(d->effectiveStepSize() * delta));
if (d->value != oldValue)
emit valueModified();
event->setAccepted(d->value != oldValue);
diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h
index d51a2ccb..d1b42497 100644
--- a/src/quicktemplates2/qquickspinbox_p.h
+++ b/src/quicktemplates2/qquickspinbox_p.h
@@ -73,6 +73,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl
Q_PROPERTY(QQuickSpinButton *down READ down CONSTANT FINAL)
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL REVISION 3)
public:
explicit QQuickSpinBox(QQuickItem *parent = nullptr);
@@ -109,6 +110,9 @@ public:
bool isInputMethodComposing() const;
+ bool wrap() const;
+ void setWrap(bool wrap);
+
public Q_SLOTS:
void increase();
void decrease();
@@ -125,6 +129,7 @@ Q_SIGNALS:
Q_REVISION(2) void valueModified();
Q_REVISION(2) void inputMethodHintsChanged();
Q_REVISION(2) void inputMethodComposingChanged();
+ Q_REVISION(3) void wrapChanged();
protected:
void hoverEnterEvent(QHoverEvent *event) override;
diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml
index 399c9b9b..6c4f15c5 100644
--- a/tests/auto/controls/data/tst_spinbox.qml
+++ b/tests/auto/controls/data/tst_spinbox.qml
@@ -115,15 +115,23 @@ TestCase {
compare(control.up.indicator.enabled, false)
compare(control.down.indicator.enabled, true)
+ control.wrap = true
+ compare(control.up.indicator.enabled, true)
+ compare(control.down.indicator.enabled, true)
+
control.value = -1
compare(control.value, 0)
compare(control.up.indicator.enabled, true)
- compare(control.down.indicator.enabled, false)
+ compare(control.down.indicator.enabled, true)
control.from = 25
compare(control.from, 25)
compare(control.value, 25)
compare(control.up.indicator.enabled, true)
+ compare(control.down.indicator.enabled, true)
+
+ control.wrap = false
+ compare(control.up.indicator.enabled, true)
compare(control.down.indicator.enabled, false)
control.value = 30
@@ -279,12 +287,15 @@ TestCase {
return [
{ tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] },
{ tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] },
- { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }
+ { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] },
+ { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] },
+ { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] },
+ { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] }
]
}
function test_keys(data) {
- var control = createTemporaryObject(spinBox, testCase, {from: data.from, to: data.to, value: data.value, stepSize: data.stepSize})
+ var control = createTemporaryObject(spinBox, testCase, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize})
verify(control)
var upPressedCount = 0
@@ -304,7 +315,7 @@ TestCase {
verify(control.activeFocus)
for (var u = 0; u < data.upSteps.length; ++u) {
- var wasUpEnabled = control.value < control.to
+ var wasUpEnabled = control.wrap || control.value < control.to
keyPress(Qt.Key_Up)
compare(control.up.pressed, wasUpEnabled)
compare(control.down.pressed, false)
@@ -327,7 +338,7 @@ TestCase {
}
for (var d = 0; d < data.downSteps.length; ++d) {
- var wasDownEnabled = control.value > control.from
+ var wasDownEnabled = control.wrap || control.value > control.from
keyPress(Qt.Key_Down)
compare(control.down.pressed, wasDownEnabled)
compare(control.up.pressed, false)
@@ -413,12 +424,15 @@ TestCase {
return [
{ tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] },
{ tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] },
- { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }
+ { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] },
+ { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] },
+ { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] },
+ { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] }
]
}
function test_wheel(data) {
- var control = createTemporaryObject(spinBox, testCase, {from: data.from, to: data.to, value: data.value, stepSize: data.stepSize, wheelEnabled: true})
+ var control = createTemporaryObject(spinBox, testCase, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize, wheelEnabled: true})
verify(control)
var valueModifiedCount = 0
@@ -428,7 +442,7 @@ TestCase {
var delta = 120
for (var u = 0; u < data.upSteps.length; ++u) {
- var wasUpEnabled = control.value < control.to
+ var wasUpEnabled = control.wrap || control.value < control.to
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
if (wasUpEnabled)
++valueModifiedCount
@@ -438,7 +452,7 @@ TestCase {
}
for (var d = 0; d < data.downSteps.length; ++d) {
- var wasDownEnabled = control.value > control.from
+ var wasDownEnabled = control.wrap || control.value > control.from
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
if (wasDownEnabled)
++valueModifiedCount