QtBase  v6.3.1
tst_qtextpiecetable.cpp
Go to the documentation of this file.
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 <QTest>
31 #include <QRandomGenerator>
32 
33 #define protected public
34 
35 #include <qtextdocument.h>
36 #undef protected
37 #include <private/qtextdocument_p.h>
39 #include <qtextobject.h>
40 #include <qdebug.h>
41 #include <stdlib.h>
42 #include <qtextcursor.h>
43 #include "../qtextdocument/common.h"
44 
46 {
47  Q_OBJECT
48 
49 public:
51 
52 
53 public slots:
54  void init();
55  void cleanup();
56 private slots:
57  void insertion1();
58  void insertion2();
59  void insertion3();
60  void insertion4();
61  void insertion5();
62 
63  void removal1();
64  void removal2();
65  void removal3();
66  void removal4();
67 
68  void undoRedo1();
69  void undoRedo2();
70  void undoRedo3();
71  void undoRedo4();
72  void undoRedo5();
73  void undoRedo6();
74  void undoRedo7();
75  void undoRedo8();
76  void undoRedo9();
77  void undoRedo10();
78  void undoRedo11();
79 
80  void checkDocumentChanged();
81  void checkDocumentChanged2();
82  void setBlockFormat();
83 
84  void blockInsertion();
85  void blockInsertion2();
86 
87  void blockRemoval1();
88  void blockRemoval2();
89  void blockRemoval3();
90  void blockRemoval4();
91  void blockRemoval5();
92 
93  void checkBlockSeparation();
94 
95  void checkFrames1();
96  void removeFrameDirect();
97  void removeWithChildFrame();
98  void clearWithFrames();
99 
100 private:
101  QTextDocument *doc;
103  int blockFormatIndex;
104  int charFormatIndex;
105 };
106 
108 { doc = 0; table = 0; }
109 
110 
112 {
113  doc = new QTextDocument(0);
115  blockFormatIndex = table->formatCollection()->indexForFormat(QTextBlockFormat());
116  charFormatIndex = table->formatCollection()->indexForFormat(QTextCharFormat());
117 }
118 
120 {
121  delete doc;
122  doc = 0;
123 }
124 
125 void tst_QTextPieceTable::insertion1()
126 {
127  table->insert(0, "aacc", charFormatIndex);
128  QCOMPARE(table->plainText(), QString("aacc"));
129  table->insert(2, "bb", charFormatIndex);
130  QCOMPARE(table->plainText(), QString("aabbcc"));
131  table->insert(1, "1", charFormatIndex);
132  QCOMPARE(table->plainText(), QString("a1abbcc"));
133  table->insert(6, "d", charFormatIndex);
134  QCOMPARE(table->plainText(), QString("a1abbcdc"));
135  table->insert(8, "z", charFormatIndex);
136  QCOMPARE(table->plainText(), QString("a1abbcdcz"));
137 }
138 
139 void tst_QTextPieceTable::insertion2()
140 {
141  table->insert(0, "bb", charFormatIndex);
142  QCOMPARE(table->plainText(), QString("bb"));
143 }
144 
145 void tst_QTextPieceTable::insertion3()
146 {
148  for (int i = 0; i < 20000; ++i) {
150  QChar c((unsigned short)(i & 0xff) + 1);
151  QString str;
152  str += c;
153  table->insert(pos, str, charFormatIndex);
154  compare.insert(pos, str);
155  }
156  QCOMPARE(table->plainText(), compare);
157 }
158 
159 void tst_QTextPieceTable::insertion4()
160 {
162  for (int i = 0; i < 20000; ++i) {
163  int pos = QRandomGenerator::global()->generate() % (i+1);
164  QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
165  QString str;
166  str += c;
167  str += c;
168  table->insert(pos, str, charFormatIndex);
169  compare.insert(pos, str);
170 // if (table->text() != compare) {
171 // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1());
172 // exit(12);
173 // }
174  }
175  QCOMPARE(table->plainText(), compare);
176 }
177 
178 void tst_QTextPieceTable::insertion5()
179 {
181  for (int i = 0; i < 20000; ++i) {
182  int pos = QRandomGenerator::global()->generate() % (i+1);
183  QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
184  QString str;
185  str += c;
186  str += c;
187  if (c == 'a') {
188  table->insertBlock(pos, blockFormatIndex, charFormatIndex);
190  } else {
191  table->insert(pos, str, charFormatIndex);
192  }
193  compare.insert(pos, str);
194  }
195  QCOMPARE(table->plainText(), compare);
196  for (QTextBlock it = table->blocksBegin(); it != table->blocksEnd(); it = it.next()) {
197  QTextDocumentPrivate::FragmentIterator fit = table->find(it.position());
198  QCOMPARE(fit.position(), it.position());
199  }
200 }
201 
202 void tst_QTextPieceTable::removal1()
203 {
204  table->insert(0, "abbccc", charFormatIndex);
205  QCOMPARE(table->plainText(), QString("abbccc"));
206  table->remove(1, 2);
207  QCOMPARE(table->plainText(), QString("accc"));
208  table->insert(1, "1", charFormatIndex);
209  QCOMPARE(table->plainText(), QString("a1ccc"));
210  table->remove(4, 1);
211  QCOMPARE(table->plainText(), QString("a1cc"));
212  table->insert(4, "z", charFormatIndex);
213  QCOMPARE(table->plainText(), QString("a1ccz"));
214 }
215 
216 void tst_QTextPieceTable::removal2()
217 {
218  table->insert(0, "bb", charFormatIndex);
219  QCOMPARE(table->plainText(), QString("bb"));
220  table->remove(0, 2);
221  QCOMPARE(table->plainText(), QString(""));
222  table->insertBlock(0, blockFormatIndex, charFormatIndex);
224  table->remove(0, 1);
225  QCOMPARE(table->plainText(), QString(""));
226 
227  table->insert(0, "bb", charFormatIndex);
228  QCOMPARE(table->plainText(), QString("bb"));
229  table->insertBlock(1, blockFormatIndex, charFormatIndex);
230  QCOMPARE(table->plainText(), QString("b") + QString(QChar(QChar::ParagraphSeparator)) + QString("b"));
231  table->remove(1, 1);
232  QCOMPARE(table->plainText(), QString("bb"));
233 }
234 
235 void tst_QTextPieceTable::removal3()
236 {
238  int l = 0;
239  for (int i = 0; i < 20000; ++i) {
240  bool remove = l && (QRandomGenerator::global()->bounded(2));
241  int pos = QRandomGenerator::global()->bounded(remove ? l : (l+1));
242  QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
243  QString str;
244  str += c;
245  str += c;
246  if (remove && pos < table->length()) {
247  compare.remove(pos, 1);
248  table->remove(pos, 1);
249  } else {
250  compare.insert(pos, str);
251  table->insert(pos, str, charFormatIndex);
252  }
253  l += remove ? -1 : 2;
254 // if (table->text() != compare) {
255 // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1());
256 // exit(12);
257 // }
258  }
259  QCOMPARE(table->plainText(), compare);
260 }
261 
262 void tst_QTextPieceTable::removal4()
263 {
265  int l = 0;
266  for (int i = 0; i < 20000; ++i) {
267  bool remove = l && (QRandomGenerator::global()->bounded(2));
268  int pos = (l > 1) ? QRandomGenerator::global()->bounded(remove ? l-1 : l) : 0;
269  QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
270  QString str;
271  if (c != 'a') {
272  str += c;
273  str += c;
274  } else {
276  }
277  if (remove && pos < table->length() - 1) {
278  compare.remove(pos, 1);
279  table->remove(pos, 1);
280  } else {
282  table->insertBlock(pos, blockFormatIndex, charFormatIndex);
283  else
284  table->insert(pos, str, charFormatIndex);
285  compare.insert(pos, str);
286  }
287  l += remove ? -1 : 2;
288 // if (table->plainText() != compare) {
289 // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->plainText().latin1());
290 // exit(12);
291 // }
292  }
293  QCOMPARE(table->plainText(), compare);
294 }
295 
296 void tst_QTextPieceTable::undoRedo1()
297 {
298  table->insert(0, "01234567", charFormatIndex);
299  table->insert(0, "a", charFormatIndex);
300  table->insert(1, "b", charFormatIndex);
301  QCOMPARE(table->plainText(), QString("ab01234567"));
302  table->undo();
303  QCOMPARE(table->plainText(), QString("01234567"));
304  table->redo();
305  QCOMPARE(table->plainText(), QString("ab01234567"));
306  table->undo();
307  table->insert(1, "c", charFormatIndex);
308  QCOMPARE(table->plainText(), QString("0c1234567"));
309  table->undo();
310  QCOMPARE(table->plainText(), QString("01234567"));
311  table->undo();
312  QVERIFY(table->plainText().isEmpty());
313 }
314 
315 void tst_QTextPieceTable::undoRedo2()
316 {
317  table->insert(0, "01", charFormatIndex);
318  table->insert(1, "a", charFormatIndex);
319  QCOMPARE(table->plainText(), QString("0a1"));
320  table->undo();
321  QCOMPARE(table->plainText(), QString("01"));
322  table->undo();
323  QCOMPARE(table->plainText(), QString(""));
324  table->redo();
325  QCOMPARE(table->plainText(), QString("01"));
326  table->redo();
327  QCOMPARE(table->plainText(), QString("0a1"));
328 }
329 
330 void tst_QTextPieceTable::undoRedo3()
331 {
332  table->insert(0, "01", charFormatIndex);
333  table->insert(2, "ab", charFormatIndex);
334  table->remove(2, 1);
335  QCOMPARE(table->plainText(), QString("01b"));
336  table->undo();
337  QCOMPARE(table->plainText(), QString("01ab"));
338  table->undo();
339  QVERIFY(table->plainText().isEmpty());
340  table->redo();
341  QCOMPARE(table->plainText(), QString("01ab"));
342  table->redo();
343  QCOMPARE(table->plainText(), QString("01b"));
344 }
345 
346 void tst_QTextPieceTable::undoRedo4()
347 {
348  table->insert(0, "01", charFormatIndex);
349  table->insert(0, "ab", charFormatIndex);
350  table->remove(0, 1);
351  QCOMPARE(table->plainText(), QString("b01"));
352  table->undo();
353  QCOMPARE(table->plainText(), QString("ab01"));
354  table->undo();
355  QCOMPARE(table->plainText(), QString("01"));
356  table->undo();
357  QCOMPARE(table->plainText(), QString(""));
358  table->redo();
359  QCOMPARE(table->plainText(), QString("01"));
360  table->redo();
361  QCOMPARE(table->plainText(), QString("ab01"));
362  table->redo();
363  QCOMPARE(table->plainText(), QString("b01"));
364 }
365 
366 void tst_QTextPieceTable::undoRedo5()
367 {
368  table->beginEditBlock();
369  table->insert(0, "01", charFormatIndex);
370  table->remove(1, 1);
371  table->endEditBlock();
372  QCOMPARE(table->plainText(), QString("0"));
373  table->undo();
374  QCOMPARE(table->plainText(), QString(""));
375 }
376 
377 void tst_QTextPieceTable::undoRedo6()
378 {
379  // this is essentially a test for the undoStack[undoPosition - 1].block = false in PieceTable::endUndoBlock()
380  QTextDocument doc;
381  QTextCursor cursor(&doc);
382  cursor.insertText("Hello World");
383 
384  cursor.insertBlock();
385  cursor.insertText("Hello World2");
386 
387  cursor.movePosition(QTextCursor::Start);
388  QTextBlockFormat bfmt;
390  cursor.setBlockFormat(bfmt);
391  QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter);
392 
394  range.clearSelection();
395  range.movePosition(QTextCursor::Start);
397 
398  QTextCharFormat modifier;
399  modifier.setFontItalic(true);
400  range.mergeCharFormat(modifier);
401 
402  cursor.movePosition(QTextCursor::Start);
403  QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter);
404 
405  doc.undo();
406 
407  QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter);
408 }
409 
410 void tst_QTextPieceTable::undoRedo7()
411 {
412  table->insert(0, "a", charFormatIndex);
413  table->insert(1, "b", charFormatIndex);
414  QCOMPARE(table->plainText(), QString("ab"));
415 
416  table->undo();
417  QVERIFY(table->plainText().isEmpty());
418 }
419 
420 void tst_QTextPieceTable::undoRedo8()
421 {
422  table->insert(0, "a", charFormatIndex);
423  table->insert(1, "b", charFormatIndex);
424  QCOMPARE(table->plainText(), QString("ab"));
425 
426  table->remove(0, 1);
427  table->remove(0, 1);
428 
429  QVERIFY(table->plainText().isEmpty());
430  table->undo();
431  QCOMPARE(table->plainText(), QString("ab"));
432 }
433 
434 void tst_QTextPieceTable::undoRedo9()
435 {
436  table->insert(0, "a", charFormatIndex);
437  table->insert(1, "b", charFormatIndex);
438  QCOMPARE(table->plainText(), QString("ab"));
439 
440  table->remove(1, 1);
441  table->remove(0, 1);
442 
443  QVERIFY(table->plainText().isEmpty());
444  table->undo();
445  QCOMPARE(table->plainText(), QString("ab"));
446 }
447 
448 void tst_QTextPieceTable::undoRedo10()
449 {
450  // testcase for the beginUndoBlock/endUndoBlock calls being surrounded by an if (undoEnabled)
451  QTextCharFormat cf;
453  int cfIdx = table->formatCollection()->indexForFormat(cf);
454 
456  int idx = table->formatCollection()->indexForFormat(f);
457 
458  table->insert(0, "a", cfIdx);
459  table->insertBlock(1, idx, cfIdx);
460  table->insert(1, "b", cfIdx);
461 
463  int newCfIdx = table->formatCollection()->indexForFormat(cf);
464 
465  table->setCharFormat(0, 3, cf, QTextDocumentPrivate::MergeFormat);
466 
467  QCOMPARE(table->find(0).value()->format, newCfIdx);
468 
469  table->undo();
470 
471  QCOMPARE(table->find(0).value()->format, cfIdx);
472 }
473 
474 void tst_QTextPieceTable::undoRedo11()
475 {
476  const int loops = 20;
478  int l = 0;
479  for (int i = 0; i < loops; ++i) {
480  bool remove = l && (QRandomGenerator::global()->bounded(2));
481  int pos = (l > 1) ? QRandomGenerator::global()->bounded(remove ? l-1 : l) : 0;
482  QChar c((unsigned short)((i % 26) + (i>25?'A':'a')));
483  QString str;
484  str += c;
485  str += c;
486  if (remove) {
487  compare.remove(pos, 1);
488  table->remove(pos, 1);
489  } else {
490  compare.insert(pos, str);
491  table->insert(pos, str, charFormatIndex);
492  }
493  l += remove ? -1 : 2;
494  }
495  QCOMPARE(table->plainText(), compare);
496  for (int i = 0; i < loops; ++i)
497  table->undo();
498  QCOMPARE(table->plainText(), QString(""));
499  for (int i = 0; i < loops; ++i)
500  table->redo();
501  QCOMPARE(table->plainText(), compare);
502 }
503 
504 
505 void tst_QTextPieceTable::checkDocumentChanged()
506 {
507  table->enableUndoRedo(false);
510 
511  // single insert
512  layout->expect(0, 0, 15);
513  table->insert(0, "012345678901234", charFormatIndex);
514  QVERIFY(!layout->error);
515 
516  // single remove
517  layout->expect(0, 5, 0);
518  table->remove(0, 5);
519  QVERIFY(!layout->error);
520 
521  // symmetric insert/remove
522  layout->expect(0, 0, 0);
523  table->beginEditBlock();
524  table->insert(0, "01234", charFormatIndex);
525  table->remove(0, 5);
526  table->endEditBlock();
527  QVERIFY(!layout->error);
528 
529  layout->expect(0, 5, 5);
530  table->beginEditBlock();
531  table->remove(0, 5);
532  table->insert(0, "01234", charFormatIndex);
533  table->endEditBlock();
534  QVERIFY(!layout->error);
535 
536  // replace
537  layout->expect(0, 3, 5);
538  table->beginEditBlock();
539  table->remove(0, 3);
540  table->insert(0, "01234", charFormatIndex);
541  table->endEditBlock();
542  QVERIFY(!layout->error);
543 
544  layout->expect(0, 0, 2);
545  table->beginEditBlock();
546  table->insert(0, "01234", charFormatIndex);
547  table->remove(0, 3);
548  table->endEditBlock();
549  QVERIFY(!layout->error);
550 
551  // insert + remove inside insert block
552  layout->expect(0, 0, 2);
553  table->beginEditBlock();
554  table->insert(0, "01234", charFormatIndex);
555  table->remove(1, 3);
556  table->endEditBlock();
557  QVERIFY(!layout->error);
558 
559  layout->expect(0, 0, 2);
560  table->beginEditBlock();
561  table->insert(0, "01234", charFormatIndex);
562  table->remove(2, 3);
563  table->endEditBlock();
564  QVERIFY(!layout->error);
565 
566  // insert + remove partly outside
567  layout->expect(0, 1, 0);
568  table->beginEditBlock();
569  table->insert(1, "0", charFormatIndex);
570  table->remove(0, 2);
571  table->endEditBlock();
572  QVERIFY(!layout->error);
573 
574  layout->expect(0, 1, 1);
575  table->beginEditBlock();
576  table->insert(1, "01", charFormatIndex);
577  table->remove(0, 2);
578  table->endEditBlock();
579  QVERIFY(!layout->error);
580 
581  layout->expect(0, 1, 2);
582  table->beginEditBlock();
583  table->insert(1, "012", charFormatIndex);
584  table->remove(0, 2);
585  table->endEditBlock();
586  QVERIFY(!layout->error);
587 
588  layout->expect(1, 1, 0);
589  table->beginEditBlock();
590  table->insert(1, "0", charFormatIndex);
591  table->remove(1, 2);
592  table->endEditBlock();
593  QVERIFY(!layout->error);
594 
595  layout->expect(1, 1, 1);
596  table->beginEditBlock();
597  table->insert(1, "01", charFormatIndex);
598  table->remove(2, 2);
599  table->endEditBlock();
600  QVERIFY(!layout->error);
601 
602  layout->expect(1, 1, 2);
603  table->beginEditBlock();
604  table->insert(1, "012", charFormatIndex);
605  table->remove(3, 2);
606  table->endEditBlock();
607  QVERIFY(!layout->error);
608 
609  // insert + remove non overlapping
610  layout->expect(0, 1, 1);
611  table->beginEditBlock();
612  table->insert(1, "0", charFormatIndex);
613  table->remove(0, 1);
614  table->endEditBlock();
615  QVERIFY(!layout->error);
616 
617  layout->expect(0, 2, 2);
618  table->beginEditBlock();
619  table->insert(2, "1", charFormatIndex);
620  table->remove(0, 1);
621  table->endEditBlock();
622  QVERIFY(!layout->error);
623 
624  layout->expect(0, 2, 2);
625  table->beginEditBlock();
626  table->remove(0, 1);
627  table->insert(1, "0", charFormatIndex);
628  table->endEditBlock();
629  QVERIFY(!layout->error);
630 
631  layout->expect(0, 3, 3);
632  table->beginEditBlock();
633  table->remove(0, 1);
634  table->insert(2, "1", charFormatIndex);
635  table->endEditBlock();
636 
637 
638  layout->expect(0, 3, 3);
639  QTextCharFormat fmt;
640  fmt.setForeground(Qt::blue);
641  table->beginEditBlock();
642  table->setCharFormat(0, 1, fmt);
643  table->setCharFormat(2, 1, fmt);
644  table->endEditBlock();
645  QVERIFY(!layout->error);
646 }
647 
648 void tst_QTextPieceTable::checkDocumentChanged2()
649 {
652 
653  QTextCharFormat fmt;
654  fmt.setForeground(Qt::blue);
655  int anotherCharFormatIndex = table->formatCollection()->indexForFormat(fmt);
656 
657  layout->expect(0, 0, 12);
658  table->beginEditBlock();
659  table->insert(0, "0123", charFormatIndex);
660  table->insert(4, "4567", anotherCharFormatIndex);
661  table->insert(8, "8901", charFormatIndex);
662  table->endEditBlock();
663  QVERIFY(!layout->error);
664 
665  fmt.setFontItalic(true);
666 
667  layout->expect(1, 10, 10);
668  table->beginEditBlock();
669  table->setCharFormat(8, 3, fmt);
670  table->setCharFormat(4, 4, fmt);
671  table->setCharFormat(1, 3, fmt);
672  table->endEditBlock();
673  QVERIFY(!layout->error);
674 }
675 
676 void tst_QTextPieceTable::setBlockFormat()
677 {
678  QTextBlockFormat bfmt;
679  int index = table->formatCollection()->indexForFormat(bfmt);
680 
681  table->insertBlock(0, index, charFormatIndex);
682  table->insertBlock(0, index, charFormatIndex);
683  table->insertBlock(0, index, charFormatIndex);
684 
685  QTextBlockFormat newbfmt = bfmt;
686  newbfmt.setAlignment(Qt::AlignRight);
687  index = table->formatCollection()->indexForFormat(bfmt);
688  QTextBlock b = table->blocksFind(1);
689  table->setBlockFormat(b, b, newbfmt);
690 
691  QCOMPARE(table->blocksFind(0).blockFormat(), bfmt);
692  QCOMPARE(table->blocksFind(1).blockFormat(), newbfmt);
693  QCOMPARE(table->blocksFind(2).blockFormat(), bfmt);
694 }
695 
696 
697 void tst_QTextPieceTable::blockInsertion()
698 {
699  QTextBlockFormat fmt;
700  fmt.setTopMargin(100);
701  int idx = table->formatCollection()->indexForFormat(fmt);
702  int charFormat = table->formatCollection()->indexForFormat(QTextCharFormat());
703  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
704 
705  table->insertBlock(0, idx, charFormat);
706  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
707  QCOMPARE(table->blocksFind(1).blockFormat(), fmt);
708 
709  table->undo();
710  QCOMPARE(table->blockMap().length(), 1);
711  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
712 
713  table->redo();
714  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
715  QCOMPARE(table->blocksFind(1).blockFormat(), fmt);
716 }
717 
718 void tst_QTextPieceTable::blockInsertion2()
719 {
720  // caused evil failing assertion in fragmentmap
721  int pos = 0;
722  table->insertBlock(pos, blockFormatIndex, charFormatIndex);
723  pos += 1;
724  table->insert(pos, "a", charFormatIndex);
725  pos += 1;
726 
727  pos -= 1;
728  table->insertBlock(pos, blockFormatIndex, charFormatIndex);
729  QCOMPARE(table->blocksFind(0).position(), 0);
730  QCOMPARE(table->blocksFind(1).position(), 1);
731  QCOMPARE(table->blocksFind(2).position(), 2);
732 }
733 
734 /*
735  Tests correct removal behaviour when deleting over block boundaries or complete blocks.
736 */
737 
738 void tst_QTextPieceTable::blockRemoval1()
739 {
740  QTextBlockFormat fmt1;
741  fmt1.setTopMargin(100);
742  QTextBlockFormat fmt2;
744  int idx1 = table->formatCollection()->indexForFormat(fmt1);
745  int idx2 = table->formatCollection()->indexForFormat(fmt2);
746 
747  table->insert(0, "0123", charFormatIndex);
748  table->insertBlock(4, idx1, charFormatIndex);
749  table->insert(5, "5678", charFormatIndex);
750  table->insertBlock(9, idx2, charFormatIndex);
751  table->insert(10, "0123", charFormatIndex);
752 
753  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
754  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
755  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
756  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
757  QCOMPARE(table->blocksFind(1).position(), 0);
758  QCOMPARE(table->blocksFind(6).position(), 5);
759  QCOMPARE(table->blocksFind(11).position(), 10);
760 
761  table->beginEditBlock();
762  table->remove(5, 5);
763  table->endEditBlock();
764  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
765  QCOMPARE(table->blocksFind(5).blockFormat(), fmt2);
766  QCOMPARE(table->blocksFind(4).position(), 0);
767  QCOMPARE(table->blocksFind(5).position(), 5);
768 
769  table->undo();
770 
771  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
772  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
773  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
774  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
775  QCOMPARE(table->blocksFind(1).position(), 0);
776  QCOMPARE(table->blocksFind(6).position(), 5);
777  QCOMPARE(table->blocksFind(11).position(), 10);
778 
779  table->redo();
780  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
781  QCOMPARE(table->blocksFind(5).blockFormat(), fmt2);
782  QCOMPARE(table->blocksFind(4).position(), 0);
783  QCOMPARE(table->blocksFind(5).position(), 5);
784 }
785 
786 void tst_QTextPieceTable::blockRemoval2()
787 {
788  QTextBlockFormat fmt1;
789  fmt1.setTopMargin(100);
790  QTextBlockFormat fmt2;
792  int idx1 = table->formatCollection()->indexForFormat(fmt1);
793  int idx2 = table->formatCollection()->indexForFormat(fmt2);
794 
795  table->insert(0, "0123", charFormatIndex);
796  table->insertBlock(4, idx1, charFormatIndex);
797  table->insert(5, "5678", charFormatIndex);
798  table->insertBlock(9, idx2, charFormatIndex);
799  table->insert(10, "0123", charFormatIndex);
800 
801  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
802  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
803  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
804  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
805  QCOMPARE(table->blocksFind(1).position(), 0);
806  QCOMPARE(table->blocksFind(6).position(), 5);
807  QCOMPARE(table->blocksFind(11).position(), 10);
808 
809  table->remove(4, 1);
810  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
811  QCOMPARE(table->blocksFind(6).blockFormat(), QTextBlockFormat());
812  QCOMPARE(table->blocksFind(4).position(), 0);
813  QCOMPARE(table->blocksFind(6).position(), 0);
814 
815  table->undo();
816 
817  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
818  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
819  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
820  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
821  QCOMPARE(table->blocksFind(1).position(), 0);
822  QCOMPARE(table->blocksFind(6).position(), 5);
823  QCOMPARE(table->blocksFind(11).position(), 10);
824 
825  table->redo();
826  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
827  QCOMPARE(table->blocksFind(6).blockFormat(), QTextBlockFormat());
828  QCOMPARE(table->blocksFind(4).position(), 0);
829  QCOMPARE(table->blocksFind(6).position(), 0);
830 }
831 
832 void tst_QTextPieceTable::blockRemoval3()
833 {
834  QTextBlockFormat fmt1;
835  fmt1.setTopMargin(100);
836  QTextBlockFormat fmt2;
838  int idx1 = table->formatCollection()->indexForFormat(fmt1);
839  int idx2 = table->formatCollection()->indexForFormat(fmt2);
840 
841  table->insert(0, "0123", charFormatIndex);
842  table->insertBlock(4, idx1, charFormatIndex);
843  table->insert(5, "5678", charFormatIndex);
844  table->insertBlock(9, idx2, charFormatIndex);
845  table->insert(10, "0123", charFormatIndex);
846 
847  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
848  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
849  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
850  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
851  QCOMPARE(table->blocksFind(1).position(), 0);
852  QCOMPARE(table->blocksFind(6).position(), 5);
853  QCOMPARE(table->blocksFind(11).position(), 10);
854 
855  table->beginEditBlock();
856  table->remove(3, 4);
857  table->endEditBlock();
858 
859  QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat());
860  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
861  QCOMPARE(table->blocksFind(1).position(), 0);
862  QCOMPARE(table->blocksFind(5).position(), 0);
863 
864  table->undo();
865 
866  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
867  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
868  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
869  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
870  QCOMPARE(table->blocksFind(1).position(), 0);
871  QCOMPARE(table->blocksFind(6).position(), 5);
872  QCOMPARE(table->blocksFind(11).position(), 10);
873 
874  table->redo();
875  QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat());
876  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
877  QCOMPARE(table->blocksFind(1).position(), 0);
878  QCOMPARE(table->blocksFind(5).position(), 0);
879 }
880 
881 void tst_QTextPieceTable::blockRemoval4()
882 {
883 #if 0
884  QTextBlockFormat fmt1;
885  fmt1.setTopMargin(100);
886  QTextBlockFormat fmt2;
888  int idx1 = table->formatCollection()->indexForFormat(fmt1);
889  int idx2 = table->formatCollection()->indexForFormat(fmt2);
890 
891  table->insert(0, "0123", charFormatIndex);
892  table->insertBlock(4, idx1, charFormatIndex);
893  table->insert(5, "5678", charFormatIndex);
894  table->insertBlock(9, idx2, charFormatIndex);
895  table->insert(10, "0123", charFormatIndex);
896 
897  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
898  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
899  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
900  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
901  QCOMPARE(table->blocksFind(1).position(), 0);
902  QCOMPARE(table->blocksFind(6).position(), 5);
903  QCOMPARE(table->blocksFind(11).position(), 10);
904 
905  table->remove(3, 7);
906  QCOMPARE(table->blocksFind(1).position(), 0);
907  QCOMPARE(table->blocksFind(5).position(), 0);
908  QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat());
909  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
910 
911  table->undo();
912 
913  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
914  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
915  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
916  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
917  QCOMPARE(table->blocksFind(1).position(), 0);
918  QCOMPARE(table->blocksFind(6).position(), 5);
919  QCOMPARE(table->blocksFind(11).position(), 10);
920 
921  table->redo();
922  QCOMPARE(table->blocksFind(1).position(), 0);
923  QCOMPARE(table->blocksFind(5).position(), 0);
924  QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat());
925  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
926 #endif
927 }
928 
929 void tst_QTextPieceTable::blockRemoval5()
930 {
931  QTextBlockFormat fmt1;
932  fmt1.setTopMargin(100);
933  QTextBlockFormat fmt2;
935  int idx1 = table->formatCollection()->indexForFormat(fmt1);
936  int idx2 = table->formatCollection()->indexForFormat(fmt2);
937 
938  table->insert(0, "0123", charFormatIndex);
939  table->insertBlock(4, idx1, charFormatIndex);
940  table->insert(5, "5678", charFormatIndex);
941  table->insertBlock(9, idx2, charFormatIndex);
942  table->insert(10, "0123", charFormatIndex);
943 
944  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
945  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
946  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
947  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
948  QCOMPARE(table->blocksFind(1).position(), 0);
949  QCOMPARE(table->blocksFind(6).position(), 5);
950  QCOMPARE(table->blocksFind(11).position(), 10);
951 
952  table->beginEditBlock();
953  table->remove(3, 8);
954  table->endEditBlock();
955 
956  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
957  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
958  QCOMPARE(table->blocksFind(1).position(), 0);
959  QCOMPARE(table->blocksFind(5).position(), 0);
960 
961  table->undo();
962 
963  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
964  QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat());
965  QCOMPARE(table->blocksFind(5).blockFormat(), fmt1);
966  QCOMPARE(table->blocksFind(10).blockFormat(), fmt2);
967  QCOMPARE(table->blocksFind(1).position(), 0);
968  QCOMPARE(table->blocksFind(6).position(), 5);
969  QCOMPARE(table->blocksFind(11).position(), 10);
970 
971  table->redo();
972  QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat());
973  QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat());
974  QCOMPARE(table->blocksFind(1).position(), 0);
975  QCOMPARE(table->blocksFind(5).position(), 0);
976 }
977 
978 
979 void tst_QTextPieceTable::checkBlockSeparation()
980 {
981  table->insertBlock(0, blockFormatIndex, charFormatIndex);
982  table->insertBlock(1, blockFormatIndex, charFormatIndex);
983 
984  QVERIFY(table->find(0) != table->find(1));
985 }
986 
987 void tst_QTextPieceTable::checkFrames1()
988 {
989  QTextFrameFormat ffmt;
990  table->insert(0, "Hello", charFormatIndex);
991  QPointer<QTextFrame> frame = table->insertFrame(1, 3, ffmt);
992  QTextFrame *root = table->rootFrame();
993 
994  QCOMPARE(root, frame->parentFrame());
995 
996  QVERIFY(root);
997  QVERIFY(!root->parentFrame());
998 
999  QCOMPARE(root->childFrames().count(), 1);
1000  QVERIFY(frame->format() == ffmt);
1001  QCOMPARE(frame->firstPosition(), 2);
1002  QCOMPARE(frame->lastPosition(), 4);
1003 
1004 
1005  QPointer<QTextFrame> frame2 = table->insertFrame(2, 3, ffmt);
1006 
1007  QCOMPARE(root->childFrames().count(), 1);
1008  QCOMPARE(root->childFrames().at(0), frame.data());
1009  QCOMPARE(frame->childFrames().count(), 1);
1010  QCOMPARE(frame2->childFrames().count(), 0);
1011  QCOMPARE(frame2->parentFrame(), frame.data());
1012  QCOMPARE(frame2->firstPosition(), 3);
1013  QCOMPARE(frame2->lastPosition(), 4);
1014 
1015  QVERIFY(frame->format() == ffmt);
1016  QCOMPARE(frame->firstPosition(), 2);
1017  QCOMPARE(frame->lastPosition(), 6);
1018 
1019  table->removeFrame(frame);
1020 
1021  QCOMPARE(root->childFrames().count(), 1);
1022  QCOMPARE(root->childFrames().at(0), frame2.data());
1023  QVERIFY(!frame);
1024  QCOMPARE(frame2->childFrames().count(), 0);
1025  QCOMPARE(frame2->parentFrame(), root);
1026  QCOMPARE(frame2->firstPosition(), 2);
1027  QCOMPARE(frame2->lastPosition(), 3);
1028 
1029  table->undo();
1030 
1031  frame = table->frameAt(2);
1032 
1033  QCOMPARE(root->childFrames().count(), 1);
1034  QCOMPARE(root->childFrames().at(0), frame.data());
1035  QCOMPARE(frame->childFrames().count(), 1);
1036  QCOMPARE(frame->childFrames().at(0), frame2.data());
1037  QCOMPARE(frame2->childFrames().count(), 0);
1038  QCOMPARE(frame2->parentFrame(), frame.data());
1039  QCOMPARE(frame2->firstPosition(), 3);
1040  QCOMPARE(frame2->lastPosition(), 4);
1041 
1042  QCOMPARE(frame->firstPosition(), 2);
1043  QCOMPARE(frame->lastPosition(), 6);
1044 
1045  table->undo();
1046 
1047  QCOMPARE(root->childFrames().count(), 1);
1048  QCOMPARE(root->childFrames().at(0), frame.data());
1049  QCOMPARE(frame->childFrames().count(), 0);
1050  QVERIFY(!frame2);
1051 
1052  QCOMPARE(frame->firstPosition(), 2);
1053  QCOMPARE(frame->lastPosition(), 4);
1054 }
1055 
1056 void tst_QTextPieceTable::removeFrameDirect()
1057 {
1058  QTextFrameFormat ffmt;
1059  table->insert(0, "Hello", charFormatIndex);
1060 
1061  QTextFrame *frame = table->insertFrame(1, 5, ffmt);
1062 
1063  QCOMPARE(frame->parentFrame(), table->rootFrame());
1064 
1065  const int start = frame->firstPosition() - 1;
1066  const int end = frame->lastPosition();
1067  const int length = end - start + 1;
1068 
1069  table->remove(start, length);
1070 }
1071 
1072 void tst_QTextPieceTable::removeWithChildFrame()
1073 {
1074  /*
1075  The piecetable layout is:
1076 
1077  ...
1078  1 BeginningOfFrame(first frame)
1079  2 text
1080  3 BeginningOfFrame(second frame)
1081  4 text
1082  5 text
1083  6 EndOfFrame(second frame)
1084  7 text
1085  8 text
1086  9 EndOfFrame(first frame)
1087  ...
1088 
1089  The idea is to remove from [2] until [6], basically some trailing text and the second frame.
1090  In this case frameAt(2) != frameAt(6), so the assertion in remove() needed an adjustement.
1091  */
1092  QTextFrameFormat ffmt;
1093  table->insert(0, "Hello World", charFormatIndex);
1094 
1095  QTextFrame *frame = table->insertFrame(1, 6, ffmt);
1096  QTextFrame *childFrame = table->insertFrame(3, 5, ffmt);
1097  Q_UNUSED(frame);
1098  Q_UNUSED(childFrame);
1099 
1100  // used to give a failing assertion
1101  table->remove(2, 5);
1102  QVERIFY(true);
1103 }
1104 
1105 void tst_QTextPieceTable::clearWithFrames()
1106 {
1107  /*
1108  The piecetable layout is:
1109 
1110  ...
1111  1 BeginningOfFrame(first frame)
1112  2 text
1113  3 EndOfFrame(first frame)
1114  4 BeginningOfFrame(second frame)
1115  5 text
1116  6 text
1117  7 EndOfFrame(second frame)
1118  ...
1119 
1120  The idea is to remove from [1] until [7].
1121  */
1122  QTextFrameFormat ffmt;
1123  table->insert(0, "Hello World", charFormatIndex);
1124 
1125  QTextFrame *firstFrame = table->insertFrame(1, 2, ffmt);
1126  QTextFrame *secondFrame = table->insertFrame(4, 6, ffmt);
1127 
1128  const int start = firstFrame->firstPosition() - 1;
1129  const int end = secondFrame->lastPosition();
1130  const int length = end - start + 1;
1131  // used to give a failing assertion
1132  table->remove(start, length);
1133  QVERIFY(true);
1134 }
1135 
1137 
1138 
1139 #include "tst_qtextpiecetable.moc"
1140 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:84
@ ParagraphSeparator
Definition: qchar.h:99
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
qsizetype count() const noexcept
Definition: qlist.h:415
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
quint32 generate()
Definition: qrandom.h:84
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
Definition: qrandom.h:311
double bounded(double highest)
Definition: qrandom.h:108
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QTextBlockFormat class provides formatting information for blocks of text in a QTextDocument....
Definition: qtextformat.h:640
void setAlignment(Qt::Alignment alignment)
Definition: qtextformat.h:733
void setTopMargin(qreal margin)
Definition: qtextformat.h:664
The QTextBlock class provides a container for text fragments in a QTextDocument. \inmodule QtGui.
Definition: qtextobject.h:193
The QTextCharFormat class provides formatting information for characters in a QTextDocument....
Definition: qtextformat.h:416
void setFontItalic(bool italic)
Definition: qtextformat.h:485
The QTextCursor class offers an API to access and modify QTextDocuments.
Definition: qtextcursor.h:67
The QTextDocument class holds formatted text.
Definition: qtextdocument.h:93
void undo(QTextCursor *cursor)
void setDocumentLayout(QAbstractTextDocumentLayout *layout)
FragmentMap::ConstIterator FragmentIterator
static const QTextDocumentPrivate * get(const QTextDocument *document)
void setForeground(const QBrush &brush)
Definition: qtextformat.h:391
The QTextFrameFormat class provides formatting information for frames in a QTextDocument....
Definition: qtextformat.h:859
The QTextFrame class represents a frame in a QTextDocument. \inmodule QtGui.
Definition: qtextobject.h:117
int lastPosition() const
QList< QTextFrame * > childFrames() const
QTextFrame * parentFrame() const
int firstPosition() const
QString str
[2]
QCursor cursor
QCOMPARE(spy.count(), 1)
QPainterPath frame2()
Definition: paths.cpp:477
@ AlignRight
Definition: qnamespace.h:171
@ AlignHCenter
Definition: qnamespace.h:173
@ blue
Definition: qnamespace.h:68
@ red
Definition: qnamespace.h:66
#define QString()
Definition: parse-defines.h:51
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLboolean GLboolean GLboolean b
GLuint index
[2]
GLuint GLuint end
GLfloat GLfloat f
GLsizei range
GLuint start
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLenum GLsizei void * table
Definition: qopenglext.h:2745
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
Q_UNUSED(salary)
[21]
settings remove("monkey")
QVBoxLayout * layout
QFrame frame
[0]
QStringList::Iterator it
void compare(Input input, FnUnderTest fn_under_test, const QByteArray &output)