Skip to content

Commit

Permalink
Added triple click on TextInput to select text.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rafael Brandao authored and Qt by Nokia committed Sep 29, 2011
1 parent 55b4b63 commit 40f6318
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/declarative/items/qsgtextinput.cpp
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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());
Expand Down
8 changes: 8 additions & 0 deletions src/declarative/items/qsgtextinput_p_p.h
Expand Up @@ -50,7 +50,10 @@
#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>


//
Expand Down Expand Up @@ -142,6 +145,8 @@ class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizeItemPrivate
QPointer<QSGItem> cursorItem;
QPointF pressPos;
QSGTextNode *textNode;
QElapsedTimer tripleClickTimer;
QPoint tripleClickStartPoint;

int lastSelectionStart;
int lastSelectionEnd;
Expand All @@ -166,6 +171,9 @@ class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizeItemPrivate
static inline QSGTextInputPrivate *get(QSGTextInput *t) {
return t->d_func();
}
bool hasPendingTripleClick() const {
return !tripleClickTimer.hasExpired(qApp->styleHints()->mouseDoubleClickInterval());
}
};

QT_END_NAMESPACE
Expand Down
44 changes: 44 additions & 0 deletions tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
Expand Up @@ -110,6 +110,7 @@ private slots:
void dragMouseSelection();
void mouseSelectionMode_data();
void mouseSelectionMode();
void tripleClickSelectsAll();

void horizontalAlignment_data();
void horizontalAlignment();
Expand Down Expand Up @@ -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"

0 comments on commit 40f6318

Please sign in to comment.