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 <michael.brasser@live.com>
This commit is contained in:
Olivier JG 2016-12-07 11:57:03 -06:00 committed by Olivier de Gaalon
parent 0e80d28aa5
commit 17a1c12a45
6 changed files with 111 additions and 2 deletions

View File

@ -368,6 +368,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
#if QT_CONFIG(quick_shadereffect)
qmlRegisterType<QQuickBorderImageMesh>("QtQuick", 2, 8, "BorderImageMesh");
#endif
qmlRegisterType<QQuickMouseArea, 9>(uri, 2, 9, "MouseArea");
}
static void initResources()

View File

@ -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

View File

@ -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);

View File

@ -95,6 +95,7 @@ public:
bool propagateComposedEvents : 1;
bool overThreshold : 1;
Qt::MouseButtons pressed;
int pressAndHoldInterval;
#if QT_CONFIG(draganddrop)
QQuickDrag *drag;
#endif

View File

@ -0,0 +1,12 @@
import QtQuick 2.9
Item {
width: 100
height: 100
MouseArea {
id: mouseArea
objectName: "mouseArea"
anchors.fill: parent
}
}

View File

@ -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<int>("pressAndHoldInterval");
QTest::addColumn<int>("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<QQuickMouseArea*>("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"