diff options
-rw-r--r-- | src/controls/qquicktextfield.cpp | 71 | ||||
-rw-r--r-- | src/controls/qquicktextfield_p.h | 6 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_textfield.qml | 52 |
3 files changed, 128 insertions, 1 deletions
diff --git a/src/controls/qquicktextfield.cpp b/src/controls/qquicktextfield.cpp index 694e3f5d..de6840bd 100644 --- a/src/controls/qquicktextfield.cpp +++ b/src/controls/qquicktextfield.cpp @@ -36,10 +36,12 @@ #include "qquicktextfield_p.h" +#include <QtCore/qbasictimer.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquicktext_p.h> #include <QtQuick/private/qquickclipnode_p.h> #include <QtQuick/private/qquicktextinput_p_p.h> +#include <QtQuick/private/qquickevents_p_p.h> QT_BEGIN_NAMESPACE @@ -72,17 +74,32 @@ QT_BEGIN_NAMESPACE \sa TextArea, {Customizing TextField} */ +/*! + \qmlsignal QtQuickControls2::TextField::pressAndHold(MouseEvent mouse) + + This signal is emitted when there is a long press (the delay depends on the platform plugin). + The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y + position of the press, and which button is pressed. +*/ + class QQuickTextFieldPrivate : public QQuickTextInputPrivate { Q_DECLARE_PUBLIC(QQuickTextField) public: - QQuickTextFieldPrivate() : background(Q_NULLPTR), placeholder(Q_NULLPTR) { } + QQuickTextFieldPrivate() + : background(Q_NULLPTR) + , placeholder(Q_NULLPTR) + , longPress(false) + { } void resizeBackground(); + bool isPressAndHoldConnected(); QQuickItem *background; QQuickText *placeholder; + QBasicTimer pressAndHoldTimer; + bool longPress; }; void QQuickTextFieldPrivate::resizeBackground() @@ -101,6 +118,12 @@ void QQuickTextFieldPrivate::resizeBackground() } } +bool QQuickTextFieldPrivate::isPressAndHoldConnected() +{ + Q_Q(QQuickTextField); + IS_SIGNAL_CONNECTED(q, QQuickTextField, pressAndHold, (QQuickMouseEvent *)); +} + QQuickTextField::QQuickTextField(QQuickItem *parent) : QQuickTextInput(*(new QQuickTextFieldPrivate), parent) { @@ -193,4 +216,50 @@ QSGNode *QQuickTextField::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData return clipNode; } +void QQuickTextField::mousePressEvent(QMouseEvent *event) +{ + Q_D(QQuickTextField); + d->longPress = false; + if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) + d->pressAndHoldTimer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), this); + else + d->pressAndHoldTimer.stop(); + QQuickTextInput::mousePressEvent(event); +} + +void QQuickTextField::mouseMoveEvent(QMouseEvent *event) +{ + Q_D(QQuickTextField); + if (qAbs(int(event->localPos().x() - d->pressPos.x())) > QGuiApplication::styleHints()->startDragDistance()) + d->pressAndHoldTimer.stop(); + if (!d->pressAndHoldTimer.isActive()) + QQuickTextInput::mouseMoveEvent(event); +} + +void QQuickTextField::mouseReleaseEvent(QMouseEvent *event) +{ + Q_D(QQuickTextField); + if (!d->longPress) { + d->pressAndHoldTimer.stop(); + QQuickTextInput::mouseReleaseEvent(event); + } +} + +void QQuickTextField::timerEvent(QTimerEvent *event) +{ + Q_D(QQuickTextField); + if (event->timerId() == d->pressAndHoldTimer.timerId()) { + d->pressAndHoldTimer.stop(); + d->longPress = true; + QQuickMouseEvent me(d->pressPos.x(), d->pressPos.y(), Qt::LeftButton, Qt::LeftButton, + QGuiApplication::keyboardModifiers(), false/*isClick*/, true/*wasHeld*/); + me.setAccepted(d->isPressAndHoldConnected()); + emit pressAndHold(&me); + if (!me.isAccepted()) + d->longPress = false; + } else { + QQuickTextInput::timerEvent(event); + } +} + QT_END_NAMESPACE diff --git a/src/controls/qquicktextfield_p.h b/src/controls/qquicktextfield_p.h index 41d39316..1cc7ffe4 100644 --- a/src/controls/qquicktextfield_p.h +++ b/src/controls/qquicktextfield_p.h @@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE class QQuickText; class QQuickTextFieldPrivate; +class QQuickMouseEvent; class Q_QUICKCONTROLS_EXPORT QQuickTextField : public QQuickTextInput { @@ -75,10 +76,15 @@ public: Q_SIGNALS: void backgroundChanged(); void placeholderChanged(); + void pressAndHold(QQuickMouseEvent *mouse); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QQuickTextField) diff --git a/tests/auto/controls/data/tst_textfield.qml b/tests/auto/controls/data/tst_textfield.qml index 4a55ef97..9ce325b3 100644 --- a/tests/auto/controls/data/tst_textfield.qml +++ b/tests/auto/controls/data/tst_textfield.qml @@ -60,4 +60,56 @@ TestCase { verify(control) control.destroy() } + + SignalSpy { + id: pressAndHoldSpy + signalName: "pressAndHold" + } + + function test_pressAndHold() { + var control = textField.createObject(testCase) + control.width = 200 + pressAndHoldSpy.target = control + + mouseClick(control) + compare(pressAndHoldSpy.count, 0) + var interval = Qt.styleHints.mousePressAndHoldInterval + + // Short press duration => nothing happens + mousePress(control) + wait(interval * 0.3) + mouseRelease(control) + compare(pressAndHoldSpy.count, 0) + + // Long enough press duration => signal emitted + mousePress(control, 10, 10) + // Add 10% extra time to allow the control to + // receive the timer event before we come back here + wait(interval * 1.1) + compare(pressAndHoldSpy.count, 1) + mouseRelease(control) + compare(pressAndHoldSpy.count, 1) + + // Long enough, but move in between => nothing happens + pressAndHoldSpy.clear() + mousePress(control) + wait(interval * 0.6) + mouseMove(control, 5, 5, Qt.LeftButton) + wait(interval * 0.6) + compare(pressAndHoldSpy.count, 0) + mouseRelease(control) + compare(pressAndHoldSpy.count, 0) + + // Long enough, but 2nd press in between => nothing happens + pressAndHoldSpy.clear() + mousePress(control, 10, 10) + wait(interval * 0.6) + mousePress(control, 10, 10, Qt.RightButton) + wait(interval * 0.6) + compare(pressAndHoldSpy.count, 0) + mouseRelease(control, 10, 10, Qt.LeftButton|Qt.RightButton) + compare(pressAndHoldSpy.count, 0) + + control.destroy() + } } |