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#include <QHeaderView>
30#include <QLineEdit>
31#include <QMimeData>
32#include <QSignalSpy>
33#include <QTableWidget>
34#include <QTest>
35
36class QObjectTableItem : public QObject, public QTableWidgetItem
37{
38 Q_OBJECT
39};
40
41class tst_QTableWidget : public QObject
42{
43 Q_OBJECT
44
45public:
46 using QObject::QObject;
47
48private slots:
49 void initTestCase();
50 void init();
51 void getSetCheck();
52 void clear();
53 void clearContents();
54 void rowCount();
55 void columnCount();
56 void itemAssignment();
57 void item_data();
58 void item();
59 void takeItem_data();
60 void takeItem();
61 void selectedItems_data();
62 void selectedItems();
63 void removeRow_data();
64 void removeRow();
65 void removeColumn_data();
66 void removeColumn();
67 void insertRow_data();
68 void insertRow();
69 void insertColumn_data();
70 void insertColumn();
71 void itemStreaming_data();
72 void itemStreaming();
73 void itemOwnership();
74 void sortItems_data();
75 void sortItems();
76 void setItemWithSorting_data();
77 void setItemWithSorting();
78 void itemData();
79 void setItemData();
80 void cellWidget();
81 void cellWidgetGeometry();
82 void sizeHint_data();
83 void sizeHint();
84 void task231094();
85 void task219380_removeLastRow();
86 void task262056_sortDuplicate();
87 void itemWithHeaderItems();
88 void mimeData();
89 void selectedRowAfterSorting();
90 void search();
91#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
92 void clearItemData();
93#endif
94
95private:
96 std::unique_ptr<QTableWidget> testWidget;
97};
98
99using IntPair = QPair<int, int>;
100using IntList = QVector<int>;
101using IntIntList = QVector<IntPair>;
102
103Q_DECLARE_METATYPE(QTableWidgetSelectionRange)
104
105
106// Testing get/set functions
107void tst_QTableWidget::getSetCheck()
108{
109 QTableWidget obj1;
110 // int QTableWidget::rowCount()
111 // void QTableWidget::setRowCount(int)
112 obj1.setRowCount(0);
113 QCOMPARE(0, obj1.rowCount());
114 obj1.setRowCount(INT_MIN);
115 QCOMPARE(0, obj1.rowCount()); // Row count can never be negative
116// obj1.setRowCount(INT_MAX);
117// QCOMPARE(INT_MAX, obj1.rowCount());
118 obj1.setRowCount(100);
119 QCOMPARE(100, obj1.rowCount());
120
121
122 // int QTableWidget::columnCount()
123 // void QTableWidget::setColumnCount(int)
124 obj1.setColumnCount(0);
125 QCOMPARE(0, obj1.columnCount());
126 obj1.setColumnCount(INT_MIN);
127 QCOMPARE(0, obj1.columnCount()); // Column count can never be negative
128 obj1.setColumnCount(1000);
129 QCOMPARE(1000, obj1.columnCount());
130// obj1.setColumnCount(INT_MAX);
131// QCOMPARE(INT_MAX, obj1.columnCount());
132
133 // QTableWidgetItem * QTableWidget::currentItem()
134 // void QTableWidget::setCurrentItem(QTableWidgetItem *)
135 QTableWidgetItem *var3 = new QTableWidgetItem("0,0");
136 obj1.setItem(row: 0, column: 0, item: var3);
137 obj1.setItem(row: 1, column: 1, item: new QTableWidgetItem("1,1"));
138 obj1.setItem(row: 2, column: 2, item: new QTableWidgetItem("2,2"));
139 obj1.setItem(row: 3, column: 3, item: new QTableWidgetItem("3,3"));
140 obj1.setCurrentItem(var3);
141 QCOMPARE(var3, obj1.currentItem());
142 obj1.setCurrentItem(nullptr);
143 QCOMPARE(obj1.currentItem(), nullptr);
144 obj1.setItem(row: 0, column: 0, item: nullptr);
145 QCOMPARE(obj1.item(0, 0), nullptr);
146
147 // const QTableWidgetItem * QTableWidget::itemPrototype()
148 // void QTableWidget::setItemPrototype(const QTableWidgetItem *)
149 const QTableWidgetItem *var4 = new QTableWidgetItem;
150 obj1.setItemPrototype(var4);
151 QCOMPARE(var4, obj1.itemPrototype());
152 obj1.setItemPrototype(nullptr);
153 QCOMPARE(obj1.itemPrototype(), nullptr);
154}
155
156void tst_QTableWidget::initTestCase()
157{
158 testWidget.reset(p: new QTableWidget);
159 testWidget->show();
160 QApplication::setKeyboardInputInterval(100);
161}
162
163void tst_QTableWidget::init()
164{
165 testWidget->clear();
166 testWidget->setRowCount(5);
167 testWidget->setColumnCount(5);
168
169 for (int row = 0; row < testWidget->rowCount(); ++row)
170 testWidget->showRow(row);
171 for (int column = 0; column < testWidget->columnCount(); ++column)
172 testWidget->showColumn(column);
173}
174
175void tst_QTableWidget::clearContents()
176{
177 QTableWidgetItem *item = new QTableWidgetItem("test");
178 testWidget->setHorizontalHeaderItem(column: 0, item);
179 QCOMPARE(testWidget->horizontalHeaderItem(0), item);
180 testWidget->clearContents();
181 QCOMPARE(testWidget->horizontalHeaderItem(0), item);
182}
183
184void tst_QTableWidget::clear()
185{
186 QTableWidgetItem *item = new QTableWidgetItem("foo");
187 testWidget->setItem(row: 0, column: 0, item);
188 item->setSelected(true);
189
190 QVERIFY(testWidget->item(0, 0) == item);
191 QVERIFY(item->isSelected());
192
193
194 QPointer<QObjectTableItem> bla = new QObjectTableItem();
195 testWidget->setItem(row: 1, column: 1, item: bla);
196
197 testWidget->clear();
198
199 QVERIFY(bla.isNull());
200
201 QVERIFY(!testWidget->item(0,0));
202 QVERIFY(!testWidget->selectedRanges().count());
203 QVERIFY(!testWidget->selectedItems().count());
204}
205
206void tst_QTableWidget::rowCount()
207{
208 int rowCountBefore = 5;
209 int rowCountAfter = 10;
210
211 int rowCount = testWidget->rowCount();
212 QCOMPARE(rowCount, rowCountBefore);
213
214 testWidget->setRowCount(rowCountAfter);
215 rowCount = testWidget->rowCount();
216 QCOMPARE(rowCount, rowCountAfter);
217
218 QPersistentModelIndex index(testWidget->model()->index(row: rowCountAfter - 1, column: 0,
219 parent: testWidget->rootIndex()));
220 QCOMPARE(index.row(), rowCountAfter - 1);
221 QCOMPARE(index.column(), 0);
222 QVERIFY(index.isValid());
223 testWidget->setRowCount(rowCountBefore);
224 QCOMPARE(index.row(), -1);
225 QCOMPARE(index.column(), -1);
226 QVERIFY(!index.isValid());
227
228 rowCountBefore = testWidget->rowCount();
229 testWidget->setRowCount(-1);
230 QCOMPARE(testWidget->rowCount(), rowCountBefore);
231}
232
233void tst_QTableWidget::columnCount()
234{
235 int columnCountBefore = 5;
236 int columnCountAfter = 10;
237
238 int columnCount = testWidget->columnCount();
239 QCOMPARE(columnCount, columnCountBefore);
240
241 testWidget->setColumnCount(columnCountAfter);
242 columnCount = testWidget->columnCount();
243 QCOMPARE(columnCount, columnCountAfter);
244
245 QPersistentModelIndex index(testWidget->model()->index(row: 0, column: columnCountAfter - 1,
246 parent: testWidget->rootIndex()));
247 QCOMPARE(index.row(), 0);
248 QCOMPARE(index.column(), columnCountAfter - 1);
249 QVERIFY(index.isValid());
250 testWidget->setColumnCount(columnCountBefore);
251 QCOMPARE(index.row(), -1);
252 QCOMPARE(index.column(), -1);
253 QVERIFY(!index.isValid());
254
255 columnCountBefore = testWidget->columnCount();
256 testWidget->setColumnCount(-1);
257 QCOMPARE(testWidget->columnCount(), columnCountBefore);
258}
259
260void tst_QTableWidget::itemAssignment()
261{
262 QTableWidgetItem itemInWidget("inWidget");
263 testWidget->setItem(row: 0, column: 0, item: &itemInWidget);
264 itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsUserTristate);
265 QTableWidgetItem itemOutsideWidget("outsideWidget");
266
267 QVERIFY(itemInWidget.tableWidget());
268 QCOMPARE(itemInWidget.text(), QString("inWidget"));
269 QVERIFY(itemInWidget.flags() & Qt::ItemIsUserTristate);
270
271 QVERIFY(!itemOutsideWidget.tableWidget());
272 QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
273 QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsUserTristate));
274
275 itemOutsideWidget = itemInWidget;
276 QVERIFY(!itemOutsideWidget.tableWidget());
277 QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
278 QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsUserTristate);
279}
280
281void tst_QTableWidget::item_data()
282{
283 QTest::addColumn<int>(name: "rowCount");
284 QTest::addColumn<int>(name: "columnCount");
285 QTest::addColumn<int>(name: "row");
286 QTest::addColumn<int>(name: "column");
287 QTest::addColumn<bool>(name: "expectItem");
288
289 QTest::newRow(dataTag: "0x0 take [0,0]") << 0 << 0 << 0 << 0 << false;
290 QTest::newRow(dataTag: "0x0 take [4,4]") << 0 << 0 << 4 << 4 << false;
291 QTest::newRow(dataTag: "4x4 take [0,0]") << 4 << 4 << 0 << 0 << true;
292 QTest::newRow(dataTag: "4x4 take [4,4]") << 4 << 4 << 4 << 4 << false;
293 QTest::newRow(dataTag: "4x4 take [2,2]") << 4 << 4 << 2 << 2 << true;
294}
295
296void tst_QTableWidget::item()
297{
298 QFETCH(int, rowCount);
299 QFETCH(int, columnCount);
300 QFETCH(int, row);
301 QFETCH(int, column);
302 QFETCH(bool, expectItem);
303
304 testWidget->setRowCount(rowCount);
305 testWidget->setColumnCount(columnCount);
306 QCOMPARE(testWidget->rowCount(), rowCount);
307 QCOMPARE(testWidget->columnCount(), columnCount);
308
309 for (int r = 0; r < testWidget->rowCount(); ++r) {
310 for (int c = 0; c < testWidget->columnCount(); ++c)
311 testWidget->setItem(row: r, column: c, item: new QTableWidgetItem(QString::number(r * c + c)));
312 }
313
314 for (int r = 0; r < testWidget->rowCount(); ++r) {
315 for (int c = 0; c < testWidget->columnCount(); ++c)
316 QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
317 }
318
319 QTableWidgetItem *item = testWidget->item(row, column);
320 QCOMPARE(!!item, expectItem);
321 if (expectItem)
322 QCOMPARE(item->text(), QString::number(row * column + column));
323}
324
325void tst_QTableWidget::takeItem_data()
326{
327 QTest::addColumn<int>(name: "rowCount");
328 QTest::addColumn<int>(name: "columnCount");
329 QTest::addColumn<int>(name: "row");
330 QTest::addColumn<int>(name: "column");
331 QTest::addColumn<bool>(name: "expectItem");
332
333 QTest::newRow(dataTag: "0x0 take [0,0]") << 0 << 0 << 0 << 0 << false;
334 QTest::newRow(dataTag: "0x0 take [4,4]") << 0 << 0 << 4 << 4 << false;
335 QTest::newRow(dataTag: "4x4 take [0,0]") << 4 << 4 << 0 << 0 << true;
336 QTest::newRow(dataTag: "4x4 take [4,4]") << 4 << 4 << 4 << 4 << false;
337 QTest::newRow(dataTag: "4x4 take [2,2]") << 4 << 4 << 2 << 2 << true;
338}
339
340void tst_QTableWidget::takeItem()
341{
342 QFETCH(int, rowCount);
343 QFETCH(int, columnCount);
344 QFETCH(int, row);
345 QFETCH(int, column);
346 QFETCH(bool, expectItem);
347
348 testWidget->setRowCount(rowCount);
349 testWidget->setColumnCount(columnCount);
350 QCOMPARE(testWidget->rowCount(), rowCount);
351 QCOMPARE(testWidget->columnCount(), columnCount);
352
353 for (int r = 0; r < testWidget->rowCount(); ++r) {
354 for (int c = 0; c < testWidget->columnCount(); ++c)
355 testWidget->setItem(row: r, column: c, item: new QTableWidgetItem(QString::number(r * c + c)));
356 }
357
358 for (int r = 0; r < testWidget->rowCount(); ++r) {
359 for (int c = 0; c < testWidget->columnCount(); ++c)
360 QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
361 }
362
363 QSignalSpy spy(testWidget.get(), &QTableWidget::cellChanged);
364 QTableWidgetItem *item = testWidget->takeItem(row, column);
365 QCOMPARE(!!item, expectItem);
366 if (expectItem) {
367 QCOMPARE(item->text(), QString::number(row * column + column));
368 delete item;
369
370 QTRY_COMPARE(spy.count(), 1);
371 const QList<QVariant> arguments = spy.takeFirst();
372 QCOMPARE(arguments.size(), 2);
373 QCOMPARE(arguments.at(0).toInt(), row);
374 QCOMPARE(arguments.at(1).toInt(), column);
375 }
376 QVERIFY(!testWidget->takeItem(row, column));
377}
378
379void tst_QTableWidget::selectedItems_data()
380{
381 QTest::addColumn<int>(name: "rowCount");
382 QTest::addColumn<int>(name: "columnCount");
383 QTest::addColumn<IntIntList>(name: "createItems");
384 QTest::addColumn<IntList>(name: "hiddenRows");
385 QTest::addColumn<IntList>(name: "hiddenColumns");
386 QTest::addColumn<QTableWidgetSelectionRange>(name: "selectionRange");
387 QTest::addColumn<IntIntList>(name: "expectedItems");
388
389 QTest::newRow(dataTag: "3x3 empty cells, no hidden rows/columns, none selected")
390 << 3 << 3
391 << IntIntList()
392 << IntList()
393 << IntList()
394 << QTableWidgetSelectionRange()
395 << IntIntList();
396
397 QTest::newRow(dataTag: "3x3 empty cells,no hidden rows/columnms, all selected")
398 << 3 << 3
399 << IntIntList()
400 << IntList()
401 << IntList()
402 << QTableWidgetSelectionRange(0, 0, 2, 2)
403 << IntIntList();
404
405 QTest::newRow(dataTag: "3x3 (1,1) exists, no hidden rows/columnms, all selected")
406 << 3 << 3
407 << (IntIntList() << IntPair(1,1))
408 << IntList()
409 << IntList()
410 << QTableWidgetSelectionRange(0, 0, 2, 2)
411 << (IntIntList() << IntPair(1,1));
412
413 QTest::newRow(dataTag: "3x3 (1,1) exists, row 1 hidden, all selected")
414 << 3 << 3
415 << (IntIntList() << IntPair(1,1))
416 << (IntList() << 1)
417 << IntList()
418 << QTableWidgetSelectionRange(0, 0, 2, 2)
419 << IntIntList();
420
421 QTest::newRow(dataTag: "3x3 (1,1) exists, column 1 hidden, all selected")
422 << 3 << 3
423 << (IntIntList() << IntPair(1,1))
424 << IntList()
425 << (IntList() << 1)
426 << QTableWidgetSelectionRange(0, 0, 2, 2)
427 << IntIntList();
428
429 QTest::newRow(dataTag: "3x3 all exists, no hidden rows/columns, all selected")
430 << 3 << 3
431 << (IntIntList()
432 << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
433 << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
434 << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
435 << IntList()
436 << IntList()
437 << QTableWidgetSelectionRange(0, 0, 2, 2)
438 << (IntIntList()
439 << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
440 << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
441 << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
442
443 QTest::newRow(dataTag: "3x3 all exists, row 1 hidden, all selected")
444 << 3 << 3
445 << (IntIntList()
446 << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
447 << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
448 << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
449 << (IntList() << 1)
450 << IntList()
451 << QTableWidgetSelectionRange(0, 0, 2, 2)
452 << (IntIntList()
453 << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
454 << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
455
456 QTest::newRow(dataTag: "3x3 all exists, column 1 hidden, all selected")
457 << 3 << 3
458 << (IntIntList()
459 << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
460 << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
461 << IntPair(2,0) << IntPair(2,1) << IntPair(2,2))
462 << IntList()
463 << (IntList() << 1)
464 << QTableWidgetSelectionRange(0, 0, 2, 2)
465 << (IntIntList()
466 << IntPair(0,0) << IntPair(0,2)
467 << IntPair(1,0) << IntPair(1,2)
468 << IntPair(2,0) << IntPair(2,2));
469
470 QTest::newRow(dataTag: "3x3 none exists, no hidden rows/columns, all selected")
471 << 3 << 3
472 << IntIntList()
473 << IntList()
474 << IntList()
475 << QTableWidgetSelectionRange(0, 0, 2, 2)
476 << IntIntList();
477// << (IntIntList()
478// << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
479// << IntPair(1,0) << IntPair(1,1) << IntPair(1,2)
480// << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
481
482 QTest::newRow(dataTag: "3x3 none exists, row 1 hidden, all selected, filling empty cells")
483 << 3 << 3
484 << IntIntList()
485 << (IntList() << 1)
486 << IntList()
487 << QTableWidgetSelectionRange(0, 0, 2, 2)
488 << IntIntList();
489// << (IntIntList()
490// << IntPair(0,0) << IntPair(0,1) << IntPair(0,2)
491// << IntPair(2,0) << IntPair(2,1) << IntPair(2,2));
492
493 QTest::newRow(dataTag: "3x3 none exists, column 1 hidden, all selected")
494 << 3 << 3
495 << IntIntList()
496 << IntList()
497 << (IntList() << 1)
498 << QTableWidgetSelectionRange(0, 0, 2, 2)
499 << IntIntList();
500// << (IntIntList()
501// << IntPair(0,0) << IntPair(0,2)
502// << IntPair(1,0) << IntPair(1,2)
503// << IntPair(2,0) << IntPair(2,2));
504}
505
506void tst_QTableWidget::selectedItems()
507{
508 QFETCH(int, rowCount);
509 QFETCH(int, columnCount);
510 QFETCH(const IntIntList, createItems);
511 QFETCH(const IntList, hiddenRows);
512 QFETCH(const IntList, hiddenColumns);
513 QFETCH(const QTableWidgetSelectionRange, selectionRange);
514 QFETCH(const IntIntList, expectedItems);
515
516 // set dimensions and test they are ok
517 testWidget->setRowCount(rowCount);
518 testWidget->setColumnCount(columnCount);
519 QCOMPARE(testWidget->rowCount(), rowCount);
520 QCOMPARE(testWidget->columnCount(), columnCount);
521
522 // create and set items
523 for (const auto &intPair : createItems) {
524 testWidget->setItem(row: intPair.first, column: intPair.second,
525 item: new QTableWidgetItem(QString("Item %1 %2")
526 .arg(a: intPair.first).arg(a: intPair.second)));
527 }
528 // hide rows/columns
529 for (int row : hiddenRows)
530 testWidget->setRowHidden(row, hide: true);
531 for (int column : hiddenColumns)
532 testWidget->setColumnHidden(column, hide: true);
533
534 // make sure we don't have any previous selections hanging around
535 QVERIFY(!testWidget->selectedRanges().count());
536 QVERIFY(!testWidget->selectedItems().count());
537
538 // select range and check that it is set correctly
539 testWidget->setRangeSelected(range: selectionRange, select: true);
540 if (selectionRange.topRow() >= 0) {
541 QCOMPARE(testWidget->selectedRanges().count(), 1);
542 QCOMPARE(testWidget->selectedRanges().at(0).topRow(), selectionRange.topRow());
543 QCOMPARE(testWidget->selectedRanges().at(0).bottomRow(), selectionRange.bottomRow());
544 QCOMPARE(testWidget->selectedRanges().at(0).leftColumn(), selectionRange.leftColumn());
545 QCOMPARE(testWidget->selectedRanges().at(0).rightColumn(), selectionRange.rightColumn());
546 } else {
547 QCOMPARE(testWidget->selectedRanges().count(), 0);
548 }
549
550 // check that the correct number of items and the expected items are there
551 const QList<QTableWidgetItem *> selectedItems = testWidget->selectedItems();
552 QCOMPARE(selectedItems.count(), expectedItems.count());
553 for (const auto &intPair : expectedItems)
554 QVERIFY(selectedItems.contains(testWidget->item(intPair.first, intPair.second)));
555
556 // check that setItemSelected agrees with selectedItems
557 for (int row = 0; row < testWidget->rowCount(); ++row) {
558 if (hiddenRows.contains(t: row))
559 continue;
560
561 for (int column = 0; column < testWidget->columnCount(); ++column) {
562 if (hiddenColumns.contains(t: column))
563 continue;
564
565 QTableWidgetItem *item = testWidget->item(row, column);
566 if (item && item->isSelected())
567 QVERIFY(selectedItems.contains(item));
568 }
569 }
570}
571
572void tst_QTableWidget::removeRow_data()
573{
574 QTest::addColumn<int>(name: "rowCount");
575 QTest::addColumn<int>(name: "columnCount");
576 QTest::addColumn<int>(name: "row");
577 QTest::addColumn<int>(name: "expectedRowCount");
578 QTest::addColumn<int>(name: "expectedColumnCount");
579
580 QTest::newRow(dataTag: "Empty") << 0 << 0 << 0 << 0 << 0;
581 QTest::newRow(dataTag: "1x1:0") << 1 << 1 << 0 << 0 << 1;
582 QTest::newRow(dataTag: "3x3:0") << 3 << 3 << 0 << 2 << 3;
583 QTest::newRow(dataTag: "3x3:1") << 3 << 3 << 1 << 2 << 3;
584 QTest::newRow(dataTag: "3x3:2") << 3 << 3 << 2 << 2 << 3;
585}
586
587void tst_QTableWidget::removeRow()
588{
589 QFETCH(int, rowCount);
590 QFETCH(int, columnCount);
591 QFETCH(int, row);
592 QFETCH(int, expectedRowCount);
593 QFETCH(int, expectedColumnCount);
594
595 // set dimensions and test they are ok
596 testWidget->setRowCount(rowCount);
597 testWidget->setColumnCount(columnCount);
598 QCOMPARE(testWidget->rowCount(), rowCount);
599 QCOMPARE(testWidget->columnCount(), columnCount);
600
601 // fill table with items
602 for (int r = 0; r < rowCount; ++r) {
603 const QString rRow = QString::number(r) + QLatin1Char(':');
604 for (int c = 0; c < columnCount; ++c) {
605 testWidget->setItem(row: r, column: c,
606 item: new QTableWidgetItem(rRow + QString::number(c)));
607 }
608 }
609
610 // remove and compare the results
611 testWidget->removeRow(row);
612 QCOMPARE(testWidget->rowCount(), expectedRowCount);
613 QCOMPARE(testWidget->columnCount(), expectedColumnCount);
614
615 // check if the correct items were removed
616 for (int r = 0; r < expectedRowCount; ++r) {
617 const QString rRow = QString::number(r < row ? r : r + 1) +
618 QLatin1Char(':');
619 for (int c = 0; c < expectedColumnCount; ++c) {
620 if (r < row)
621 QCOMPARE(testWidget->item(r, c)->text(),
622 rRow + QString::number(c));
623 else
624 QCOMPARE(testWidget->item(r, c)->text(),
625 rRow + QString::number(c));
626 }
627 }
628}
629
630void tst_QTableWidget::removeColumn_data()
631{
632 QTest::addColumn<int>(name: "rowCount");
633 QTest::addColumn<int>(name: "columnCount");
634 QTest::addColumn<int>(name: "column");
635 QTest::addColumn<int>(name: "expectedRowCount");
636 QTest::addColumn<int>(name: "expectedColumnCount");
637
638 QTest::newRow(dataTag: "Empty") << 0 << 0 << 0 << 0 << 0;
639 QTest::newRow(dataTag: "1x1:0") << 1 << 1 << 0 << 1 << 0;
640 QTest::newRow(dataTag: "3x3:0") << 3 << 3 << 0 << 3 << 2;
641 QTest::newRow(dataTag: "3x3:1") << 3 << 3 << 1 << 3 << 2;
642 QTest::newRow(dataTag: "3x3:2") << 3 << 3 << 2 << 3 << 2;
643}
644
645void tst_QTableWidget::removeColumn()
646{
647 QFETCH(int, rowCount);
648 QFETCH(int, columnCount);
649 QFETCH(int, column);
650 QFETCH(int, expectedRowCount);
651 QFETCH(int, expectedColumnCount);
652
653 // set dimensions and test they are ok
654 testWidget->setRowCount(rowCount);
655 testWidget->setColumnCount(columnCount);
656 QCOMPARE(testWidget->rowCount(), rowCount);
657 QCOMPARE(testWidget->columnCount(), columnCount);
658
659 // fill table with items
660 for (int r = 0; r < rowCount; ++r) {
661 const QString rStr = QString::number(r) + QLatin1Char(':');
662 for (int c = 0; c < columnCount; ++c) {
663 testWidget->setItem(row: r, column: c,
664 item: new QTableWidgetItem(
665 rStr + QString::number(c)));
666 }
667 }
668
669 // remove and compare the results
670 testWidget->removeColumn(column);
671 QCOMPARE(testWidget->rowCount(), expectedRowCount);
672 QCOMPARE(testWidget->columnCount(), expectedColumnCount);
673
674
675 // check if the correct items were removed
676 for (int r = 0; r < expectedRowCount; ++r) {
677 const QString rStr = QString::number(r) + QLatin1Char(':');
678 for (int c = 0; c < expectedColumnCount; ++c) {
679 if (c < column)
680 QCOMPARE(testWidget->item(r, c)->text(),
681 rStr + QString::number(c));
682 else
683 QCOMPARE(testWidget->item(r, c)->text(),
684 rStr + QString::number(c + 1));
685 }
686 }
687}
688
689void tst_QTableWidget::insertRow_data()
690{
691 QTest::addColumn<int>(name: "rowCount");
692 QTest::addColumn<int>(name: "columnCount");
693 QTest::addColumn<int>(name: "row");
694 QTest::addColumn<int>(name: "expectedRowCount");
695 QTest::addColumn<int>(name: "expectedColumnCount");
696
697 QTest::newRow(dataTag: "Empty") << 0 << 0 << 0 << 1 << 0;
698 QTest::newRow(dataTag: "1x1:0") << 1 << 1 << 0 << 2 << 1;
699 QTest::newRow(dataTag: "3x3:-1") << 3 << 3 << -1 << 3 << 3;
700 QTest::newRow(dataTag: "3x3:0") << 3 << 3 << 0 << 4 << 3;
701 QTest::newRow(dataTag: "3x3:1") << 3 << 3 << 1 << 4 << 3;
702 QTest::newRow(dataTag: "3x3:2") << 3 << 3 << 2 << 4 << 3;
703 QTest::newRow(dataTag: "3x3:3") << 3 << 3 << 3 << 4 << 3;
704 QTest::newRow(dataTag: "3x3:4") << 3 << 3 << 4 << 3 << 3;
705}
706
707void tst_QTableWidget::insertRow()
708{
709 QFETCH(int, rowCount);
710 QFETCH(int, columnCount);
711 QFETCH(int, row);
712 QFETCH(int, expectedRowCount);
713 QFETCH(int, expectedColumnCount);
714
715 // set dimensions and test they are ok
716 testWidget->setRowCount(rowCount);
717 testWidget->setColumnCount(columnCount);
718 QCOMPARE(testWidget->rowCount(), rowCount);
719 QCOMPARE(testWidget->columnCount(), columnCount);
720
721 // insert and compare the results
722 testWidget->insertRow(row);
723 QCOMPARE(testWidget->rowCount(), expectedRowCount);
724 QCOMPARE(testWidget->columnCount(), expectedColumnCount);
725}
726
727void tst_QTableWidget::insertColumn_data()
728{
729 QTest::addColumn<int>(name: "rowCount");
730 QTest::addColumn<int>(name: "columnCount");
731 QTest::addColumn<int>(name: "column");
732 QTest::addColumn<int>(name: "expectedRowCount");
733 QTest::addColumn<int>(name: "expectedColumnCount");
734
735 QTest::newRow(dataTag: "Empty") << 0 << 0 << 0 << 0 << 1;
736 QTest::newRow(dataTag: "1x1:0") << 1 << 1 << 0 << 1 << 2;
737 QTest::newRow(dataTag: "3x3:-1") << 3 << 3 << -1 << 3 << 3;
738 QTest::newRow(dataTag: "3x3:0") << 3 << 3 << 0 << 3 << 4;
739 QTest::newRow(dataTag: "3x3:1") << 3 << 3 << 1 << 3 << 4;
740 QTest::newRow(dataTag: "3x3:2") << 3 << 3 << 2 << 3 << 4;
741 QTest::newRow(dataTag: "3x3:3") << 3 << 3 << 3 << 3 << 4;
742 QTest::newRow(dataTag: "3x3:4") << 3 << 3 << 4 << 3 << 3;
743}
744
745void tst_QTableWidget::insertColumn()
746{
747 QFETCH(int, rowCount);
748 QFETCH(int, columnCount);
749 QFETCH(int, column);
750 QFETCH(int, expectedRowCount);
751 QFETCH(int, expectedColumnCount);
752
753 // set dimensions and test they are ok
754 testWidget->setRowCount(rowCount);
755 testWidget->setColumnCount(columnCount);
756 QCOMPARE(testWidget->rowCount(), rowCount);
757 QCOMPARE(testWidget->columnCount(), columnCount);
758
759 // insert and compare the results
760 testWidget->insertColumn(column);
761 QCOMPARE(testWidget->rowCount(), expectedRowCount);
762 QCOMPARE(testWidget->columnCount(), expectedColumnCount);
763}
764
765void tst_QTableWidget::itemStreaming_data()
766{
767 QTest::addColumn<QString>(name: "text");
768 QTest::addColumn<QString>(name: "toolTip");
769
770 QTest::newRow(dataTag: "Data") << "item text" << "tool tip text";
771}
772
773void tst_QTableWidget::itemStreaming()
774{
775 QFETCH(QString, text);
776 QFETCH(QString, toolTip);
777
778 QTableWidgetItem item;
779 QCOMPARE(item.text(), QString());
780 QCOMPARE(item.toolTip(), QString());
781
782 item.setText(text);
783 item.setToolTip(toolTip);
784 QCOMPARE(item.text(), text);
785 QCOMPARE(item.toolTip(), toolTip);
786
787 QByteArray buffer;
788 QDataStream out(&buffer, QIODevice::WriteOnly);
789 out << item;
790
791 QTableWidgetItem item2;
792 QCOMPARE(item2.text(), QString());
793 QCOMPARE(item2.toolTip(), QString());
794
795 QVERIFY(!buffer.isEmpty());
796
797 QDataStream in(&buffer, QIODevice::ReadOnly);
798 in >> item2;
799 QCOMPARE(item2.text(), text);
800 QCOMPARE(item2.toolTip(), toolTip);
801}
802
803void tst_QTableWidget::itemOwnership()
804{
805 QPointer<QObjectTableItem> item;
806 QPointer<QObjectTableItem> headerItem;
807
808 //delete from outside
809 item = new QObjectTableItem();
810 testWidget->setItem(row: 0, column: 0, item);
811 delete item;
812 QCOMPARE(testWidget->item(0, 0), nullptr);
813
814 //delete vertical headeritem from outside
815 headerItem = new QObjectTableItem();
816 testWidget->setVerticalHeaderItem(row: 0, item: headerItem);
817 delete headerItem;
818 QCOMPARE(testWidget->verticalHeaderItem(0), nullptr);
819
820 //delete horizontal headeritem from outside
821 headerItem = new QObjectTableItem();
822 testWidget->setHorizontalHeaderItem(column: 0, item: headerItem);
823 delete headerItem;
824 QCOMPARE(testWidget->horizontalHeaderItem(0), nullptr);
825
826 //setItem
827 item = new QObjectTableItem();
828 testWidget->setItem(row: 0, column: 0, item);
829 testWidget->setItem(row: 0, column: 0, item: new QTableWidgetItem());
830 QVERIFY(item.isNull());
831
832 //setHorizontalHeaderItem
833 headerItem = new QObjectTableItem();
834 testWidget->setHorizontalHeaderItem(column: 0, item: headerItem);
835 testWidget->setHorizontalHeaderItem(column: 0, item: new QTableWidgetItem());
836 QVERIFY(headerItem.isNull());
837
838 //setVerticalHeaderItem
839 headerItem = new QObjectTableItem();
840 testWidget->setVerticalHeaderItem(row: 0, item: headerItem);
841 testWidget->setVerticalHeaderItem(row: 0, item: new QTableWidgetItem());
842 QVERIFY(headerItem.isNull());
843
844 //takeItem
845 item = new QObjectTableItem();
846 testWidget->setItem(row: 0, column: 0, item);
847 testWidget->takeItem(row: 0, column: 0);
848 QVERIFY(!item.isNull());
849 delete item;
850
851 // removeRow
852 item = new QObjectTableItem();
853 headerItem = new QObjectTableItem();
854 testWidget->setItem(row: 0, column: 0, item);
855 testWidget->setVerticalHeaderItem(row: 0, item: headerItem);
856 testWidget->removeRow(row: 0);
857 QVERIFY(item.isNull());
858 QVERIFY(headerItem.isNull());
859
860 // removeColumn
861 item = new QObjectTableItem();
862 headerItem = new QObjectTableItem();
863 testWidget->setItem(row: 0, column: 0, item);
864 testWidget->setHorizontalHeaderItem(column: 0, item: headerItem);
865 testWidget->removeColumn(column: 0);
866 QVERIFY(item.isNull());
867 QVERIFY(headerItem.isNull());
868
869 // clear
870 item = new QObjectTableItem();
871 testWidget->setItem(row: 0, column: 0, item);
872 testWidget->clear();
873 QVERIFY(item.isNull());
874}
875
876void tst_QTableWidget::sortItems_data()
877{
878 QTest::addColumn<int>(name: "rowCount");
879 QTest::addColumn<int>(name: "columnCount");
880 QTest::addColumn<Qt::SortOrder>(name: "sortOrder");
881 QTest::addColumn<int>(name: "sortColumn");
882 QTest::addColumn<QStringList>(name: "initial");
883 QTest::addColumn<QStringList>(name: "expected");
884 QTest::addColumn<IntList>(name: "rows");
885 QTest::addColumn<IntList>(name: "initialHidden");
886 QTest::addColumn<IntList>(name: "expectedHidden");
887
888 QTest::newRow(dataTag: "ascending")
889 << 4 << 5
890 << Qt::AscendingOrder
891 << 0
892 << (QStringList()
893 << "0" << "a" << "o" << "8" << "k"
894 << "3" << "d" << "k" << "o" << "6"
895 << "2" << "c" << "9" << "y" << "8"
896 << "1" << "b" << "7" << "3" << "u")
897 << (QStringList()
898 << "0" << "a" << "o" << "8" << "k"
899 << "1" << "b" << "7" << "3" << "u"
900 << "2" << "c" << "9" << "y" << "8"
901 << "3" << "d" << "k" << "o" << "6")
902 << (IntList() << 0 << 3 << 2 << 1)
903 << IntList()
904 << IntList();
905
906 QTest::newRow(dataTag: "descending")
907 << 4 << 5
908 << Qt::DescendingOrder
909 << 0
910 << (QStringList()
911 << "0" << "a" << "o" << "8" << "k"
912 << "3" << "d" << "k" << "o" << "6"
913 << "2" << "c" << "9" << "y" << "8"
914 << "1" << "b" << "7" << "3" << "u")
915 << (QStringList()
916 << "3" << "d" << "k" << "o" << "6"
917 << "2" << "c" << "9" << "y" << "8"
918 << "1" << "b" << "7" << "3" << "u"
919 << "0" << "a" << "o" << "8" << "k")
920 << (IntList() << 3 << 0 << 1 << 2)
921 << IntList()
922 << IntList();
923
924 QTest::newRow(dataTag: "empty table")
925 << 4 << 5
926 << Qt::AscendingOrder
927 << 0
928 << (QStringList()
929 << QString() << QString() << QString() << QString() << QString()
930 << QString() << QString() << QString() << QString() << QString()
931 << QString() << QString() << QString() << QString() << QString()
932 << QString() << QString() << QString() << QString() << QString())
933 << (QStringList()
934 << QString() << QString() << QString() << QString() << QString()
935 << QString() << QString() << QString() << QString() << QString()
936 << QString() << QString() << QString() << QString() << QString()
937 << QString() << QString() << QString() << QString() << QString())
938 << IntList()
939 << IntList()
940 << IntList();
941
942 QTest::newRow(dataTag: "half-empty table")
943 << 4 << 5
944 << Qt::AscendingOrder
945 << 0
946 << (QStringList()
947 << "0" << QString() << QString() << QString() << QString()
948 << "3" << "d" << QString() << QString() << QString()
949 << "2" << "c" << QString() << QString() << QString()
950 << QString() << QString() << QString() << QString() << QString())
951 << (QStringList()
952 << "0" << QString() << QString() << QString() << QString()
953 << "2" << "c" << QString() << QString() << QString()
954 << "3" << "d" << QString() << QString() << QString()
955 << QString() << QString() << QString() << QString() << QString())
956 << (IntList() << 0 << 2 << 1)
957 << IntList()
958 << IntList();
959
960 QTest::newRow(dataTag: "empty column, should not sort.")
961 << 4 << 5
962 << Qt::AscendingOrder
963 << 3
964 << (QStringList()
965 << "0" << QString() << QString() << QString() << QString()
966 << "3" << "d" << QString() << QString() << QString()
967 << "2" << "c" << QString() << QString() << QString()
968 << QString() << QString() << QString() << QString() << QString())
969 << (QStringList()
970 << "0" << QString() << QString() << QString() << QString()
971 << "3" << "d" << QString() << QString() << QString()
972 << "2" << "c" << QString() << QString() << QString()
973 << QString() << QString() << QString() << QString() << QString())
974 << IntList()
975 << IntList()
976 << IntList();
977
978 QTest::newRow(dataTag: "descending with null cell, the null cell should be placed at the bottom")
979 << 4 << 5
980 << Qt::DescendingOrder
981 << 0
982 << (QStringList()
983 << "0" << "a" << "o" << "8" << "k"
984 << "3" << "d" << "k" << "o" << "6"
985 << "2" << "c" << "9" << "y" << "8"
986 << QString() << "b" << "7" << "3" << "u")
987 << (QStringList()
988 << "3" << "d" << "k" << "o" << "6"
989 << "2" << "c" << "9" << "y" << "8"
990 << "0" << "a" << "o" << "8" << "k"
991 << QString() << "b" << "7" << "3" << "u")
992 << (IntList() << 2 << 0 << 1)
993 << IntList()
994 << IntList();
995
996 QTest::newRow(dataTag: "ascending with null cell, the null cell should be placed at the bottom")
997 << 4 << 5
998 << Qt::AscendingOrder
999 << 0
1000 << (QStringList()
1001 << "0" << "a" << "o" << "8" << "k"
1002 << "3" << "d" << "k" << "o" << "6"
1003 << "2" << "c" << "9" << "y" << "8"
1004 << QString() << "b" << "7" << "3" << "u")
1005 << (QStringList()
1006 << "0" << "a" << "o" << "8" << "k"
1007 << "2" << "c" << "9" << "y" << "8"
1008 << "3" << "d" << "k" << "o" << "6"
1009 << QString() << "b" << "7" << "3" << "u")
1010 << (IntList() << 0 << 2 << 1)
1011 << IntList()
1012 << IntList();
1013
1014 QTest::newRow(dataTag: "ascending with null cells, the null cells should be placed at the bottom")
1015 << 4 << 5
1016 << Qt::AscendingOrder
1017 << 0
1018 << (QStringList()
1019 << "3" << "d" << "k" << "o" << "6"
1020 << "0" << "a" << "o" << "8" << "k"
1021 << QString() << "c" << "9" << "y" << "8"
1022 << QString() << "b" << "7" << "3" << "u")
1023 << (QStringList()
1024 << "0" << "a" << "o" << "8" << "k"
1025 << "3" << "d" << "k" << "o" << "6"
1026 << QString() << "c" << "9" << "y" << "8"
1027 << QString() << "b" << "7" << "3" << "u")
1028 << (IntList() << 1 << 0)
1029 << IntList()
1030 << IntList();
1031
1032 QTest::newRow(dataTag: "ascending... Check a bug in PersistentIndexes")
1033 << 4 << 5
1034 << Qt::AscendingOrder
1035 << 0
1036 << (QStringList()
1037 << "3" << "c" << "9" << "y" << "8"
1038 << "2" << "b" << "7" << "3" << "u"
1039 << "4" << "d" << "k" << "o" << "6"
1040 << "1" << "a" << "o" << "8" << "k")
1041 << (QStringList()
1042 << "1" << "a" << "o" << "8" << "k"
1043 << "2" << "b" << "7" << "3" << "u"
1044 << "3" << "c" << "9" << "y" << "8"
1045 << "4" << "d" << "k" << "o" << "6")
1046 << (IntList() << 2 << 1 << 3 << 0)
1047 << IntList()
1048 << IntList();
1049
1050 QTest::newRow(dataTag: "ascending with some null cells inbetween")
1051 << 4 << 5
1052 << Qt::AscendingOrder
1053 << 0
1054 << (QStringList()
1055 << QString() << "a" << "o" << "8" << "k"
1056 << "2" << "c" << "9" << "y" << "8"
1057 << QString() << "d" << "k" << "o" << "6"
1058 << "1" << "b" << "7" << "3" << "u")
1059 << (QStringList()
1060 << "1" << "b" << "7" << "3" << "u"
1061 << "2" << "c" << "9" << "y" << "8"
1062 << QString() << "a" << "o" << "8" << "k"
1063 << QString() << "d" << "k" << "o" << "6")
1064 << (IntList() << 1 << 0)
1065 << IntList()
1066 << IntList();
1067
1068 QTest::newRow(dataTag: "ascending hidden")
1069 << 4 << 5
1070 << Qt::AscendingOrder
1071 << 0
1072 << (QStringList()
1073 << "0" << "a" << "o" << "8" << "k"
1074 << "3" << "d" << "k" << "o" << "6"
1075 << "2" << "c" << "9" << "y" << "8"
1076 << "1" << "b" << "7" << "3" << "u")
1077 << (QStringList()
1078 << "0" << "a" << "o" << "8" << "k"
1079 << "1" << "b" << "7" << "3" << "u"
1080 << "2" << "c" << "9" << "y" << "8"
1081 << "3" << "d" << "k" << "o" << "6")
1082 << (IntList() << 0 << 3 << 2 << 1)
1083 << (IntList() << 0 << 2)
1084 << (IntList() << 0 << 2);
1085
1086 QTest::newRow(dataTag: "descending hidden")
1087 << 4 << 5
1088 << Qt::DescendingOrder
1089 << 0
1090 << (QStringList()
1091 << "0" << "a" << "o" << "8" << "k"
1092 << "3" << "d" << "k" << "o" << "6"
1093 << "2" << "c" << "9" << "y" << "8"
1094 << "1" << "b" << "7" << "3" << "u")
1095 << (QStringList()
1096 << "3" << "d" << "k" << "o" << "6"
1097 << "2" << "c" << "9" << "y" << "8"
1098 << "1" << "b" << "7" << "3" << "u"
1099 << "0" << "a" << "o" << "8" << "k")
1100 << (IntList() << 3 << 0 << 1 << 2)
1101 << (IntList() << 0 << 2)
1102 << (IntList() << 3 << 1);
1103}
1104
1105void tst_QTableWidget::sortItems()
1106{
1107 QFETCH(int, rowCount);
1108 QFETCH(int, columnCount);
1109 QFETCH(Qt::SortOrder, sortOrder);
1110 QFETCH(int, sortColumn);
1111 QFETCH(QStringList, initial);
1112 QFETCH(QStringList, expected);
1113 QFETCH(IntList, rows);
1114 QFETCH(IntList, initialHidden);
1115 QFETCH(IntList, expectedHidden);
1116
1117 testWidget->setRowCount(rowCount);
1118 testWidget->setColumnCount(columnCount);
1119
1120 QAbstractItemModel *model = testWidget->model();
1121 QVector<QPersistentModelIndex> persistent;
1122
1123 int ti = 0;
1124 for (int r = 0; r < rowCount; ++r) {
1125 for (int c = 0; c < columnCount; ++c) {
1126 QString str = initial.at(i: ti++);
1127 if (!str.isEmpty()) {
1128 testWidget->setItem(row: r, column: c, item: new QTableWidgetItem(str));
1129 }
1130 }
1131 if (testWidget->item(row: r, column: sortColumn))
1132 persistent << model->index(row: r, column: sortColumn, parent: QModelIndex());
1133 }
1134
1135 for (int h = 0; h < initialHidden.count(); ++h)
1136 testWidget->hideRow(row: initialHidden.at(i: h));
1137
1138 QCOMPARE(testWidget->verticalHeader()->hiddenSectionCount(), initialHidden.count());
1139
1140 testWidget->sortItems(column: sortColumn, order: sortOrder);
1141
1142 int te = 0;
1143 for (int i = 0; i < rows.count(); ++i) {
1144 for (int j = 0; j < columnCount; ++j) {
1145 QString value;
1146 QTableWidgetItem *itm = testWidget->item(row: i, column: j);
1147 if (itm) {
1148 value = itm->text();
1149 }
1150 QCOMPARE(value, expected.at(te++));
1151 }
1152 QCOMPARE(persistent.at(i).row(), rows.at(i));
1153 //qDebug() << "persistent" << persistent.at(i).row()
1154 // << "expected" << rows.at(i);
1155 }
1156
1157 for (int k = 0; k < expectedHidden.count(); ++k)
1158 QVERIFY(testWidget->isRowHidden(expectedHidden.at(k)));
1159}
1160
1161void tst_QTableWidget::setItemWithSorting_data()
1162{
1163 QTest::addColumn<int>(name: "rowCount");
1164 QTest::addColumn<int>(name: "columnCount");
1165 QTest::addColumn<Qt::SortOrder>(name: "sortOrder");
1166 QTest::addColumn<int>(name: "sortColumn");
1167 QTest::addColumn<QStringList>(name: "initialValues");
1168 QTest::addColumn<int>(name: "row");
1169 QTest::addColumn<int>(name: "column");
1170 QTest::addColumn<QString>(name: "newValue");
1171 QTest::addColumn<QStringList>(name: "expectedValues");
1172 QTest::addColumn<IntList>(name: "expectedRows");
1173 QTest::addColumn<bool>(name: "reorderingExpected");
1174
1175 QTest::newRow(dataTag: "2x1 no change (ascending)")
1176 << 2 << 1
1177 << Qt::AscendingOrder << 0
1178 << (QStringList() << "0" << "1")
1179 << 1 << 0 << "2"
1180 << (QStringList() << "0" << "2")
1181 << (IntList() << 0 << 1)
1182 << false;
1183 QTest::newRow(dataTag: "2x1 no change (descending)")
1184 << 2 << 1
1185 << Qt::DescendingOrder << 0
1186 << (QStringList() << "1" << "0")
1187 << 0 << 0 << "2"
1188 << (QStringList() << "2" << "0")
1189 << (IntList() << 0 << 1)
1190 << false;
1191 QTest::newRow(dataTag: "2x1 reorder (ascending)")
1192 << 2 << 1
1193 << Qt::AscendingOrder << 0
1194 << (QStringList() << "0" << "1")
1195 << 0 << 0 << "2"
1196 << (QStringList() << "1" << "2")
1197 << (IntList() << 1 << 0)
1198 << true;
1199 QTest::newRow(dataTag: "2x1 reorder (descending)")
1200 << 2 << 1
1201 << Qt::DescendingOrder << 0
1202 << (QStringList() << "1" << "0")
1203 << 1 << 0 << "2"
1204 << (QStringList() << "2" << "1")
1205 << (IntList() << 1 << 0)
1206 << true;
1207 QTest::newRow(dataTag: "2x2 no change (ascending)")
1208 << 2 << 2
1209 << Qt::AscendingOrder << 0
1210 << (QStringList()
1211 << "0" << "00"
1212 << "1" << "11")
1213 << 1 << 0 << "2"
1214 << (QStringList()
1215 << "0" << "00"
1216 << "2" << "11")
1217 << (IntList() << 0 << 1)
1218 << false;
1219 QTest::newRow(dataTag: "2x2 reorder (ascending)")
1220 << 2 << 2
1221 << Qt::AscendingOrder << 0
1222 << (QStringList()
1223 << "0" << "00"
1224 << "1" << "11")
1225 << 0 << 0 << "2"
1226 << (QStringList()
1227 << "1" << "11"
1228 << "2" << "00")
1229 << (IntList() << 1 << 0)
1230 << true;
1231 QTest::newRow(dataTag: "2x2 reorder (ascending, sortColumn = 1)")
1232 << 2 << 2
1233 << Qt::AscendingOrder << 1
1234 << (QStringList()
1235 << "00" << "0"
1236 << "11" << "1")
1237 << 0 << 1 << "2"
1238 << (QStringList()
1239 << "11" << "1"
1240 << "00" << "2")
1241 << (IntList() << 1 << 0)
1242 << true;
1243 QTest::newRow(dataTag: "2x2 no change (column != sortColumn)")
1244 << 2 << 2
1245 << Qt::AscendingOrder << 1
1246 << (QStringList()
1247 << "00" << "0"
1248 << "11" << "1")
1249 << 0 << 0 << "22"
1250 << (QStringList()
1251 << "22" << "0"
1252 << "11" << "1")
1253 << (IntList() << 0 << 1)
1254 << false;
1255 QTest::newRow(dataTag: "8x4 reorder (ascending, sortColumn = 3)")
1256 << 8 << 4
1257 << Qt::AscendingOrder << 3
1258 << (QStringList()
1259 << "q" << "v" << "u" << "0"
1260 << "e" << "j" << "i" << "10"
1261 << "h" << "d" << "c" << "12"
1262 << "k" << "g" << "f" << "14"
1263 << "w" << "y" << "x" << "2"
1264 << "t" << "s" << "o" << "4"
1265 << "z" << "p" << "r" << "6"
1266 << "n" << "m" << "l" << "8")
1267 << 2 << 3 << "5"
1268 << (QStringList()
1269 << "q" << "v" << "u" << "0"
1270 << "e" << "j" << "i" << "10"
1271 << "k" << "g" << "f" << "14"
1272 << "w" << "y" << "x" << "2"
1273 << "t" << "s" << "o" << "4"
1274 << "h" << "d" << "c" << "5"
1275 << "z" << "p" << "r" << "6"
1276 << "n" << "m" << "l" << "8")
1277 << (IntList() << 0 << 1 << 5 << 2 << 3 << 4 << 6 << 7)
1278 << true;
1279}
1280
1281void tst_QTableWidget::setItemWithSorting()
1282{
1283 static int dummy1 = qRegisterMetaType<QList<QPersistentModelIndex>>();
1284 static int dummy2 = qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
1285 Q_UNUSED(dummy1);
1286 Q_UNUSED(dummy2);
1287 QFETCH(int, rowCount);
1288 QFETCH(int, columnCount);
1289 QFETCH(Qt::SortOrder, sortOrder);
1290 QFETCH(int, sortColumn);
1291 QFETCH(QStringList, initialValues);
1292 QFETCH(int, row);
1293 QFETCH(int, column);
1294 QFETCH(QString, newValue);
1295 QFETCH(QStringList, expectedValues);
1296 QFETCH(IntList, expectedRows);
1297 QFETCH(bool, reorderingExpected);
1298
1299 for (int i = 0; i < 2; ++i) {
1300 QTableWidget w(rowCount, columnCount);
1301
1302 QAbstractItemModel *model = w.model();
1303 QVector<QPersistentModelIndex> persistent;
1304
1305 int ti = 0;
1306 for (int r = 0; r < rowCount; ++r) {
1307 for (int c = 0; c < columnCount; ++c) {
1308 QString str = initialValues.at(i: ti++);
1309 w.setItem(row: r, column: c, item: new QTableWidgetItem(str));
1310 }
1311 persistent << model->index(row: r, column: sortColumn);
1312 }
1313
1314 w.sortItems(column: sortColumn, order: sortOrder);
1315 w.setSortingEnabled(true);
1316
1317 QSignalSpy dataChangedSpy(model, &QAbstractItemModel::dataChanged);
1318 QSignalSpy layoutChangedSpy(model, &QAbstractItemModel::layoutChanged);
1319
1320 if (i == 0) {
1321 // set a new item
1322 QTableWidgetItem *item = new QTableWidgetItem(newValue);
1323 w.setItem(row, column, item);
1324 } else {
1325 // change the data of existing item
1326 QTableWidgetItem *item = w.item(row, column);
1327 item->setText(newValue);
1328 }
1329
1330 ti = 0;
1331 for (int r = 0; r < rowCount; ++r) {
1332 for (int c = 0; c < columnCount; ++c) {
1333 QString str = expectedValues.at(i: ti++);
1334 QCOMPARE(w.item(r, c)->text(), str);
1335 }
1336 }
1337
1338 for (int k = 0; k < persistent.count(); ++k) {
1339 QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
1340 int i = (persistent.at(i: k).row() * columnCount) + sortColumn;
1341 QCOMPARE(persistent.at(k).data().toString(), expectedValues.at(i));
1342 }
1343
1344 if (i == 0)
1345 QCOMPARE(dataChangedSpy.count(), reorderingExpected ? 0 : 1);
1346 else
1347 QCOMPARE(dataChangedSpy.count(), 1);
1348
1349 QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
1350 }
1351}
1352
1353class QTableWidgetDataChanged : public QTableWidget
1354{
1355 Q_OBJECT
1356public:
1357 using QTableWidget::QTableWidget;
1358
1359 void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) override
1360 {
1361 QTableWidget::dataChanged(topLeft, bottomRight, roles);
1362 currentRoles = roles;
1363 }
1364 QVector<int> currentRoles;
1365};
1366
1367void tst_QTableWidget::itemData()
1368{
1369 QTableWidgetDataChanged widget(2, 2);
1370 widget.setItem(row: 0, column: 0, item: new QTableWidgetItem);
1371 QTableWidgetItem *item = widget.item(row: 0, column: 0);
1372 QVERIFY(item);
1373 item->setFlags(item->flags() | Qt::ItemIsEditable);
1374 item->setData(role: Qt::DisplayRole, value: QString("0"));
1375 QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
1376 item->setData(role: Qt::CheckStateRole, value: Qt::PartiallyChecked);
1377 QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
1378 for (int i = 0; i < 4; ++i)
1379 {
1380 item->setData(role: Qt::UserRole + i, value: QString::number(i + 1));
1381 QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
1382 }
1383 QMap<int, QVariant> flags = widget.model()->itemData(index: widget.model()->index(row: 0, column: 0));
1384 QCOMPARE(flags.count(), 6);
1385 for (int i = 0; i < 4; ++i)
1386 QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1));
1387}
1388
1389void tst_QTableWidget::setItemData()
1390{
1391 QTableWidgetDataChanged table(10, 10);
1392 table.setSortingEnabled(false);
1393 QSignalSpy dataChangedSpy(table.model(), &QAbstractItemModel::dataChanged);
1394
1395 QTableWidgetItem *item = new QTableWidgetItem;
1396 table.setItem(row: 0, column: 0, item);
1397 QCOMPARE(dataChangedSpy.count(), 1);
1398 QModelIndex idx = qvariant_cast<QModelIndex>(v: dataChangedSpy.takeFirst().at(i: 0));
1399
1400 QMap<int, QVariant> data;
1401 data.insert(akey: Qt::DisplayRole, avalue: QLatin1String("Display"));
1402 data.insert(akey: Qt::ToolTipRole, avalue: QLatin1String("ToolTip"));
1403 table.model()->setItemData(index: idx, roles: data);
1404 QCOMPARE(table.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole, Qt::ToolTipRole}));
1405
1406 QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("Display"));
1407 QCOMPARE(table.model()->data(idx, Qt::EditRole).toString(), QLatin1String("Display"));
1408 QCOMPARE(table.model()->data(idx, Qt::ToolTipRole).toString(), QLatin1String("ToolTip"));
1409 QCOMPARE(dataChangedSpy.count(), 1);
1410 QCOMPARE(idx, qvariant_cast<QModelIndex>(dataChangedSpy.first().at(0)));
1411 QCOMPARE(idx, qvariant_cast<QModelIndex>(dataChangedSpy.first().at(1)));
1412 const auto roles = qvariant_cast<QVector<int>>(v: dataChangedSpy.first().at(i: 2));
1413 QCOMPARE(roles.size(), 3);
1414 QVERIFY(roles.contains(Qt::DisplayRole));
1415 QVERIFY(roles.contains(Qt::EditRole));
1416 QVERIFY(roles.contains(Qt::ToolTipRole));
1417 dataChangedSpy.clear();
1418
1419 table.model()->setItemData(index: idx, roles: data);
1420 QCOMPARE(dataChangedSpy.count(), 0);
1421
1422 data.clear();
1423 data.insert(akey: Qt::DisplayRole, avalue: QLatin1String("dizplaye"));
1424 table.model()->setItemData(index: idx, roles: data);
1425 QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("dizplaye"));
1426 QCOMPARE(dataChangedSpy.count(), 1);
1427 QCOMPARE(QVector<int>({Qt::DisplayRole, Qt::EditRole}), qvariant_cast<QVector<int>>(dataChangedSpy.first().at(2)));
1428
1429 item->setBackground(QBrush(Qt::red));
1430 item->setForeground(QBrush(Qt::green));
1431 item->setSizeHint(QSize(10, 10));
1432 QCOMPARE(item->data(Qt::BackgroundRole), QVariant(QBrush(Qt::red)));
1433 QCOMPARE(item->data(Qt::ForegroundRole), QVariant(QBrush(Qt::green)));
1434 QCOMPARE(item->data(Qt::SizeHintRole), QVariant(QSize(10, 10)));
1435 // an empty brush should result in a QVariant()
1436 item->setBackground(QBrush());
1437 item->setForeground(QBrush());
1438 item->setSizeHint(QSize());
1439 QCOMPARE(item->data(Qt::BackgroundRole), QVariant());
1440 QCOMPARE(item->data(Qt::ForegroundRole), QVariant());
1441 QCOMPARE(item->data(Qt::SizeHintRole), QVariant());
1442}
1443
1444void tst_QTableWidget::cellWidget()
1445{
1446 QTableWidget table(10, 10);
1447 QWidget widget;
1448
1449 QCOMPARE(table.cellWidget(5, 5), nullptr);
1450 table.setCellWidget(row: 5, column: 5, widget: &widget);
1451 QCOMPARE(table.cellWidget(5, 5), &widget);
1452 table.removeCellWidget(arow: 5, acolumn: 5);
1453 QCOMPARE(table.cellWidget(5, 5), nullptr);
1454}
1455
1456void tst_QTableWidget::cellWidgetGeometry()
1457{
1458 QTableWidget tw(3,2);
1459 tw.show();
1460 // make sure the next row added is not completely visibile
1461 tw.resize(w: 300, h: tw.rowHeight(row: 0) * 3 + tw.rowHeight(row: 0) / 2);
1462 QVERIFY(QTest::qWaitForWindowExposed(&tw));
1463
1464 tw.scrollToBottom();
1465 tw.setRowCount(tw.rowCount() + 1);
1466 auto item = new QTableWidgetItem("Hello");
1467 tw.setItem(row: 0,column: 0,item);
1468 auto le = new QLineEdit("world");
1469 tw.setCellWidget(row: 0,column: 1,widget: le);
1470 // process delayedPendingLayout triggered by setting the row count
1471 tw.doItemsLayout();
1472 // so y pos is 0 for the first row
1473 tw.scrollToTop();
1474 // check if updateEditorGeometries has set the correct y pos for the editors
1475 QCOMPARE(tw.visualItemRect(item).top(), le->geometry().top());
1476}
1477
1478void tst_QTableWidget::sizeHint_data()
1479{
1480 QTest::addColumn<Qt::ScrollBarPolicy>(name: "scrollBarPolicy");
1481 QTest::addColumn<QSize>(name: "viewSize");
1482 QTest::newRow(dataTag: "ScrollBarAlwaysOn") << Qt::ScrollBarAlwaysOn << QSize();
1483 QTest::newRow(dataTag: "ScrollBarAlwaysOff") << Qt::ScrollBarAlwaysOff << QSize();
1484 // make sure the scrollbars are shown by resizing the view to 40x40
1485 QTest::newRow(dataTag: "ScrollBarAsNeeded (40x40)") << Qt::ScrollBarAsNeeded << QSize(40, 40);
1486 QTest::newRow(dataTag: "ScrollBarAsNeeded (1000x1000)") << Qt::ScrollBarAsNeeded << QSize(1000, 1000);
1487}
1488
1489void tst_QTableWidget::sizeHint()
1490{
1491 QFETCH(Qt::ScrollBarPolicy, scrollBarPolicy);
1492 QFETCH(QSize, viewSize);
1493
1494 QTableWidget view(2, 2);
1495 view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
1496 view.setVerticalScrollBarPolicy(scrollBarPolicy);
1497 view.setHorizontalScrollBarPolicy(scrollBarPolicy);
1498 for (int r = 0 ; r < view.rowCount(); ++r) {
1499 const QString rStr = QString::number(r) + QLatin1Char('/');
1500 for (int c = 0 ; c < view.columnCount(); ++c)
1501 view.setItem(row: r, column: c, item: new QTableWidgetItem(rStr + QString::number(c)));
1502 }
1503
1504 view.show();
1505 QVERIFY(QTest::qWaitForWindowExposed(&view));
1506 if (viewSize.isValid()) {
1507 view.resize(viewSize);
1508 view.setColumnWidth(column: 0, width: 100);
1509 view.setRowHeight(row: 0, height: 100);
1510 QTRY_COMPARE(view.size(), viewSize);
1511 }
1512
1513 auto sizeHint = view.sizeHint();
1514 view.hide();
1515 QCOMPARE(view.sizeHint(), sizeHint);
1516
1517 view.horizontalHeader()->hide();
1518 view.show();
1519 sizeHint = view.sizeHint();
1520 view.hide();
1521 QCOMPARE(view.sizeHint(), sizeHint);
1522
1523 view.verticalHeader()->hide();
1524 view.show();
1525 sizeHint = view.sizeHint();
1526 view.hide();
1527 QCOMPARE(view.sizeHint(), sizeHint);
1528}
1529
1530void tst_QTableWidget::task231094()
1531{
1532 QTableWidget tw(5, 3);
1533 for (int x = 0; x < 3; x++) {
1534 for (int y = 0; y < 5; y++) {
1535 QTableWidgetItem *twi = new QTableWidgetItem(QLatin1String("1"));
1536 if (y == 1)
1537 twi->setFlags(Qt::ItemIsEnabled);
1538 else
1539 twi->setFlags({});
1540 tw.setItem(row: y, column: x, item: twi);
1541 }
1542 }
1543
1544 tw.setCurrentCell(row: 1, column: 1);
1545 QCOMPARE(tw.currentRow(), 1);
1546 QCOMPARE(tw.currentColumn(), 1);
1547
1548 //this would provoke a end-less loop
1549 QTest::keyClick(widget: &tw, key: '1');
1550
1551 //all the items are disabled: the current item shouldn't have changed
1552 QCOMPARE(tw.currentRow(), 1);
1553 QCOMPARE(tw.currentColumn(), 1);
1554}
1555
1556void tst_QTableWidget::task219380_removeLastRow()
1557{
1558 testWidget->setColumnCount(1);
1559 testWidget->setRowCount(20);
1560 QTableWidgetItem item;
1561 testWidget->setItem(row: 18, column: 0, item: &item); //we put the item in the second last row
1562 testWidget->openPersistentEditor(item: &item);
1563
1564 testWidget->scrollToBottom();
1565
1566 testWidget->removeRow(row: 19); //we remove the last row
1567
1568 //we make sure the editor is at the cell position
1569 QTRY_COMPARE(testWidget->cellWidget(18, 0)->geometry(), testWidget->visualItemRect(&item));
1570}
1571
1572void tst_QTableWidget::task262056_sortDuplicate()
1573{
1574 testWidget->setColumnCount(2);
1575 testWidget->setRowCount(8);
1576 testWidget->setSortingEnabled(true);
1577 const QStringList items({"AAA", "BBB", "CCC", "CCC", "DDD",
1578 "EEE", "FFF", "GGG"});
1579 for (int i = 0; i < 8; i++ ) {
1580 QTableWidgetItem *twi = new QTableWidgetItem(items.at(i));
1581 testWidget->setItem(row: i, column: 0, item: twi);
1582 testWidget->setItem(row: i, column: 1, item: new QTableWidgetItem(QLatin1String("item ") + QString::number(i)));
1583 }
1584 testWidget->sortItems(column: 0, order: Qt::AscendingOrder);
1585 QSignalSpy layoutChangedSpy(testWidget->model(), &QAbstractItemModel::layoutChanged);
1586 testWidget->item(row: 3,column: 0)->setBackground(Qt::red);
1587
1588 QCOMPARE(layoutChangedSpy.count(),0);
1589
1590}
1591
1592void tst_QTableWidget::itemWithHeaderItems()
1593{
1594 // Need a separate testcase for this because the tst_QTableWidget::item testcase
1595 // does creates QTableWidgetItems for each available cell in the table. We're testing
1596 // the case of not all available cells having a QTableWidgetItem set.
1597 QTableWidget table(2, 1);
1598
1599 QTableWidgetItem *item0_0 = new QTableWidgetItem(QTableWidgetItem::UserType);
1600 table.setItem(row: 0, column: 0, item: item0_0);
1601
1602 QTableWidgetItem *item1_0 = new QTableWidgetItem(QTableWidgetItem::UserType);
1603 table.setItem(row: 1, column: 0, item: item1_0);
1604
1605 QCOMPARE(table.item(0, 1), nullptr);
1606}
1607
1608class TestTableWidget : public QTableWidget
1609{
1610 Q_OBJECT
1611public:
1612 using QTableWidget::QTableWidget;
1613 using QTableWidget::mimeData;
1614 using QTableWidget::indexFromItem;
1615 using QTableWidget::keyPressEvent;
1616};
1617
1618void tst_QTableWidget::mimeData()
1619{
1620 TestTableWidget table(10, 10);
1621
1622 for (int x = 0; x < 10; ++x) {
1623 for (int y = 0; y < 10; ++y) {
1624 QTableWidgetItem *item = new QTableWidgetItem(QStringLiteral("123"));
1625 table.setItem(row: y, column: x, item);
1626 }
1627 }
1628
1629 QList<QTableWidgetItem *> tableWidgetItemList;
1630 QModelIndexList modelIndexList;
1631
1632 // do these checks more than once to ensure that the "cached indexes" work as expected
1633 QVERIFY(!table.mimeData(tableWidgetItemList));
1634 QVERIFY(!table.model()->mimeData(modelIndexList));
1635 QVERIFY(!table.model()->mimeData(modelIndexList));
1636 QVERIFY(!table.mimeData(tableWidgetItemList));
1637
1638 tableWidgetItemList << table.item(row: 1, column: 1);
1639 modelIndexList << table.indexFromItem(item: table.item(row: 1, column: 1));
1640
1641 QMimeData *data;
1642
1643 QVERIFY((data = table.mimeData(tableWidgetItemList)));
1644 delete data;
1645
1646 QVERIFY((data = table.model()->mimeData(modelIndexList)));
1647 delete data;
1648
1649 QVERIFY((data = table.model()->mimeData(modelIndexList)));
1650 delete data;
1651
1652 QVERIFY((data = table.mimeData(tableWidgetItemList)));
1653 delete data;
1654
1655 // check the saved data is actually the same
1656
1657 QMimeData *data2;
1658
1659 data = table.mimeData(items: tableWidgetItemList);
1660 data2 = table.model()->mimeData(indexes: modelIndexList);
1661
1662 const QString format = QStringLiteral("application/x-qabstractitemmodeldatalist");
1663
1664 QVERIFY(data->hasFormat(format));
1665 QVERIFY(data2->hasFormat(format));
1666 QCOMPARE(data->data(format), data2->data(format));
1667
1668 delete data;
1669 delete data2;
1670}
1671
1672void tst_QTableWidget::selectedRowAfterSorting()
1673{
1674 TestTableWidget table(3,3);
1675 table.setSelectionBehavior(QAbstractItemView::SelectRows);
1676 for (int r = 0; r < 3; r++) {
1677 for (int c = 0; c < 3; c++)
1678 table.setItem(row: r, column: c, item: new QTableWidgetItem(QStringLiteral("0")));
1679 }
1680 QHeaderView *localHorizontalHeader = table.horizontalHeader();
1681 localHorizontalHeader->setSortIndicator(logicalIndex: 1,order: Qt::DescendingOrder);
1682 table.setProperty(name: "sortingEnabled",value: true);
1683 table.selectRow(row: 1);
1684 table.item(row: 1,column: 1)->setText("9");
1685 QCOMPARE(table.selectedItems().count(),3);
1686 const auto selectedItems = table.selectedItems();
1687 for (QTableWidgetItem *item : selectedItems)
1688 QCOMPARE(item->row(), 0);
1689}
1690
1691void tst_QTableWidget::search()
1692{
1693 auto createItem = [](const QString &txt)
1694 {
1695 auto item = new QTableWidgetItem(txt);
1696 item->setFlags(item->flags().setFlag(flag: Qt::ItemIsEditable, on: false));
1697 return item;
1698 };
1699
1700 auto checkSeries = [](TestTableWidget &tw, const QVector<QPair<QKeyEvent, int>> &series)
1701 {
1702 for (const auto &p : series) {
1703 QKeyEvent e = p.first;
1704 tw.keyPressEvent(event: &e);
1705 QVERIFY(tw.selectionModel()->isSelected(tw.model()->index(p.second, 0)));
1706 }
1707 };
1708 TestTableWidget tw(5, 1);
1709 tw.setItem(row: 0, column: 0, item: createItem("12"));
1710 tw.setItem(row: 1, column: 0, item: createItem("123"));
1711 tw.setItem(row: 2, column: 0, item: createItem("123 4"));
1712 tw.setItem(row: 3, column: 0, item: createItem("123 5"));
1713 tw.setItem(row: 4, column: 0, item: createItem(" "));
1714 tw.show();
1715
1716 QKeyEvent evSpace(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier, " ");
1717 QKeyEvent ev1(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier, "1");
1718 QKeyEvent ev2(QEvent::KeyPress, Qt::Key_2, Qt::NoModifier, "2");
1719 QKeyEvent ev3(QEvent::KeyPress, Qt::Key_3, Qt::NoModifier, "3");
1720 QKeyEvent ev4(QEvent::KeyPress, Qt::Key_4, Qt::NoModifier, "4");
1721 QKeyEvent ev5(QEvent::KeyPress, Qt::Key_5, Qt::NoModifier, "5");
1722
1723 checkSeries(tw, {{evSpace, 4}, {ev1, 4}});
1724 QTest::qWait(ms: QApplication::keyboardInputInterval() * 2);
1725 checkSeries(tw, {{ev1, 0}, {ev2, 0}, {ev3, 1}, {evSpace, 2}, {ev5, 3}});
1726 QTest::qWait(ms: QApplication::keyboardInputInterval() * 2);
1727 checkSeries(tw, {{ev1, 0}, {ev2, 0}, {ev3, 1}, {evSpace, 2}, {ev4, 2}});
1728}
1729
1730#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1731void tst_QTableWidget::clearItemData()
1732{
1733 QTableWidget table(3, 3);
1734 for (int r = 0; r < 3; r++) {
1735 for (int c = 0; c < 3; c++)
1736 table.setItem(r, c, new QTableWidgetItem(QStringLiteral("0")));
1737 }
1738 QSignalSpy dataChangeSpy(table.model(), &QAbstractItemModel::dataChanged);
1739 QVERIFY(dataChangeSpy.isValid());
1740 QVERIFY(!table.model()->clearItemData(QModelIndex()));
1741 QCOMPARE(dataChangeSpy.size(), 0);
1742 QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
1743 QVERIFY(!table.model()->index(0, 0).data().isValid());
1744 QCOMPARE(dataChangeSpy.size(), 1);
1745 const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
1746 QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), table.model()->index(0, 0));
1747 QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), table.model()->index(0, 0));
1748 QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
1749 QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
1750 QCOMPARE(dataChangeSpy.size(), 0);
1751}
1752#endif
1753
1754QTEST_MAIN(tst_QTableWidget)
1755#include "tst_qtablewidget.moc"
1756

source code of qtbase/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp