diff options
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r-- | src/quicktemplates2/qquickdial.cpp | 76 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdial_p.h | 15 |
2 files changed, 89 insertions, 2 deletions
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index a4124678..123f9b1b 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -75,6 +75,8 @@ QT_BEGIN_NAMESPACE \row \li Set \l value to \l to \li \c Qt.Key_End \endtable + \include qquickdial.qdocinc inputMode + \sa {Customizing Dial}, {Input Controls} */ @@ -99,9 +101,12 @@ public: qreal valueAt(qreal position) const; qreal snapPosition(qreal position) const; qreal positionAt(const QPointF &point) const; + qreal circularPositionAt(const QPointF &point) const; + qreal linearPositionAt(const QPointF &point) const; void setPosition(qreal position); void updatePosition(); bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const; + bool isHorizontalOrVertical() const; void handlePress(const QPointF &point) override; void handleMove(const QPointF &point) override; @@ -119,7 +124,9 @@ public: qreal stepSize = 0; bool pressed = false; QPointF pressPoint; + qreal positionBeforePress = 0; QQuickDial::SnapMode snapMode = QQuickDial::NoSnap; + QQuickDial::InputMode inputMode = QQuickDial::Circular; bool wrap = false; bool live = true; QQuickDeferredPointer<QQuickItem> handle; @@ -145,6 +152,11 @@ qreal QQuickDialPrivate::snapPosition(qreal position) const qreal QQuickDialPrivate::positionAt(const QPointF &point) const { + return inputMode == QQuickDial::Circular ? circularPositionAt(point) : linearPositionAt(point); +} + +qreal QQuickDialPrivate::circularPositionAt(const QPointF &point) const +{ qreal yy = height / 2.0 - point.y(); qreal xx = point.x() - width / 2.0; qreal angle = (xx || yy) ? std::atan2(yy, xx) : 0; @@ -156,6 +168,32 @@ qreal QQuickDialPrivate::positionAt(const QPointF &point) const return normalizedAngle; } +qreal QQuickDialPrivate::linearPositionAt(const QPointF &point) const +{ + // This value determines the range (either horizontal or vertical) + // within which the dial can be dragged. + // The larger this value is, the further the drag distance + // must be to go from a position of e.g. 0.0 to 1.0. + qreal dragArea = 0; + + // The linear input mode uses a "relative" input system, + // where the distance from the press point is used to calculate + // the change in position. Moving the mouse above the press + // point increases the position (when inputMode is Vertical), + // and vice versa. This prevents the dial from jumping when clicked. + qreal dragDistance = 0; + + if (inputMode == QQuickDial::Horizontal) { + dragArea = width * 2; + dragDistance = pressPoint.x() - point.x(); + } else { + dragArea = height * 2; + dragDistance = point.y() - pressPoint.y(); + } + const qreal normalisedDifference = dragDistance / dragArea; + return qBound(0.0, positionBeforePress - normalisedDifference, 1.0); +} + void QQuickDialPrivate::setPosition(qreal pos) { Q_Q(QQuickDial); @@ -184,11 +222,17 @@ bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPos return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2; } +bool QQuickDialPrivate::isHorizontalOrVertical() const +{ + return inputMode == QQuickDial::Horizontal || inputMode == QQuickDial::Vertical; +} + void QQuickDialPrivate::handlePress(const QPointF &point) { Q_Q(QQuickDial); QQuickControlPrivate::handlePress(point); pressPoint = point; + positionBeforePress = position; q->setPressed(true); } @@ -201,7 +245,7 @@ void QQuickDialPrivate::handleMove(const QPointF &point) if (snapMode == QQuickDial::SnapAlways) pos = snapPosition(pos); - if (wrap || (!wrap && !isLargeChange(point, pos))) { + if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos)))) { if (live) q->setValue(valueAt(pos)); else @@ -221,7 +265,7 @@ void QQuickDialPrivate::handleRelease(const QPointF &point) if (snapMode != QQuickDial::NoSnap) pos = snapPosition(pos); - if (wrap || (!wrap && !isLargeChange(point, pos))) + if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos)))) q->setValue(valueAt(pos)); if (!qFuzzyCompare(pos, oldPos)) emit q->moved(); @@ -232,6 +276,7 @@ void QQuickDialPrivate::handleRelease(const QPointF &point) q->setPressed(false); pressPoint = QPointF(); + positionBeforePress = 0; } void QQuickDialPrivate::handleUngrab() @@ -239,6 +284,7 @@ void QQuickDialPrivate::handleUngrab() Q_Q(QQuickDial); QQuickControlPrivate::handleUngrab(); pressPoint = QPointF(); + positionBeforePress = 0; q->setPressed(false); } @@ -454,6 +500,32 @@ void QQuickDial::setSnapMode(SnapMode mode) } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty enumeration QtQuick.Controls::Dial::inputMode + + This property holds the input mode. + + \include qquickdial.qdocinc inputMode + + The default value is \c Dial.Circular. +*/ +QQuickDial::InputMode QQuickDial::inputMode() const +{ + Q_D(const QQuickDial); + return d->inputMode; +} + +void QQuickDial::setInputMode(QQuickDial::InputMode mode) +{ + Q_D(QQuickDial); + if (d->inputMode == mode) + return; + + d->inputMode = mode; + emit inputModeChanged(); +} + +/*! \qmlproperty bool QtQuick.Controls::Dial::wrap This property holds whether the dial wraps when dragged. diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h index d2caccfc..cc641c78 100644 --- a/src/quicktemplates2/qquickdial_p.h +++ b/src/quicktemplates2/qquickdial_p.h @@ -72,6 +72,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDial : public QQuickControl Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL) // 2.2 (Qt 5.9) Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2) + // 2.5 (Qt 5.12) + Q_PROPERTY(InputMode inputMode READ inputMode WRITE setInputMode NOTIFY inputModeChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,handle") public: @@ -103,6 +105,13 @@ public: SnapMode snapMode() const; void setSnapMode(SnapMode mode); + enum InputMode { + Circular, + Horizontal, + Vertical, + }; + Q_ENUM(InputMode) + bool wrap() const; void setWrap(bool wrap); @@ -116,6 +125,10 @@ public: bool live() const; void setLive(bool live); + // 2.5 (Qt 5.12) + InputMode inputMode() const; + void setInputMode(InputMode mode); + public Q_SLOTS: void increase(); void decrease(); @@ -134,6 +147,8 @@ Q_SIGNALS: // 2.2 (Qt 5.9) Q_REVISION(2) void moved(); Q_REVISION(2) void liveChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void inputModeChanged(); protected: void keyPressEvent(QKeyEvent *event) override; |