qt5base-lts/tests/auto/qtextcursor/tst_qtextcursor.cpp
Qt by Nokia 38be0d1383 Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:

http://qt.gitorious.org/qt/pages/GitIntroductionWithQt

If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.

Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
2011-04-27 12:05:43 +02:00

1863 lines
61 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qtextdocument.h>
#include <qtexttable.h>
#include <qvariant.h>
#include <qtextdocumentfragment.h>
#include <qabstracttextdocumentlayout.h>
#include <qtextlayout.h>
#include <qtextcursor.h>
#include <qdebug.h>
//TESTED_FILES=gui/text/qtextcursor.cpp gui/text/qtextcursor_p.h
QT_FORWARD_DECLARE_CLASS(QTextDocument)
class tst_QTextCursor : public QObject
{
Q_OBJECT
public:
tst_QTextCursor();
public slots:
void init();
void cleanup();
private slots:
void navigation1();
void navigation2_data();
void navigation2();
void navigation3();
void navigation4();
void navigation5();
void navigation6();
void navigation7();
void navigation8();
void navigation9();
void navigation10();
void movePositionEndOfLine();
void insertBlock();
void insertWithBlockSeparator1();
void insertWithBlockSeparator2();
void insertWithBlockSeparator3();
void insertWithBlockSeparator4();
void clearObjectType1();
void clearObjectType2();
void clearObjectType3();
void comparisonOperators1();
void comparisonOperators2();
void selection1();
void dontCopyTableAttributes();
void checkFrame1();
void checkFrame2();
void tableMovement();
void selectionsInTable();
void insertBlockToUseCharFormat();
void selectedText();
void insertBlockShouldRemoveSelection();
void insertBlockShouldRemoveSelection2();
void mergeCellShouldUpdateSelection();
void joinPreviousEditBlock();
void setBlockFormatInTable();
void blockCharFormat();
void blockCharFormat2();
void blockCharFormat3();
void blockCharFormatOnSelection();
void anchorInitialized1();
void anchorInitialized2();
void anchorInitialized3();
void selectWord();
void selectWordWithSeparators_data();
void selectWordWithSeparators();
void startOfWord();
void selectBlock();
void selectVisually();
void insertText();
void insertFragmentShouldUseCurrentCharFormat();
void endOfLine();
void editBlocksDuringRemove();
void selectAllDuringRemove();
void update_data();
void update();
void disallowSettingObjectIndicesOnCharFormats();
void blockAndColumnNumber();
void clearCells();
void task244408_wordUnderCursor_data();
void task244408_wordUnderCursor();
void adjustCursorsOnInsert();
void cursorPositionWithBlockUndoAndRedo();
void cursorPositionWithBlockUndoAndRedo2();
void cursorPositionWithBlockUndoAndRedo3();
private:
int blockCount();
QTextDocument *doc;
QTextCursor cursor;
};
Q_DECLARE_METATYPE(QList<QVariant>)
tst_QTextCursor::tst_QTextCursor()
{}
void tst_QTextCursor::init()
{
doc = new QTextDocument;
cursor = QTextCursor(doc);
}
void tst_QTextCursor::cleanup()
{
cursor = QTextCursor();
delete doc;
doc = 0;
}
void tst_QTextCursor::navigation1()
{
cursor.insertText("Hello World");
QVERIFY(doc->toPlainText() == "Hello World");
cursor.movePosition(QTextCursor::End);
QVERIFY(cursor.position() == 11);
cursor.deletePreviousChar();
QVERIFY(cursor.position() == 10);
cursor.deletePreviousChar();
cursor.deletePreviousChar();
cursor.deletePreviousChar();
cursor.deletePreviousChar();
cursor.deletePreviousChar();
QVERIFY(doc->toPlainText() == "Hello");
QTextCursor otherCursor(doc);
otherCursor.movePosition(QTextCursor::Start);
otherCursor.movePosition(QTextCursor::Right);
cursor = otherCursor;
cursor.movePosition(QTextCursor::Right);
QVERIFY(cursor != otherCursor);
otherCursor.insertText("Hey");
QVERIFY(cursor.position() == 5);
doc->undo();
QVERIFY(cursor.position() == 2);
doc->redo();
QVERIFY(cursor.position() == 5);
doc->undo();
doc->undo();
QVERIFY(doc->toPlainText() == "Hello World");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 6);
QVERIFY(cursor.position() == 6);
otherCursor = cursor;
otherCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2);
otherCursor.deletePreviousChar();
otherCursor.deletePreviousChar();
otherCursor.deletePreviousChar();
QVERIFY(cursor.position() == 5);
cursor.movePosition(QTextCursor::End);
cursor.insertBlock();
{
int oldPos = cursor.position();
cursor.movePosition(QTextCursor::End);
QVERIFY(cursor.position() == oldPos);
}
QVERIFY(cursor.atBlockStart());
QVERIFY(cursor.position() == 9);
QTextCharFormat fmt;
fmt.setForeground(Qt::blue);
cursor.insertText("Test", fmt);
QVERIFY(fmt == cursor.charFormat());
QVERIFY(cursor.position() == 13);
}
void tst_QTextCursor::navigation2_data()
{
QTest::addColumn<QStringList>("sl");
QTest::addColumn<QList<QVariant> >("movement");
QTest::addColumn<int>("finalPos");
QTest::newRow("startBlock1") << QStringList("Happy happy happy joy joy joy")
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)) << 0;
QTest::newRow("endBlock1") << QStringList("Happy happy happy joy joy joy")
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::EndOfBlock)) << 29;
QTest::newRow("startBlock2") << QStringList("Happy happy happy joy joy joy")
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::EndOfBlock)
<< QVariant(QTextCursor::StartOfBlock)) << 0;
QTest::newRow("endBlock2") << QStringList("Happy happy happy joy joy joy")
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::EndOfBlock)
<< QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::EndOfBlock)
) << 29;
QTest::newRow("multiBlock1") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock))
<< 18;
QTest::newRow("multiBlock2") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::EndOfBlock))
<< 29;
QTest::newRow("multiBlock3") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
<< QVariant(QTextCursor::StartOfBlock))
<< 18;
QTest::newRow("multiBlock4") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::Start)
<< QVariant(QTextCursor::EndOfBlock))
<< 17;
QTest::newRow("multiBlock5") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::Start)
<< QVariant(QTextCursor::EndOfBlock)
<< QVariant(QTextCursor::EndOfBlock))
<< 17;
QTest::newRow("multiBlock6") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::End)
<< QVariant(QTextCursor::StartOfBlock))
<< 18;
QTest::newRow("multiBlock7") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock))
<< 0;
QTest::newRow("multiBlock8") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
<< QVariant(QTextCursor::EndOfBlock))
<< 17;
QTest::newRow("multiBlock9") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
<< QVariant(QTextCursor::NextBlock))
<< 18;
QTest::newRow("multiBlock10") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
<< QVariant(QTextCursor::NextBlock)
<< QVariant(QTextCursor::NextBlock))
<< 18;
QTest::newRow("multiBlock11") << (QStringList() << QString("Happy happy happy")
<< QString("Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
<< QVariant(QTextCursor::NextBlock)
<< QVariant(QTextCursor::EndOfBlock))
<< 29;
QTest::newRow("PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousWord))
<< 26;
QTest::newRow("PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::PreviousWord))
<< 22;
QTest::newRow("EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::EndOfWord))
<< 25;
QTest::newRow("NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::NextWord))
<< 26;
QTest::newRow("NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::Start)
<< QVariant(QTextCursor::NextWord)
<< QVariant(QTextCursor::EndOfWord))
<< 11;
QTest::newRow("StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::PreviousWord)
<< QVariant(QTextCursor::StartOfWord))
<< 22;
QTest::newRow("StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::Start)
<< QVariant(QTextCursor::NextWord)
<< QVariant(QTextCursor::EndOfWord)
<< QVariant(QTextCursor::StartOfWord))
<< 6;
QTest::newRow("PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy"))
<< (QList<QVariant>() << QVariant(QTextCursor::PreviousCharacter)
<< QVariant(QTextCursor::PreviousCharacter))
<< 17;
}
void tst_QTextCursor::navigation2()
{
QFETCH(QStringList, sl);
QFETCH(QList<QVariant>, movement);
int i;
for (i = 0; i < sl.size(); ++i) {
cursor.insertText(sl.at(i));
if (i < sl.size() - 1)
cursor.insertBlock();
}
for (i = 0; i < movement.size(); ++i)
cursor.movePosition(QTextCursor::MoveOperation(movement.at(i).toInt()));
QTEST(cursor.position(), "finalPos");
}
void tst_QTextCursor::navigation3()
{
cursor.insertText("a");
cursor.deletePreviousChar();
QCOMPARE(cursor.position(), 0);
QVERIFY(doc->toPlainText().isEmpty());
}
void tst_QTextCursor::navigation4()
{
cursor.insertText(" Test ");
cursor.setPosition(4);
cursor.movePosition(QTextCursor::EndOfWord);
QCOMPARE(cursor.position(), 6);
}
void tst_QTextCursor::navigation5()
{
cursor.insertText("Test");
cursor.insertBlock();
cursor.insertText("Test");
cursor.setPosition(0);
cursor.movePosition(QTextCursor::EndOfBlock);
QCOMPARE(cursor.position(), 4);
}
void tst_QTextCursor::navigation6()
{
// triger creation of document layout, so that QTextLines are there
doc->documentLayout();
doc->setTextWidth(1000);
cursor.insertText("Test ");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfLine);
QCOMPARE(cursor.position(), 8);
}
void tst_QTextCursor::navigation7()
{
QVERIFY(doc->isEmpty());
for (int i = QTextCursor::Start; i <= QTextCursor::WordRight; ++i)
QVERIFY(!cursor.movePosition(QTextCursor::MoveOperation(i)));
doc->setPlainText("Hello World");
cursor.movePosition(QTextCursor::Start);
do {
} while (cursor.movePosition(QTextCursor::NextCharacter));
QVERIFY(true /*reached*/);
}
void tst_QTextCursor::navigation8()
{
cursor.insertList(QTextListFormat::ListDecimal);
QCOMPARE(cursor.position(), 1);
cursor.insertText("foo");
QCOMPARE(cursor.position(), 4);
cursor.insertList(QTextListFormat::ListCircle);
QCOMPARE(cursor.position(), 5);
cursor.insertText("something");
QCOMPARE(cursor.position(), 14);
cursor.movePosition(QTextCursor::PreviousCharacter);
QCOMPARE(cursor.position(), 13);
cursor.setPosition(2);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.position(), 3);
}
void tst_QTextCursor::navigation9()
{
cursor.insertText("Hello &-=+\t World");
cursor.movePosition(QTextCursor::PreviousWord);
QCOMPARE(cursor.position(), 15);
cursor.movePosition(QTextCursor::PreviousWord);
QCOMPARE(cursor.position(), 7);
cursor.movePosition(QTextCursor::PreviousWord);
QCOMPARE(cursor.position(), 0);
cursor.movePosition(QTextCursor::NextWord);
QCOMPARE(cursor.position(), 7);
cursor.movePosition(QTextCursor::NextWord);
QCOMPARE(cursor.position(), 15);
}
void tst_QTextCursor::navigation10()
{
doc->setHtml("<html><p>just a simple paragraph.</p>"
"<table>"
"<tr><td>Cell number 1</td><td>another cell</td><td></td><td>previous</br>is</br>empty</td></tr>"
"<tr><td>row 2</td><td colspan=\"2\">foo bar</td><td>last cell</td></tr>"
"<tr><td colspan=\"3\">row 3</td><td>a</td></tr>"
"</table></html");
QCOMPARE(cursor.position(), 101); // end of document
cursor.setPosition(0);
QCOMPARE(cursor.position(), 0);
bool ok = cursor.movePosition(QTextCursor::EndOfLine);
QVERIFY(ok);
QCOMPARE(cursor.position(), 24);
ok = cursor.movePosition(QTextCursor::NextBlock);
QCOMPARE(cursor.position(), 25); // cell 1
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 39); // another..
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 52); // empty
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 53); // last on row 1
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 69); // row 2
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 75);
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 83);
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 93); // row 3
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 99);
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok == false);
QCOMPARE(cursor.position(), 99); // didn't move.
QVERIFY(cursor.currentTable());
// same thing in reverse...
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 93);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 83);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 75);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 69);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 53);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 52);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 39);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 25);
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(!ok);
QCOMPARE(cursor.position(), 25); // can't leave the table
ok = cursor.movePosition(QTextCursor::NextRow);
QVERIFY(ok);
QCOMPARE(cursor.position(), 69);
ok = cursor.movePosition(QTextCursor::NextRow);
QVERIFY(ok);
QCOMPARE(cursor.position(), 93);
ok = cursor.movePosition(QTextCursor::NextRow);
QVERIFY(!ok);
QCOMPARE(cursor.position(), 93); // didn't move
ok = cursor.movePosition(QTextCursor::PreviousRow);
QVERIFY(ok);
QCOMPARE(cursor.position(), 83); // last col in row 2
ok = cursor.movePosition(QTextCursor::PreviousRow);
QVERIFY(ok);
QCOMPARE(cursor.position(), 53); // last col in row 1
ok = cursor.movePosition(QTextCursor::PreviousRow);
QVERIFY(!ok);
QCOMPARE(cursor.position(), 53);
// test usecase of jumping over a cell
doc->clear();
doc->setHtml("<html><table>tr><td rowspan=\"2\">a</td><td>b</td></tr><tr><td>c</td></tr></table></html>");
cursor.setPosition(1); // a
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 3); // b
ok = cursor.movePosition(QTextCursor::NextCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 5); // c
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 3); // b
ok = cursor.movePosition(QTextCursor::PreviousCell);
QVERIFY(ok);
QCOMPARE(cursor.position(), 1); // a
}
void tst_QTextCursor::insertBlock()
{
QTextBlockFormat fmt;
fmt.setTopMargin(100);
cursor.insertBlock(fmt);
QVERIFY(cursor.position() == 1);
QVERIFY(cursor.blockFormat() == fmt);
}
void tst_QTextCursor::insertWithBlockSeparator1()
{
QString text = "Hello" + QString(QChar::ParagraphSeparator) + "World";
cursor.insertText(text);
cursor.movePosition(QTextCursor::PreviousBlock);
QVERIFY(cursor.position() == 0);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.position() == 6);
}
void tst_QTextCursor::insertWithBlockSeparator2()
{
cursor.insertText(QString(QChar::ParagraphSeparator));
QVERIFY(cursor.position() == 1);
}
void tst_QTextCursor::insertWithBlockSeparator3()
{
cursor.insertText(QString(QChar::ParagraphSeparator) + "Hi" + QString(QChar::ParagraphSeparator));
QVERIFY(cursor.position() == 4);
}
void tst_QTextCursor::insertWithBlockSeparator4()
{
cursor.insertText(QString(QChar::ParagraphSeparator) + QString(QChar::ParagraphSeparator));
QVERIFY(cursor.position() == 2);
}
void tst_QTextCursor::clearObjectType1()
{
cursor.insertImage("test.png");
QVERIFY(cursor.charFormat().isValid());
QVERIFY(cursor.charFormat().isImageFormat());
cursor.insertText("Hey");
QVERIFY(cursor.charFormat().isValid());
QVERIFY(!cursor.charFormat().isImageFormat());
}
void tst_QTextCursor::clearObjectType2()
{
cursor.insertImage("test.png");
QVERIFY(cursor.charFormat().isValid());
QVERIFY(cursor.charFormat().isImageFormat());
cursor.insertBlock();
QVERIFY(cursor.charFormat().isValid());
QVERIFY(!cursor.charFormat().isImageFormat());
}
void tst_QTextCursor::clearObjectType3()
{
// like clearObjectType2 but tests different insertBlock overload
cursor.insertImage("test.png");
QVERIFY(cursor.charFormat().isValid());
QVERIFY(cursor.charFormat().isImageFormat());
QTextBlockFormat bfmt;
bfmt.setAlignment(Qt::AlignRight);
cursor.insertBlock(bfmt);
QVERIFY(cursor.charFormat().isValid());
QVERIFY(!cursor.charFormat().isImageFormat());
}
void tst_QTextCursor::comparisonOperators1()
{
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::PreviousWord);
QTextCursor startCursor = cursor;
startCursor.movePosition(QTextCursor::Start);
QVERIFY(startCursor < cursor);
QTextCursor midCursor = startCursor;
midCursor.movePosition(QTextCursor::NextWord);
QVERIFY(midCursor <= cursor);
QVERIFY(midCursor == cursor);
QVERIFY(midCursor >= cursor);
QVERIFY(midCursor > startCursor);
QVERIFY(midCursor != startCursor);
QVERIFY(!(midCursor == startCursor));
QTextCursor nullCursor;
QVERIFY(!(startCursor < nullCursor));
QVERIFY(!(nullCursor < nullCursor));
QVERIFY(nullCursor < startCursor);
QVERIFY(nullCursor <= startCursor);
QVERIFY(!(startCursor <= nullCursor));
QVERIFY(!(nullCursor >= startCursor));
QVERIFY(startCursor >= nullCursor);
QVERIFY(!(nullCursor > startCursor));
QVERIFY(!(nullCursor > nullCursor));
QVERIFY(startCursor > nullCursor);
}
void tst_QTextCursor::comparisonOperators2()
{
QTextDocument doc1;
QTextDocument doc2;
QTextCursor cursor1(&doc1);
QTextCursor cursor2(&doc2);
QVERIFY(cursor1 != cursor2);
QVERIFY(cursor1 == QTextCursor(&doc1));
}
void tst_QTextCursor::selection1()
{
cursor.insertText("Hello World");
cursor.setPosition(0);
cursor.clearSelection();
cursor.setPosition(4, QTextCursor::KeepAnchor);
QCOMPARE(cursor.selectionStart(), 0);
QCOMPARE(cursor.selectionEnd(), 4);
}
void tst_QTextCursor::dontCopyTableAttributes()
{
/* when pressing 'enter' inside a cell it shouldn't
* enlarge the table by adding another cell but just
* extend the cell */
QTextTable *table = cursor.insertTable(2, 2);
QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
cursor.insertBlock();
QCOMPARE(table->columns(), 2);
}
void tst_QTextCursor::checkFrame1()
{
QVERIFY(cursor.position() == 0);
QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
QVERIFY(frame != 0);
QTextFrame *root = frame->parentFrame();
QVERIFY(root != 0);
QVERIFY(frame->firstPosition() == 1);
QVERIFY(frame->lastPosition() == 1);
QVERIFY(frame->parentFrame() != 0);
QVERIFY(root->childFrames().size() == 1);
QVERIFY(cursor.position() == 1);
QVERIFY(cursor.selectionStart() == 1);
QVERIFY(cursor.selectionEnd() == 1);
doc->undo();
QVERIFY(!frame);
QVERIFY(root->childFrames().size() == 0);
QVERIFY(cursor.position() == 0);
QVERIFY(cursor.selectionStart() == 0);
QVERIFY(cursor.selectionEnd() == 0);
doc->redo();
frame = doc->frameAt(1);
QVERIFY(frame);
QVERIFY(frame->firstPosition() == 1);
QVERIFY(frame->lastPosition() == 1);
QVERIFY(frame->parentFrame() != 0);
QVERIFY(root->childFrames().size() == 1);
QVERIFY(cursor.position() == 1);
QVERIFY(cursor.selectionStart() == 1);
QVERIFY(cursor.selectionEnd() == 1);
// cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
// QVERIFY(cursor.position() == 2);
// QVERIFY(cursor.selectionStart() == 0);
// QVERIFY(cursor.selectionEnd() == 2);
}
void tst_QTextCursor::checkFrame2()
{
QVERIFY(cursor.position() == 0);
cursor.insertText("A");
QVERIFY(cursor.position() == 1);
cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
QTextFrame *root = frame->parentFrame();
QVERIFY(frame->firstPosition() == 1);
QVERIFY(frame->lastPosition() == 2);
QVERIFY(frame->parentFrame() != 0);
QVERIFY(root->childFrames().size() == 1);
QVERIFY(cursor.position() == 1);
QVERIFY(cursor.selectionStart() == 1);
QVERIFY(cursor.selectionEnd() == 2);
doc->undo();
QVERIFY(!frame);
QVERIFY(root->childFrames().size() == 0);
QVERIFY(cursor.position() == 0);
QVERIFY(cursor.selectionStart() == 0);
QVERIFY(cursor.selectionEnd() == 1);
doc->redo();
frame = doc->frameAt(1);
QVERIFY(frame);
QVERIFY(frame->firstPosition() == 1);
QVERIFY(frame->lastPosition() == 2);
QVERIFY(frame->parentFrame() != 0);
QVERIFY(root->childFrames().size() == 1);
QVERIFY(cursor.position() == 1);
QVERIFY(cursor.selectionStart() == 1);
QVERIFY(cursor.selectionEnd() == 2);
cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
QVERIFY(cursor.position() == 0);
QVERIFY(cursor.selectionStart() == 0);
QVERIFY(cursor.selectionEnd() == 3);
}
void tst_QTextCursor::insertBlockToUseCharFormat()
{
QTextCharFormat fmt;
fmt.setForeground(Qt::blue);
cursor.insertText("Hello", fmt);
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
cursor.insertBlock();
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
fmt.setForeground(Qt::red);
cursor.insertText("Hello\nWorld", fmt);
cursor.insertText("Blah");
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
// ### we might want a testcase for createTable, too, as it calls insertBlock, too,
// and we might want to have the char format copied (the one that gets inserted
// as table separators, that are undeletable)
}
void tst_QTextCursor::tableMovement()
{
QVERIFY(cursor.position() == 0);
cursor.insertText("AA");
QVERIFY(cursor.position() == 2);
cursor.movePosition(QTextCursor::Left);
cursor.insertTable(3, 3);
QCOMPARE(cursor.position(), 2);
cursor.movePosition(QTextCursor::Down);
QCOMPARE(cursor.position(), 5);
cursor.movePosition(QTextCursor::Right);
QCOMPARE(cursor.position(), 6);
cursor.movePosition(QTextCursor::Up);
QCOMPARE(cursor.position(), 3);
cursor.movePosition(QTextCursor::Right);
QCOMPARE(cursor.position(), 4);
cursor.movePosition(QTextCursor::Right);
QCOMPARE(cursor.position(), 5);
cursor.movePosition(QTextCursor::Up);
QCOMPARE(cursor.position(), 2);
cursor.movePosition(QTextCursor::Up);
QCOMPARE(cursor.position(), 0);
}
void tst_QTextCursor::selectionsInTable()
{
QTextTable *table = cursor.insertTable(2, 2);
table->cellAt(0, 0).firstCursorPosition().insertText("First");
table->cellAt(0, 1).firstCursorPosition().insertText("Second");
table->cellAt(1, 0).firstCursorPosition().insertText("Third");
table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
cursor = table->cellAt(0, 0).lastCursorPosition();
QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
cursor = table->cellAt(1, 0).lastCursorPosition();
QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
cursor = table->cellAt(0, 1).firstCursorPosition();
QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
cursor = table->cellAt(1, 1).firstCursorPosition();
QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
}
void tst_QTextCursor::selectedText()
{
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
QCOMPARE(cursor.selectedText(), QString("Hello World"));
}
void tst_QTextCursor::insertBlockShouldRemoveSelection()
{
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectedText(), QString("Hello"));
cursor.insertBlock();
QVERIFY(!cursor.hasSelection());
QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
}
void tst_QTextCursor::insertBlockShouldRemoveSelection2()
{
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectedText(), QString("Hello"));
QTextBlockFormat fmt = cursor.blockFormat();
cursor.insertBlock(fmt);
QVERIFY(!cursor.hasSelection());
QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
}
void tst_QTextCursor::mergeCellShouldUpdateSelection()
{
QTextTable *table = cursor.insertTable(4, 4);
cursor.setPosition(table->cellAt(0, 0).firstPosition());
cursor.setPosition(table->cellAt(3, 0).firstPosition(), QTextCursor::KeepAnchor); // aka bottom left
int firstRow, numRows, firstColumn, numColumns;
cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns);
QCOMPARE(firstRow, 0);
QCOMPARE(numRows, 4);
QCOMPARE(firstColumn, 0);
QCOMPARE(numColumns, 1);
table->removeColumns(firstColumn, numColumns);
QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
QCOMPARE(cursor.position(), table->cellAt(0, 0).firstPosition());
QCOMPARE(cursor.position(), cursor.anchor()); // empty. I don't really care where it ends up.
// prepare for another test with multiple cursors.
// note we have a 4 rows, 3 cols table now.
cursor.setPosition(table->cellAt(0, 0).firstPosition());
cursor.setPosition(table->cellAt(0, 2).firstPosition(), QTextCursor::KeepAnchor);
// now create a selection of a whole row.
QTextCursor c2 = table->cellAt(2, 0).firstCursorPosition();
c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
// just for good measure, another one for a block of cells.
QTextCursor c3 = table->cellAt(2, 1).firstCursorPosition();
c3.setPosition(table->cellAt(3, 2).firstPosition(), QTextCursor::KeepAnchor);
table->removeRows(2, 1);
QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
QCOMPARE(cursor.position(), table->cellAt(0, 2).firstPosition());
QCOMPARE(c2.position(), c2.anchor()); // empty. I don't really care where it ends up.
QCOMPARE(c3.anchor(), table->cellAt(2, 1).firstPosition());
QCOMPARE(c3.position(), table->cellAt(2, 2).firstPosition());
// prepare for another test where we remove a column
// note we have a 3 rows, 3 cols table now.
cursor.setPosition(table->cellAt(0, 0).firstPosition());
cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
c2.setPosition(table->cellAt(0, 1).firstPosition());
c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
table->removeColumns(1, 1);
QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
QCOMPARE(cursor.position(), table->cellAt(2, 0).firstPosition());
QCOMPARE(c2.anchor(), table->cellAt(0, 1).firstPosition());
QCOMPARE(c2.position(), table->cellAt(2, 1).firstPosition());
// test for illegal cursor positions.
// note we have a 3 rows, 2 cols table now.
cursor.setPosition(table->cellAt(2, 0).firstPosition());
cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
c2.setPosition(table->cellAt(0, 0).firstPosition());
c2.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
c3.setPosition(table->cellAt(2, 1).firstPosition());
table->removeRows(2, 1);
QCOMPARE(cursor.anchor(), table->cellAt(1, 1).lastPosition()+1);
QCOMPARE(cursor.position(), cursor.anchor());
QCOMPARE(c2.anchor(), table->cellAt(0, 0).firstPosition());
QCOMPARE(c2.position(), table->cellAt(1, 1).firstPosition());
QCOMPARE(c3.anchor(), table->cellAt(1, 1).firstPosition());
QCOMPARE(c3.position(), table->cellAt(1, 1).firstPosition());
}
void tst_QTextCursor::joinPreviousEditBlock()
{
cursor.beginEditBlock();
cursor.insertText("Hello");
cursor.insertText("World");
cursor.endEditBlock();
QVERIFY(doc->toPlainText().startsWith("HelloWorld"));
cursor.joinPreviousEditBlock();
cursor.insertText("Hey");
cursor.endEditBlock();
QVERIFY(doc->toPlainText().startsWith("HelloWorldHey"));
doc->undo();
QVERIFY(!doc->toPlainText().contains("HelloWorldHey"));
}
void tst_QTextCursor::setBlockFormatInTable()
{
// someone reported this on qt4-preview-feedback
QTextBlockFormat fmt;
fmt.setBackground(Qt::blue);
cursor.setBlockFormat(fmt);
QTextTable *table = cursor.insertTable(2, 2);
cursor = table->cellAt(0, 0).firstCursorPosition();
fmt.setBackground(Qt::red);
cursor.setBlockFormat(fmt);
cursor.movePosition(QTextCursor::Start);
QVERIFY(cursor.blockFormat().background().color() == Qt::blue);
}
void tst_QTextCursor::blockCharFormat2()
{
QTextCharFormat fmt;
fmt.setForeground(Qt::green);
cursor.mergeBlockCharFormat(fmt);
fmt.setForeground(Qt::red);
cursor.insertText("Test", fmt);
cursor.movePosition(QTextCursor::Start);
cursor.insertText("Red");
cursor.movePosition(QTextCursor::PreviousCharacter);
QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
}
void tst_QTextCursor::blockCharFormat3()
{
QVERIFY(cursor.atBlockStart());
QVERIFY(cursor.atBlockEnd());
QVERIFY(cursor.atStart());
QTextCharFormat fmt;
fmt.setForeground(Qt::green);
cursor.setBlockCharFormat(fmt);
cursor.insertText("Test");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter);
QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
cursor.movePosition(QTextCursor::Start);
QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
fmt.setForeground(Qt::red);
cursor.setBlockCharFormat(fmt);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
cursor.movePosition(QTextCursor::End);
cursor.movePosition(QTextCursor::Start);
QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
cursor.insertText("Test");
QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
cursor.select(QTextCursor::Document);
cursor.removeSelectedText();
QVERIFY(cursor.atBlockStart());
QVERIFY(cursor.atBlockEnd());
QVERIFY(cursor.atStart());
cursor.insertText("Test");
QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
}
void tst_QTextCursor::blockCharFormat()
{
QTextCharFormat fmt;
fmt.setForeground(Qt::blue);
cursor.insertBlock(QTextBlockFormat(), fmt);
cursor.insertText("Hm");
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
fmt.setForeground(Qt::red);
cursor.setBlockCharFormat(fmt);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
}
void tst_QTextCursor::blockCharFormatOnSelection()
{
QTextCharFormat fmt;
fmt.setForeground(Qt::blue);
cursor.insertBlock(QTextBlockFormat(), fmt);
fmt.setForeground(Qt::green);
cursor.insertText("Hm", fmt);
fmt.setForeground(Qt::red);
cursor.insertBlock(QTextBlockFormat(), fmt);
cursor.insertText("Ah");
fmt.setForeground(Qt::white);
cursor.insertBlock(QTextBlockFormat(), fmt);
cursor.insertText("bleh");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextBlock);
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
fmt.setForeground(Qt::cyan);
cursor.setBlockCharFormat(fmt);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
cursor.movePosition(QTextCursor::Right);
cursor.movePosition(QTextCursor::Right);
QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
}
void tst_QTextCursor::anchorInitialized1()
{
cursor.insertBlock();
cursor = QTextCursor(cursor.block());
QCOMPARE(cursor.position(), 1);
QCOMPARE(cursor.anchor(), 1);
QCOMPARE(cursor.selectionStart(), 1);
QCOMPARE(cursor.selectionEnd(), 1);
}
void tst_QTextCursor::anchorInitialized2()
{
cursor.insertBlock();
cursor = QTextCursor(cursor.block().docHandle(), 1);
QCOMPARE(cursor.position(), 1);
QCOMPARE(cursor.anchor(), 1);
QCOMPARE(cursor.selectionStart(), 1);
QCOMPARE(cursor.selectionEnd(), 1);
}
void tst_QTextCursor::anchorInitialized3()
{
QTextFrame *frame = cursor.insertFrame(QTextFrameFormat());
cursor = QTextCursor(frame);
QCOMPARE(cursor.position(), 1);
QCOMPARE(cursor.anchor(), 1);
QCOMPARE(cursor.selectionStart(), 1);
QCOMPARE(cursor.selectionEnd(), 1);
}
void tst_QTextCursor::selectWord()
{
cursor.insertText("first second third");
cursor.insertBlock();
cursor.insertText("words in second paragraph");
cursor.setPosition(9);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 6);
QCOMPARE(cursor.selectionEnd(), 12);
cursor.setPosition(5);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 0);
QCOMPARE(cursor.selectionEnd(), 5);
cursor.setPosition(6);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 6);
QCOMPARE(cursor.selectionEnd(), 12);
cursor.setPosition(14);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 6);
QCOMPARE(cursor.selectionEnd(), 12);
cursor.movePosition(QTextCursor::Start);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 0);
QCOMPARE(cursor.selectionEnd(), 5);
cursor.movePosition(QTextCursor::EndOfBlock);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selectionStart(), 17);
QCOMPARE(cursor.selectionEnd(), 22);
}
void tst_QTextCursor::selectWordWithSeparators_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<int>("initialPosition");
QTest::addColumn<QString>("expectedSelectedText");
QTest::newRow("dereference") << QString::fromLatin1("foo->bar()") << 1 << QString::fromLatin1("foo");
QTest::newRow("funcsignature") << QString::fromLatin1("bar(int x);") << 1 << QString::fromLatin1("bar");
QTest::newRow("def") << QString::fromLatin1("foo *f;") << 1 << QString::fromLatin1("foo");
}
void tst_QTextCursor::selectWordWithSeparators()
{
QFETCH(QString, text);
QFETCH(int, initialPosition);
QFETCH(QString, expectedSelectedText);
cursor.insertText(text);
cursor.setPosition(initialPosition);
cursor.select(QTextCursor::WordUnderCursor);
QCOMPARE(cursor.selectedText(), expectedSelectedText);
}
void tst_QTextCursor::startOfWord()
{
cursor.insertText("first second");
cursor.setPosition(7);
cursor.movePosition(QTextCursor::StartOfWord);
QCOMPARE(cursor.position(), 0);
}
void tst_QTextCursor::selectBlock()
{
cursor.insertText("foobar");
QTextBlockFormat blockFmt;
blockFmt.setAlignment(Qt::AlignHCenter);
cursor.insertBlock(blockFmt);
cursor.insertText("blah");
cursor.insertBlock(QTextBlockFormat());
cursor.movePosition(QTextCursor::PreviousBlock);
QCOMPARE(cursor.block().text(), QString("blah"));
cursor.select(QTextCursor::BlockUnderCursor);
QVERIFY(cursor.hasSelection());
QTextDocumentFragment fragment(cursor);
doc->clear();
cursor.insertFragment(fragment);
QCOMPARE(blockCount(), 2);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextBlock);
QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
QCOMPARE(cursor.block().text(), QString("blah"));
}
void tst_QTextCursor::selectVisually()
{
cursor.insertText("Foo\nlong line which is probably going to be cut in two when shown in a widget\nparagraph 3\n");
cursor.setPosition(6); // somewhere in the long paragraph.
cursor.select(QTextCursor::LineUnderCursor);
// since we are not yet layed-out, we expect the whole paragraph to be selected.
QCOMPARE(cursor.position(), 77);
QCOMPARE(cursor.anchor(), 4);
}
void tst_QTextCursor::insertText()
{
QString txt = "Foo\nBar\r\nMeep";
txt += QChar::LineSeparator;
txt += "Baz";
txt += QChar::ParagraphSeparator;
txt += "yoyodyne";
cursor.insertText(txt);
QCOMPARE(blockCount(), 4);
cursor.movePosition(QTextCursor::Start);
QCOMPARE(cursor.block().text(), QString("Foo"));
cursor.movePosition(QTextCursor::NextBlock);
QCOMPARE(cursor.block().text(), QString("Bar"));
cursor.movePosition(QTextCursor::NextBlock);
QCOMPARE(cursor.block().text(), QString(QString("Meep") + QChar(QChar::LineSeparator) + QString("Baz")));
cursor.movePosition(QTextCursor::NextBlock);
QCOMPARE(cursor.block().text(), QString("yoyodyne"));
}
void tst_QTextCursor::insertFragmentShouldUseCurrentCharFormat()
{
QTextDocumentFragment fragment = QTextDocumentFragment::fromPlainText("Hello World");
QTextCharFormat fmt;
fmt.setFontUnderline(true);
cursor.clearSelection();
cursor.setCharFormat(fmt);
cursor.insertFragment(fragment);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter);
QVERIFY(cursor.charFormat() == fmt);
}
int tst_QTextCursor::blockCount()
{
int cnt = 0;
for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next())
++cnt;
return cnt;
}
void tst_QTextCursor::endOfLine()
{
doc->setPageSize(QSizeF(100000, INT_MAX));
QString text("First Line \nSecond Line ");
text.replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
cursor.insertText(text);
// ensure layouted
doc->documentLayout()->documentSize();
cursor.movePosition(QTextCursor::Start);
QCOMPARE(cursor.block().layout()->lineCount(), 2);
cursor.movePosition(QTextCursor::EndOfLine);
QCOMPARE(cursor.position(), 14);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.position(), 15);
cursor.movePosition(QTextCursor::EndOfLine);
QCOMPARE(cursor.position(), 28);
}
class CursorListener : public QObject
{
Q_OBJECT
public:
CursorListener(QTextCursor *_cursor) : lastRecordedPosition(-1), lastRecordedAnchor(-1), recordingCount(0), cursor(_cursor) {}
int lastRecordedPosition;
int lastRecordedAnchor;
int recordingCount;
public slots:
void recordCursorPosition()
{
lastRecordedPosition = cursor->position();
lastRecordedAnchor = cursor->anchor();
++recordingCount;
}
void selectAllContents()
{
// Only test the first time
if (!recordingCount) {
recordingCount++;
cursor->select(QTextCursor::Document);
lastRecordedPosition = cursor->position();
lastRecordedAnchor = cursor->anchor();
}
}
private:
QTextCursor *cursor;
};
void tst_QTextCursor::editBlocksDuringRemove()
{
CursorListener listener(&cursor);
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
QCOMPARE(cursor.selectedText(), QString("Hello World"));
connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(recordCursorPosition()));
listener.recordingCount = 0;
cursor.deleteChar();
QCOMPARE(listener.recordingCount, 1);
QCOMPARE(listener.lastRecordedPosition, 0);
QCOMPARE(listener.lastRecordedAnchor, 0);
QVERIFY(doc->toPlainText().isEmpty());
}
void tst_QTextCursor::selectAllDuringRemove()
{
CursorListener listener(&cursor);
cursor.insertText("Hello World");
cursor.movePosition(QTextCursor::End);
connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(selectAllContents()));
listener.recordingCount = 0;
QTextCursor localCursor = cursor;
localCursor.deletePreviousChar();
QCOMPARE(listener.lastRecordedPosition, 10);
QCOMPARE(listener.lastRecordedAnchor, 0);
}
void tst_QTextCursor::update_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<int>("position");
QTest::addColumn<int>("anchor");
QTest::addColumn<int>("modifyPosition");
QTest::addColumn<int>("modifyAnchor");
QTest::addColumn<QString>("insertText");
QTest::addColumn<int>("expectedPosition");
QTest::addColumn<int>("expectedAnchor");
QString text("Hello big world");
int charsToDelete = 3;
QTest::newRow("removeInsideSelection")
<< text
<< /*position*/ 0
<< /*anchor*/ text.length()
// delete 'big'
<< 6
<< 6 + charsToDelete
<< QString() // don't insert anything, just remove
<< /*expectedPosition*/ 0
<< /*expectedAnchor*/ text.length() - charsToDelete
;
text = "Hello big world";
charsToDelete = 3;
QTest::newRow("removeInsideSelectionWithSwappedAnchorAndPosition")
<< text
<< /*position*/ text.length()
<< /*anchor*/ 0
// delete 'big'
<< 6
<< 6 + charsToDelete
<< QString() // don't insert anything, just remove
<< /*expectedPosition*/ text.length() - charsToDelete
<< /*expectedAnchor*/ 0
;
text = "Hello big world";
charsToDelete = 3;
QString textToInsert("small");
QTest::newRow("replaceInsideSelection")
<< text
<< /*position*/ 0
<< /*anchor*/ text.length()
// delete 'big' ...
<< 6
<< 6 + charsToDelete
<< textToInsert // ... and replace 'big' with 'small'
<< /*expectedPosition*/ 0
<< /*expectedAnchor*/ text.length() - charsToDelete + textToInsert.length()
;
text = "Hello big world";
charsToDelete = 3;
textToInsert = "small";
QTest::newRow("replaceInsideSelectionWithSwappedAnchorAndPosition")
<< text
<< /*position*/ text.length()
<< /*anchor*/ 0
// delete 'big' ...
<< 6
<< 6 + charsToDelete
<< textToInsert // ... and replace 'big' with 'small'
<< /*expectedPosition*/ text.length() - charsToDelete + textToInsert.length()
<< /*expectedAnchor*/ 0
;
text = "Hello big world";
charsToDelete = 3;
QTest::newRow("removeBeforeSelection")
<< text
<< /*position*/ text.length() - 5
<< /*anchor*/ text.length()
// delete 'big'
<< 6
<< 6 + charsToDelete
<< QString() // don't insert anything, just remove
<< /*expectedPosition*/ text.length() - 5 - charsToDelete
<< /*expectedAnchor*/ text.length() - charsToDelete
;
text = "Hello big world";
charsToDelete = 3;
QTest::newRow("removeAfterSelection")
<< text
<< /*position*/ 0
<< /*anchor*/ 4
// delete 'big'
<< 6
<< 6 + charsToDelete
<< QString() // don't insert anything, just remove
<< /*expectedPosition*/ 0
<< /*expectedAnchor*/ 4
;
}
void tst_QTextCursor::update()
{
QFETCH(QString, text);
doc->setPlainText(text);
QFETCH(int, position);
QFETCH(int, anchor);
cursor.setPosition(anchor);
cursor.setPosition(position, QTextCursor::KeepAnchor);
QCOMPARE(cursor.position(), position);
QCOMPARE(cursor.anchor(), anchor);
QFETCH(int, modifyPosition);
QFETCH(int, modifyAnchor);
QTextCursor modifyCursor = cursor;
modifyCursor.setPosition(modifyAnchor);
modifyCursor.setPosition(modifyPosition, QTextCursor::KeepAnchor);
QCOMPARE(modifyCursor.position(), modifyPosition);
QCOMPARE(modifyCursor.anchor(), modifyAnchor);
QFETCH(QString, insertText);
modifyCursor.insertText(insertText);
QFETCH(int, expectedPosition);
QFETCH(int, expectedAnchor);
QCOMPARE(cursor.position(), expectedPosition);
QCOMPARE(cursor.anchor(), expectedAnchor);
}
void tst_QTextCursor::disallowSettingObjectIndicesOnCharFormats()
{
QTextCharFormat fmt;
fmt.setObjectIndex(42);
cursor.insertText("Hey", fmt);
QCOMPARE(cursor.charFormat().objectIndex(), -1);
cursor.select(QTextCursor::Document);
cursor.mergeCharFormat(fmt);
QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
cursor.select(QTextCursor::Document);
cursor.setCharFormat(fmt);
QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
cursor.setBlockCharFormat(fmt);
QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
cursor.movePosition(QTextCursor::End);
cursor.insertBlock(QTextBlockFormat(), fmt);
QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
doc->clear();
QTextTable *table = cursor.insertTable(1, 1);
cursor.select(QTextCursor::Document);
cursor.setCharFormat(fmt);
cursor = table->cellAt(0, 0).firstCursorPosition();
QVERIFY(!cursor.isNull());
QCOMPARE(cursor.blockCharFormat().objectIndex(), table->objectIndex());
}
void tst_QTextCursor::blockAndColumnNumber()
{
QCOMPARE(QTextCursor().columnNumber(), 0);
QCOMPARE(QTextCursor().blockNumber(), 0);
QCOMPARE(cursor.columnNumber(), 0);
QCOMPARE(cursor.blockNumber(), 0);
cursor.insertText("Hello");
QCOMPARE(cursor.columnNumber(), 5);
QCOMPARE(cursor.blockNumber(), 0);
cursor.insertBlock();
QCOMPARE(cursor.columnNumber(), 0);
QCOMPARE(cursor.blockNumber(), 1);
cursor.insertText("Blah");
QCOMPARE(cursor.blockNumber(), 1);
// trigger a layout
doc->documentLayout();
cursor.insertBlock();
QCOMPARE(cursor.columnNumber(), 0);
QCOMPARE(cursor.blockNumber(), 2);
cursor.insertText("Test");
QCOMPARE(cursor.columnNumber(), 4);
QCOMPARE(cursor.blockNumber(), 2);
cursor.insertText(QString(QChar(QChar::LineSeparator)));
QCOMPARE(cursor.columnNumber(), 0);
QCOMPARE(cursor.blockNumber(), 2);
cursor.insertText("A");
QCOMPARE(cursor.columnNumber(), 1);
QCOMPARE(cursor.blockNumber(), 2);
}
void tst_QTextCursor::movePositionEndOfLine()
{
cursor.insertText("blah\nblah\n");
// Select part of the second line ("la")
cursor.setPosition(6);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
QCOMPARE(cursor.selectedText(), QLatin1String("la"));
// trigger a layout
doc->documentLayout();
// Remove "la" and append "something" to the end in one undo operation
cursor.beginEditBlock();
cursor.removeSelectedText();
QTextCursor c2(doc);
c2.setPosition(7);
c2.insertText("foo"); // append to doc without touching the cursor.
QCOMPARE(cursor.position(), 6);
cursor.movePosition(QTextCursor::EndOfLine); // in an edit block visual movement is moved to the end of the paragraph
QCOMPARE(cursor.position(), 10);
cursor.endEditBlock();
}
void tst_QTextCursor::clearCells()
{
QTextTable *table = cursor.insertTable(3, 5);
cursor.setPosition(table->cellAt(0,0).firstPosition()); // select cell 1 and cell 2
cursor.setPosition(table->cellAt(0,1).firstPosition(), QTextCursor::KeepAnchor);
cursor.deleteChar(); // should clear the cells, and not crash ;)
}
void tst_QTextCursor::task244408_wordUnderCursor_data()
{
QTest::addColumn<QString>("input");
QTest::addColumn<QString>("expected");
QTest::newRow("trailingSpace") << QString::fromLatin1("foo ") << QString::fromLatin1("");
QTest::newRow("noTrailingSpace") << QString::fromLatin1("foo") << QString::fromLatin1("foo");
}
void tst_QTextCursor::task244408_wordUnderCursor()
{
QFETCH(QString, input);
QFETCH(QString, expected);
cursor.insertText(input);
cursor.movePosition(QTextCursor::End);
cursor.select(QTextCursor::WordUnderCursor);
QCOMPARE(cursor.selectedText(), expected);
}
void tst_QTextCursor::adjustCursorsOnInsert()
{
cursor.insertText("Some text before ");
int posBefore = cursor.position();
cursor.insertText("selected text");
int posAfter = cursor.position();
cursor.insertText(" some text afterwards");
QTextCursor selection = cursor;
selection.setPosition(posBefore);
selection.setPosition(posAfter, QTextCursor::KeepAnchor);
cursor.setPosition(posBefore-1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.anchor(), posBefore+1);
QCOMPARE(selection.position(), posAfter+1);
doc->undo();
cursor.setPosition(posBefore);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.anchor(), posBefore+1);
QCOMPARE(selection.position(), posAfter+1);
doc->undo();
cursor.setPosition(posBefore+1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.anchor(), posBefore);
QCOMPARE(selection.position(), posAfter+1);
doc->undo();
cursor.setPosition(posAfter-1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.anchor(), posBefore);
QCOMPARE(selection.position(), posAfter+1);
doc->undo();
selection.setKeepPositionOnInsert(true);
cursor.setPosition(posAfter);
cursor.insertText(QLatin1String("x"));
selection.setKeepPositionOnInsert(false);
QCOMPARE(selection.anchor(), posBefore);
QCOMPARE(selection.position(), posAfter);
doc->undo();
cursor.setPosition(posAfter+1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.anchor(), posBefore);
QCOMPARE(selection.position(), posAfter);
doc->undo();
selection.setPosition(posAfter);
selection.setPosition(posBefore, QTextCursor::KeepAnchor);
cursor.setPosition(posBefore-1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore+1);
QCOMPARE(selection.anchor(), posAfter+1);
doc->undo();
cursor.setPosition(posBefore);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore+1);
QCOMPARE(selection.anchor(), posAfter+1);
doc->undo();
cursor.setPosition(posBefore+1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore);
QCOMPARE(selection.anchor(), posAfter+1);
doc->undo();
cursor.setPosition(posAfter-1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore);
QCOMPARE(selection.anchor(), posAfter+1);
doc->undo();
cursor.setPosition(posAfter);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore);
QCOMPARE(selection.anchor(), posAfter+1);
doc->undo();
cursor.setPosition(posAfter+1);
cursor.insertText(QLatin1String("x"));
QCOMPARE(selection.position(), posBefore);
QCOMPARE(selection.anchor(), posAfter);
doc->undo();
}
void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo()
{
cursor.insertText("AAAABBBBCCCCDDDD");
cursor.setPosition(12);
int cursorPositionBefore = cursor.position();
cursor.beginEditBlock();
cursor.insertText("*");
cursor.setPosition(8);
cursor.insertText("*");
cursor.setPosition(4);
cursor.insertText("*");
cursor.setPosition(0);
cursor.insertText("*");
int cursorPositionAfter = cursor.position();
cursor.endEditBlock();
QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
QCOMPARE(12, cursorPositionBefore);
QCOMPARE(1, cursorPositionAfter);
doc->undo(&cursor);
QVERIFY(doc->toPlainText() == "AAAABBBBCCCCDDDD");
QCOMPARE(cursor.position(), cursorPositionBefore);
doc->redo(&cursor);
QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
QCOMPARE(cursor.position(), cursorPositionAfter);
}
void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo2()
{
cursor.insertText("AAAABBBB");
int cursorPositionBefore = cursor.position();
cursor.setPosition(0, QTextCursor::KeepAnchor);
cursor.beginEditBlock();
cursor.removeSelectedText();
cursor.insertText("AAAABBBBCCCCDDDD");
cursor.endEditBlock();
doc->undo(&cursor);
QVERIFY(doc->toPlainText() == "AAAABBBB");
QCOMPARE(cursor.position(), cursorPositionBefore);
cursor.insertText("CCCC");
QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
cursorPositionBefore = cursor.position();
cursor.setPosition(0, QTextCursor::KeepAnchor);
cursor.beginEditBlock();
cursor.removeSelectedText();
cursor.insertText("AAAABBBBCCCCDDDD");
cursor.endEditBlock();
/* this undo now implicitely reinserts two segments, first "CCCCC", then
"AAAABBBB". The test ensures that the two are combined in order to
reconstruct the correct cursor position */
doc->undo(&cursor);
QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
QCOMPARE(cursor.position(), cursorPositionBefore);
}
void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo3()
{
// verify that it's the position of the beginEditBlock that counts, and not the last edit position
cursor.insertText("AAAABBBB");
int cursorPositionBefore = cursor.position();
cursor.beginEditBlock();
cursor.setPosition(4);
QVERIFY(cursor.position() != cursorPositionBefore);
cursor.insertText("*");
cursor.endEditBlock();
QCOMPARE(cursor.position(), 5);
doc->undo(&cursor);
QCOMPARE(cursor.position(), cursorPositionBefore);
}
QTEST_MAIN(tst_QTextCursor)
#include "tst_qtextcursor.moc"