From 17a1c12a4520c4ae756e7dd5c08b2386ef84673a Mon Sep 17 00:00:00 2001 From: Olivier JG Date: Wed, 7 Dec 2016 11:57:03 -0600 Subject: Add pressAndHoldInterval to MouseArea Introduce pressAndHoldInterval to allow setting the pressAndHold delay per-MouseArea. [ChangeLog][QtQml][MouseArea] Introduce pressAndHoldInterval property, which controls the elapsed time before pressAndHold is emitted. Task-Id: QTBUG-47662 Change-Id: Ic2173335033a6ed0d4b652333020f030de63a8e7 Reviewed-by: Michael Brasser --- src/quick/items/qquickitemsmodule.cpp | 2 + src/quick/items/qquickmousearea.cpp | 47 +++++++++++++++++++++- src/quick/items/qquickmousearea_p.h | 6 +++ src/quick/items/qquickmousearea_p_p.h | 1 + .../quick/qquickmousearea/data/pressAndHold.qml | 12 ++++++ .../quick/qquickmousearea/tst_qquickmousearea.cpp | 45 +++++++++++++++++++++ 6 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/auto/quick/qquickmousearea/data/pressAndHold.qml diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 8dd4a96b62..dbe30fbc83 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -368,6 +368,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #if QT_CONFIG(quick_shadereffect) qmlRegisterType("QtQuick", 2, 8, "BorderImageMesh"); #endif + + qmlRegisterType(uri, 2, 9, "MouseArea"); } static void initResources() diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 5e30bf9e0a..79c957832a 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -60,7 +60,8 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false), overThreshold(false), pressed(0) + propagateComposedEvents(false), overThreshold(false), pressed(0), + pressAndHoldInterval(-1) #if QT_CONFIG(draganddrop) , drag(0) #endif @@ -685,7 +686,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) #endif setHovered(true); d->startScene = event->windowPos(); - d->pressAndHoldTimer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), this); + d->pressAndHoldTimer.start(pressAndHoldInterval(), this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(event->button(), true, event->source())); } @@ -1294,6 +1295,48 @@ void QQuickMouseArea::setCursorShape(Qt::CursorShape shape) #endif + +/*! + \qmlproperty int QtQuick::MouseArea::pressAndHoldInterval + \since 5.9 + + This property overrides the elapsed time in milliseconds before + \c pressAndHold is emitted. + + If not explicitly set -- or after reset -- the value follows + \c QStyleHints::mousePressAndHoldInterval. + + Typically it's sufficient to set this property globally using the + application style hint. This property should be used when varying intervals + are needed for certain MouseAreas. + + \sa pressAndHold +*/ +int QQuickMouseArea::pressAndHoldInterval() const +{ + Q_D(const QQuickMouseArea); + return d->pressAndHoldInterval > -1 ? + d->pressAndHoldInterval : QGuiApplication::styleHints()->mousePressAndHoldInterval(); +} + +void QQuickMouseArea::setPressAndHoldInterval(int interval) +{ + Q_D(QQuickMouseArea); + if (interval != d->pressAndHoldInterval) { + d->pressAndHoldInterval = interval; + emit pressAndHoldIntervalChanged(); + } +} + +void QQuickMouseArea::resetPressAndHoldInterval() +{ + Q_D(QQuickMouseArea); + if (d->pressAndHoldInterval > -1) { + d->pressAndHoldInterval = -1; + emit pressAndHoldIntervalChanged(); + } +} + /*! \qmlpropertygroup QtQuick::MouseArea::drag \qmlproperty Item QtQuick::MouseArea::drag.target diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index d90c8e1baa..ee166a2082 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -84,6 +84,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) #endif Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 1) + Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION 9) public: QQuickMouseArea(QQuickItem *parent=0); @@ -125,6 +126,10 @@ public: void setCursorShape(Qt::CursorShape shape); #endif + int pressAndHoldInterval() const; + void setPressAndHoldInterval(int interval); + void resetPressAndHoldInterval(); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); @@ -152,6 +157,7 @@ Q_SIGNALS: void exited(); void canceled(); Q_REVISION(1) void containsPressChanged(); + Q_REVISION(9) void pressAndHoldIntervalChanged(); protected: void setHovered(bool); diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 456b1866a3..2fa5f7cd44 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -95,6 +95,7 @@ public: bool propagateComposedEvents : 1; bool overThreshold : 1; Qt::MouseButtons pressed; + int pressAndHoldInterval; #if QT_CONFIG(draganddrop) QQuickDrag *drag; #endif diff --git a/tests/auto/quick/qquickmousearea/data/pressAndHold.qml b/tests/auto/quick/qquickmousearea/data/pressAndHold.qml new file mode 100644 index 0000000000..bde195965e --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/pressAndHold.qml @@ -0,0 +1,12 @@ +import QtQuick 2.9 + +Item { + width: 100 + height: 100 + + MouseArea { + id: mouseArea + objectName: "mouseArea" + anchors.fill: parent + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index e1f903123b..c8351b9e18 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -127,6 +127,8 @@ private slots: void containsPress(); void ignoreBySource(); void notPressedAfterStolenGrab(); + void pressAndHold_data(); + void pressAndHold(); private: int startDragDistance() const { @@ -2098,6 +2100,49 @@ void tst_QQuickMouseArea::notPressedAfterStolenGrab() QVERIFY(!ma->pressed()); } +void tst_QQuickMouseArea::pressAndHold_data() +{ + QTest::addColumn("pressAndHoldInterval"); + QTest::addColumn("waitTime"); + + QTest::newRow("default") << -1 << QGuiApplication::styleHints()->mousePressAndHoldInterval(); + QTest::newRow("short") << 500 << 500; + QTest::newRow("long") << 1000 << 1000; +} + +void tst_QQuickMouseArea::pressAndHold() +{ + QFETCH(int, pressAndHoldInterval); + QFETCH(int, waitTime); + + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("pressAndHold.qml"), true, &errorMessage), errorMessage.constData()); + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QQuickItem *root = window.rootObject(); + QVERIFY(root != 0); + + QQuickMouseArea *mouseArea = window.rootObject()->findChild("mouseArea"); + QVERIFY(mouseArea != 0); + + QSignalSpy pressAndHoldSpy(mouseArea, &QQuickMouseArea::pressAndHold); + + if (pressAndHoldInterval > -1) + mouseArea->setPressAndHoldInterval(pressAndHoldInterval); + else + mouseArea->resetPressAndHoldInterval(); + + QElapsedTimer t; + t.start(); + QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50)); + QVERIFY(pressAndHoldSpy.wait()); + // should be off by no more than 20% of waitTime + QVERIFY(qAbs(t.elapsed() - waitTime) < (waitTime * 0.2)); + QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50)); +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" -- cgit v1.2.3