1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#include <qtextdocument.h>
33#include <qtexttable.h>
34#include <qvariant.h>
35#include <qtextdocumentfragment.h>
36#include <qabstracttextdocumentlayout.h>
37#include <qtextlayout.h>
38#include <qtextcursor.h>
39#include <qtextobject.h>
40#include <qdebug.h>
41
42#include <private/qtextcursor_p.h>
43
44QT_FORWARD_DECLARE_CLASS(QTextDocument)
45
46class tst_QTextCursor : public QObject
47{
48 Q_OBJECT
49
50private slots:
51 void init();
52 void cleanup();
53 void navigation1();
54 void navigation2_data();
55 void navigation2();
56 void navigation3();
57 void navigation4();
58 void navigation5();
59 void navigation6();
60 void navigation7();
61 void navigation8();
62 void navigation9();
63 void navigation10();
64 void movePositionEndOfLine();
65 void insertBlock();
66 void insertWithBlockSeparator1();
67 void insertWithBlockSeparator2();
68 void insertWithBlockSeparator3();
69 void insertWithBlockSeparator4();
70 void clearObjectType1();
71 void clearObjectType2();
72 void clearObjectType3();
73 void comparisonOperators1();
74 void comparisonOperators2();
75 void selection1();
76 void dontCopyTableAttributes();
77
78 void checkFrame1();
79 void checkFrame2();
80
81 void tableMovement();
82 void selectionsInTable();
83
84 void insertBlockToUseCharFormat();
85
86 void selectedText();
87
88 void insertBlockShouldRemoveSelection();
89 void insertBlockShouldRemoveSelection2();
90 void mergeCellShouldUpdateSelection();
91
92 void joinPreviousEditBlock();
93
94 void setBlockFormatInTable();
95
96 void blockCharFormat();
97 void blockCharFormat2();
98 void blockCharFormat3();
99 void blockCharFormatOnSelection();
100
101 void anchorInitialized1();
102 void anchorInitialized2();
103 void anchorInitialized3();
104
105 void selectWord();
106 void selectWordWithSeparators_data();
107 void selectWordWithSeparators();
108 void startOfWord();
109 void selectBlock();
110 void selectVisually();
111
112 void insertText();
113
114 void insertFragmentShouldUseCurrentCharFormat();
115
116 void endOfLine();
117
118 void editBlocksDuringRemove();
119 void selectAllDuringRemove();
120
121 void update_data();
122 void update();
123
124 void disallowSettingObjectIndicesOnCharFormats();
125
126 void blockAndColumnNumber();
127
128 void clearCells();
129
130 void task244408_wordUnderCursor_data();
131 void task244408_wordUnderCursor();
132
133 void adjustCursorsOnInsert();
134
135 void cursorPositionWithBlockUndoAndRedo();
136 void cursorPositionWithBlockUndoAndRedo2();
137 void cursorPositionWithBlockUndoAndRedo3();
138
139 void joinNonEmptyRemovedBlockUserState();
140 void crashOnDetachingDanglingCursor();
141
142private:
143 int blockCount();
144
145 QTextDocument *doc;
146 QTextCursor cursor;
147};
148
149void tst_QTextCursor::init()
150{
151 doc = new QTextDocument;
152 cursor = QTextCursor(doc);
153}
154
155void tst_QTextCursor::cleanup()
156{
157 cursor = QTextCursor();
158 delete doc;
159 doc = 0;
160}
161
162void tst_QTextCursor::navigation1()
163{
164
165 cursor.insertText(text: "Hello World");
166 QCOMPARE(doc->toPlainText(), QLatin1String("Hello World"));
167
168 cursor.movePosition(op: QTextCursor::End);
169 QCOMPARE(cursor.position(), 11);
170 cursor.deletePreviousChar();
171 QCOMPARE(cursor.position(), 10);
172 cursor.deletePreviousChar();
173 cursor.deletePreviousChar();
174 cursor.deletePreviousChar();
175 cursor.deletePreviousChar();
176 cursor.deletePreviousChar();
177 QCOMPARE(doc->toPlainText(), QLatin1String("Hello"));
178
179 QTextCursor otherCursor(doc);
180 otherCursor.movePosition(op: QTextCursor::Start);
181 otherCursor.movePosition(op: QTextCursor::Right);
182 cursor = otherCursor;
183 cursor.movePosition(op: QTextCursor::Right);
184 QVERIFY(cursor != otherCursor);
185 otherCursor.insertText(text: "Hey");
186 QCOMPARE(cursor.position(), 5);
187
188 doc->undo();
189 QCOMPARE(cursor.position(), 2);
190 doc->redo();
191 QCOMPARE(cursor.position(), 5);
192
193 doc->undo();
194
195 doc->undo();
196 QCOMPARE(doc->toPlainText(), QLatin1String("Hello World"));
197
198 cursor.movePosition(op: QTextCursor::Start);
199 cursor.movePosition(op: QTextCursor::Right, QTextCursor::MoveAnchor, n: 6);
200 QCOMPARE(cursor.position(), 6);
201 otherCursor = cursor;
202 otherCursor.movePosition(op: QTextCursor::Right, QTextCursor::MoveAnchor, n: 2);
203 otherCursor.deletePreviousChar();
204 otherCursor.deletePreviousChar();
205 otherCursor.deletePreviousChar();
206 QCOMPARE(cursor.position(), 5);
207
208 cursor.movePosition(op: QTextCursor::End);
209 cursor.insertBlock();
210 {
211 int oldPos = cursor.position();
212 cursor.movePosition(op: QTextCursor::End);
213 QCOMPARE(cursor.position(), oldPos);
214 }
215 QVERIFY(cursor.atBlockStart());
216 QCOMPARE(cursor.position(), 9);
217
218 QTextCharFormat fmt;
219 fmt.setForeground(Qt::blue);
220 cursor.insertText(text: "Test", format: fmt);
221 QCOMPARE(fmt, cursor.charFormat());
222 QCOMPARE(cursor.position(), 13);
223}
224
225void tst_QTextCursor::navigation2_data()
226{
227 QTest::addColumn<QStringList>(name: "sl");
228 QTest::addColumn<QList<QVariant> >(name: "movement");
229 QTest::addColumn<int>(name: "finalPos");
230
231 QTest::newRow(dataTag: "startBlock1") << QStringList("Happy happy happy joy joy joy")
232 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)) << 0;
233 QTest::newRow(dataTag: "endBlock1") << QStringList("Happy happy happy joy joy joy")
234 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
235 << QVariant(QTextCursor::EndOfBlock)) << 29;
236 QTest::newRow(dataTag: "startBlock2") << QStringList("Happy happy happy joy joy joy")
237 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
238 << QVariant(QTextCursor::EndOfBlock)
239 << QVariant(QTextCursor::StartOfBlock)) << 0;
240 QTest::newRow(dataTag: "endBlock2") << QStringList("Happy happy happy joy joy joy")
241 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
242 << QVariant(QTextCursor::EndOfBlock)
243 << QVariant(QTextCursor::StartOfBlock)
244 << QVariant(QTextCursor::EndOfBlock)
245 ) << 29;
246 QTest::newRow(dataTag: "multiBlock1") << (QStringList() << QString("Happy happy happy")
247 << QString("Joy Joy Joy"))
248 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock))
249 << 18;
250 QTest::newRow(dataTag: "multiBlock2") << (QStringList() << QString("Happy happy happy")
251 << QString("Joy Joy Joy"))
252 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
253 << QVariant(QTextCursor::EndOfBlock))
254 << 29;
255 QTest::newRow(dataTag: "multiBlock3") << (QStringList() << QString("Happy happy happy")
256 << QString("Joy Joy Joy"))
257 << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
258 << QVariant(QTextCursor::StartOfBlock))
259 << 18;
260 QTest::newRow(dataTag: "multiBlock4") << (QStringList() << QString("Happy happy happy")
261 << QString("Joy Joy Joy"))
262 << (QList<QVariant>() << QVariant(QTextCursor::Start)
263 << QVariant(QTextCursor::EndOfBlock))
264 << 17;
265 QTest::newRow(dataTag: "multiBlock5") << (QStringList() << QString("Happy happy happy")
266 << QString("Joy Joy Joy"))
267 << (QList<QVariant>() << QVariant(QTextCursor::Start)
268 << QVariant(QTextCursor::EndOfBlock)
269 << QVariant(QTextCursor::EndOfBlock))
270 << 17;
271 QTest::newRow(dataTag: "multiBlock6") << (QStringList() << QString("Happy happy happy")
272 << QString("Joy Joy Joy"))
273 << (QList<QVariant>() << QVariant(QTextCursor::End)
274 << QVariant(QTextCursor::StartOfBlock))
275 << 18;
276 QTest::newRow(dataTag: "multiBlock7") << (QStringList() << QString("Happy happy happy")
277 << QString("Joy Joy Joy"))
278 << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock))
279 << 0;
280 QTest::newRow(dataTag: "multiBlock8") << (QStringList() << QString("Happy happy happy")
281 << QString("Joy Joy Joy"))
282 << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
283 << QVariant(QTextCursor::EndOfBlock))
284 << 17;
285 QTest::newRow(dataTag: "multiBlock9") << (QStringList() << QString("Happy happy happy")
286 << QString("Joy Joy Joy"))
287 << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
288 << QVariant(QTextCursor::NextBlock))
289 << 18;
290 QTest::newRow(dataTag: "multiBlock10") << (QStringList() << QString("Happy happy happy")
291 << QString("Joy Joy Joy"))
292 << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
293 << QVariant(QTextCursor::NextBlock)
294 << QVariant(QTextCursor::NextBlock))
295 << 18;
296 QTest::newRow(dataTag: "multiBlock11") << (QStringList() << QString("Happy happy happy")
297 << QString("Joy Joy Joy"))
298 << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
299 << QVariant(QTextCursor::NextBlock)
300 << QVariant(QTextCursor::EndOfBlock))
301 << 29;
302 QTest::newRow(dataTag: "PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
303 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord))
304 << 26;
305 QTest::newRow(dataTag: "PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
306 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
307 << QVariant(QTextCursor::PreviousWord))
308 << 22;
309 QTest::newRow(dataTag: "EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
310 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
311 << QVariant(QTextCursor::PreviousWord)
312 << QVariant(QTextCursor::EndOfWord))
313 << 25;
314 QTest::newRow(dataTag: "NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
315 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
316 << QVariant(QTextCursor::PreviousWord)
317 << QVariant(QTextCursor::NextWord))
318 << 26;
319 QTest::newRow(dataTag: "NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
320 << (QList<QVariant>() << QVariant(QTextCursor::Start)
321 << QVariant(QTextCursor::NextWord)
322 << QVariant(QTextCursor::EndOfWord))
323 << 11;
324 QTest::newRow(dataTag: "StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
325 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
326 << QVariant(QTextCursor::PreviousWord)
327 << QVariant(QTextCursor::StartOfWord))
328 << 22;
329 QTest::newRow(dataTag: "StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
330 << (QList<QVariant>() << QVariant(QTextCursor::Start)
331 << QVariant(QTextCursor::NextWord)
332 << QVariant(QTextCursor::EndOfWord)
333 << QVariant(QTextCursor::StartOfWord))
334 << 6;
335
336 QTest::newRow(dataTag: "PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy"))
337 << (QList<QVariant>() << QVariant(QTextCursor::PreviousCharacter)
338 << QVariant(QTextCursor::PreviousCharacter))
339 << 17;
340}
341
342void tst_QTextCursor::navigation2()
343{
344 QFETCH(QStringList, sl);
345 QFETCH(QList<QVariant>, movement);
346 int i;
347 for (i = 0; i < sl.size(); ++i) {
348 cursor.insertText(text: sl.at(i));
349 if (i < sl.size() - 1)
350 cursor.insertBlock();
351 }
352
353 for (i = 0; i < movement.size(); ++i)
354 cursor.movePosition(op: QTextCursor::MoveOperation(movement.at(i).toInt()));
355 QTEST(cursor.position(), "finalPos");
356}
357
358void tst_QTextCursor::navigation3()
359{
360 cursor.insertText(text: "a");
361 cursor.deletePreviousChar();
362 QCOMPARE(cursor.position(), 0);
363 QVERIFY(doc->toPlainText().isEmpty());
364}
365
366void tst_QTextCursor::navigation4()
367{
368 cursor.insertText(text: " Test ");
369
370 cursor.setPosition(pos: 4);
371 cursor.movePosition(op: QTextCursor::EndOfWord);
372 QCOMPARE(cursor.position(), 6);
373}
374
375void tst_QTextCursor::navigation5()
376{
377 cursor.insertText(text: "Test");
378 cursor.insertBlock();
379 cursor.insertText(text: "Test");
380
381 cursor.setPosition(pos: 0);
382 cursor.movePosition(op: QTextCursor::EndOfBlock);
383 QCOMPARE(cursor.position(), 4);
384}
385
386void tst_QTextCursor::navigation6()
387{
388 // triger creation of document layout, so that QTextLines are there
389 doc->documentLayout();
390 doc->setTextWidth(1000);
391
392 cursor.insertText(text: "Test ");
393
394 cursor.movePosition(op: QTextCursor::Start);
395 cursor.movePosition(op: QTextCursor::EndOfLine);
396 QCOMPARE(cursor.position(), 8);
397}
398
399void tst_QTextCursor::navigation7()
400{
401 QVERIFY(doc->isEmpty());
402 for (int i = QTextCursor::Start; i <= QTextCursor::WordRight; ++i)
403 QVERIFY(!cursor.movePosition(QTextCursor::MoveOperation(i)));
404
405 doc->setPlainText("Hello World");
406 cursor.movePosition(op: QTextCursor::Start);
407 do {
408 } while (cursor.movePosition(op: QTextCursor::NextCharacter));
409 QVERIFY(true /*reached*/);
410}
411
412void tst_QTextCursor::navigation8()
413{
414 cursor.insertList(style: QTextListFormat::ListDecimal);
415 QCOMPARE(cursor.position(), 1);
416 cursor.insertText(text: "foo");
417 QCOMPARE(cursor.position(), 4);
418
419 cursor.insertList(style: QTextListFormat::ListCircle);
420 QCOMPARE(cursor.position(), 5);
421 cursor.insertText(text: "something");
422 QCOMPARE(cursor.position(), 14);
423
424 cursor.movePosition(op: QTextCursor::PreviousCharacter);
425 QCOMPARE(cursor.position(), 13);
426
427 cursor.setPosition(pos: 2);
428 cursor.movePosition(op: QTextCursor::NextCharacter);
429 QCOMPARE(cursor.position(), 3);
430}
431
432void tst_QTextCursor::navigation9()
433{
434 cursor.insertText(text: "Hello &-=+\t World");
435 cursor.movePosition(op: QTextCursor::PreviousWord);
436 QCOMPARE(cursor.position(), 15);
437 cursor.movePosition(op: QTextCursor::PreviousWord);
438 QCOMPARE(cursor.position(), 7);
439 cursor.movePosition(op: QTextCursor::PreviousWord);
440 QCOMPARE(cursor.position(), 0);
441 cursor.movePosition(op: QTextCursor::NextWord);
442 QCOMPARE(cursor.position(), 7);
443 cursor.movePosition(op: QTextCursor::NextWord);
444 QCOMPARE(cursor.position(), 15);
445}
446
447void tst_QTextCursor::navigation10()
448{
449 doc->setHtml("<html><p>just a simple paragraph.</p>"
450 "<table>"
451 "<tr><td>Cell number 1</td><td>another cell</td><td></td><td>previous</br>is</br>empty</td></tr>"
452 "<tr><td>row 2</td><td colspan=\"2\">foo bar</td><td>last cell</td></tr>"
453 "<tr><td colspan=\"3\">row 3</td><td>a</td></tr>"
454 "</table></html");
455 QCOMPARE(cursor.position(), 101); // end of document
456 cursor.setPosition(pos: 0);
457 QCOMPARE(cursor.position(), 0);
458 bool ok = cursor.movePosition(op: QTextCursor::EndOfLine);
459 QVERIFY(ok);
460 QCOMPARE(cursor.position(), 24);
461 ok = cursor.movePosition(op: QTextCursor::NextBlock);
462 QCOMPARE(cursor.position(), 25); // cell 1
463 ok = cursor.movePosition(op: QTextCursor::NextCell);
464 QVERIFY(ok);
465 QCOMPARE(cursor.position(), 39); // another..
466 ok = cursor.movePosition(op: QTextCursor::NextCell);
467 QVERIFY(ok);
468 QCOMPARE(cursor.position(), 52); // empty
469 ok = cursor.movePosition(op: QTextCursor::NextCell);
470 QVERIFY(ok);
471 QCOMPARE(cursor.position(), 53); // last on row 1
472 ok = cursor.movePosition(op: QTextCursor::NextCell);
473 QVERIFY(ok);
474 QCOMPARE(cursor.position(), 69); // row 2
475 ok = cursor.movePosition(op: QTextCursor::NextCell);
476 QVERIFY(ok);
477 QCOMPARE(cursor.position(), 75);
478 ok = cursor.movePosition(op: QTextCursor::NextCell);
479 QVERIFY(ok);
480 QCOMPARE(cursor.position(), 83);
481 ok = cursor.movePosition(op: QTextCursor::NextCell);
482 QVERIFY(ok);
483 QCOMPARE(cursor.position(), 93); // row 3
484 ok = cursor.movePosition(op: QTextCursor::NextCell);
485 QVERIFY(ok);
486 QCOMPARE(cursor.position(), 99);
487 ok = cursor.movePosition(op: QTextCursor::NextCell);
488 QVERIFY(!ok);
489 QCOMPARE(cursor.position(), 99); // didn't move.
490 QVERIFY(cursor.currentTable());
491
492 // same thing in reverse...
493 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
494 QVERIFY(ok);
495 QCOMPARE(cursor.position(), 93);
496 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
497 QVERIFY(ok);
498 QCOMPARE(cursor.position(), 83);
499 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
500 QVERIFY(ok);
501 QCOMPARE(cursor.position(), 75);
502 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
503 QVERIFY(ok);
504 QCOMPARE(cursor.position(), 69);
505 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
506 QVERIFY(ok);
507 QCOMPARE(cursor.position(), 53);
508 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
509 QVERIFY(ok);
510 QCOMPARE(cursor.position(), 52);
511 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
512 QVERIFY(ok);
513 QCOMPARE(cursor.position(), 39);
514 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
515 QVERIFY(ok);
516 QCOMPARE(cursor.position(), 25);
517 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
518 QVERIFY(!ok);
519 QCOMPARE(cursor.position(), 25); // can't leave the table
520
521 ok = cursor.movePosition(op: QTextCursor::NextRow);
522 QVERIFY(ok);
523 QCOMPARE(cursor.position(), 69);
524 ok = cursor.movePosition(op: QTextCursor::NextRow);
525 QVERIFY(ok);
526 QCOMPARE(cursor.position(), 93);
527 ok = cursor.movePosition(op: QTextCursor::NextRow);
528 QVERIFY(!ok);
529 QCOMPARE(cursor.position(), 93); // didn't move
530
531 ok = cursor.movePosition(op: QTextCursor::PreviousRow);
532 QVERIFY(ok);
533 QCOMPARE(cursor.position(), 83); // last col in row 2
534 ok = cursor.movePosition(op: QTextCursor::PreviousRow);
535 QVERIFY(ok);
536 QCOMPARE(cursor.position(), 53); // last col in row 1
537 ok = cursor.movePosition(op: QTextCursor::PreviousRow);
538 QVERIFY(!ok);
539 QCOMPARE(cursor.position(), 53);
540
541 // test usecase of jumping over a cell
542 doc->clear();
543 doc->setHtml("<html><table>tr><td rowspan=\"2\">a</td><td>b</td></tr><tr><td>c</td></tr></table></html>");
544 cursor.setPosition(pos: 1); // a
545 ok = cursor.movePosition(op: QTextCursor::NextCell);
546 QVERIFY(ok);
547 QCOMPARE(cursor.position(), 3); // b
548 ok = cursor.movePosition(op: QTextCursor::NextCell);
549 QVERIFY(ok);
550 QCOMPARE(cursor.position(), 5); // c
551 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
552 QVERIFY(ok);
553 QCOMPARE(cursor.position(), 3); // b
554 ok = cursor.movePosition(op: QTextCursor::PreviousCell);
555 QVERIFY(ok);
556 QCOMPARE(cursor.position(), 1); // a
557}
558
559void tst_QTextCursor::insertBlock()
560{
561 QTextBlockFormat fmt;
562 fmt.setTopMargin(100);
563 cursor.insertBlock(format: fmt);
564 QCOMPARE(cursor.position(), 1);
565 QCOMPARE(cursor.blockFormat(), fmt);
566}
567
568void tst_QTextCursor::insertWithBlockSeparator1()
569{
570 QString text = "Hello" + QString(QChar::ParagraphSeparator) + "World";
571
572 cursor.insertText(text);
573
574 cursor.movePosition(op: QTextCursor::PreviousBlock);
575 QCOMPARE(cursor.position(), 0);
576
577 cursor.movePosition(op: QTextCursor::NextBlock);
578 QCOMPARE(cursor.position(), 6);
579}
580
581void tst_QTextCursor::insertWithBlockSeparator2()
582{
583 cursor.insertText(text: QString(QChar::ParagraphSeparator));
584 QCOMPARE(cursor.position(), 1);
585}
586
587void tst_QTextCursor::insertWithBlockSeparator3()
588{
589 cursor.insertText(text: QString(QChar::ParagraphSeparator) + "Hi" + QString(QChar::ParagraphSeparator));
590 QCOMPARE(cursor.position(), 4);
591}
592
593void tst_QTextCursor::insertWithBlockSeparator4()
594{
595 cursor.insertText(text: QString(QChar::ParagraphSeparator) + QString(QChar::ParagraphSeparator));
596 QCOMPARE(cursor.position(), 2);
597}
598
599void tst_QTextCursor::clearObjectType1()
600{
601 cursor.insertImage(name: "test.png");
602 QVERIFY(cursor.charFormat().isValid());
603 QVERIFY(cursor.charFormat().isImageFormat());
604 cursor.insertText(text: "Hey");
605 QVERIFY(cursor.charFormat().isValid());
606 QVERIFY(!cursor.charFormat().isImageFormat());
607}
608
609void tst_QTextCursor::clearObjectType2()
610{
611 cursor.insertImage(name: "test.png");
612 QVERIFY(cursor.charFormat().isValid());
613 QVERIFY(cursor.charFormat().isImageFormat());
614 cursor.insertBlock();
615 QVERIFY(cursor.charFormat().isValid());
616 QVERIFY(!cursor.charFormat().isImageFormat());
617}
618
619void tst_QTextCursor::clearObjectType3()
620{
621 // like clearObjectType2 but tests different insertBlock overload
622 cursor.insertImage(name: "test.png");
623 QVERIFY(cursor.charFormat().isValid());
624 QVERIFY(cursor.charFormat().isImageFormat());
625 QTextBlockFormat bfmt;
626 bfmt.setAlignment(Qt::AlignRight);
627 cursor.insertBlock(format: bfmt);
628 QVERIFY(cursor.charFormat().isValid());
629 QVERIFY(!cursor.charFormat().isImageFormat());
630}
631
632void tst_QTextCursor::comparisonOperators1()
633{
634 cursor.insertText(text: "Hello World");
635
636 cursor.movePosition(op: QTextCursor::PreviousWord);
637
638 QTextCursor startCursor = cursor;
639 startCursor.movePosition(op: QTextCursor::Start);
640
641 QVERIFY(startCursor < cursor);
642
643 QTextCursor midCursor = startCursor;
644 midCursor.movePosition(op: QTextCursor::NextWord);
645
646 QVERIFY(midCursor <= cursor);
647 QCOMPARE(midCursor, cursor);
648 QVERIFY(midCursor >= cursor);
649
650 QVERIFY(midCursor > startCursor);
651
652 QVERIFY(midCursor != startCursor);
653 QVERIFY(!(midCursor == startCursor));
654
655 QTextCursor nullCursor;
656
657 QVERIFY(!(startCursor < nullCursor));
658 QVERIFY(!(nullCursor < nullCursor));
659 QVERIFY(nullCursor < startCursor);
660
661 QVERIFY(nullCursor <= startCursor);
662 QVERIFY(!(startCursor <= nullCursor));
663
664 QVERIFY(!(nullCursor >= startCursor));
665 QVERIFY(startCursor >= nullCursor);
666
667 QVERIFY(!(nullCursor > startCursor));
668 QVERIFY(!(nullCursor > nullCursor));
669 QVERIFY(startCursor > nullCursor);
670}
671
672void tst_QTextCursor::comparisonOperators2()
673{
674 QTextDocument doc1;
675 QTextDocument doc2;
676
677 QTextCursor cursor1(&doc1);
678 QTextCursor cursor2(&doc2);
679
680 QVERIFY(cursor1 != cursor2);
681 QCOMPARE(cursor1, QTextCursor(&doc1));
682}
683
684void tst_QTextCursor::selection1()
685{
686 cursor.insertText(text: "Hello World");
687
688 cursor.setPosition(pos: 0);
689 cursor.clearSelection();
690 cursor.setPosition(pos: 4, mode: QTextCursor::KeepAnchor);
691
692 QCOMPARE(cursor.selectionStart(), 0);
693 QCOMPARE(cursor.selectionEnd(), 4);
694}
695
696void tst_QTextCursor::dontCopyTableAttributes()
697{
698 /* when pressing 'enter' inside a cell it shouldn't
699 * enlarge the table by adding another cell but just
700 * extend the cell */
701 QTextTable *table = cursor.insertTable(rows: 2, cols: 2);
702 QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
703 cursor.insertBlock();
704 QCOMPARE(table->columns(), 2);
705}
706
707void tst_QTextCursor::checkFrame1()
708{
709 QCOMPARE(cursor.position(), 0);
710 QPointer<QTextFrame> frame = cursor.insertFrame(format: QTextFrameFormat());
711 QVERIFY(frame != 0);
712
713 QTextFrame *root = frame->parentFrame();
714 QVERIFY(root != 0);
715
716 QCOMPARE(frame->firstPosition(), 1);
717 QCOMPARE(frame->lastPosition(), 1);
718 QVERIFY(frame->parentFrame() != 0);
719 QCOMPARE(root->childFrames().size(), 1);
720
721 QCOMPARE(cursor.position(), 1);
722 QCOMPARE(cursor.selectionStart(), 1);
723 QCOMPARE(cursor.selectionEnd(), 1);
724
725 doc->undo();
726
727 QVERIFY(!frame);
728 QCOMPARE(root->childFrames().size(), 0);
729
730 QCOMPARE(cursor.position(), 0);
731 QCOMPARE(cursor.selectionStart(), 0);
732 QCOMPARE(cursor.selectionEnd(), 0);
733
734 doc->redo();
735
736 frame = doc->frameAt(pos: 1);
737
738 QVERIFY(frame);
739 QCOMPARE(frame->firstPosition(), 1);
740 QCOMPARE(frame->lastPosition(), 1);
741 QVERIFY(frame->parentFrame() != 0);
742 QCOMPARE(root->childFrames().size(), 1);
743
744 QCOMPARE(cursor.position(), 1);
745 QCOMPARE(cursor.selectionStart(), 1);
746 QCOMPARE(cursor.selectionEnd(), 1);
747
748// cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
749// QCOMPARE(cursor.position(), 2);
750// QCOMPARE(cursor.selectionStart(), 0);
751// QCOMPARE(cursor.selectionEnd(), 2);
752}
753
754void tst_QTextCursor::checkFrame2()
755{
756 QCOMPARE(cursor.position(), 0);
757 cursor.insertText(text: "A");
758 QCOMPARE(cursor.position(), 1);
759 cursor.movePosition(op: QTextCursor::Start, QTextCursor::KeepAnchor);
760
761 QPointer<QTextFrame> frame = cursor.insertFrame(format: QTextFrameFormat());
762 QTextFrame *root = frame->parentFrame();
763
764 QCOMPARE(frame->firstPosition(), 1);
765 QCOMPARE(frame->lastPosition(), 2);
766 QVERIFY(frame->parentFrame() != 0);
767 QCOMPARE(root->childFrames().size(), 1);
768
769 QCOMPARE(cursor.position(), 1);
770 QCOMPARE(cursor.selectionStart(), 1);
771 QCOMPARE(cursor.selectionEnd(), 2);
772
773 doc->undo();
774
775 QVERIFY(!frame);
776 QCOMPARE(root->childFrames().size(), 0);
777
778 QCOMPARE(cursor.position(), 0);
779 QCOMPARE(cursor.selectionStart(), 0);
780 QCOMPARE(cursor.selectionEnd(), 1);
781
782 doc->redo();
783
784 frame = doc->frameAt(pos: 1);
785
786 QVERIFY(frame);
787 QCOMPARE(frame->firstPosition(), 1);
788 QCOMPARE(frame->lastPosition(), 2);
789 QVERIFY(frame->parentFrame() != 0);
790 QCOMPARE(root->childFrames().size(), 1);
791
792 QCOMPARE(cursor.position(), 1);
793 QCOMPARE(cursor.selectionStart(), 1);
794 QCOMPARE(cursor.selectionEnd(), 2);
795
796 cursor.movePosition(op: QTextCursor::Left, QTextCursor::KeepAnchor);
797 QCOMPARE(cursor.position(), 0);
798 QCOMPARE(cursor.selectionStart(), 0);
799 QCOMPARE(cursor.selectionEnd(), 3);
800}
801
802void tst_QTextCursor::insertBlockToUseCharFormat()
803{
804 QTextCharFormat fmt;
805 fmt.setForeground(Qt::blue);
806 cursor.insertText(text: "Hello", format: fmt);
807 QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
808
809 cursor.insertBlock();
810 QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
811
812 fmt.setForeground(Qt::red);
813 cursor.insertText(text: "Hello\nWorld", format: fmt);
814 cursor.insertText(text: "Blah");
815 QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
816
817 // ### we might want a testcase for createTable, too, as it calls insertBlock, too,
818 // and we might want to have the char format copied (the one that gets inserted
819 // as table separators, that are undeletable)
820}
821
822void tst_QTextCursor::tableMovement()
823{
824 QCOMPARE(cursor.position(), 0);
825 cursor.insertText(text: "AA");
826 QCOMPARE(cursor.position(), 2);
827 cursor.movePosition(op: QTextCursor::Left);
828
829 cursor.insertTable(rows: 3, cols: 3);
830 QCOMPARE(cursor.position(), 2);
831
832 cursor.movePosition(op: QTextCursor::Down);
833 QCOMPARE(cursor.position(), 5);
834
835 cursor.movePosition(op: QTextCursor::Right);
836 QCOMPARE(cursor.position(), 6);
837
838 cursor.movePosition(op: QTextCursor::Up);
839 QCOMPARE(cursor.position(), 3);
840
841 cursor.movePosition(op: QTextCursor::Right);
842 QCOMPARE(cursor.position(), 4);
843
844 cursor.movePosition(op: QTextCursor::Right);
845 QCOMPARE(cursor.position(), 5);
846
847 cursor.movePosition(op: QTextCursor::Up);
848 QCOMPARE(cursor.position(), 2);
849
850 cursor.movePosition(op: QTextCursor::Up);
851 QCOMPARE(cursor.position(), 0);
852
853}
854
855void tst_QTextCursor::selectionsInTable()
856{
857 QTextTable *table = cursor.insertTable(rows: 3, cols: 3);
858 table->cellAt(row: 0, col: 0).firstCursorPosition().insertText(text: "A a"); // first = 1
859 table->cellAt(row: 0, col: 1).firstCursorPosition().insertText(text: "B b"); // first = 5
860 table->cellAt(row: 0, col: 2).firstCursorPosition().insertText(text: "C c"); // first = 9
861 table->cellAt(row: 1, col: 0).firstCursorPosition().insertText(text: "D d"); // first = 13
862 table->cellAt(row: 1, col: 1).firstCursorPosition().insertText(text: "E e"); // first = 17
863 table->cellAt(row: 1, col: 2).firstCursorPosition().insertText(text: "F f"); // first = 21
864 table->cellAt(row: 2, col: 0).firstCursorPosition().insertText(text: "G g"); // first = 25
865 table->cellAt(row: 2, col: 1).firstCursorPosition().insertText(text: "H h"); // first = 29
866 table->cellAt(row: 2, col: 2).firstCursorPosition().insertText(text: "I i"); // first = 33
867
868 cursor = table->cellAt(row: 0, col: 0).lastCursorPosition();
869 QCOMPARE(cursor.position(), 4);
870 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
871 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
872 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
873 QCOMPARE(cursor.position(), 1);
874
875 cursor = table->cellAt(row: 1, col: 0).lastCursorPosition();
876 QCOMPARE(cursor.position(), 16);
877 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
878 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
879 QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
880 QCOMPARE(cursor.position(), 13);
881
882 cursor = table->cellAt(row: 0, col: 2).firstCursorPosition();
883 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
884 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
885 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
886
887 cursor = table->cellAt(row: 1, col: 2).firstCursorPosition();
888 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
889 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
890 QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
891
892 // Next let's test selecting entire cells one at a time
893 cursor = table->cellAt(row: 0, col: 0).firstCursorPosition();
894 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
895 QCOMPARE(cursor.position(), 5);
896 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
897 QCOMPARE(cursor.position(), 9);
898 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
899 QCOMPARE(cursor.position(), 13);
900 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
901 QCOMPARE(cursor.position(), 17);
902 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
903 QCOMPARE(cursor.position(), 21);
904 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
905 QCOMPARE(cursor.position(), 25);
906 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
907 QCOMPARE(cursor.position(), 29);
908 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
909 QCOMPARE(cursor.position(), 33);
910 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor) == false);
911
912 // And now lets walk all the way back
913 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
914 QCOMPARE(cursor.position(), 29);
915 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
916 QCOMPARE(cursor.position(), 25);
917 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
918 QCOMPARE(cursor.position(), 21);
919 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
920 QCOMPARE(cursor.position(), 17);
921 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
922 QCOMPARE(cursor.position(), 13);
923 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
924 QCOMPARE(cursor.position(), 9);
925 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
926 QCOMPARE(cursor.position(), 5);
927 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor));
928 QCOMPARE(cursor.position(), 1);
929 QVERIFY(cursor.movePosition(QTextCursor::PreviousCell, QTextCursor::KeepAnchor) == false);
930
931 QTextCursor::MoveOperation leftMovements[5] = {
932 QTextCursor::PreviousBlock
933 , QTextCursor::PreviousCharacter
934 , QTextCursor::PreviousWord
935 , QTextCursor::Left
936 , QTextCursor::WordLeft
937 };
938
939 QTextCursor::MoveOperation rightMovements[5] = {
940 QTextCursor::NextBlock
941 , QTextCursor::NextCharacter
942 , QTextCursor::NextWord
943 , QTextCursor::Right
944 , QTextCursor::WordRight
945 };
946
947 for (int i = 0; i < 5; ++i) {
948 QTextCursor::MoveOperation left = leftMovements[i];
949 QTextCursor::MoveOperation right = rightMovements[i];
950
951 // Lets walk circle around anchor placed at 1,1 using up, down, left and right
952 cursor = table->cellAt(row: 1, col: 1).firstCursorPosition();
953 QCOMPARE(cursor.position(), 17);
954 QVERIFY(cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor));
955 QCOMPARE(cursor.position(), 18); // First right should not jump more than one char
956 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
957 QCOMPARE(cursor.position(), 21); // Lets jump to the next cell
958 QVERIFY(cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor));
959 QCOMPARE(cursor.position(), 33);
960 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
961 QCOMPARE(cursor.position(), 29);
962 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
963 QCOMPARE(cursor.position(), 25);
964 QVERIFY(cursor.movePosition(QTextCursor::Up, QTextCursor::KeepAnchor));
965 QCOMPARE(cursor.position(), 13);
966 QVERIFY(cursor.movePosition(QTextCursor::Up, QTextCursor::KeepAnchor));
967 QCOMPARE(cursor.position(), 1);
968 QVERIFY(cursor.movePosition(right, QTextCursor::KeepAnchor));
969 QCOMPARE(cursor.position(), 5);
970 QVERIFY(cursor.movePosition(right, QTextCursor::KeepAnchor));
971 QCOMPARE(cursor.position(), 9);
972 QVERIFY(cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor));
973 QCOMPARE(cursor.position(), 21);
974
975 // Lets walk to the side 2 cells and back, first right
976 cursor = table->cellAt(row: 0, col: 0).firstCursorPosition();
977 QVERIFY(cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor));
978 QCOMPARE(cursor.position(), 5); // Lets jump to the next cell
979 QVERIFY(cursor.movePosition(right, QTextCursor::KeepAnchor));
980 QCOMPARE(cursor.position(), 9);
981 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
982 QCOMPARE(cursor.position(), 5);
983 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
984 QVERIFY(cursor.position() < 5);
985
986 // Then left
987 cursor = table->cellAt(row: 0, col: 2).firstCursorPosition();
988 QCOMPARE(cursor.position(), 9);
989 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
990 QCOMPARE(cursor.position(), 5); // A single left should do
991 QVERIFY(cursor.movePosition(left, QTextCursor::KeepAnchor));
992 QCOMPARE(cursor.position(), 1);
993 QVERIFY(cursor.movePosition(right, QTextCursor::KeepAnchor));
994 QCOMPARE(cursor.position(), 5);
995 QVERIFY(cursor.movePosition(right, QTextCursor::KeepAnchor));
996 QCOMPARE(cursor.position(), 9);
997 }
998}
999
1000void tst_QTextCursor::selectedText()
1001{
1002 cursor.insertText(text: "Hello World");
1003 cursor.movePosition(op: QTextCursor::Start);
1004 cursor.movePosition(op: QTextCursor::End, QTextCursor::KeepAnchor);
1005
1006 QCOMPARE(cursor.selectedText(), QString("Hello World"));
1007}
1008
1009void tst_QTextCursor::insertBlockShouldRemoveSelection()
1010{
1011 cursor.insertText(text: "Hello World");
1012 cursor.movePosition(op: QTextCursor::Start);
1013 cursor.movePosition(op: QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
1014
1015 QVERIFY(cursor.hasSelection());
1016 QCOMPARE(cursor.selectedText(), QString("Hello"));
1017
1018 cursor.insertBlock();
1019
1020 QVERIFY(!cursor.hasSelection());
1021 QCOMPARE(doc->toPlainText().indexOf("Hello"), -1);
1022}
1023
1024void tst_QTextCursor::insertBlockShouldRemoveSelection2()
1025{
1026 cursor.insertText(text: "Hello World");
1027 cursor.movePosition(op: QTextCursor::Start);
1028 cursor.movePosition(op: QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
1029
1030 QVERIFY(cursor.hasSelection());
1031 QCOMPARE(cursor.selectedText(), QString("Hello"));
1032
1033 QTextBlockFormat fmt = cursor.blockFormat();
1034 cursor.insertBlock(format: fmt);
1035
1036 QVERIFY(!cursor.hasSelection());
1037 QCOMPARE(doc->toPlainText().indexOf("Hello"), -1);
1038}
1039
1040void tst_QTextCursor::mergeCellShouldUpdateSelection()
1041{
1042 QTextTable *table = cursor.insertTable(rows: 4, cols: 4);
1043 cursor.setPosition(pos: table->cellAt(row: 0, col: 0).firstPosition());
1044 cursor.setPosition(pos: table->cellAt(row: 3, col: 0).firstPosition(), mode: QTextCursor::KeepAnchor); // aka bottom left
1045 int firstRow, numRows, firstColumn, numColumns;
1046 cursor.selectedTableCells(firstRow: &firstRow, numRows: &numRows, firstColumn: &firstColumn, numColumns: &numColumns);
1047 QCOMPARE(firstRow, 0);
1048 QCOMPARE(numRows, 4);
1049 QCOMPARE(firstColumn, 0);
1050 QCOMPARE(numColumns, 1);
1051
1052 table->removeColumns(pos: firstColumn, num: numColumns);
1053
1054 QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
1055 QCOMPARE(cursor.position(), table->cellAt(0, 0).firstPosition());
1056 QCOMPARE(cursor.position(), cursor.anchor()); // empty. I don't really care where it ends up.
1057
1058 // prepare for another test with multiple cursors.
1059 // note we have a 4 rows, 3 cols table now.
1060 cursor.setPosition(pos: table->cellAt(row: 0, col: 0).firstPosition());
1061 cursor.setPosition(pos: table->cellAt(row: 0, col: 2).firstPosition(), mode: QTextCursor::KeepAnchor);
1062
1063 // now create a selection of a whole row.
1064 QTextCursor c2 = table->cellAt(row: 2, col: 0).firstCursorPosition();
1065 c2.setPosition(pos: table->cellAt(row: 2, col: 2).firstPosition(), mode: QTextCursor::KeepAnchor);
1066
1067 // just for good measure, another one for a block of cells.
1068 QTextCursor c3 = table->cellAt(row: 2, col: 1).firstCursorPosition();
1069 c3.setPosition(pos: table->cellAt(row: 3, col: 2).firstPosition(), mode: QTextCursor::KeepAnchor);
1070
1071 table->removeRows(pos: 2, num: 1);
1072
1073 QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
1074 QCOMPARE(cursor.position(), table->cellAt(0, 2).firstPosition());
1075
1076 QCOMPARE(c2.position(), c2.anchor()); // empty. I don't really care where it ends up.
1077
1078 QCOMPARE(c3.anchor(), table->cellAt(2, 1).firstPosition());
1079 QCOMPARE(c3.position(), table->cellAt(2, 2).firstPosition());
1080
1081
1082 // prepare for another test where we remove a column
1083 // note we have a 3 rows, 3 cols table now.
1084 cursor.setPosition(pos: table->cellAt(row: 0, col: 0).firstPosition());
1085 cursor.setPosition(pos: table->cellAt(row: 2, col: 1).firstPosition(), mode: QTextCursor::KeepAnchor);
1086
1087 c2.setPosition(pos: table->cellAt(row: 0, col: 1).firstPosition());
1088 c2.setPosition(pos: table->cellAt(row: 2, col: 2).firstPosition(), mode: QTextCursor::KeepAnchor);
1089
1090 table->removeColumns(pos: 1, num: 1);
1091
1092 QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
1093 QCOMPARE(cursor.position(), table->cellAt(2, 0).firstPosition());
1094
1095 QCOMPARE(c2.anchor(), table->cellAt(0, 1).firstPosition());
1096 QCOMPARE(c2.position(), table->cellAt(2, 1).firstPosition());
1097
1098 // test for illegal cursor positions.
1099 // note we have a 3 rows, 2 cols table now.
1100 cursor.setPosition(pos: table->cellAt(row: 2, col: 0).firstPosition());
1101 cursor.setPosition(pos: table->cellAt(row: 2, col: 1).firstPosition(), mode: QTextCursor::KeepAnchor);
1102
1103 c2.setPosition(pos: table->cellAt(row: 0, col: 0).firstPosition());
1104 c2.setPosition(pos: table->cellAt(row: 2, col: 1).firstPosition(), mode: QTextCursor::KeepAnchor);
1105
1106 c3.setPosition(pos: table->cellAt(row: 2, col: 1).firstPosition());
1107
1108 table->removeRows(pos: 2, num: 1);
1109
1110 QCOMPARE(cursor.anchor(), table->cellAt(1, 1).lastPosition()+1);
1111 QCOMPARE(cursor.position(), cursor.anchor());
1112
1113 QCOMPARE(c2.anchor(), table->cellAt(0, 0).firstPosition());
1114 QCOMPARE(c2.position(), table->cellAt(1, 1).firstPosition());
1115
1116 QCOMPARE(c3.anchor(), table->cellAt(1, 1).firstPosition());
1117 QCOMPARE(c3.position(), table->cellAt(1, 1).firstPosition());
1118}
1119
1120void tst_QTextCursor::joinPreviousEditBlock()
1121{
1122 cursor.beginEditBlock();
1123 cursor.insertText(text: "Hello");
1124 cursor.insertText(text: "World");
1125 cursor.endEditBlock();
1126 QVERIFY(doc->toPlainText().startsWith("HelloWorld"));
1127
1128 cursor.joinPreviousEditBlock();
1129 cursor.insertText(text: "Hey");
1130 cursor.endEditBlock();
1131 QVERIFY(doc->toPlainText().startsWith("HelloWorldHey"));
1132
1133 doc->undo();
1134 QVERIFY(!doc->toPlainText().contains("HelloWorldHey"));
1135}
1136
1137void tst_QTextCursor::setBlockFormatInTable()
1138{
1139 // someone reported this on qt4-preview-feedback
1140 QTextBlockFormat fmt;
1141 fmt.setBackground(Qt::blue);
1142 cursor.setBlockFormat(fmt);
1143
1144 QTextTable *table = cursor.insertTable(rows: 2, cols: 2);
1145 cursor = table->cellAt(row: 0, col: 0).firstCursorPosition();
1146 fmt.setBackground(Qt::red);
1147 cursor.setBlockFormat(fmt);
1148
1149 cursor.movePosition(op: QTextCursor::Start);
1150 QCOMPARE(cursor.blockFormat().background().color(), QColor(Qt::blue));
1151}
1152
1153void tst_QTextCursor::blockCharFormat2()
1154{
1155 QTextCharFormat fmt;
1156 fmt.setForeground(Qt::green);
1157 cursor.mergeBlockCharFormat(modifier: fmt);
1158
1159 fmt.setForeground(Qt::red);
1160
1161 cursor.insertText(text: "Test", format: fmt);
1162 cursor.movePosition(op: QTextCursor::Start);
1163 cursor.insertText(text: "Red");
1164 cursor.movePosition(op: QTextCursor::PreviousCharacter);
1165 QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
1166}
1167
1168void tst_QTextCursor::blockCharFormat3()
1169{
1170 QVERIFY(cursor.atBlockStart());
1171 QVERIFY(cursor.atBlockEnd());
1172 QVERIFY(cursor.atStart());
1173
1174 QTextCharFormat fmt;
1175 fmt.setForeground(Qt::green);
1176 cursor.setBlockCharFormat(fmt);
1177 cursor.insertText(text: "Test");
1178 cursor.movePosition(op: QTextCursor::Start);
1179 cursor.movePosition(op: QTextCursor::NextCharacter);
1180 const QColor red(Qt::red);
1181 const QColor green(Qt::green);
1182 QCOMPARE(cursor.charFormat().foreground().color(), green);
1183
1184 cursor.movePosition(op: QTextCursor::Start);
1185 QCOMPARE(cursor.charFormat().foreground().color(), green);
1186
1187 fmt.setForeground(Qt::red);
1188 cursor.setBlockCharFormat(fmt);
1189 QCOMPARE(cursor.blockCharFormat().foreground().color(), red);
1190
1191 cursor.movePosition(op: QTextCursor::End);
1192 cursor.movePosition(op: QTextCursor::Start);
1193 QCOMPARE(cursor.charFormat().foreground().color(), green);
1194
1195 cursor.insertText(text: "Test");
1196 QCOMPARE(cursor.charFormat().foreground().color(), green);
1197
1198 cursor.select(selection: QTextCursor::Document);
1199 cursor.removeSelectedText();
1200 QVERIFY(cursor.atBlockStart());
1201 QVERIFY(cursor.atBlockEnd());
1202 QVERIFY(cursor.atStart());
1203
1204 cursor.insertText(text: "Test");
1205 QCOMPARE(cursor.charFormat().foreground().color(), red);
1206}
1207
1208void tst_QTextCursor::blockCharFormat()
1209{
1210 QTextCharFormat fmt;
1211 fmt.setForeground(Qt::blue);
1212 cursor.insertBlock(format: QTextBlockFormat(), charFormat: fmt);
1213 cursor.insertText(text: "Hm");
1214
1215 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::blue));
1216
1217 fmt.setForeground(Qt::red);
1218
1219 cursor.setBlockCharFormat(fmt);
1220 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::red));
1221}
1222
1223void tst_QTextCursor::blockCharFormatOnSelection()
1224{
1225 QTextCharFormat fmt;
1226 fmt.setForeground(Qt::blue);
1227 cursor.insertBlock(format: QTextBlockFormat(), charFormat: fmt);
1228
1229 fmt.setForeground(Qt::green);
1230 cursor.insertText(text: "Hm", format: fmt);
1231
1232 fmt.setForeground(Qt::red);
1233 cursor.insertBlock(format: QTextBlockFormat(), charFormat: fmt);
1234 cursor.insertText(text: "Ah");
1235
1236 fmt.setForeground(Qt::white);
1237 cursor.insertBlock(format: QTextBlockFormat(), charFormat: fmt);
1238 cursor.insertText(text: "bleh");
1239
1240 cursor.movePosition(op: QTextCursor::Start);
1241 cursor.movePosition(op: QTextCursor::NextBlock);
1242 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::blue));
1243 cursor.movePosition(op: QTextCursor::NextBlock);
1244 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::red));
1245 cursor.movePosition(op: QTextCursor::NextBlock);
1246 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::white));
1247
1248 cursor.movePosition(op: QTextCursor::Start);
1249 cursor.movePosition(op: QTextCursor::NextBlock);
1250 cursor.movePosition(op: QTextCursor::NextBlock, QTextCursor::KeepAnchor);
1251
1252 fmt.setForeground(Qt::cyan);
1253 cursor.setBlockCharFormat(fmt);
1254
1255 cursor.movePosition(op: QTextCursor::Start);
1256 cursor.movePosition(op: QTextCursor::NextBlock);
1257 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::cyan));
1258
1259 cursor.movePosition(op: QTextCursor::Right);
1260 cursor.movePosition(op: QTextCursor::Right);
1261 QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::green));
1262
1263 cursor.movePosition(op: QTextCursor::NextBlock);
1264 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::cyan));
1265
1266 cursor.movePosition(op: QTextCursor::NextBlock);
1267 QCOMPARE(cursor.blockCharFormat().foreground().color(), QColor(Qt::white));
1268}
1269
1270void tst_QTextCursor::anchorInitialized1()
1271{
1272 cursor.insertBlock();
1273 cursor = QTextCursor(cursor.block());
1274 QCOMPARE(cursor.position(), 1);
1275 QCOMPARE(cursor.anchor(), 1);
1276 QCOMPARE(cursor.selectionStart(), 1);
1277 QCOMPARE(cursor.selectionEnd(), 1);
1278}
1279
1280void tst_QTextCursor::anchorInitialized2()
1281{
1282 cursor.insertBlock();
1283 cursor = QTextCursorPrivate::fromPosition(d: cursor.block().docHandle(), pos: 1);
1284 QCOMPARE(cursor.position(), 1);
1285 QCOMPARE(cursor.anchor(), 1);
1286 QCOMPARE(cursor.selectionStart(), 1);
1287 QCOMPARE(cursor.selectionEnd(), 1);
1288}
1289
1290void tst_QTextCursor::anchorInitialized3()
1291{
1292 QTextFrame *frame = cursor.insertFrame(format: QTextFrameFormat());
1293 cursor = QTextCursor(frame);
1294 QCOMPARE(cursor.position(), 1);
1295 QCOMPARE(cursor.anchor(), 1);
1296 QCOMPARE(cursor.selectionStart(), 1);
1297 QCOMPARE(cursor.selectionEnd(), 1);
1298}
1299
1300void tst_QTextCursor::selectWord()
1301{
1302 cursor.insertText(text: "first second third");
1303 cursor.insertBlock();
1304 cursor.insertText(text: "words in second paragraph");
1305
1306 cursor.setPosition(pos: 9);
1307 cursor.select(selection: QTextCursor::WordUnderCursor);
1308 QVERIFY(cursor.hasSelection());
1309 QCOMPARE(cursor.selectionStart(), 6);
1310 QCOMPARE(cursor.selectionEnd(), 12);
1311
1312 cursor.setPosition(pos: 5);
1313 cursor.select(selection: QTextCursor::WordUnderCursor);
1314 QVERIFY(cursor.hasSelection());
1315 QCOMPARE(cursor.selectionStart(), 0);
1316 QCOMPARE(cursor.selectionEnd(), 5);
1317
1318 cursor.setPosition(pos: 6);
1319 cursor.select(selection: QTextCursor::WordUnderCursor);
1320 QVERIFY(cursor.hasSelection());
1321 QCOMPARE(cursor.selectionStart(), 6);
1322 QCOMPARE(cursor.selectionEnd(), 12);
1323
1324 cursor.setPosition(pos: 14);
1325 cursor.select(selection: QTextCursor::WordUnderCursor);
1326 QVERIFY(cursor.hasSelection());
1327 QCOMPARE(cursor.selectionStart(), 6);
1328 QCOMPARE(cursor.selectionEnd(), 12);
1329
1330 cursor.movePosition(op: QTextCursor::Start);
1331 cursor.select(selection: QTextCursor::WordUnderCursor);
1332 QVERIFY(cursor.hasSelection());
1333 QCOMPARE(cursor.selectionStart(), 0);
1334 QCOMPARE(cursor.selectionEnd(), 5);
1335
1336 cursor.movePosition(op: QTextCursor::EndOfBlock);
1337 cursor.select(selection: QTextCursor::WordUnderCursor);
1338 QVERIFY(cursor.hasSelection());
1339 QCOMPARE(cursor.selectionStart(), 17);
1340 QCOMPARE(cursor.selectionEnd(), 22);
1341}
1342
1343void tst_QTextCursor::selectWordWithSeparators_data()
1344{
1345 QTest::addColumn<QString>(name: "text");
1346 QTest::addColumn<int>(name: "initialPosition");
1347 QTest::addColumn<QString>(name: "expectedSelectedText");
1348
1349 QTest::newRow(dataTag: "dereference") << QString::fromLatin1(str: "foo->bar()") << 1 << QString::fromLatin1(str: "foo");
1350 QTest::newRow(dataTag: "funcsignature") << QString::fromLatin1(str: "bar(int x);") << 1 << QString::fromLatin1(str: "bar");
1351 QTest::newRow(dataTag: "def") << QString::fromLatin1(str: "foo *f;") << 1 << QString::fromLatin1(str: "foo");
1352}
1353
1354void tst_QTextCursor::selectWordWithSeparators()
1355{
1356 QFETCH(QString, text);
1357 QFETCH(int, initialPosition);
1358 QFETCH(QString, expectedSelectedText);
1359
1360 cursor.insertText(text);
1361 cursor.setPosition(pos: initialPosition);
1362 cursor.select(selection: QTextCursor::WordUnderCursor);
1363
1364 QCOMPARE(cursor.selectedText(), expectedSelectedText);
1365}
1366
1367void tst_QTextCursor::startOfWord()
1368{
1369 cursor.insertText(text: "first second");
1370 cursor.setPosition(pos: 7);
1371 cursor.movePosition(op: QTextCursor::StartOfWord);
1372 QCOMPARE(cursor.position(), 0);
1373}
1374
1375void tst_QTextCursor::selectBlock()
1376{
1377 cursor.insertText(text: "foobar");
1378 QTextBlockFormat blockFmt;
1379 blockFmt.setAlignment(Qt::AlignHCenter);
1380 cursor.insertBlock(format: blockFmt);
1381 cursor.insertText(text: "blah");
1382 cursor.insertBlock(format: QTextBlockFormat());
1383
1384 cursor.movePosition(op: QTextCursor::PreviousBlock);
1385 QCOMPARE(cursor.block().text(), QString("blah"));
1386
1387 cursor.select(selection: QTextCursor::BlockUnderCursor);
1388 QVERIFY(cursor.hasSelection());
1389
1390 QTextDocumentFragment fragment(cursor);
1391 doc->clear();
1392 cursor.insertFragment(fragment);
1393 QCOMPARE(blockCount(), 2);
1394
1395 cursor.movePosition(op: QTextCursor::Start);
1396 cursor.movePosition(op: QTextCursor::NextBlock);
1397 QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter);
1398 QCOMPARE(cursor.block().text(), QString("blah"));
1399}
1400
1401void tst_QTextCursor::selectVisually()
1402{
1403 cursor.insertText(text: "Foo\nlong line which is probably going to be cut in two when shown in a widget\nparagraph 3\n");
1404
1405 cursor.setPosition(pos: 6); // somewhere in the long paragraph.
1406 cursor.select(selection: QTextCursor::LineUnderCursor);
1407 // since we are not yet laid-out, we expect the whole paragraph to be selected.
1408 QCOMPARE(cursor.position(), 77);
1409 QCOMPARE(cursor.anchor(), 4);
1410}
1411
1412void tst_QTextCursor::insertText()
1413{
1414 QString txt = "Foo\nBar\r\nMeep";
1415 txt += QChar::LineSeparator;
1416 txt += "Baz";
1417 txt += QChar::ParagraphSeparator;
1418 txt += "yoyodyne";
1419 cursor.insertText(text: txt);
1420 QCOMPARE(blockCount(), 4);
1421 cursor.movePosition(op: QTextCursor::Start);
1422 QCOMPARE(cursor.block().text(), QString("Foo"));
1423 cursor.movePosition(op: QTextCursor::NextBlock);
1424 QCOMPARE(cursor.block().text(), QString("Bar"));
1425 cursor.movePosition(op: QTextCursor::NextBlock);
1426 QCOMPARE(cursor.block().text(), QString(QString("Meep") + QChar(QChar::LineSeparator) + QString("Baz")));
1427 cursor.movePosition(op: QTextCursor::NextBlock);
1428 QCOMPARE(cursor.block().text(), QString("yoyodyne"));
1429}
1430
1431void tst_QTextCursor::insertFragmentShouldUseCurrentCharFormat()
1432{
1433 QTextDocumentFragment fragment = QTextDocumentFragment::fromPlainText(plainText: "Hello World");
1434 QTextCharFormat fmt;
1435 fmt.setFontUnderline(true);
1436
1437 cursor.clearSelection();
1438 cursor.setCharFormat(fmt);
1439 cursor.insertFragment(fragment);
1440 cursor.movePosition(op: QTextCursor::Start);
1441 cursor.movePosition(op: QTextCursor::NextCharacter);
1442 QCOMPARE(cursor.charFormat(), fmt);
1443}
1444
1445int tst_QTextCursor::blockCount()
1446{
1447 int cnt = 0;
1448 for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next())
1449 ++cnt;
1450 return cnt;
1451}
1452
1453void tst_QTextCursor::endOfLine()
1454{
1455 doc->setPageSize(QSizeF(100000, INT_MAX));
1456
1457 QString text("First Line \nSecond Line ");
1458 text.replace(before: QLatin1Char('\n'), after: QChar(QChar::LineSeparator));
1459 cursor.insertText(text);
1460
1461 // ensure layouted
1462 doc->documentLayout()->documentSize();
1463
1464 cursor.movePosition(op: QTextCursor::Start);
1465
1466 QCOMPARE(cursor.block().layout()->lineCount(), 2);
1467
1468 cursor.movePosition(op: QTextCursor::EndOfLine);
1469 QCOMPARE(cursor.position(), 14);
1470 cursor.movePosition(op: QTextCursor::NextCharacter);
1471 QCOMPARE(cursor.position(), 15);
1472 cursor.movePosition(op: QTextCursor::EndOfLine);
1473 QCOMPARE(cursor.position(), 28);
1474}
1475
1476class CursorListener : public QObject
1477{
1478 Q_OBJECT
1479public:
1480 CursorListener(QTextCursor *_cursor) : lastRecordedPosition(-1), lastRecordedAnchor(-1), recordingCount(0), cursor(_cursor) {}
1481
1482 int lastRecordedPosition;
1483 int lastRecordedAnchor;
1484 int recordingCount;
1485
1486public slots:
1487 void recordCursorPosition()
1488 {
1489 lastRecordedPosition = cursor->position();
1490 lastRecordedAnchor = cursor->anchor();
1491 ++recordingCount;
1492 }
1493
1494 void selectAllContents()
1495 {
1496 // Only test the first time
1497 if (!recordingCount) {
1498 recordingCount++;
1499 cursor->select(selection: QTextCursor::Document);
1500 lastRecordedPosition = cursor->position();
1501 lastRecordedAnchor = cursor->anchor();
1502 }
1503 }
1504
1505private:
1506 QTextCursor *cursor;
1507};
1508
1509void tst_QTextCursor::editBlocksDuringRemove()
1510{
1511 CursorListener listener(&cursor);
1512
1513 cursor.insertText(text: "Hello World");
1514 cursor.movePosition(op: QTextCursor::Start, QTextCursor::KeepAnchor);
1515 QCOMPARE(cursor.selectedText(), QString("Hello World"));
1516
1517 connect(sender: doc, SIGNAL(contentsChanged()), receiver: &listener, SLOT(recordCursorPosition()));
1518 listener.recordingCount = 0;
1519 cursor.deleteChar();
1520
1521 QCOMPARE(listener.recordingCount, 1);
1522 QCOMPARE(listener.lastRecordedPosition, 0);
1523 QCOMPARE(listener.lastRecordedAnchor, 0);
1524
1525 QVERIFY(doc->toPlainText().isEmpty());
1526}
1527
1528void tst_QTextCursor::selectAllDuringRemove()
1529{
1530 CursorListener listener(&cursor);
1531
1532 cursor.insertText(text: "Hello World");
1533 cursor.movePosition(op: QTextCursor::End);
1534
1535 connect(sender: doc, SIGNAL(contentsChanged()), receiver: &listener, SLOT(selectAllContents()));
1536 listener.recordingCount = 0;
1537 QTextCursor localCursor = cursor;
1538 localCursor.deletePreviousChar();
1539
1540 QCOMPARE(listener.lastRecordedPosition, 10);
1541 QCOMPARE(listener.lastRecordedAnchor, 0);
1542}
1543
1544void tst_QTextCursor::update_data()
1545{
1546 QTest::addColumn<QString>(name: "text");
1547 QTest::addColumn<int>(name: "position");
1548 QTest::addColumn<int>(name: "anchor");
1549 QTest::addColumn<int>(name: "modifyPosition");
1550 QTest::addColumn<int>(name: "modifyAnchor");
1551 QTest::addColumn<QString>(name: "insertText");
1552 QTest::addColumn<int>(name: "expectedPosition");
1553 QTest::addColumn<int>(name: "expectedAnchor");
1554
1555 QString text("Hello big world");
1556 int charsToDelete = 3;
1557 QTest::newRow(dataTag: "removeInsideSelection")
1558 << text
1559 << /*position*/ 0
1560 << /*anchor*/ text.length()
1561 // delete 'big'
1562 << 6
1563 << 6 + charsToDelete
1564 << QString() // don't insert anything, just remove
1565 << /*expectedPosition*/ 0
1566 << /*expectedAnchor*/ text.length() - charsToDelete
1567 ;
1568
1569 text = "Hello big world";
1570 charsToDelete = 3;
1571 QTest::newRow(dataTag: "removeInsideSelectionWithSwappedAnchorAndPosition")
1572 << text
1573 << /*position*/ text.length()
1574 << /*anchor*/ 0
1575 // delete 'big'
1576 << 6
1577 << 6 + charsToDelete
1578 << QString() // don't insert anything, just remove
1579 << /*expectedPosition*/ text.length() - charsToDelete
1580 << /*expectedAnchor*/ 0
1581 ;
1582
1583
1584 text = "Hello big world";
1585 charsToDelete = 3;
1586 QString textToInsert("small");
1587 QTest::newRow(dataTag: "replaceInsideSelection")
1588 << text
1589 << /*position*/ 0
1590 << /*anchor*/ text.length()
1591 // delete 'big' ...
1592 << 6
1593 << 6 + charsToDelete
1594 << textToInsert // ... and replace 'big' with 'small'
1595 << /*expectedPosition*/ 0
1596 << /*expectedAnchor*/ text.length() - charsToDelete + textToInsert.length()
1597 ;
1598
1599 text = "Hello big world";
1600 charsToDelete = 3;
1601 textToInsert = "small";
1602 QTest::newRow(dataTag: "replaceInsideSelectionWithSwappedAnchorAndPosition")
1603 << text
1604 << /*position*/ text.length()
1605 << /*anchor*/ 0
1606 // delete 'big' ...
1607 << 6
1608 << 6 + charsToDelete
1609 << textToInsert // ... and replace 'big' with 'small'
1610 << /*expectedPosition*/ text.length() - charsToDelete + textToInsert.length()
1611 << /*expectedAnchor*/ 0
1612 ;
1613
1614
1615 text = "Hello big world";
1616 charsToDelete = 3;
1617 QTest::newRow(dataTag: "removeBeforeSelection")
1618 << text
1619 << /*position*/ text.length() - 5
1620 << /*anchor*/ text.length()
1621 // delete 'big'
1622 << 6
1623 << 6 + charsToDelete
1624 << QString() // don't insert anything, just remove
1625 << /*expectedPosition*/ text.length() - 5 - charsToDelete
1626 << /*expectedAnchor*/ text.length() - charsToDelete
1627 ;
1628
1629 text = "Hello big world";
1630 charsToDelete = 3;
1631 QTest::newRow(dataTag: "removeAfterSelection")
1632 << text
1633 << /*position*/ 0
1634 << /*anchor*/ 4
1635 // delete 'big'
1636 << 6
1637 << 6 + charsToDelete
1638 << QString() // don't insert anything, just remove
1639 << /*expectedPosition*/ 0
1640 << /*expectedAnchor*/ 4
1641 ;
1642
1643}
1644
1645void tst_QTextCursor::update()
1646{
1647 QFETCH(QString, text);
1648
1649 doc->setPlainText(text);
1650
1651 QFETCH(int, position);
1652 QFETCH(int, anchor);
1653
1654 cursor.setPosition(pos: anchor);
1655 cursor.setPosition(pos: position, mode: QTextCursor::KeepAnchor);
1656
1657 QCOMPARE(cursor.position(), position);
1658 QCOMPARE(cursor.anchor(), anchor);
1659
1660 QFETCH(int, modifyPosition);
1661 QFETCH(int, modifyAnchor);
1662
1663 QTextCursor modifyCursor = cursor;
1664 modifyCursor.setPosition(pos: modifyAnchor);
1665 modifyCursor.setPosition(pos: modifyPosition, mode: QTextCursor::KeepAnchor);
1666
1667 QCOMPARE(modifyCursor.position(), modifyPosition);
1668 QCOMPARE(modifyCursor.anchor(), modifyAnchor);
1669
1670 QFETCH(QString, insertText);
1671 modifyCursor.insertText(text: insertText);
1672
1673 QFETCH(int, expectedPosition);
1674 QFETCH(int, expectedAnchor);
1675
1676 QCOMPARE(cursor.position(), expectedPosition);
1677 QCOMPARE(cursor.anchor(), expectedAnchor);
1678}
1679
1680void tst_QTextCursor::disallowSettingObjectIndicesOnCharFormats()
1681{
1682 QTextCharFormat fmt;
1683 fmt.setObjectIndex(42);
1684 cursor.insertText(text: "Hey", format: fmt);
1685 QCOMPARE(cursor.charFormat().objectIndex(), -1);
1686
1687 cursor.select(selection: QTextCursor::Document);
1688 cursor.mergeCharFormat(modifier: fmt);
1689 QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
1690
1691 cursor.select(selection: QTextCursor::Document);
1692 cursor.setCharFormat(fmt);
1693 QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
1694
1695 cursor.setBlockCharFormat(fmt);
1696 QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
1697
1698 cursor.movePosition(op: QTextCursor::End);
1699 cursor.insertBlock(format: QTextBlockFormat(), charFormat: fmt);
1700 QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
1701
1702 doc->clear();
1703
1704 QTextTable *table = cursor.insertTable(rows: 1, cols: 1);
1705 cursor.select(selection: QTextCursor::Document);
1706 cursor.setCharFormat(fmt);
1707
1708 cursor = table->cellAt(row: 0, col: 0).firstCursorPosition();
1709 QVERIFY(!cursor.isNull());
1710 QCOMPARE(cursor.blockCharFormat().objectIndex(), table->objectIndex());
1711}
1712
1713void tst_QTextCursor::blockAndColumnNumber()
1714{
1715 QCOMPARE(QTextCursor().columnNumber(), 0);
1716 QCOMPARE(QTextCursor().blockNumber(), 0);
1717
1718 QCOMPARE(cursor.columnNumber(), 0);
1719 QCOMPARE(cursor.blockNumber(), 0);
1720 cursor.insertText(text: "Hello");
1721 QCOMPARE(cursor.columnNumber(), 5);
1722 QCOMPARE(cursor.blockNumber(), 0);
1723
1724 cursor.insertBlock();
1725 QCOMPARE(cursor.columnNumber(), 0);
1726 QCOMPARE(cursor.blockNumber(), 1);
1727 cursor.insertText(text: "Blah");
1728 QCOMPARE(cursor.blockNumber(), 1);
1729
1730 // trigger a layout
1731 doc->documentLayout();
1732
1733 cursor.insertBlock();
1734 QCOMPARE(cursor.columnNumber(), 0);
1735 QCOMPARE(cursor.blockNumber(), 2);
1736 cursor.insertText(text: "Test");
1737 QCOMPARE(cursor.columnNumber(), 4);
1738 QCOMPARE(cursor.blockNumber(), 2);
1739 cursor.insertText(text: QString(QChar(QChar::LineSeparator)));
1740 QCOMPARE(cursor.columnNumber(), 0);
1741 QCOMPARE(cursor.blockNumber(), 2);
1742 cursor.insertText(text: "A");
1743 QCOMPARE(cursor.columnNumber(), 1);
1744 QCOMPARE(cursor.blockNumber(), 2);
1745}
1746
1747void tst_QTextCursor::movePositionEndOfLine()
1748{
1749 cursor.insertText(text: "blah\nblah\n");
1750 // Select part of the second line ("la")
1751 cursor.setPosition(pos: 6);
1752 cursor.movePosition(op: QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n: 2);
1753 QCOMPARE(cursor.selectedText(), QLatin1String("la"));
1754
1755 // trigger a layout
1756 doc->documentLayout();
1757
1758 // Remove "la" and append "something" to the end in one undo operation
1759 cursor.beginEditBlock();
1760 cursor.removeSelectedText();
1761 QTextCursor c2(doc);
1762 c2.setPosition(pos: 7);
1763 c2.insertText(text: "foo"); // append to doc without touching the cursor.
1764
1765 QCOMPARE(cursor.position(), 6);
1766 cursor.movePosition(op: QTextCursor::EndOfLine); // in an edit block visual movement is moved to the end of the paragraph
1767 QCOMPARE(cursor.position(), 10);
1768 cursor.endEditBlock();
1769}
1770
1771void tst_QTextCursor::clearCells()
1772{
1773 QTextTable *table = cursor.insertTable(rows: 3, cols: 5);
1774 cursor.setPosition(pos: table->cellAt(row: 0,col: 0).firstPosition()); // select cell 1 and cell 2
1775 cursor.setPosition(pos: table->cellAt(row: 0,col: 1).firstPosition(), mode: QTextCursor::KeepAnchor);
1776 cursor.deleteChar(); // should clear the cells, and not crash ;)
1777}
1778
1779void tst_QTextCursor::task244408_wordUnderCursor_data()
1780{
1781 QTest::addColumn<QString>(name: "input");
1782 QTest::addColumn<QString>(name: "expected");
1783 QTest::newRow(dataTag: "trailingSpace") << QString::fromLatin1(str: "foo ") << QString::fromLatin1(str: "");
1784 QTest::newRow(dataTag: "noTrailingSpace") << QString::fromLatin1(str: "foo") << QString::fromLatin1(str: "foo");
1785}
1786
1787void tst_QTextCursor::task244408_wordUnderCursor()
1788{
1789 QFETCH(QString, input);
1790 QFETCH(QString, expected);
1791 cursor.insertText(text: input);
1792 cursor.movePosition(op: QTextCursor::End);
1793 cursor.select(selection: QTextCursor::WordUnderCursor);
1794 QCOMPARE(cursor.selectedText(), expected);
1795}
1796
1797void tst_QTextCursor::adjustCursorsOnInsert()
1798{
1799 cursor.insertText(text: "Some text before ");
1800 int posBefore = cursor.position();
1801 cursor.insertText(text: "selected text");
1802 int posAfter = cursor.position();
1803 cursor.insertText(text: " some text afterwards");
1804
1805 QTextCursor selection = cursor;
1806 selection.setPosition(pos: posBefore);
1807 selection.setPosition(pos: posAfter, mode: QTextCursor::KeepAnchor);
1808
1809 cursor.setPosition(pos: posBefore-1);
1810 cursor.insertText(text: QLatin1String("x"));
1811 QCOMPARE(selection.anchor(), posBefore+1);
1812 QCOMPARE(selection.position(), posAfter+1);
1813 doc->undo();
1814
1815 cursor.setPosition(pos: posBefore);
1816 cursor.insertText(text: QLatin1String("x"));
1817 QCOMPARE(selection.anchor(), posBefore+1);
1818 QCOMPARE(selection.position(), posAfter+1);
1819 doc->undo();
1820
1821 cursor.setPosition(pos: posBefore+1);
1822 cursor.insertText(text: QLatin1String("x"));
1823 QCOMPARE(selection.anchor(), posBefore);
1824 QCOMPARE(selection.position(), posAfter+1);
1825 doc->undo();
1826
1827 cursor.setPosition(pos: posAfter-1);
1828 cursor.insertText(text: QLatin1String("x"));
1829 QCOMPARE(selection.anchor(), posBefore);
1830 QCOMPARE(selection.position(), posAfter+1);
1831 doc->undo();
1832
1833 selection.setKeepPositionOnInsert(true);
1834 cursor.setPosition(pos: posAfter);
1835 cursor.insertText(text: QLatin1String("x"));
1836 selection.setKeepPositionOnInsert(false);
1837 QCOMPARE(selection.anchor(), posBefore);
1838 QCOMPARE(selection.position(), posAfter);
1839 doc->undo();
1840
1841 cursor.setPosition(pos: posAfter+1);
1842 cursor.insertText(text: QLatin1String("x"));
1843 QCOMPARE(selection.anchor(), posBefore);
1844 QCOMPARE(selection.position(), posAfter);
1845 doc->undo();
1846
1847 selection.setPosition(pos: posAfter);
1848 selection.setPosition(pos: posBefore, mode: QTextCursor::KeepAnchor);
1849
1850 cursor.setPosition(pos: posBefore-1);
1851 cursor.insertText(text: QLatin1String("x"));
1852 QCOMPARE(selection.position(), posBefore+1);
1853 QCOMPARE(selection.anchor(), posAfter+1);
1854 doc->undo();
1855
1856 cursor.setPosition(pos: posBefore);
1857 cursor.insertText(text: QLatin1String("x"));
1858 QCOMPARE(selection.position(), posBefore+1);
1859 QCOMPARE(selection.anchor(), posAfter+1);
1860 doc->undo();
1861
1862 cursor.setPosition(pos: posBefore+1);
1863 cursor.insertText(text: QLatin1String("x"));
1864 QCOMPARE(selection.position(), posBefore);
1865 QCOMPARE(selection.anchor(), posAfter+1);
1866 doc->undo();
1867
1868 cursor.setPosition(pos: posAfter-1);
1869 cursor.insertText(text: QLatin1String("x"));
1870 QCOMPARE(selection.position(), posBefore);
1871 QCOMPARE(selection.anchor(), posAfter+1);
1872 doc->undo();
1873
1874 cursor.setPosition(pos: posAfter);
1875 cursor.insertText(text: QLatin1String("x"));
1876 QCOMPARE(selection.position(), posBefore);
1877 QCOMPARE(selection.anchor(), posAfter+1);
1878 doc->undo();
1879
1880 cursor.setPosition(pos: posAfter+1);
1881 cursor.insertText(text: QLatin1String("x"));
1882 QCOMPARE(selection.position(), posBefore);
1883 QCOMPARE(selection.anchor(), posAfter);
1884 doc->undo();
1885
1886}
1887void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo()
1888{
1889 cursor.insertText(text: "AAAABBBBCCCCDDDD");
1890 cursor.setPosition(pos: 12);
1891 int cursorPositionBefore = cursor.position();
1892 cursor.beginEditBlock();
1893 cursor.insertText(text: "*");
1894 cursor.setPosition(pos: 8);
1895 cursor.insertText(text: "*");
1896 cursor.setPosition(pos: 4);
1897 cursor.insertText(text: "*");
1898 cursor.setPosition(pos: 0);
1899 cursor.insertText(text: "*");
1900 int cursorPositionAfter = cursor.position();
1901 cursor.endEditBlock();
1902
1903 QCOMPARE(doc->toPlainText(), QLatin1String("*AAAA*BBBB*CCCC*DDDD"));
1904 QCOMPARE(12, cursorPositionBefore);
1905 QCOMPARE(1, cursorPositionAfter);
1906
1907 doc->undo(cursor: &cursor);
1908 QCOMPARE(doc->toPlainText(), QLatin1String("AAAABBBBCCCCDDDD"));
1909 QCOMPARE(cursor.position(), cursorPositionBefore);
1910 doc->redo(cursor: &cursor);
1911 QCOMPARE(doc->toPlainText(), QLatin1String("*AAAA*BBBB*CCCC*DDDD"));
1912 QCOMPARE(cursor.position(), cursorPositionAfter);
1913}
1914
1915void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo2()
1916{
1917 cursor.insertText(text: "AAAABBBB");
1918 int cursorPositionBefore = cursor.position();
1919 cursor.setPosition(pos: 0, mode: QTextCursor::KeepAnchor);
1920 cursor.beginEditBlock();
1921 cursor.removeSelectedText();
1922 cursor.insertText(text: "AAAABBBBCCCCDDDD");
1923 cursor.endEditBlock();
1924 doc->undo(cursor: &cursor);
1925 QCOMPARE(doc->toPlainText(), QLatin1String("AAAABBBB"));
1926 QCOMPARE(cursor.position(), cursorPositionBefore);
1927
1928 cursor.insertText(text: "CCCC");
1929 QCOMPARE(doc->toPlainText(), QLatin1String("AAAABBBBCCCC"));
1930
1931 cursorPositionBefore = cursor.position();
1932 cursor.setPosition(pos: 0, mode: QTextCursor::KeepAnchor);
1933 cursor.beginEditBlock();
1934 cursor.removeSelectedText();
1935 cursor.insertText(text: "AAAABBBBCCCCDDDD");
1936 cursor.endEditBlock();
1937
1938 /* this undo now implicitely reinserts two segments, first "CCCCC", then
1939 "AAAABBBB". The test ensures that the two are combined in order to
1940 reconstruct the correct cursor position */
1941 doc->undo(cursor: &cursor);
1942
1943
1944 QCOMPARE(doc->toPlainText(), QLatin1String("AAAABBBBCCCC"));
1945 QCOMPARE(cursor.position(), cursorPositionBefore);
1946}
1947
1948void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo3()
1949{
1950 // verify that it's the position of the beginEditBlock that counts, and not the last edit position
1951 cursor.insertText(text: "AAAABBBB");
1952 int cursorPositionBefore = cursor.position();
1953 cursor.beginEditBlock();
1954 cursor.setPosition(pos: 4);
1955 QVERIFY(cursor.position() != cursorPositionBefore);
1956 cursor.insertText(text: "*");
1957 cursor.endEditBlock();
1958 QCOMPARE(cursor.position(), 5);
1959 doc->undo(cursor: &cursor);
1960 QCOMPARE(cursor.position(), cursorPositionBefore);
1961}
1962
1963void tst_QTextCursor::joinNonEmptyRemovedBlockUserState()
1964{
1965 cursor.insertText(text: "Hello");
1966 cursor.insertBlock();
1967 cursor.insertText(text: "World");
1968 cursor.block().setUserState(10);
1969
1970 cursor.movePosition(op: QTextCursor::EndOfBlock);
1971 cursor.movePosition(op: QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
1972 cursor.movePosition(op: QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1973 cursor.removeSelectedText();
1974
1975 QCOMPARE(cursor.block().userState(), 10);
1976}
1977
1978void tst_QTextCursor::crashOnDetachingDanglingCursor()
1979{
1980 QTextDocument *document = new QTextDocument;
1981 QTextCursor cursor(document);
1982 QTextCursor cursor2 = cursor;
1983 delete document;
1984 cursor2.setPosition(pos: 0); // Don't crash here
1985}
1986
1987QTEST_MAIN(tst_QTextCursor)
1988#include "tst_qtextcursor.moc"
1989

source code of qtbase/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp