Added triple click on TextInput to select text.
authorRafael Brandao <rafael.lobo@openbossa.org>
Thu, 29 Sep 2011 00:53:15 +0000 (10:53 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 29 Sep 2011 01:00:38 +0000 (03:00 +0200)
Once it gets a double click, it'll start to monitor any other extra
click for a short duration. Once it is detected, the monitor stops
watching and all text is selected. It only works when selectByMouse
property is set, just like double click selecting current word.

Also added a test case that simulates clicking at the same point
and triggering the triple click, and another one that contemplates
movement of mouse between the second and the third click. Also test
timing between clicks.

Task-number: QTBUG-21038

Change-Id: I139f7ece2107f5dbfcba1836afb27aaa9b24fc57
Merge-request: 6
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
Reviewed-on: http://codereview.qt-project.org/5761
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
src/declarative/items/qsgtextinput.cpp
src/declarative/items/qsgtextinput_p_p.h
tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp

index ab6be66..cfb1c6f 100644 (file)
@@ -1088,6 +1088,10 @@ void QSGTextInput::mouseDoubleClickEvent(QMouseEvent *event)
         int cursor = d->xToPos(event->localPos().x());
         d->control->selectWordAtPos(cursor);
         event->setAccepted(true);
+        if (!d->hasPendingTripleClick()) {
+            d->tripleClickStartPoint = event->localPos().toPoint();
+            d->tripleClickTimer.start();
+        }
     } else {
         QSGImplicitSizeItem::mouseDoubleClickEvent(event);
     }
@@ -1116,6 +1120,13 @@ void QSGTextInput::mousePressEvent(QMouseEvent *event)
         setKeepMouseGrab(false);
         d->selectPressed = true;
         d->pressPos = event->localPos();
+        QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
+        if (d->hasPendingTripleClick()
+            && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
+            event->setAccepted(true);
+            selectAll();
+            return;
+        }
     }
     bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
     int cursor = d->xToPos(event->localPos().x());
index 49680ce..7022dd7 100644 (file)
 #include <private/qlinecontrol_p.h>
 
 #include <QtDeclarative/qdeclarative.h>
+#include <QtCore/qelapsedtimer.h>
 #include <QtCore/qpointer.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qstylehints.h>
 
 
 //
@@ -142,6 +145,8 @@ public:
     QPointer<QSGItem> cursorItem;
     QPointF pressPos;
     QSGTextNode *textNode;
+    QElapsedTimer tripleClickTimer;
+    QPoint tripleClickStartPoint;
 
     int lastSelectionStart;
     int lastSelectionEnd;
@@ -166,6 +171,9 @@ public:
     static inline QSGTextInputPrivate *get(QSGTextInput *t) {
         return t->d_func();
     }
+    bool hasPendingTripleClick() const {
+        return !tripleClickTimer.hasExpired(qApp->styleHints()->mouseDoubleClickInterval());
+    }
 };
 
 QT_END_NAMESPACE
index b522251..394c68d 100644 (file)
@@ -110,6 +110,7 @@ private slots:
     void dragMouseSelection();
     void mouseSelectionMode_data();
     void mouseSelectionMode();
+    void tripleClickSelectsAll();
 
     void horizontalAlignment_data();
     void horizontalAlignment();
@@ -2723,6 +2724,49 @@ void tst_qsgtextinput::cursorRectangleSize()
 #endif
 }
 
+void tst_qsgtextinput::tripleClickSelectsAll()
+{
+    QString qmlfile = SRCDIR "/data/positionAt.qml";
+    QSGView view(QUrl::fromLocalFile(qmlfile));
+    view.requestActivateWindow();
+    view.show();
+    QTest::qWaitForWindowShown(&view);
+
+    QEXPECT_FAIL("", QTBUG_21489_MESSAGE, Continue);
+    QTRY_COMPARE(view.windowState(), Qt::WindowActive);
+
+    QSGTextInput* input = qobject_cast<QSGTextInput*>(view.rootObject());
+    QVERIFY(input);
+
+    QLatin1String hello("Hello world!");
+    input->setSelectByMouse(true);
+    input->setText(hello);
+
+    // Clicking on the same point inside TextInput three times in a row
+    // should trigger a triple click, thus selecting all the text.
+    QPoint pointInside = input->pos().toPoint() + QPoint(2,2);
+    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+    QGuiApplication::processEvents();
+    QCOMPARE(input->selectedText(), hello);
+
+    // Now it simulates user moving the mouse between the second and the third click.
+    // In this situation, we don't expect a triple click.
+    QPoint pointInsideButFar = QPoint(input->width(),input->height()) - QPoint(2,2);
+    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInsideButFar);
+    QGuiApplication::processEvents();
+    QVERIFY(input->selectedText().isEmpty());
+
+    // And now we press the third click too late, so no triple click event is triggered.
+    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+    QGuiApplication::processEvents();
+    QTest::qWait(QApplication::doubleClickInterval() + 1);
+    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+    QGuiApplication::processEvents();
+    QVERIFY(input->selectedText().isEmpty());
+}
+
 QTEST_MAIN(tst_qsgtextinput)
 
 #include "tst_qsgtextinput.moc"