diff options
Diffstat (limited to 'src/quicktemplates2/qquickdial.cpp')
-rw-r--r-- | src/quicktemplates2/qquickdial.cpp | 211 |
1 files changed, 176 insertions, 35 deletions
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index fbc73c2a..bb939dd9 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -77,6 +77,14 @@ QT_BEGIN_NAMESPACE \sa {Customizing Dial}, {Input Controls} */ +/*! + \since QtQuick.Controls 2.2 + \qmlsignal QtQuick.Controls::Dial::moved() + + This signal is emitted when the dial has been interactively moved + by the user by either touch, mouse, or keys. +*/ + static const qreal startAngleRadians = (M_PI * 2.0) * (4.0 / 6.0); static const qreal startAngle = -140; static const qreal endAngleRadians = (M_PI * 2.0) * (5.0 / 6.0); @@ -88,6 +96,7 @@ class QQuickDialPrivate : public QQuickControlPrivate public: QQuickDialPrivate() : + touchId(-1), from(0), to(1), value(0), @@ -97,17 +106,24 @@ public: pressed(false), snapMode(QQuickDial::NoSnap), wrap(false), + live(false), handle(nullptr) { } qreal valueAt(qreal position) const; qreal snapPosition(qreal position) const; - qreal positionAt(const QPoint &point) const; + qreal positionAt(const QPointF &point) const; void setPosition(qreal position); void updatePosition(); - bool isLargeChange(const QPoint &eventPos, qreal proposedPosition) const; + bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const; + + void handlePress(const QPointF &point); + void handleMove(const QPointF &point); + void handleRelease(const QPointF &point); + void handleUngrab(); + int touchId; qreal from; qreal to; qreal value; @@ -115,9 +131,10 @@ public: qreal angle; qreal stepSize; bool pressed; - QPoint pressPoint; + QPointF pressPoint; QQuickDial::SnapMode snapMode; bool wrap; + bool live; QQuickItem *handle; }; @@ -139,7 +156,7 @@ qreal QQuickDialPrivate::snapPosition(qreal position) const return qRound(position / effectiveStep) * effectiveStep; } -qreal QQuickDialPrivate::positionAt(const QPoint &point) const +qreal QQuickDialPrivate::positionAt(const QPointF &point) const { qreal yy = height / 2.0 - point.y(); qreal xx = point.x() - width / 2.0; @@ -175,11 +192,68 @@ void QQuickDialPrivate::updatePosition() setPosition(pos); } -bool QQuickDialPrivate::isLargeChange(const QPoint &eventPos, qreal proposedPosition) const +bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPosition) const { return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2; } +void QQuickDialPrivate::handlePress(const QPointF &point) +{ + Q_Q(QQuickDial); + pressPoint = point; + q->setPressed(true); +} + +void QQuickDialPrivate::handleMove(const QPointF &point) +{ + Q_Q(QQuickDial); + if (!q->keepMouseGrab()) + return; + const qreal oldPos = position; + qreal pos = positionAt(point); + if (snapMode == QQuickDial::SnapAlways) + pos = snapPosition(pos); + + if (wrap || (!wrap && !isLargeChange(point, pos))) { + if (live) + q->setValue(valueAt(pos)); + else + setPosition(pos); + if (!qFuzzyCompare(pos, oldPos)) + emit q->moved(); + } +} + +void QQuickDialPrivate::handleRelease(const QPointF &point) +{ + Q_Q(QQuickDial); + if (q->keepMouseGrab()) { + const qreal oldPos = position; + qreal pos = positionAt(point); + if (snapMode != QQuickDial::NoSnap) + pos = snapPosition(pos); + + if (wrap || (!wrap && !isLargeChange(point, pos))) + q->setValue(valueAt(pos)); + if (!qFuzzyCompare(pos, oldPos)) + emit q->moved(); + + q->setKeepMouseGrab(false); + } + + q->setPressed(false); + pressPoint = QPointF(); + touchId = -1; +} + +void QQuickDialPrivate::handleUngrab() +{ + Q_Q(QQuickDial); + pressPoint = QPointF(); + touchId = -1; + q->setPressed(false); +} + QQuickDial::QQuickDial(QQuickItem *parent) : QQuickControl(*(new QQuickDialPrivate), parent) { @@ -248,11 +322,12 @@ void QQuickDial::setTo(qreal to) This property holds the value in the range \c from - \c to. The default value is \c 0.0. - Unlike the \l position property, the \c value is not updated while the - handle is dragged. The value is updated after the value has been chosen - and the dial has been released. + Unlike the \l position property, the \c value is not updated by default + while the handle is dragged. The value is updated after the value has + been chosen and the dial has been released. The \l live property can be + used to make the dial provide live updates for the \c value property. - \sa position + \sa position, live */ qreal QQuickDial::value() const { @@ -447,6 +522,33 @@ void QQuickDial::setPressed(bool pressed) } /*! + \since QtQuick.Controls 2.2 + \qmlproperty bool QtQuick.Controls::Dial::live + + This property holds whether the dial provides live updates for the \l value + property while the handle is dragged. + + The default value is \c false. + + \sa value +*/ +bool QQuickDial::live() const +{ + Q_D(const QQuickDial); + return d->live; +} + +void QQuickDial::setLive(bool live) +{ + Q_D(QQuickDial); + if (d->live == live) + return; + + d->live = live; + emit liveChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::Dial::increase() Increases the value by \l stepSize, or \c 0.1 if stepSize is not defined. @@ -505,6 +607,7 @@ void QQuickDial::setHandle(QQuickItem *handle) void QQuickDial::keyPressEvent(QKeyEvent *event) { Q_D(QQuickDial); + const qreal oldValue = d->value; switch (event->key()) { case Qt::Key_Left: case Qt::Key_Down: @@ -539,6 +642,8 @@ void QQuickDial::keyPressEvent(QKeyEvent *event) QQuickControl::keyPressEvent(event); break; } + if (!qFuzzyCompare(d->value, oldValue)) + emit moved(); } void QQuickDial::keyReleaseEvent(QKeyEvent *event) @@ -551,8 +656,7 @@ void QQuickDial::mousePressEvent(QMouseEvent *event) { Q_D(QQuickDial); QQuickControl::mousePressEvent(event); - d->pressPoint = event->pos(); - setPressed(true); + d->handlePress(event->localPos()); } void QQuickDial::mouseMoveEvent(QMouseEvent *event) @@ -560,50 +664,87 @@ void QQuickDial::mouseMoveEvent(QMouseEvent *event) Q_D(QQuickDial); QQuickControl::mouseMoveEvent(event); if (!keepMouseGrab()) { - bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event); + bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event); setKeepMouseGrab(overXDragThreshold); if (!overXDragThreshold) { - bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event); + bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event); setKeepMouseGrab(overYDragThreshold); } } - if (keepMouseGrab()) { - qreal pos = d->positionAt(event->pos()); - if (d->snapMode == SnapAlways) - pos = d->snapPosition(pos); - - if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos))) - d->setPosition(pos); - } + d->handleMove(event->localPos()); } void QQuickDial::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickDial); QQuickControl::mouseReleaseEvent(event); + d->handleRelease(event->localPos()); +} - if (keepMouseGrab()) { - qreal pos = d->positionAt(event->pos()); - if (d->snapMode != NoSnap) - pos = d->snapPosition(pos); +void QQuickDial::mouseUngrabEvent() +{ + Q_D(QQuickDial); + QQuickControl::mouseUngrabEvent(); + d->handleUngrab(); +} - if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos))) - setValue(d->valueAt(pos)); +void QQuickDial::touchEvent(QTouchEvent *event) +{ + Q_D(QQuickDial); + switch (event->type()) { + case QEvent::TouchBegin: + if (d->touchId == -1) { + const QTouchEvent::TouchPoint point = event->touchPoints().first(); + d->touchId = point.id(); + d->handlePress(point.pos()); + } else { + event->ignore(); + } + break; - setKeepMouseGrab(false); - } + case QEvent::TouchUpdate: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + if (!keepMouseGrab()) { + bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point); + setKeepMouseGrab(overXDragThreshold); + + if (!overXDragThreshold) { + bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point); + setKeepMouseGrab(overYDragThreshold); + } + } + d->handleMove(point.pos()); + } + break; - setPressed(false); - d->pressPoint = QPoint(); + case QEvent::TouchEnd: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + d->handleRelease(point.pos()); + } + break; + + case QEvent::TouchCancel: + d->handleUngrab(); + break; + + default: + QQuickControl::touchEvent(event); + break; + } } -void QQuickDial::mouseUngrabEvent() +void QQuickDial::touchUngrabEvent() { Q_D(QQuickDial); - QQuickControl::mouseUngrabEvent(); - d->pressPoint = QPoint(); - setPressed(false); + QQuickControl::touchUngrabEvent(); + d->handleUngrab(); } void QQuickDial::wheelEvent(QWheelEvent *event) |