aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quicktemplates2/qquickdial.cpp48
-rw-r--r--src/quicktemplates2/qquickdial_p.h5
-rw-r--r--tests/auto/controls/data/tst_dial.qml38
3 files changed, 88 insertions, 3 deletions
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp
index 7f73d399..e1084978 100644
--- a/src/quicktemplates2/qquickdial.cpp
+++ b/src/quicktemplates2/qquickdial.cpp
@@ -94,6 +94,7 @@ public:
stepSize(0),
pressed(false),
snapMode(QQuickDial::NoSnap),
+ wrap(true),
handle(nullptr)
{
}
@@ -103,6 +104,7 @@ public:
qreal positionAt(const QPoint &point) const;
void setPosition(qreal position);
void updatePosition();
+ bool isLargeChange(const QPoint &eventPos, qreal proposedPosition) const;
qreal from;
qreal to;
@@ -113,6 +115,7 @@ public:
bool pressed;
QPoint pressPoint;
QQuickDial::SnapMode snapMode;
+ bool wrap;
QQuickItem *handle;
};
@@ -164,6 +167,11 @@ void QQuickDialPrivate::updatePosition()
setPosition(pos);
}
+bool QQuickDialPrivate::isLargeChange(const QPoint &eventPos, qreal proposedPosition) const
+{
+ return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2;
+}
+
QQuickDial::QQuickDial(QQuickItem *parent) :
QQuickControl(*(new QQuickDialPrivate), parent)
{
@@ -349,6 +357,33 @@ void QQuickDial::setSnapMode(SnapMode mode)
}
/*!
+ \qmlproperty bool Qt.labs.controls::Dial::wrap
+
+ This property holds whether the dial wraps when dragged.
+
+ For example, when this property is set to \c true, dragging the dial past
+ the \e "zero" position will result in the handle being positioned at the
+ opposite side, and vice versa.
+
+ The default value is \c true.
+*/
+bool QQuickDial::wrap() const
+{
+ Q_D(const QQuickDial);
+ return d->wrap;
+}
+
+void QQuickDial::setWrap(bool wrap)
+{
+ Q_D(QQuickDial);
+ if (d->wrap == wrap)
+ return;
+
+ d->wrap = wrap;
+ emit wrapChanged();
+}
+
+/*!
\qmlproperty bool Qt.labs.controls::Dial::pressed
This property holds whether the dial is pressed.
@@ -508,7 +543,9 @@ void QQuickDial::mouseMoveEvent(QMouseEvent *event)
qreal pos = d->positionAt(event->pos());
if (d->snapMode == SnapAlways)
pos = d->snapPosition(pos);
- d->setPosition(pos);
+
+ if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
+ d->setPosition(pos);
}
}
@@ -516,15 +553,20 @@ void QQuickDial::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickDial);
QQuickControl::mouseReleaseEvent(event);
- d->pressPoint = QPoint();
+
if (keepMouseGrab()) {
qreal pos = d->positionAt(event->pos());
if (d->snapMode != NoSnap)
pos = d->snapPosition(pos);
- setValue(d->valueAt(pos));
+
+ if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
+ setValue(d->valueAt(pos));
+
setKeepMouseGrab(false);
}
+
setPressed(false);
+ d->pressPoint = QPoint();
}
void QQuickDial::mouseUngrabEvent()
diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h
index 6c83baef..f736e607 100644
--- a/src/quicktemplates2/qquickdial_p.h
+++ b/src/quicktemplates2/qquickdial_p.h
@@ -67,6 +67,7 @@ class Q_QUICKTEMPLATES2_EXPORT QQuickDial : public QQuickControl
Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged FINAL)
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL)
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
@@ -99,6 +100,9 @@ public:
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
+ bool wrap() const;
+ void setWrap(bool wrap);
+
bool isPressed() const;
void setPressed(bool pressed);
@@ -117,6 +121,7 @@ Q_SIGNALS:
void angleChanged();
void stepSizeChanged();
void snapModeChanged();
+ void wrapChanged();
void pressedChanged();
void handleChanged();
diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml
index e0eba27e..0f7a4f85 100644
--- a/tests/auto/controls/data/tst_dial.qml
+++ b/tests/auto/controls/data/tst_dial.qml
@@ -179,6 +179,7 @@ TestCase {
}
function test_dragging(data) {
+ verify(dial.wrap);
dial.from = data.from;
dial.to = data.to;
@@ -210,6 +211,43 @@ TestCase {
valueSpy.clear();
}
+ function test_nonWrapping() {
+ dial.wrap = false;
+ dial.value = 0;
+
+ // Ensure that dragging from bottom left to bottom right doesn't work.
+ var yPos = dial.height * 0.75;
+ mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
+ var positionAtPress = dial.position;
+ mouseMove(dial, dial.width * 0.5, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+ mouseMove(dial, dial.width * 0.75, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+ mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+
+ // Try the same thing, but a bit higher.
+ yPos = dial.height * 0.6;
+ mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
+ positionAtPress = dial.position;
+ mouseMove(dial, dial.width * 0.5, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+ mouseMove(dial, dial.width * 0.75, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+ mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+
+ // Going from below the center of the dial to above it should work (once it gets above the center).
+ mousePress(dial, dial.width * 0.25, dial.height * 0.75, Qt.LeftButton);
+ positionAtPress = dial.position;
+ mouseMove(dial, dial.width * 0.5, dial.height * 0.6, Qt.LeftButton);
+ compare(dial.position, positionAtPress);
+ mouseMove(dial, dial.width * 0.75, dial.height * 0.4, Qt.LeftButton);
+ verify(dial.position > positionAtPress);
+ mouseRelease(dial, dial.width * 0.75, dial.height * 0.3, Qt.LeftButton);
+ verify(dial.position > positionAtPress);
+ }
+
property Component focusTest: Component {
FocusScope {
signal receivedKeyPress