1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45
46 #include <qtextdocument.h>
47 #include <qtextdocumentfragment.h>
48 #include <qtexttable.h>
49 #include <qdebug.h>
50 #include <qtextcursor.h>
51 #include <qtextdocument.h>
52 #include <qtextedit.h>
53
54 //TESTED_FILES=
55
56 typedef QList<int> IntList;
57 Q_DECLARE_METATYPE(IntList)
58
59 QT_FORWARD_DECLARE_CLASS(QTextDocument)
60
61 class tst_QTextTable : public QObject
62 {
63 Q_OBJECT
64
65 public:
66 tst_QTextTable();
67
68
69 public slots:
70 void init();
71 void cleanup();
72 private slots:
73 void cursorPositioning();
74 void variousTableModifications();
75 void tableShrinking();
76 void spans();
77 void variousModifications2();
78 void tableManager_undo();
79 void tableManager_removeCell();
80 void rowAt();
81 void rowAtWithSpans();
82 void multiBlockCells();
83 void insertRows();
84 void deleteInTable();
85 void mergeCells();
86 void mergeAndInsert();
87 void splitCells();
88 void blocksForTableShouldHaveEmptyFormat();
89 void removeTableByRemoveRows();
90 void removeTableByRemoveColumns();
91 void setCellFormat();
92 void removeRows1();
93 void removeRows2();
94 void removeRows3();
95 void removeRows4();
96 void removeRows5();
97 void removeColumns1();
98 void removeColumns2();
99 void removeColumns3();
100 void removeColumns4();
101 void removeColumns5();
102 void removeColumnsInTableWithMergedRows();
103 void QTBUG11282_insertBeforeMergedEnding_data();
104 void QTBUG11282_insertBeforeMergedEnding();
105 void QTBUG22011_insertBeforeRowSpan();
106
107 private:
108 QTextTable *create2x2Table();
109 QTextTable *create4x4Table();
110
111 QTextTable *createTable(int rows, int cols);
112
113 QTextDocument *doc;
114 QTextCursor cursor;
115 };
116
tst_QTextTable()117 tst_QTextTable::tst_QTextTable()
118 {}
119
init()120 void tst_QTextTable::init()
121 {
122 doc = new QTextDocument;
123 cursor = QTextCursor(doc);
124 }
125
cleanup()126 void tst_QTextTable::cleanup()
127 {
128 cursor = QTextCursor();
129 delete doc;
130 doc = 0;
131 }
132
cursorPositioning()133 void tst_QTextTable::cursorPositioning()
134 {
135 // ensure the cursor is placed at the beginning of the first cell upon
136 // table creation
137 QTextTable *table = cursor.insertTable(2, 2);
138
139 QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
140 QVERIFY(table->cellAt(0, 0).firstPosition() == table->firstPosition());
141 }
142
variousTableModifications()143 void tst_QTextTable::variousTableModifications()
144 {
145 QTextTableFormat tableFmt;
146
147 QTextTable *tab = cursor.insertTable(2, 2, tableFmt);
148 QVERIFY(doc->toPlainText().length() == 5);
149 QVERIFY(tab == cursor.currentTable());
150 QVERIFY(tab->columns() == 2);
151 QVERIFY(tab->rows() == 2);
152
153 QVERIFY(cursor.position() == 1);
154 QTextCharFormat fmt = cursor.charFormat();
155 QVERIFY(fmt.objectIndex() == -1);
156 QTextTableCell cell = tab->cellAt(cursor);
157 QVERIFY(cell.isValid());
158 QVERIFY(cell.row() == 0);
159 QVERIFY(cell.column() == 0);
160
161 cursor.movePosition(QTextCursor::NextBlock);
162 QVERIFY(cursor.position() == 2);
163 fmt = cursor.charFormat();
164 QVERIFY(fmt.objectIndex() == -1);
165 cell = tab->cellAt(cursor);
166 QVERIFY(cell.isValid());
167 QVERIFY(cell.row() == 0);
168 QVERIFY(cell.column() == 1);
169
170 cursor.movePosition(QTextCursor::NextBlock);
171 QVERIFY(cursor.position() == 3);
172 fmt = cursor.charFormat();
173 QVERIFY(fmt.objectIndex() == -1);
174 cell = tab->cellAt(cursor);
175 QVERIFY(cell.isValid());
176 QVERIFY(cell.row() == 1);
177 QVERIFY(cell.column() == 0);
178
179 cursor.movePosition(QTextCursor::NextBlock);
180 QVERIFY(cursor.position() == 4);
181 fmt = cursor.charFormat();
182 QVERIFY(fmt.objectIndex() == -1);
183 cell = tab->cellAt(cursor);
184 QVERIFY(cell.isValid());
185 QVERIFY(cell.row() == 1);
186 QVERIFY(cell.column() == 1);
187
188 cursor.movePosition(QTextCursor::NextBlock);
189 QVERIFY(cursor.position() == 5);
190 fmt = cursor.charFormat();
191 QVERIFY(fmt.objectIndex() == -1);
192 cell = tab->cellAt(cursor);
193 QVERIFY(!cell.isValid());
194
195 cursor.movePosition(QTextCursor::NextBlock);
196 QVERIFY(cursor.position() == 5);
197
198 // check we can't delete the cells with the cursor
199 cursor.movePosition(QTextCursor::Start);
200 cursor.movePosition(QTextCursor::NextBlock);
201 QVERIFY(cursor.position() == 1);
202 cursor.deleteChar();
203 QVERIFY(doc->toPlainText().length() == 5);
204 cursor.movePosition(QTextCursor::NextBlock);
205 QVERIFY(cursor.position() == 2);
206 cursor.deleteChar();
207 QVERIFY(doc->toPlainText().length() == 5);
208 cursor.deletePreviousChar();
209 QVERIFY(cursor.position() == 2);
210 QVERIFY(doc->toPlainText().length() == 5);
211
212 QTextTable *table = cursor.currentTable();
213 QVERIFY(table->rows() == 2);
214 QVERIFY(table->columns() == 2);
215
216 table->insertRows(2, 1);
217 QVERIFY(table->rows() == 3);
218 QVERIFY(table->columns() == 2);
219 QVERIFY(doc->toPlainText().length() == 7);
220 table->insertColumns(2, 2);
221 QVERIFY(table->rows() == 3);
222 QVERIFY(table->columns() == 4);
223 QVERIFY(doc->toPlainText().length() == 13);
224
225 table->resize(4, 5);
226 QVERIFY(table->rows() == 4);
227 QVERIFY(table->columns() == 5);
228 QVERIFY(doc->toPlainText().length() == 21);
229 }
230
tableShrinking()231 void tst_QTextTable::tableShrinking()
232 {
233 QTextTableFormat tableFmt;
234
235 cursor.insertTable(3, 4, tableFmt);
236 QVERIFY(doc->toPlainText().length() == 13);
237
238 QTextTable *table = cursor.currentTable();
239 QVERIFY(table->rows() == 3);
240 QVERIFY(table->columns() == 4);
241
242 table->removeRows(1, 1);
243 QVERIFY(table->rows() == 2);
244 QVERIFY(table->columns() == 4);
245 QVERIFY(doc->toPlainText().length() == 9);
246 table->removeColumns(1, 2);
247 QVERIFY(table->rows() == 2);
248 QVERIFY(table->columns() == 2);
249 QVERIFY(doc->toPlainText().length() == 5);
250
251 table->resize(1, 1);
252 QVERIFY(table->rows() == 1);
253 QVERIFY(table->columns() == 1);
254 QVERIFY(doc->toPlainText().length() == 2);
255 }
256
spans()257 void tst_QTextTable::spans()
258 {
259 QTextTableFormat tableFmt;
260
261 cursor.insertTable(2, 2, tableFmt);
262
263 QTextTable *table = cursor.currentTable();
264 QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
265 table->mergeCells(0, 0, 1, 2);
266 QVERIFY(table->rows() == 2);
267 QVERIFY(table->columns() == 2);
268 QVERIFY(table->cellAt(0, 0) == table->cellAt(0, 1));
269 table->mergeCells(0, 0, 2, 2);
270 QVERIFY(table->rows() == 2);
271 QVERIFY(table->columns() == 2);
272 }
273
variousModifications2()274 void tst_QTextTable::variousModifications2()
275 {
276 QTextTableFormat tableFmt;
277
278 cursor.insertTable(2, 5, tableFmt);
279 QVERIFY(doc->toPlainText().length() == 11);
280 QTextTable *table = cursor.currentTable();
281 QVERIFY(cursor.position() == 1);
282 QVERIFY(table->rows() == 2);
283 QVERIFY(table->columns() == 5);
284
285 table->insertColumns(0, 1);
286 QVERIFY(table->rows() == 2);
287 QVERIFY(table->columns() == 6);
288 table->insertColumns(6, 1);
289 QVERIFY(table->rows() == 2);
290 QVERIFY(table->columns() == 7);
291
292 table->insertRows(0, 1);
293 QVERIFY(table->rows() == 3);
294 QVERIFY(table->columns() == 7);
295 table->insertRows(3, 1);
296 QVERIFY(table->rows() == 4);
297 QVERIFY(table->columns() == 7);
298
299 table->removeRows(0, 1);
300 QVERIFY(table->rows() == 3);
301 QVERIFY(table->columns() == 7);
302 table->removeRows(2, 1);
303 QVERIFY(table->rows() == 2);
304 QVERIFY(table->columns() == 7);
305
306 table->removeColumns(0, 1);
307 QVERIFY(table->rows() == 2);
308 QVERIFY(table->columns() == 6);
309 table->removeColumns(5, 1);
310 QVERIFY(table->rows() == 2);
311 QVERIFY(table->columns() == 5);
312
313 tableFmt = table->format();
314 table->insertColumns(2, 1);
315 table->setFormat(tableFmt);
316 table->insertColumns(2, 1);
317 QVERIFY(table->columns() == 7);
318 }
319
tableManager_undo()320 void tst_QTextTable::tableManager_undo()
321 {
322 QTextTableFormat fmt;
323 fmt.setBorder(10);
324 QTextTable *table = cursor.insertTable(2, 2, fmt);
325 QVERIFY(table);
326
327 QVERIFY(table->format().border() == 10);
328
329 fmt.setBorder(20);
330 table->setFormat(fmt);
331
332 QVERIFY(table->format().border() == 20);
333
334 doc->undo();
335
336 QVERIFY(table->format().border() == 10);
337 }
338
tableManager_removeCell()339 void tst_QTextTable::tableManager_removeCell()
340 {
341 // essentially a test for TableManager::removeCell, in particular to remove empty items from the rowlist.
342 // If it fails it'll triger assertions inside TableManager. Yeah, not pretty, should VERIFY here ;(
343 cursor.insertTable(2, 2, QTextTableFormat());
344 doc->undo();
345 // ###
346 QVERIFY(true);
347 }
348
rowAt()349 void tst_QTextTable::rowAt()
350 {
351 // test TablePrivate::rowAt
352 QTextTable *table = cursor.insertTable(4, 2);
353
354 QCOMPARE(table->rows(), 4);
355 QCOMPARE(table->columns(), 2);
356
357 QTextCursor cell00Cursor = table->cellAt(0, 0).firstCursorPosition();
358 QTextCursor cell10Cursor = table->cellAt(1, 0).firstCursorPosition();
359 QTextCursor cell20Cursor = table->cellAt(2, 0).firstCursorPosition();
360 QTextCursor cell21Cursor = table->cellAt(2, 1).firstCursorPosition();
361 QTextCursor cell30Cursor = table->cellAt(3, 0).firstCursorPosition();
362 QVERIFY(table->cellAt(cell00Cursor).firstCursorPosition() == cell00Cursor);
363 QVERIFY(table->cellAt(cell10Cursor).firstCursorPosition() == cell10Cursor);
364 QVERIFY(table->cellAt(cell20Cursor).firstCursorPosition() == cell20Cursor);
365 QVERIFY(table->cellAt(cell30Cursor).firstCursorPosition() == cell30Cursor);
366
367 table->mergeCells(1, 0, 2, 1);
368
369 QCOMPARE(table->rows(), 4);
370 QCOMPARE(table->columns(), 2);
371
372 QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
373 QVERIFY(cell10Cursor == table->cellAt(1, 0).firstCursorPosition());
374 QVERIFY(cell10Cursor == table->cellAt(2, 0).firstCursorPosition());
375 QVERIFY(cell21Cursor == table->cellAt(2, 1).firstCursorPosition());
376 QVERIFY(cell30Cursor == table->cellAt(3, 0).firstCursorPosition());
377
378 table->mergeCells(1, 0, 2, 2);
379
380 QCOMPARE(table->rows(), 4);
381 QCOMPARE(table->columns(), 2);
382
383 QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
384 QVERIFY(cell00Cursor == table->cellAt(0, 0).firstCursorPosition());
385 QVERIFY(cell10Cursor == table->cellAt(1, 0).firstCursorPosition());
386 QVERIFY(cell10Cursor == table->cellAt(1, 1).firstCursorPosition());
387 QVERIFY(cell10Cursor == table->cellAt(2, 0).firstCursorPosition());
388 QVERIFY(cell10Cursor == table->cellAt(2, 1).firstCursorPosition());
389 QVERIFY(cell30Cursor == table->cellAt(3, 0).firstCursorPosition());
390 }
391
rowAtWithSpans()392 void tst_QTextTable::rowAtWithSpans()
393 {
394 QTextTable *table = cursor.insertTable(2, 2);
395
396 QCOMPARE(table->rows(), 2);
397 QCOMPARE(table->columns(), 2);
398
399 table->mergeCells(0, 0, 2, 1);
400 QVERIFY(table->cellAt(0, 0).rowSpan() == 2);
401
402 QCOMPARE(table->rows(), 2);
403 QCOMPARE(table->columns(), 2);
404
405 table->mergeCells(0, 0, 2, 2);
406 QVERIFY(table->cellAt(0, 0).columnSpan() == 2);
407
408 QCOMPARE(table->rows(), 2);
409 QCOMPARE(table->columns(), 2);
410 }
411
multiBlockCells()412 void tst_QTextTable::multiBlockCells()
413 {
414 // little testcase for multi-block cells
415 QTextTable *table = cursor.insertTable(2, 2);
416
417 QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
418
419 cursor.insertText("Hello");
420 cursor.insertBlock(QTextBlockFormat());
421 cursor.insertText("World");
422
423 cursor.movePosition(QTextCursor::Left);
424 QVERIFY(table->cellAt(0, 0) == table->cellAt(cursor));
425 }
426
insertRows()427 void tst_QTextTable::insertRows()
428 {
429 // little testcase for multi-block cells
430 QTextTable *table = cursor.insertTable(2, 2);
431
432 QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
433
434 table->insertRows(0, 1);
435 QVERIFY(table->rows() == 3);
436
437 table->insertRows(1, 1);
438 QVERIFY(table->rows() == 4);
439
440 table->insertRows(-1, 1);
441 QVERIFY(table->rows() == 5);
442
443 table->insertRows(5, 2);
444 QVERIFY(table->rows() == 7);
445
446 }
447
deleteInTable()448 void tst_QTextTable::deleteInTable()
449 {
450 QTextTable *table = cursor.insertTable(2, 2);
451 table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
452 table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
453 table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
454 table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
455
456 cursor = table->cellAt(1, 1).firstCursorPosition();
457 cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
458
459 QCOMPARE(table->cellAt(cursor.position()).row(), 1);
460 QCOMPARE(table->cellAt(cursor.position()).column(), 0);
461
462 cursor.removeSelectedText();
463
464 QCOMPARE(table->columns(), 2);
465 QCOMPARE(table->rows(), 2);
466
467 // verify table is still all in shape. Only the text inside should get deleted
468 for (int row = 0; row < table->rows(); ++row)
469 for (int col = 0; col < table->columns(); ++col) {
470 const QTextTableCell cell = table->cellAt(row, col);
471 QVERIFY(cell.isValid());
472 QCOMPARE(cell.rowSpan(), 1);
473 QCOMPARE(cell.columnSpan(), 1);
474 }
475 }
476
create2x2Table()477 QTextTable *tst_QTextTable::create2x2Table()
478 {
479 cleanup();
480 init();
481 QTextTable *table = cursor.insertTable(2, 2);
482 table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
483 table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
484 table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
485 table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
486 return table;
487 }
488
create4x4Table()489 QTextTable *tst_QTextTable::create4x4Table()
490 {
491 cleanup();
492 init();
493 QTextTable *table = cursor.insertTable(4, 4);
494 table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
495 table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
496 table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
497 table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
498 return table;
499 }
500
createTable(int rows,int cols)501 QTextTable *tst_QTextTable::createTable(int rows, int cols)
502 {
503 cleanup();
504 init();
505 QTextTable *table = cursor.insertTable(rows, cols);
506 return table;
507 }
508
mergeCells()509 void tst_QTextTable::mergeCells()
510 {
511 QTextTable *table = create4x4Table();
512
513 table->mergeCells(1, 1, 1, 2);
514 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
515
516 table->mergeCells(1, 1, 2, 2);
517 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
518 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
519 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
520
521 table = create4x4Table();
522
523 table->mergeCells(1, 1, 2, 1);
524 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
525
526 table->mergeCells(1, 1, 2, 2);
527 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
528 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
529 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
530
531 table = create4x4Table();
532
533 table->mergeCells(1, 1, 2, 2);
534 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
535 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
536 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
537
538 // should do nothing
539 table->mergeCells(1, 1, 1, 1);
540 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
541 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
542 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
543
544 table = create2x2Table();
545
546 table->mergeCells(0, 1, 2, 1);
547 table->mergeCells(0, 0, 2, 2);
548 QVERIFY(table->cellAt(0, 0) == table->cellAt(0, 1));
549 QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 0));
550 QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 1));
551
552 QTextBlock block = table->cellAt(0, 0).firstCursorPosition().block();
553
554 QVERIFY(block.text() == "Blah Foo");
555 QVERIFY(block.next().text() == "Hah");
556 QVERIFY(block.next().next().text() == "Bar");
557
558 table = create4x4Table();
559
560 QTextCursor cursor = table->cellAt(3, 3).firstCursorPosition();
561 QTextTable *t2 = cursor.insertTable(2, 2);
562 t2->cellAt(0, 0).firstCursorPosition().insertText("Test");
563
564 table->mergeCells(2, 2, 2, 2);
565 cursor = table->cellAt(2, 2).firstCursorPosition();
566
567 QTextFrame *frame = cursor.currentFrame();
568
569 QTextFrame::iterator it = frame->begin();
570
571 // find the embedded table
572 while (it != frame->end() && !it.currentFrame())
573 ++it;
574
575 table = qobject_cast<QTextTable *>(it.currentFrame());
576
577 QVERIFY(table);
578
579 if (table) {
580 cursor = table->cellAt(0, 0).firstCursorPosition();
581
582 QVERIFY(cursor.block().text() == "Test");
583 }
584
585 table = create2x2Table();
586
587 table->mergeCells(0, 1, 2, 1);
588
589 QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
590 QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
591
592 // should do nothing
593 table->mergeCells(0, 0, 1, 2);
594
595 QVERIFY(table->cellAt(0, 0) != table->cellAt(0, 1));
596 QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
597 }
598
mergeAndInsert()599 void tst_QTextTable::mergeAndInsert()
600 {
601 QTextTable *table = cursor.insertTable(4,3);
602 table->mergeCells(0,1,3,2);
603 table->mergeCells(3,0,1,3);
604 //Don't crash !
605 table->insertColumns(1,2);
606 QCOMPARE(table->columns(), 5);
607 }
608
splitCells()609 void tst_QTextTable::splitCells()
610 {
611 QTextTable *table = create4x4Table();
612 table->mergeCells(1, 1, 2, 2);
613 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
614 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
615 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
616
617 table->splitCell(1, 1, 1, 2);
618 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
619 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
620 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
621
622 table->splitCell(1, 1, 1, 1);
623 QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
624 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
625 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
626
627
628 table = create4x4Table();
629 table->mergeCells(1, 1, 2, 2);
630 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
631 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
632 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
633
634 table->splitCell(1, 1, 2, 1);
635 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
636 QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
637 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
638
639 table->splitCell(1, 1, 1, 1);
640 QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
641 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
642 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
643
644
645 table = create4x4Table();
646 table->mergeCells(1, 1, 2, 2);
647 QVERIFY(table->cellAt(1, 1) == table->cellAt(1, 2));
648 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 1));
649 QVERIFY(table->cellAt(1, 1) == table->cellAt(2, 2));
650
651 table->splitCell(1, 1, 1, 1);
652 QVERIFY(table->cellAt(1, 1) != table->cellAt(1, 2));
653 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 1));
654 QVERIFY(table->cellAt(1, 1) != table->cellAt(2, 2));
655
656 table = createTable(2, 5);
657 table->mergeCells(0, 0, 2, 1);
658 table->mergeCells(0, 1, 2, 1);
659 QVERIFY(table->cellAt(0, 0) == table->cellAt(1, 0));
660 QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
661 table->splitCell(0, 0, 1, 1);
662 QVERIFY(table->cellAt(0, 0) != table->cellAt(1, 0));
663 QVERIFY(table->cellAt(0, 1) == table->cellAt(1, 1));
664
665 table = createTable(2, 5);
666 table->mergeCells(0, 4, 2, 1);
667 QVERIFY(table->cellAt(0, 4) == table->cellAt(1, 4));
668
669 table->splitCell(0, 4, 1, 1);
670 QVERIFY(table->cellAt(0, 4) != table->cellAt(1, 4));
671 }
672
blocksForTableShouldHaveEmptyFormat()673 void tst_QTextTable::blocksForTableShouldHaveEmptyFormat()
674 {
675 QTextBlockFormat fmt;
676 fmt.setProperty(QTextFormat::UserProperty, true);
677 cursor.insertBlock(fmt);
678 QVERIFY(cursor.blockFormat().hasProperty(QTextFormat::UserProperty));
679
680 QTextTable *table = cursor.insertTable(1, 1);
681 QVERIFY(!table->cellAt(0, 0).firstCursorPosition().blockFormat().hasProperty(QTextFormat::UserProperty));
682
683 int userPropCount = 0;
684 for (QTextBlock block = doc->begin();
685 block.isValid(); block = block.next()) {
686 if (block.blockFormat().hasProperty(QTextFormat::UserProperty))
687 userPropCount++;
688 }
689 QCOMPARE(userPropCount, 1);
690 }
691
removeTableByRemoveRows()692 void tst_QTextTable::removeTableByRemoveRows()
693 {
694 QPointer<QTextTable> table1 = QTextCursor(cursor).insertTable(4, 4);
695 QPointer<QTextTable> table2 = QTextCursor(cursor).insertTable(4, 4);
696 QPointer<QTextTable> table3 = QTextCursor(cursor).insertTable(4, 4);
697
698 QVERIFY(table1);
699 QVERIFY(table2);
700 QVERIFY(table3);
701
702 table2->removeRows(1, 1);
703
704 QVERIFY(table1);
705 QVERIFY(table2);
706 QVERIFY(table3);
707
708 table2->removeRows(0, table2->rows());
709
710 QVERIFY(table1);
711 QVERIFY(!table2);
712 QVERIFY(table3);
713 }
714
removeTableByRemoveColumns()715 void tst_QTextTable::removeTableByRemoveColumns()
716 {
717 QPointer<QTextTable> table1 = QTextCursor(cursor).insertTable(4, 4);
718 QPointer<QTextTable> table2 = QTextCursor(cursor).insertTable(4, 4);
719 QPointer<QTextTable> table3 = QTextCursor(cursor).insertTable(4, 4);
720
721 QVERIFY(table1);
722 QVERIFY(table2);
723 QVERIFY(table3);
724
725 table2->removeColumns(1, 1);
726
727 QVERIFY(table1);
728 QVERIFY(table2);
729 QVERIFY(table3);
730
731 table2->removeColumns(0, table2->columns());
732
733 QVERIFY(table1);
734 QVERIFY(!table2);
735 QVERIFY(table3);
736 }
737
setCellFormat()738 void tst_QTextTable::setCellFormat()
739 {
740 QTextTable *table = cursor.insertTable(2, 2);
741 table->cellAt(0, 0).firstCursorPosition().insertText("First");
742 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
743 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
744 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
745 QTextTableCell cell = table->cellAt(0, 0);
746 QTextCharFormat fmt;
747 fmt.setObjectIndex(23);
748 fmt.setBackground(Qt::blue);
749 fmt.setTableCellColumnSpan(25);
750 fmt.setTableCellRowSpan(42);
751 cell.setFormat(fmt);
752 QVERIFY(cell.format().background().color() == QColor(Qt::blue));
753 QCOMPARE(cell.format().tableCellColumnSpan(), 1);
754 QCOMPARE(cell.format().tableCellRowSpan(), 1);
755 }
756
removeRows1()757 void tst_QTextTable::removeRows1()
758 {
759 QTextTable *table = cursor.insertTable(2, 2);
760 table->cellAt(0, 0).firstCursorPosition().insertText("First");
761 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
762 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
763 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
764 table->removeRows(0, 1);
765 QCOMPARE(table->rows(), 1);
766 QCOMPARE(table->columns(), 2);
767 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Third"));
768 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Fourth"));
769 }
770
removeRows2()771 void tst_QTextTable::removeRows2()
772 {
773 QTextTable *table = cursor.insertTable(2, 2);
774 table->cellAt(0, 0).firstCursorPosition().insertText("First");
775 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
776 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
777 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
778 table->removeRows(1, 1);
779 QCOMPARE(table->rows(), 1);
780 QCOMPARE(table->columns(), 2);
781 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
782 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
783 }
784
removeRows3()785 void tst_QTextTable::removeRows3()
786 {
787 QTextTable *table = cursor.insertTable(3, 2);
788 table->cellAt(0, 0).firstCursorPosition().insertText("First");
789 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
790 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
791 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
792 table->cellAt(2, 0).firstCursorPosition().insertText("Fifth");
793 table->cellAt(2, 1).firstCursorPosition().insertText("Sixth");
794 table->removeRows(1, 1);
795 QCOMPARE(table->rows(), 2);
796 QCOMPARE(table->columns(), 2);
797 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
798 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
799 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fifth"));
800 QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Sixth"));
801 }
802
removeRows4()803 void tst_QTextTable::removeRows4()
804 {
805 QTextTable *table = cursor.insertTable(4, 2);
806 table->cellAt(0, 0).firstCursorPosition().insertText("First");
807 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
808 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
809 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
810 table->cellAt(2, 0).firstCursorPosition().insertText("Fifth");
811 table->cellAt(2, 1).firstCursorPosition().insertText("Sixth");
812 table->cellAt(3, 0).firstCursorPosition().insertText("Seventh");
813 table->cellAt(3, 1).firstCursorPosition().insertText("Eighth");
814 table->removeRows(1, 2);
815 QCOMPARE(table->rows(), 2);
816 QCOMPARE(table->columns(), 2);
817 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
818 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
819 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Seventh"));
820 QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Eighth"));
821 }
822
removeRows5()823 void tst_QTextTable::removeRows5()
824 {
825 QTextTable *table = cursor.insertTable(2,2);
826 table->cellAt(0, 0).firstCursorPosition().insertText("First");
827 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
828 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
829 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
830 table->insertRows(1,1);
831 table->mergeCells(1,0,1,2);
832 table->removeRows(1,1);
833 QCOMPARE(table->rows(), 2);
834 QCOMPARE(table->columns(), 2);
835 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
836 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second"));
837 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Third"));
838 QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Fourth"));
839 }
840
removeColumns1()841 void tst_QTextTable::removeColumns1()
842 {
843 QTextTable *table = cursor.insertTable(2, 2);
844 table->cellAt(0, 0).firstCursorPosition().insertText("First");
845 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
846 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
847 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
848 table->removeColumns(0, 1);
849 QCOMPARE(table->rows(), 2);
850 QCOMPARE(table->columns(), 1);
851 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Second"));
852 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fourth"));
853 }
854
removeColumns2()855 void tst_QTextTable::removeColumns2()
856 {
857 QTextTable *table = cursor.insertTable(2, 2);
858 table->cellAt(0, 0).firstCursorPosition().insertText("First");
859 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
860 table->cellAt(1, 0).firstCursorPosition().insertText("Third");
861 table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
862 table->removeColumns(1, 1);
863 QCOMPARE(table->rows(), 2);
864 QCOMPARE(table->columns(), 1);
865 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
866 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Third"));
867 }
868
removeColumns3()869 void tst_QTextTable::removeColumns3()
870 {
871 QTextTable *table = cursor.insertTable(2, 3);
872 table->cellAt(0, 0).firstCursorPosition().insertText("First");
873 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
874 table->cellAt(0, 2).firstCursorPosition().insertText("Third");
875 table->cellAt(1, 0).firstCursorPosition().insertText("Fourth");
876 table->cellAt(1, 1).firstCursorPosition().insertText("Fifth");
877 table->cellAt(1, 2).firstCursorPosition().insertText("Sixth");
878 table->removeColumns(1, 1);
879 QCOMPARE(table->rows(), 2);
880 QCOMPARE(table->columns(), 2);
881 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
882 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Third"));
883 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fourth"));
884 QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Sixth"));
885 }
886
removeColumns4()887 void tst_QTextTable::removeColumns4()
888 {
889 QTextTable *table = cursor.insertTable(2, 4);
890 table->cellAt(0, 0).firstCursorPosition().insertText("First");
891 table->cellAt(0, 1).firstCursorPosition().insertText("Second");
892 table->cellAt(0, 2).firstCursorPosition().insertText("Third");
893 table->cellAt(0, 3).firstCursorPosition().insertText("Fourth");
894 table->cellAt(1, 0).firstCursorPosition().insertText("Fifth");
895 table->cellAt(1, 1).firstCursorPosition().insertText("Sixth");
896 table->cellAt(1, 2).firstCursorPosition().insertText("Seventh");
897 table->cellAt(1, 3).firstCursorPosition().insertText("Eighth");
898 table->removeColumns(1, 2);
899 QCOMPARE(table->rows(), 2);
900 QCOMPARE(table->columns(), 2);
901 QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First"));
902 QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Fourth"));
903 QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Fifth"));
904 QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Eighth"));
905 }
906
removeColumns5()907 void tst_QTextTable::removeColumns5()
908 {
909 QTextTable *table = cursor.insertTable(4, 4);
910 QTextCursor tc (doc);
911 tc.setPosition(table->cellAt(2,0).firstPosition());
912 tc.setPosition(table->cellAt(3,1).firstPosition(), QTextCursor::KeepAnchor);
913 table->mergeCells(tc);
914 QCOMPARE(table->rows(), 4);
915 QCOMPARE(table->columns(), 4);
916 QCOMPARE(table->cellAt(0, 0).firstPosition(), 1);
917 QCOMPARE(table->cellAt(0, 1).firstPosition(), 2);
918 QCOMPARE(table->cellAt(0, 2).firstPosition(), 3);
919 QCOMPARE(table->cellAt(0, 3).firstPosition(), 4);
920 QCOMPARE(table->cellAt(1, 0).firstPosition(), 5);
921 QCOMPARE(table->cellAt(1, 1).firstPosition(), 6);
922 QCOMPARE(table->cellAt(1, 2).firstPosition(), 7);
923 QCOMPARE(table->cellAt(1, 3).firstPosition(), 8);
924 QCOMPARE(table->cellAt(2, 0).firstPosition(), 9);
925 QCOMPARE(table->cellAt(2, 0).rowSpan(), 2);
926 QCOMPARE(table->cellAt(2, 0).columnSpan(), 2);
927 QCOMPARE(table->cellAt(2, 1).firstPosition(), 9);
928 QCOMPARE(table->cellAt(2, 2).firstPosition(), 10);
929 QCOMPARE(table->cellAt(2, 3).firstPosition(), 11);
930 QCOMPARE(table->cellAt(3, 0).firstPosition(), 9);
931 QCOMPARE(table->cellAt(3, 1).firstPosition(), 9);
932 QCOMPARE(table->cellAt(3, 2).firstPosition(), 12);
933 QCOMPARE(table->cellAt(3, 3).firstPosition(), 13);
934
935 table->removeColumns(1, 1);
936 QCOMPARE(table->rows(), 4);
937 QCOMPARE(table->columns(), 3);
938 QCOMPARE(table->cellAt(0, 0).firstPosition(), 1);
939 QCOMPARE(table->cellAt(0, 1).firstPosition(), 2);
940 QCOMPARE(table->cellAt(0, 2).firstPosition(), 3);
941 QCOMPARE(table->cellAt(1, 0).firstPosition(), 4);
942 QCOMPARE(table->cellAt(1, 1).firstPosition(), 5);
943 QCOMPARE(table->cellAt(1, 2).firstPosition(), 6);
944 QCOMPARE(table->cellAt(2, 0).firstPosition(), 7);
945 QCOMPARE(table->cellAt(2, 0).rowSpan(), 2);
946 QCOMPARE(table->cellAt(2, 0).columnSpan(), 1);
947 QCOMPARE(table->cellAt(2, 1).firstPosition(), 8);
948 QCOMPARE(table->cellAt(2, 2).firstPosition(), 9);
949 QCOMPARE(table->cellAt(3, 0).firstPosition(), 7);
950 QCOMPARE(table->cellAt(3, 1).firstPosition(), 10);
951 QCOMPARE(table->cellAt(3, 2).firstPosition(), 11);
952 }
953
removeColumnsInTableWithMergedRows()954 void tst_QTextTable::removeColumnsInTableWithMergedRows()
955 {
956 QTextTable *table = cursor.insertTable(3, 4);
957 table->mergeCells(0, 0, 1, 4);
958 QCOMPARE(table->rows(), 3);
959 QCOMPARE(table->columns(), 4);
960
961 table->removeColumns(0, table->columns() - 1);
962
963 QCOMPARE(table->rows(), 3);
964 QCOMPARE(table->columns(), 1);
965 }
966
QTBUG11282_insertBeforeMergedEnding_data()967 void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding_data()
968 {
969 QTest::addColumn<int>("rows");
970 QTest::addColumn<int>("columns");
971 QTest::addColumn<QList<int> >("merge");
972 QTest::addColumn<QList<int> >("insert");
973
974 QTest::newRow("2x3, merge two, insert one") << 2 << 3 << (QList<int>() << 1 << 2 << 2)
975 << (QList<int>() << 1 << 1) ;
976 QTest::newRow("3x4, merge three, insert one") << 3 << 4 << (QList<int>() << 1 << 3 << 3)
977 << (QList<int>() << 1 << 1) ;
978 QTest::newRow("4x3, merge two, insert two") << 4 << 3 << (QList<int>() << 1 << 4 << 2)
979 << (QList<int>() << 1 << 2) ;
980 QTest::newRow("4x4, merge middle two, insert one") << 4 << 4 << (QList<int>() << 1 << 4 << 2)
981 << (QList<int>() << 1 << 1) ;
982 }
983
QTBUG11282_insertBeforeMergedEnding()984 void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding()
985 {
986 QFETCH(int, rows);
987 QFETCH(int, columns);
988 QFETCH(QList<int>, merge);
989 QFETCH(QList<int>, insert);
990 QTextTable *table = cursor.insertTable(rows, columns);
991 QTextEdit *textEdit = new QTextEdit;
992 textEdit->setDocument(doc);
993 textEdit->show();
994 QTest::qWaitForWindowShown(textEdit);
995 table->mergeCells(0,merge.at(0), merge.at(1), merge.at(2));
996 //Don't crash !
997 table->insertColumns(insert.at(0), insert.at(1));
998 //Check that the final size is what we expected
999 QCOMPARE(table->rows(), rows);
1000 QCOMPARE(table->columns(), columns + insert.at(1));
1001 delete textEdit;
1002 }
1003
QTBUG22011_insertBeforeRowSpan()1004 void tst_QTextTable::QTBUG22011_insertBeforeRowSpan()
1005 {
1006 QTextDocument doc;
1007 QTextCursor cursor(&doc);
1008 QTextTable *table = cursor.insertTable(1,1); // 1x1
1009
1010 table->appendColumns(1); // 1x2
1011 table->appendRows(1); // 2x2
1012 table->mergeCells(0, 0, 2, 1); // 2x2
1013 table->insertColumns(1, 1); // 2x3
1014 table->mergeCells(0, 1, 1, 2); // 2x3
1015 table->appendRows(1); // 3x3
1016 table->mergeCells(0, 0, 3, 1); // 3x3
1017 table->appendRows(1); // 4x3
1018 table->insertColumns(1, 1); // 4x4
1019 table->mergeCells(0, 1, 1, 3);
1020 table->mergeCells(1, 1, 1, 2);
1021 table->mergeCells(2, 1, 1, 2);
1022 table->mergeCells(3, 0, 1, 2);
1023 table->insertColumns(3, 1); // 4x5
1024 table->mergeCells(0, 1, 1, 4);
1025
1026 table->appendColumns(1); // 4x6
1027
1028 QCOMPARE(table->rows(), 4);
1029 QCOMPARE(table->columns(), 6);
1030 }
1031
1032 QTEST_MAIN(tst_QTextTable)
1033 #include "tst_qtexttable.moc"
1034