diff options
Diffstat (limited to 'src/quicktemplates2/qquickslider.cpp')
-rw-r--r-- | src/quicktemplates2/qquickslider.cpp | 246 |
1 files changed, 194 insertions, 52 deletions
diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index da352f36..266f883f 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -75,29 +75,53 @@ QT_BEGIN_NAMESPACE \sa {Customizing Slider}, {Input Controls} */ +/*! + \since QtQuick.Controls 2.2 + \qmlsignal QtQuick.Controls::Slider::moved() + + This signal is emitted when the slider has been interactively moved + by the user by either touch, mouse, wheel, or keys. +*/ + class QQuickSliderPrivate : public QQuickControlPrivate { Q_DECLARE_PUBLIC(QQuickSlider) public: - QQuickSliderPrivate() : from(0), to(1), value(0), position(0), stepSize(0), pressed(false), - orientation(Qt::Horizontal), snapMode(QQuickSlider::NoSnap), - handle(nullptr) + QQuickSliderPrivate() + : from(0), + to(1), + value(0), + position(0), + stepSize(0), + live(true), + pressed(false), + touchId(-1), + orientation(Qt::Horizontal), + snapMode(QQuickSlider::NoSnap), + handle(nullptr) { } qreal snapPosition(qreal position) const; - qreal positionAt(const QPoint &point) const; + qreal positionAt(const QPointF &point) const; void setPosition(qreal position); void updatePosition(); + void handlePress(const QPointF &point); + void handleMove(const QPointF &point); + void handleRelease(const QPointF &point); + void handleUngrab(); + qreal from; qreal to; qreal value; qreal position; qreal stepSize; + bool live; bool pressed; - QPoint pressPoint; + int touchId; + QPointF pressPoint; Qt::Orientation orientation; QQuickSlider::SnapMode snapMode; QQuickItem *handle; @@ -116,26 +140,28 @@ qreal QQuickSliderPrivate::snapPosition(qreal position) const return qRound(position / effectiveStep) * effectiveStep; } -qreal QQuickSliderPrivate::positionAt(const QPoint &point) const +qreal QQuickSliderPrivate::positionAt(const QPointF &point) const { Q_Q(const QQuickSlider); + qreal pos = 0.0; if (orientation == Qt::Horizontal) { const qreal hw = handle ? handle->width() : 0; const qreal offset = hw / 2; const qreal extent = q->availableWidth() - hw; if (!qFuzzyIsNull(extent)) { if (q->isMirrored()) - return (q->width() - point.x() - q->rightPadding() - offset) / extent; - return (point.x() - q->leftPadding() - offset) / extent; + pos = (q->width() - point.x() - q->rightPadding() - offset) / extent; + else + pos = (point.x() - q->leftPadding() - offset) / extent; } } else { const qreal hh = handle ? handle->height() : 0; const qreal offset = hh / 2; const qreal extent = q->availableHeight() - hh; if (!qFuzzyIsNull(extent)) - return (q->height() - point.y() - q->bottomPadding() - offset) / extent; + pos = (q->height() - point.y() - q->bottomPadding() - offset) / extent; } - return 0; + return qBound<qreal>(0.0, pos, 1.0); } void QQuickSliderPrivate::setPosition(qreal pos) @@ -158,8 +184,61 @@ void QQuickSliderPrivate::updatePosition() setPosition(pos); } -QQuickSlider::QQuickSlider(QQuickItem *parent) : - QQuickControl(*(new QQuickSliderPrivate), parent) +void QQuickSliderPrivate::handlePress(const QPointF &point) +{ + Q_Q(QQuickSlider); + pressPoint = point; + q->setPressed(true); +} + +void QQuickSliderPrivate::handleMove(const QPointF &point) +{ + Q_Q(QQuickSlider); + if (!q->keepMouseGrab() && !q->keepTouchGrab()) + return; + const qreal oldPos = position; + qreal pos = positionAt(point); + if (snapMode == QQuickSlider::SnapAlways) + pos = snapPosition(pos); + if (live) + q->setValue(q->valueAt(pos)); + else + setPosition(pos); + if (!qFuzzyCompare(pos, oldPos)) + emit q->moved(); +} + +void QQuickSliderPrivate::handleRelease(const QPointF &point) +{ + Q_Q(QQuickSlider); + touchId = -1; + pressPoint = QPointF(); + const qreal oldPos = position; + qreal pos = positionAt(point); + if (snapMode != QQuickSlider::NoSnap) + pos = snapPosition(pos); + qreal val = q->valueAt(pos); + if (!qFuzzyCompare(val, value)) + q->setValue(val); + else if (snapMode != QQuickSlider::NoSnap) + setPosition(pos); + if (!qFuzzyCompare(pos, oldPos)) + emit q->moved(); + q->setKeepMouseGrab(false); + q->setKeepTouchGrab(false); + q->setPressed(false); +} + +void QQuickSliderPrivate::handleUngrab() +{ + Q_Q(QQuickSlider); + touchId = -1; + pressPoint = QPointF(); + q->setPressed(false); +} + +QQuickSlider::QQuickSlider(QQuickItem *parent) + : QQuickControl(*(new QQuickSliderPrivate), parent) { setActiveFocusOnTab(true); setFocusPolicy(Qt::StrongFocus); @@ -225,12 +304,7 @@ void QQuickSlider::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, but only after the value has been chosen and the slider - has been released. The \l valueAt() method can be used to get continuous - updates. - - \sa position, valueAt() + \sa position */ qreal QQuickSlider::value() const { @@ -259,9 +333,8 @@ void QQuickSlider::setValue(qreal value) This property holds the logical position of the handle. The position is expressed as a fraction of the control's size, in the range - \c {0.0 - 1.0}. Unlike the \l value property, the \c position is - continuously updated while the handle is dragged. For visualizing a - slider, the right-to-left aware \l visualPosition should be used instead. + \c {0.0 - 1.0}. For visualizing a slider, the right-to-left aware + \l visualPosition should be used instead. \sa value, visualPosition, valueAt() */ @@ -356,6 +429,33 @@ void QQuickSlider::setSnapMode(SnapMode mode) } /*! + \since QtQuick.Controls 2.2 + \qmlproperty bool QtQuick.Controls::Slider::live + + This property holds whether the slider provides live updates for the \l value + property while the handle is dragged. + + The default value is \c true. + + \sa value, valueAt() +*/ +bool QQuickSlider::live() const +{ + Q_D(const QQuickSlider); + return d->live; +} + +void QQuickSlider::setLive(bool live) +{ + Q_D(QQuickSlider); + if (d->live == live) + return; + + d->live = live; + emit liveChanged(); +} + +/*! \qmlproperty bool QtQuick.Controls::Slider::pressed This property holds whether the slider is pressed. @@ -421,7 +521,7 @@ void QQuickSlider::setHandle(QQuickItem *handle) if (d->handle == handle) return; - d->deleteDelegate(d->handle); + QQuickControlPrivate::destroyDelegate(d->handle, this); d->handle = handle; if (handle && !handle->parentItem()) handle->setParentItem(this); @@ -434,11 +534,6 @@ void QQuickSlider::setHandle(QQuickItem *handle) Returns the value for the given \a position. - The \l value property is not updated while the handle is dragged, but this - method can be used to get continuous value updates: - - \snippet qtquickcontrols2-tooltip-slider.qml 1 - \sa value, position */ qreal QQuickSlider::valueAt(qreal position) const @@ -479,6 +574,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event) { Q_D(QQuickSlider); QQuickControl::keyPressEvent(event); + + const qreal oldValue = d->value; if (d->orientation == Qt::Horizontal) { if (event->key() == Qt::Key_Left) { setPressed(true); @@ -506,6 +603,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event) event->accept(); } } + if (!qFuzzyCompare(d->value, oldValue)) + emit moved(); } void QQuickSlider::keyReleaseEvent(QKeyEvent *event) @@ -518,8 +617,7 @@ void QQuickSlider::mousePressEvent(QMouseEvent *event) { Q_D(QQuickSlider); QQuickControl::mousePressEvent(event); - d->pressPoint = event->pos(); - setPressed(true); + d->handlePress(event->localPos()); } void QQuickSlider::mouseMoveEvent(QMouseEvent *event) @@ -528,43 +626,83 @@ void QQuickSlider::mouseMoveEvent(QMouseEvent *event) QQuickControl::mouseMoveEvent(event); if (!keepMouseGrab()) { if (d->orientation == Qt::Horizontal) - setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event)); + setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event)); else - setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event)); - } - if (keepMouseGrab()) { - qreal pos = d->positionAt(event->pos()); - if (d->snapMode == SnapAlways) - pos = d->snapPosition(pos); - d->setPosition(pos); + setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event)); } + d->handleMove(event->localPos()); } void QQuickSlider::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickSlider); QQuickControl::mouseReleaseEvent(event); - d->pressPoint = QPoint(); - qreal pos = d->positionAt(event->pos()); - if (d->snapMode != NoSnap) - pos = d->snapPosition(pos); - qreal val = valueAt(pos); - if (!qFuzzyCompare(val, d->value)) - setValue(val); - else if (d->snapMode != NoSnap) - d->setPosition(pos); - setKeepMouseGrab(false); - setPressed(false); + d->handleRelease(event->localPos()); } void QQuickSlider::mouseUngrabEvent() { Q_D(QQuickSlider); QQuickControl::mouseUngrabEvent(); - d->pressPoint = QPoint(); - setPressed(false); + d->handleUngrab(); +} + +void QQuickSlider::touchEvent(QTouchEvent *event) +{ + Q_D(QQuickSlider); + 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; + + case QEvent::TouchUpdate: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + if (!keepTouchGrab()) { + if (d->orientation == Qt::Horizontal) + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point)); + else + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point)); + } + d->handleMove(point.pos()); + } + break; + + 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 QQuickSlider::touchUngrabEvent() +{ + Q_D(QQuickSlider); + QQuickControl::touchUngrabEvent(); + d->handleUngrab(); +} + +#if QT_CONFIG(wheelevent) void QQuickSlider::wheelEvent(QWheelEvent *event) { Q_D(QQuickSlider); @@ -575,9 +713,13 @@ void QQuickSlider::wheelEvent(QWheelEvent *event) const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : (event->inverted() ? -angle.y() : angle.y())) / QWheelEvent::DefaultDeltasPerStep; const qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; setValue(oldValue + step * delta); - event->setAccepted(!qFuzzyCompare(d->value, oldValue)); + const bool wasMoved = !qFuzzyCompare(d->value, oldValue); + if (wasMoved) + emit moved(); + event->setAccepted(wasMoved); } } +#endif void QQuickSlider::mirrorChange() { @@ -593,7 +735,7 @@ void QQuickSlider::componentComplete() d->updatePosition(); } -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) void QQuickSlider::accessibilityActiveChanged(bool active) { QQuickControl::accessibilityActiveChanged(active); |