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