| /**************************************************************************** |
| ** |
| ** Copyright (C) 2017 The Qt Company Ltd. |
| ** Contact: http://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL3$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see http://www.qt.io/terms-conditions. For further |
| ** information use the contact form at http://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or later as published by the Free |
| ** Software Foundation and appearing in the file LICENSE.GPL included in |
| ** the packaging of this file. Please review the following information to |
| ** ensure the GNU General Public License version 2.0 requirements will be |
| ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qquickslider_p.h" |
| #include "qquickcontrol_p_p.h" |
| #include "qquickdeferredexecute_p_p.h" |
| |
| #include <QtQuick/private/qquickwindow_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \qmltype Slider |
| \inherits Control |
| //! \instantiates QQuickSlider |
| \inqmlmodule QtQuick.Controls |
| \since 5.7 |
| \ingroup qtquickcontrols2-input |
| \brief Used to select a value by sliding a handle along a track. |
| |
| \image qtquickcontrols2-slider.gif |
| |
| Slider is used to select a value by sliding a handle along a track. |
| |
| In the example below, custom \l from, \l value, and \l to values are set: |
| |
| \code |
| Slider { |
| from: 1 |
| value: 25 |
| to: 100 |
| } |
| \endcode |
| |
| The \l position property is expressed as a fraction of the control's size, |
| in the range \c {0.0 - 1.0}. The \l visualPosition property is |
| the same, except that it is reversed in a |
| \l {Right-to-left User Interfaces}{right-to-left} application. The |
| visualPosition is useful for positioning the handle when styling Slider. |
| In the example above, \l visualPosition will be \c 0.24 in a left-to-right |
| application, and \c 0.76 in a right-to-left application. |
| |
| For a slider that allows the user to select a range by providing two |
| handles, see \l RangeSlider. |
| |
| \sa {Customizing Slider}, {Input Controls} |
| */ |
| |
| /*! |
| \since QtQuick.Controls 2.2 (Qt 5.9) |
| \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: |
| qreal snapPosition(qreal position) const; |
| qreal positionAt(const QPointF &point) const; |
| void setPosition(qreal position); |
| void updatePosition(); |
| |
| void handlePress(const QPointF &point) override; |
| void handleMove(const QPointF &point) override; |
| void handleRelease(const QPointF &point) override; |
| void handleUngrab() override; |
| |
| void cancelHandle(); |
| void executeHandle(bool complete = false); |
| |
| void itemImplicitWidthChanged(QQuickItem *item) override; |
| void itemImplicitHeightChanged(QQuickItem *item) override; |
| |
| qreal from = 0; |
| qreal to = 1; |
| qreal value = 0; |
| qreal position = 0; |
| qreal stepSize = 0; |
| qreal touchDragThreshold = -1; // in QQuickWindowPrivate::dragOverThreshold, '-1' implies using styleHints::startDragDistance() |
| bool live = true; |
| bool pressed = false; |
| QPointF pressPoint; |
| Qt::Orientation orientation = Qt::Horizontal; |
| QQuickSlider::SnapMode snapMode = QQuickSlider::NoSnap; |
| QQuickDeferredPointer<QQuickItem> handle; |
| }; |
| |
| qreal QQuickSliderPrivate::snapPosition(qreal position) const |
| { |
| const qreal range = to - from; |
| if (qFuzzyIsNull(range)) |
| return position; |
| |
| const qreal effectiveStep = stepSize / range; |
| if (qFuzzyIsNull(effectiveStep)) |
| return position; |
| |
| return qRound(position / effectiveStep) * effectiveStep; |
| } |
| |
| 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()) |
| 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)) |
| pos = (q->height() - point.y() - q->bottomPadding() - offset) / extent; |
| } |
| return qBound<qreal>(0.0, pos, 1.0); |
| } |
| |
| void QQuickSliderPrivate::setPosition(qreal pos) |
| { |
| Q_Q(QQuickSlider); |
| pos = qBound<qreal>(0.0, pos, 1.0); |
| if (qFuzzyCompare(position, pos)) |
| return; |
| |
| position = pos; |
| emit q->positionChanged(); |
| emit q->visualPositionChanged(); |
| } |
| |
| void QQuickSliderPrivate::updatePosition() |
| { |
| qreal pos = 0; |
| if (!qFuzzyCompare(from, to)) |
| pos = (value - from) / (to - from); |
| setPosition(pos); |
| } |
| |
| void QQuickSliderPrivate::handlePress(const QPointF &point) |
| { |
| Q_Q(QQuickSlider); |
| QQuickControlPrivate::handlePress(point); |
| pressPoint = point; |
| q->setPressed(true); |
| } |
| |
| void QQuickSliderPrivate::handleMove(const QPointF &point) |
| { |
| Q_Q(QQuickSlider); |
| QQuickControlPrivate::handleMove(point); |
| 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); |
| QQuickControlPrivate::handleRelease(point); |
| 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); |
| QQuickControlPrivate::handleUngrab(); |
| pressPoint = QPointF(); |
| q->setPressed(false); |
| } |
| |
| static inline QString handleName() { return QStringLiteral("handle"); } |
| |
| void QQuickSliderPrivate::cancelHandle() |
| { |
| Q_Q(QQuickSlider); |
| quickCancelDeferred(q, handleName()); |
| } |
| |
| void QQuickSliderPrivate::executeHandle(bool complete) |
| { |
| Q_Q(QQuickSlider); |
| if (handle.wasExecuted()) |
| return; |
| |
| if (!handle || complete) |
| quickBeginDeferred(q, handleName(), handle); |
| if (complete) |
| quickCompleteDeferred(q, handleName(), handle); |
| } |
| |
| void QQuickSliderPrivate::itemImplicitWidthChanged(QQuickItem *item) |
| { |
| Q_Q(QQuickSlider); |
| QQuickControlPrivate::itemImplicitWidthChanged(item); |
| if (item == handle) |
| emit q->implicitHandleWidthChanged(); |
| } |
| |
| void QQuickSliderPrivate::itemImplicitHeightChanged(QQuickItem *item) |
| { |
| Q_Q(QQuickSlider); |
| QQuickControlPrivate::itemImplicitHeightChanged(item); |
| if (item == handle) |
| emit q->implicitHandleHeightChanged(); |
| } |
| |
| QQuickSlider::QQuickSlider(QQuickItem *parent) |
| : QQuickControl(*(new QQuickSliderPrivate), parent) |
| { |
| setActiveFocusOnTab(true); |
| setFocusPolicy(Qt::StrongFocus); |
| setAcceptedMouseButtons(Qt::LeftButton); |
| #if QT_CONFIG(cursor) |
| setCursor(Qt::ArrowCursor); |
| #endif |
| } |
| |
| QQuickSlider::~QQuickSlider() |
| { |
| Q_D(QQuickSlider); |
| d->removeImplicitSizeListener(d->handle); |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::from |
| |
| This property holds the starting value for the range. The default value is \c 0.0. |
| |
| \sa to, value |
| */ |
| qreal QQuickSlider::from() const |
| { |
| Q_D(const QQuickSlider); |
| return d->from; |
| } |
| |
| void QQuickSlider::setFrom(qreal from) |
| { |
| Q_D(QQuickSlider); |
| if (qFuzzyCompare(d->from, from)) |
| return; |
| |
| d->from = from; |
| emit fromChanged(); |
| if (isComponentComplete()) { |
| setValue(d->value); |
| d->updatePosition(); |
| } |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::to |
| |
| This property holds the end value for the range. The default value is \c 1.0. |
| |
| \sa from, value |
| */ |
| qreal QQuickSlider::to() const |
| { |
| Q_D(const QQuickSlider); |
| return d->to; |
| } |
| |
| void QQuickSlider::setTo(qreal to) |
| { |
| Q_D(QQuickSlider); |
| if (qFuzzyCompare(d->to, to)) |
| return; |
| |
| d->to = to; |
| emit toChanged(); |
| if (isComponentComplete()) { |
| setValue(d->value); |
| d->updatePosition(); |
| } |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::value |
| |
| This property holds the value in the range \c from - \c to. The default value is \c 0.0. |
| |
| \sa position |
| */ |
| qreal QQuickSlider::value() const |
| { |
| Q_D(const QQuickSlider); |
| return d->value; |
| } |
| |
| void QQuickSlider::setValue(qreal value) |
| { |
| Q_D(QQuickSlider); |
| if (isComponentComplete()) |
| value = d->from > d->to ? qBound(d->to, value, d->from) : qBound(d->from, value, d->to); |
| |
| if (qFuzzyCompare(d->value, value)) |
| return; |
| |
| d->value = value; |
| d->updatePosition(); |
| emit valueChanged(); |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::position |
| \readonly |
| |
| 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}. For visualizing a slider, the right-to-left aware |
| \l visualPosition should be used instead. |
| |
| \sa value, visualPosition, valueAt() |
| */ |
| qreal QQuickSlider::position() const |
| { |
| Q_D(const QQuickSlider); |
| return d->position; |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::visualPosition |
| \readonly |
| |
| This property holds the visual position of the handle. |
| |
| The position is expressed as a fraction of the control's size, in the range |
| \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, the |
| value is equal to \c {1.0 - position}. This makes the value suitable for |
| visualizing the slider, taking right-to-left support into account. |
| |
| \sa position |
| */ |
| qreal QQuickSlider::visualPosition() const |
| { |
| Q_D(const QQuickSlider); |
| if (d->orientation == Qt::Vertical || isMirrored()) |
| return 1.0 - d->position; |
| return d->position; |
| } |
| |
| /*! |
| \qmlproperty real QtQuick.Controls::Slider::stepSize |
| |
| This property holds the step size. The default value is \c 0.0. |
| |
| \sa snapMode, increase(), decrease() |
| */ |
| qreal QQuickSlider::stepSize() const |
| { |
| Q_D(const QQuickSlider); |
| return d->stepSize; |
| } |
| |
| void QQuickSlider::setStepSize(qreal step) |
| { |
| Q_D(QQuickSlider); |
| if (qFuzzyCompare(d->stepSize, step)) |
| return; |
| |
| d->stepSize = step; |
| emit stepSizeChanged(); |
| } |
| |
| /*! |
| \qmlproperty enumeration QtQuick.Controls::Slider::snapMode |
| |
| This property holds the snap mode. |
| |
| The snap mode determines how the slider handle behaves with |
| regards to the \l stepSize. |
| |
| Possible values: |
| \value Slider.NoSnap The slider does not snap (default). |
| \value Slider.SnapAlways The slider snaps while the handle is dragged. |
| \value Slider.SnapOnRelease The slider does not snap while being dragged, but only after the handle is released. |
| |
| In the following table, the various modes are illustrated with animations. |
| The movement of the mouse cursor and the \l stepSize (\c 0.2) are identical |
| in each animation. |
| |
| \table |
| \header |
| \row \li \b Value \li \b Example |
| \row \li \c Slider.NoSnap \li \image qtquickcontrols2-slider-nosnap.gif |
| \row \li \c Slider.SnapAlways \li \image qtquickcontrols2-slider-snapalways.gif |
| \row \li \c Slider.SnapOnRelease \li \image qtquickcontrols2-slider-snaponrelease.gif |
| \endtable |
| |
| \sa stepSize |
| */ |
| QQuickSlider::SnapMode QQuickSlider::snapMode() const |
| { |
| Q_D(const QQuickSlider); |
| return d->snapMode; |
| } |
| |
| void QQuickSlider::setSnapMode(SnapMode mode) |
| { |
| Q_D(QQuickSlider); |
| if (d->snapMode == mode) |
| return; |
| |
| d->snapMode = mode; |
| emit snapModeChanged(); |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick.Controls::Slider::pressed |
| |
| This property holds whether the slider is pressed by either touch, mouse, |
| or keys. |
| */ |
| bool QQuickSlider::isPressed() const |
| { |
| Q_D(const QQuickSlider); |
| return d->pressed; |
| } |
| |
| void QQuickSlider::setPressed(bool pressed) |
| { |
| Q_D(QQuickSlider); |
| if (d->pressed == pressed) |
| return; |
| |
| d->pressed = pressed; |
| setAccessibleProperty("pressed", pressed); |
| emit pressedChanged(); |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.3 (Qt 5.10) |
| \qmlproperty bool QtQuick.Controls::Slider::horizontal |
| \readonly |
| |
| This property holds whether the slider is horizontal. |
| |
| \sa orientation |
| */ |
| bool QQuickSlider::isHorizontal() const |
| { |
| Q_D(const QQuickSlider); |
| return d->orientation == Qt::Horizontal; |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.3 (Qt 5.10) |
| \qmlproperty bool QtQuick.Controls::Slider::vertical |
| \readonly |
| |
| This property holds whether the slider is vertical. |
| |
| \sa orientation |
| */ |
| bool QQuickSlider::isVertical() const |
| { |
| Q_D(const QQuickSlider); |
| return d->orientation == Qt::Vertical; |
| } |
| |
| /*! |
| \qmlproperty enumeration QtQuick.Controls::Slider::orientation |
| |
| This property holds the orientation. |
| |
| Possible values: |
| \value Qt.Horizontal Horizontal (default) |
| \value Qt.Vertical Vertical |
| |
| \sa horizontal, vertical |
| */ |
| Qt::Orientation QQuickSlider::orientation() const |
| { |
| Q_D(const QQuickSlider); |
| return d->orientation; |
| } |
| |
| void QQuickSlider::setOrientation(Qt::Orientation orientation) |
| { |
| Q_D(QQuickSlider); |
| if (d->orientation == orientation) |
| return; |
| |
| d->orientation = orientation; |
| emit orientationChanged(); |
| } |
| |
| /*! |
| \qmlproperty Item QtQuick.Controls::Slider::handle |
| |
| This property holds the handle item. |
| |
| \sa {Customizing Slider} |
| */ |
| QQuickItem *QQuickSlider::handle() const |
| { |
| QQuickSliderPrivate *d = const_cast<QQuickSliderPrivate *>(d_func()); |
| if (!d->handle) |
| d->executeHandle(); |
| return d->handle; |
| } |
| |
| void QQuickSlider::setHandle(QQuickItem *handle) |
| { |
| Q_D(QQuickSlider); |
| if (d->handle == handle) |
| return; |
| |
| if (!d->handle.isExecuting()) |
| d->cancelHandle(); |
| |
| const qreal oldImplicitHandleWidth = implicitHandleWidth(); |
| const qreal oldImplicitHandleHeight = implicitHandleHeight(); |
| |
| d->removeImplicitSizeListener(d->handle); |
| QQuickControlPrivate::hideOldItem(d->handle); |
| d->handle = handle; |
| |
| if (handle) { |
| if (!handle->parentItem()) |
| handle->setParentItem(this); |
| d->addImplicitSizeListener(handle); |
| } |
| |
| if (!qFuzzyCompare(oldImplicitHandleWidth, implicitHandleWidth())) |
| emit implicitHandleWidthChanged(); |
| if (!qFuzzyCompare(oldImplicitHandleHeight, implicitHandleHeight())) |
| emit implicitHandleHeightChanged(); |
| if (!d->handle.isExecuting()) |
| emit handleChanged(); |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.1 (Qt 5.8) |
| \qmlmethod real QtQuick.Controls::Slider::valueAt(real position) |
| |
| Returns the value for the given \a position. |
| |
| \sa value, position |
| */ |
| qreal QQuickSlider::valueAt(qreal position) const |
| { |
| Q_D(const QQuickSlider); |
| const qreal value = (d->to - d->from) * position; |
| if (qFuzzyIsNull(d->stepSize)) |
| return d->from + value; |
| return d->from + qRound(value / d->stepSize) * d->stepSize; |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.2 (Qt 5.9) |
| \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(); |
| } |
| |
| /*! |
| \qmlmethod void QtQuick.Controls::Slider::increase() |
| |
| Increases the value by \l stepSize or \c 0.1 if stepSize is not defined. |
| |
| \sa stepSize |
| */ |
| void QQuickSlider::increase() |
| { |
| Q_D(QQuickSlider); |
| qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; |
| setValue(d->value + step); |
| } |
| |
| /*! |
| \qmlmethod void QtQuick.Controls::Slider::decrease() |
| |
| Decreases the value by \l stepSize or \c 0.1 if stepSize is not defined. |
| |
| \sa stepSize |
| */ |
| void QQuickSlider::decrease() |
| { |
| Q_D(QQuickSlider); |
| qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; |
| setValue(d->value - step); |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.5 (Qt 5.12) |
| \qmlproperty qreal QtQuick.Controls::Slider::touchDragThreshold |
| |
| This property holds the threshold (in logical pixels) at which a touch drag event will be initiated. |
| The mouse drag threshold won't be affected. |
| The default value is \c Qt.styleHints.startDragDistance. |
| |
| \sa QStyleHints |
| */ |
| qreal QQuickSlider::touchDragThreshold() const |
| { |
| Q_D(const QQuickSlider); |
| return d->touchDragThreshold; |
| } |
| |
| void QQuickSlider::setTouchDragThreshold(qreal touchDragThreshold) |
| { |
| Q_D(QQuickSlider); |
| if (d->touchDragThreshold == touchDragThreshold) |
| return; |
| |
| d->touchDragThreshold = touchDragThreshold; |
| emit touchDragThresholdChanged(); |
| } |
| |
| void QQuickSlider::resetTouchDragThreshold() |
| { |
| setTouchDragThreshold(-1); |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.5 (Qt 5.12) |
| \qmlproperty real QtQuick.Controls::Slider::implicitHandleWidth |
| \readonly |
| |
| This property holds the implicit handle width. |
| |
| The value is equal to \c {handle ? handle.implicitWidth : 0}. |
| |
| This is typically used, together with \l {Control::}{implicitContentWidth} and |
| \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. |
| |
| \sa implicitHandleHeight |
| */ |
| qreal QQuickSlider::implicitHandleWidth() const |
| { |
| Q_D(const QQuickSlider); |
| if (!d->handle) |
| return 0; |
| return d->handle->implicitWidth(); |
| } |
| |
| /*! |
| \since QtQuick.Controls 2.5 (Qt 5.12) |
| \qmlproperty real QtQuick.Controls::Slider::implicitHandleHeight |
| \readonly |
| |
| This property holds the implicit handle height. |
| |
| The value is equal to \c {handle ? handle.implicitHeight : 0}. |
| |
| This is typically used, together with \l {Control::}{implicitContentHeight} and |
| \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. |
| |
| \sa implicitHandleWidth |
| */ |
| qreal QQuickSlider::implicitHandleHeight() const |
| { |
| Q_D(const QQuickSlider); |
| if (!d->handle) |
| return 0; |
| return d->handle->implicitHeight(); |
| } |
| |
| 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); |
| if (isMirrored()) |
| increase(); |
| else |
| decrease(); |
| event->accept(); |
| } else if (event->key() == Qt::Key_Right) { |
| setPressed(true); |
| if (isMirrored()) |
| decrease(); |
| else |
| increase(); |
| event->accept(); |
| } |
| } else { |
| if (event->key() == Qt::Key_Up) { |
| setPressed(true); |
| increase(); |
| event->accept(); |
| } else if (event->key() == Qt::Key_Down) { |
| setPressed(true); |
| decrease(); |
| event->accept(); |
| } |
| } |
| if (!qFuzzyCompare(d->value, oldValue)) |
| emit moved(); |
| } |
| |
| void QQuickSlider::keyReleaseEvent(QKeyEvent *event) |
| { |
| QQuickControl::keyReleaseEvent(event); |
| setPressed(false); |
| } |
| |
| void QQuickSlider::mousePressEvent(QMouseEvent *event) |
| { |
| Q_D(QQuickSlider); |
| QQuickControl::mousePressEvent(event); |
| d->handleMove(event->localPos()); |
| setKeepMouseGrab(true); |
| } |
| |
| #if QT_CONFIG(quicktemplates2_multitouch) |
| void QQuickSlider::touchEvent(QTouchEvent *event) |
| { |
| Q_D(QQuickSlider); |
| switch (event->type()) { |
| case QEvent::TouchUpdate: |
| for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { |
| if (!d->acceptTouch(point)) |
| continue; |
| |
| switch (point.state()) { |
| case Qt::TouchPointPressed: |
| d->handlePress(point.pos()); |
| break; |
| case Qt::TouchPointMoved: |
| if (!keepTouchGrab()) { |
| if (d->orientation == Qt::Horizontal) |
| setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point, qRound(d->touchDragThreshold))); |
| else |
| setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point, qRound(d->touchDragThreshold))); |
| } |
| if (keepTouchGrab()) |
| d->handleMove(point.pos()); |
| break; |
| case Qt::TouchPointReleased: |
| d->handleRelease(point.pos()); |
| break; |
| default: |
| break; |
| } |
| } |
| break; |
| |
| default: |
| QQuickControl::touchEvent(event); |
| break; |
| } |
| } |
| #endif |
| |
| #if QT_CONFIG(wheelevent) |
| void QQuickSlider::wheelEvent(QWheelEvent *event) |
| { |
| Q_D(QQuickSlider); |
| QQuickControl::wheelEvent(event); |
| if (d->wheelEnabled) { |
| const qreal oldValue = d->value; |
| const QPointF angle = event->angleDelta(); |
| 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); |
| const bool wasMoved = !qFuzzyCompare(d->value, oldValue); |
| if (wasMoved) |
| emit moved(); |
| } |
| } |
| #endif |
| |
| void QQuickSlider::mirrorChange() |
| { |
| QQuickControl::mirrorChange(); |
| emit visualPositionChanged(); |
| } |
| |
| void QQuickSlider::componentComplete() |
| { |
| Q_D(QQuickSlider); |
| d->executeHandle(true); |
| QQuickControl::componentComplete(); |
| setValue(d->value); |
| d->updatePosition(); |
| } |
| |
| #if QT_CONFIG(accessibility) |
| void QQuickSlider::accessibilityActiveChanged(bool active) |
| { |
| QQuickControl::accessibilityActiveChanged(active); |
| |
| Q_D(QQuickSlider); |
| if (active) |
| setAccessibleProperty("pressed", d->pressed); |
| } |
| |
| QAccessible::Role QQuickSlider::accessibleRole() const |
| { |
| return QAccessible::Slider; |
| } |
| #endif |
| |
| QT_END_NAMESPACE |