From 5c639a07fd90916d39823e800d5d89f779d892e9 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 18 Nov 2016 15:02:18 +0100 Subject: TapHandler: add long-press feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a longPressed signal, emitted when the point is held long enough. Add the longPressThreshold to control how long that is. Change-Id: I95a65f1e4c62eb41fb9ea02b14bdc3f16aa72ec2 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquicktaphandler.cpp | 44 ++++++++++++++++++++++++++++++++- src/quick/handlers/qquicktaphandler_p.h | 11 +++++++++ tests/manual/pointer/tapHandler.qml | 19 ++++++++++---- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index e0e66be01c..f1bb2f96b6 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -83,6 +83,7 @@ QQuickTapHandler::QQuickTapHandler(QObject *parent) : QQuickPointerSingleHandler(parent) , m_pressed(false) , m_tapCount(0) + , m_longPressThreshold(-1) , m_lastTapTimestamp(0.0) { setAcceptedButtons(Qt::LeftButton); @@ -127,11 +128,52 @@ void QQuickTapHandler::handleEventPoint(QQuickEventPoint *point) } } +/*! + \qmlproperty longPressThreshold + + The time in seconds that an event point must be pressed in order to + trigger a long press gesture and emit the \l longPressed() signal. + If the point is released before this time limit, a tap can be detected + if the other constraints are satisfied. The default value is + QStyleHints::mousePressAndHoldInterval() converted to seconds. +*/ +qreal QQuickTapHandler::longPressThreshold() const +{ + return longPressThresholdMilliseconds() / 1000.0; +} + +void QQuickTapHandler::setLongPressThreshold(qreal longPressThreshold) +{ + int ms = qRound(longPressThreshold * 1000); + if (m_longPressThreshold == ms) + return; + + m_longPressThreshold = ms; + emit longPressThresholdChanged(); +} + +int QQuickTapHandler::longPressThresholdMilliseconds() const +{ + return (m_longPressThreshold < 0 ? QGuiApplication::styleHints()->mousePressAndHoldInterval() : m_longPressThreshold); +} + +void QQuickTapHandler::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_longPressTimer.timerId()) { + m_longPressTimer.stop(); + emit longPressed(); + } +} + void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *point) { if (m_pressed != press) { m_pressed = press; - if (!cancel && !press && point->timeHeld() < m_multiTapInterval) { + if (press) + m_longPressTimer.start(longPressThresholdMilliseconds(), this); + else + m_longPressTimer.stop(); + if (!cancel && !press && point->timeHeld() < longPressThreshold()) { // Assuming here that pointerEvent()->timestamp() is in ms. qreal ts = point->pointerEvent()->timestamp() / 1000.0; if (ts - m_lastTapTimestamp < m_multiTapInterval && diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h index c11d51ee03..0559089fbf 100644 --- a/src/quick/handlers/qquicktaphandler_p.h +++ b/src/quick/handlers/qquicktaphandler_p.h @@ -54,6 +54,7 @@ #include "qquickitem.h" #include "qevent.h" #include "qquickpointersinglehandler_p.h" +#include QT_BEGIN_NAMESPACE @@ -62,6 +63,7 @@ class Q_AUTOTEST_EXPORT QQuickTapHandler : public QQuickPointerSingleHandler Q_OBJECT Q_PROPERTY(bool isPressed READ isPressed NOTIFY pressedChanged) Q_PROPERTY(int tapCount READ tapCount NOTIFY tapCountChanged) + Q_PROPERTY(qreal longPressThreshold READ longPressThreshold WRITE setLongPressThreshold NOTIFY longPressThresholdChanged) public: QQuickTapHandler(QObject *parent = 0); @@ -74,20 +76,29 @@ public: int tapCount() const { return m_tapCount; } + qreal longPressThreshold() const; + void setLongPressThreshold(qreal longPressThreshold); + Q_SIGNALS: void pressedChanged(); void tapCountChanged(); + void longPressThresholdChanged(); void tapped(QQuickEventPoint *point); + void longPressed(); protected: void handleGrabCancel(QQuickEventPoint *point) override; + void timerEvent(QTimerEvent *event) override; private: void setPressed(bool press, bool cancel, QQuickEventPoint *point); + int longPressThresholdMilliseconds() const; private: bool m_pressed; int m_tapCount; + int m_longPressThreshold; + QBasicTimer m_longPressTimer; QPointF m_lastTapPos; qreal m_lastTapTimestamp; diff --git a/tests/manual/pointer/tapHandler.qml b/tests/manual/pointer/tapHandler.qml index d099fc7faf..f2a454fb80 100644 --- a/tests/manual/pointer/tapHandler.qml +++ b/tests/manual/pointer/tapHandler.qml @@ -57,6 +57,11 @@ Item { acceptedButtons: (leftAllowedCB.checked ? Qt.LeftButton : Qt.NoButton) | (middleAllowedCB.checked ? Qt.MiddleButton : Qt.NoButton) | (rightAllowedCB.checked ? Qt.RightButton : Qt.NoButton) + onPressedButtonsChanged: switch (pressedButtons) { + case Qt.MiddleButton: borderBlink.blinkColor = "orange"; break; + case Qt.RightButton: borderBlink.blinkColor = "magenta"; break; + default: borderBlink.blinkColor = "green"; break; + } onCanceled: { console.log("canceled @ " + pos) borderBlink.blinkColor = "red" @@ -68,14 +73,13 @@ Item { tapCountLabel.text = tapCount flashAnimation.start() } else { - switch (point.event.button) { - case Qt.LeftButton: borderBlink.blinkColor = "green"; break; - case Qt.MiddleButton: borderBlink.blinkColor = "orange"; break; - case Qt.RightButton: borderBlink.blinkColor = "magenta"; break; - } borderBlink.start() } } + onLongPressed: longPressFeedback.createObject(rect, + {"x": pos.x, "y": pos.y, + "text": "long press", + "color": borderBlink.blinkColor}) } Text { @@ -105,6 +109,11 @@ Item { } } + Component { + id: longPressFeedback + Text { } + } + SequentialAnimation { id: borderBlink property color blinkColor: "blue" -- cgit v1.2.3