From 7d22f04a0d2af6752fbbcaa970808a6e8d33399b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 3 Mar 2011 15:26:57 +1000 Subject: Fix word selection locking on string boundaries. QTextBoundaryFinder will return the position -1 if it reaches the end of a string without finding a boundary, reset the cursor and anchor to 0 or the string length as appropriate in those cases. Also allow selection to lock onto the string limits as if they were words. Change-Id: Ie9d233967c73eb6a61f19c76494f04bca18612f8 Task-number: QTBUG-17860 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextinput.cpp | 25 ++++---- .../tst_qdeclarativetextinput.cpp | 73 +++++++++++++++++++++- 2 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index f41ab03..8b21008 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1570,38 +1570,41 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) anchor = d->control->selectionStart(); if (anchor < pos || (anchor == pos && cursor < pos)) { - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + const QString text = d->control->text(); + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); finder.setPosition(anchor); const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (!(reasons & QTextBoundaryFinder::StartWord) + if (anchor < text.length() && !(reasons & QTextBoundaryFinder::StartWord) || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor)) { finder.toPreviousBoundary(); } - anchor = finder.position(); + anchor = finder.position() != -1 ? finder.position() : 0; finder.setPosition(pos); - if (!finder.isAtBoundary()) + if (pos > 0 && !finder.boundaryReasons()) finder.toNextBoundary(); + const int cursor = finder.position() != -1 ? finder.position() : text.length(); - d->control->setSelection(anchor, finder.position() - anchor); + d->control->setSelection(anchor, cursor - anchor); } else if (anchor > pos || (anchor == pos && cursor > pos)) { - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + const QString text = d->control->text(); + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); finder.setPosition(anchor); const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (!(reasons & QTextBoundaryFinder::EndWord) + if (anchor > 0 && !(reasons & QTextBoundaryFinder::EndWord) || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor)) { finder.toNextBoundary(); } - - anchor = finder.position(); + anchor = finder.position() != -1 ? finder.position() : text.length(); finder.setPosition(pos); - if (!finder.isAtBoundary()) + if (pos < text.length() && !finder.boundaryReasons()) finder.toPreviousBoundary(); + const int cursor = finder.position() != -1 ? finder.position() : 0; - d->control->setSelection(anchor, finder.position() - anchor); + d->control->setSelection(anchor, cursor - anchor); } } } diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 0320ce2..e7235f7 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -145,7 +145,8 @@ tst_qdeclarativetextinput::tst_qdeclarativetextinput() standard << "the quick brown fox jumped over the lazy dog" << "It's supercalifragisiticexpialidocious!" << "Hello, world!" - << "!dlrow ,olleH"; + << "!dlrow ,olleH" + << " spacey text "; colorStrings << "aliceblue" << "antiquewhite" @@ -446,6 +447,9 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() QTest::addColumn("selectionEnd"); QTest::addColumn("reversible"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + QTest::newRow("(t)he|characters") << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectCharacters << 0 << 1 << true; QTest::newRow("do(g)|characters") @@ -583,6 +587,24 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; QTest::newRow("!<()>dlrow|words") << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; + + QTest::newRow(" text |words") + << standard[4] << 1 << 4 << QDeclarativeTextInput::SelectWords << 1 << 7 << true; + QTest::newRow(" spacey |words") + << standard[4] << 11 << 13 << QDeclarativeTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365 + QTest::newRow("<( )>spacey text |words|ltr") + << standard[4] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << false; + QTest::newRow("<( )spacey> text |words|rtl") + << standard[4] << 1 << 0 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("spacey |words|ltr") + << standard[4] << 14 << 15 << QDeclarativeTextInput::SelectWords << 10 << 15 << false; +// QTBUG-11365 +// QTest::newRow("spacey text<( )>|words|rtl") +// << standard[4] << 15 << 14 << QDeclarativeTextInput::SelectWords << 14 << 15 << false; + QTest::newRow("<()> spacey text |words") + << standard[4] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << false; + QTest::newRow(" spacey text <()>|words") + << standard[4] << 15 << 15 << QDeclarativeTextInput::SelectWords << 15 << 15 << false; } void tst_qdeclarativetextinput::moveCursorSelection() @@ -629,6 +651,11 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() QTest::addColumn("selection2Start"); QTest::addColumn("selection2End"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + // ^ is the revised cursor position. + // {} contains the revised selection. + QTest::newRow("the { f^ox} jumped|ltr") << standard[0] << 9 << 13 << 17 @@ -741,6 +768,50 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() << 11 << 9 << 5 << 8 << 13 << 1 << 13; + + QTest::newRow("{<(^} sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 0 + << 0 << 7 + << 0 << 0; + QTest::newRow("{<( ^}sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 1 + << 0 << 7 + << 0 << 1; + QTest::newRow("<( {s^p)acey>} text |rtl") + << standard[4] + << 3 << 0 << 2 + << 0 << 7 + << 1 << 7; + QTest::newRow("<( {^sp)acey>} text |rtl") + << standard[4] + << 3 << 0 << 1 + << 0 << 7 + << 1 << 7; + + QTest::newRow(" spacey }|rtl") + << standard[4] + << 15 << 12 << 15 + << 10 << 15 + << 15 << 15; +// QTBUG-11365 +// QTest::newRow(" spacey }|rtl") +// << standard[4] +// << 15 << 12 << 14 +// << 10 << 15 +// << 14 << 15; + QTest::newRow(" spacey {|ltr") + << standard[4] + << 12 << 15 << 13 + << 10 << 15 + << 10 << 14; +// QTBUG-11365 +// QTest::newRow(" spacey {|ltr") +// << standard[4] +// << 12 << 15 << 14 +// << 10 << 15 +// << 10 << 14; } void tst_qdeclarativetextinput::moveCursorSelectionSequence() -- cgit v0.12