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 <QtGui/QtGui>
44 #include <private/qtablewidget_p.h>
45 #include <QtTest/QtTest>
46 #include "../../shared/util.h"
47 #include "private/qapplication_p.h"
48 
49 //TESTED_CLASS=
50 //TESTED_FILES=
51 
52 // Will try to wait for the condition while allowing event processing
53 // for a maximum of 2 seconds.
54 #define WAIT_FOR_CONDITION(expr, expected) \
55     do { \
56         const int step = 100; \
57         for (int i = 0; i < 2000 && expr != expected; i+=step) { \
58             QTest::qWait(step); \
59         } \
60     } while(0)
61 
62 #ifdef QT_BUILD_INTERNAL
63 #define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) \
64     QVERIFY(static_cast<QTableViewPrivate*>(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency())
65 #else
66 #define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) (void)false
67 #endif
68 
69 typedef QList<int> IntList;
70 Q_DECLARE_METATYPE(IntList)
71 
72 typedef QList<bool> BoolList;
73 Q_DECLARE_METATYPE(BoolList)
74 
75 class tst_QTableView : public QObject
76 {
77     Q_OBJECT
78 
79 public:
80     tst_QTableView();
81     virtual ~tst_QTableView();
82 
83 public slots:
84     void initTestCase();
85     void cleanupTestCase();
86     void init();
87     void cleanup();
88 
89 private slots:
90     void getSetCheck();
91 
92     void noDelegate();
93     void noModel();
94     void emptyModel();
95 
96     void removeRows_data();
97     void removeRows();
98 
99     void removeColumns_data();
100     void removeColumns();
101 
102     void keyboardNavigation_data();
103     void keyboardNavigation();
104 
105     void headerSections_data();
106     void headerSections();
107 
108     void moveCursor_data();
109     void moveCursor();
110 
111     void moveCursorStrikesBack_data();
112     void moveCursorStrikesBack();
113 
114     void hideRows_data();
115     void hideRows();
116 
117     void hideColumns_data();
118     void hideColumns();
119 
120     void selection_data();
121     void selection();
122 
123     void selectRow_data();
124     void selectRow();
125 
126     void selectColumn_data();
127     void selectColumn();
128 
129     void visualRect_data();
130     void visualRect();
131 
132     void fetchMore();
133     void setHeaders();
134 
135     void resizeRowsToContents_data();
136     void resizeRowsToContents();
137 
138     void resizeColumnsToContents_data();
139     void resizeColumnsToContents();
140 
141     void rowViewportPosition_data();
142     void rowViewportPosition();
143 
144     void rowAt_data();
145     void rowAt();
146 
147     void rowHeight_data();
148     void rowHeight();
149 
150     void columnViewportPosition_data();
151     void columnViewportPosition();
152 
153     void columnAt_data();
154     void columnAt();
155 
156     void columnWidth_data();
157     void columnWidth();
158 
159     void hiddenRow_data();
160     void hiddenRow();
161 
162     void hiddenColumn_data();
163     void hiddenColumn();
164 
165     void sortingEnabled_data();
166     void sortingEnabled();
167 
168     void scrollTo_data();
169     void scrollTo();
170 
171     void indexAt_data();
172     void indexAt();
173 
174     void span_data();
175     void span();
176     void spans();
177     void spans_data();
178     void spansAfterRowInsertion();
179     void spansAfterColumnInsertion();
180     void spansAfterRowRemoval();
181     void spansAfterColumnRemoval();
182 
183     void checkHeaderReset();
184     void checkHeaderMinSize();
185 
186     void resizeToContents();
187 
188     void tabFocus();
189     void bigModel();
190     void selectionSignal();
191 
192     // task-specific tests:
193     void task173773_updateVerticalHeader();
194     void task227953_setRootIndex();
195     void task240266_veryBigColumn();
196     void task248688_autoScrollNavigation();
197     void task259308_scrollVerticalHeaderSwappedSections();
198     void task191545_dragSelectRows();
199     void taskQTBUG_5062_spansInconsistency();
200     void taskQTBUG_4516_clickOnRichTextLabel();
201     void taskQTBUG_5237_wheelEventOnHeader();
202     void taskQTBUG_8585_crashForNoGoodReason();
203     void taskQTBUG_7774_RtoLVisualRegionForSelection();
204     void taskQTBUG_8777_scrollToSpans();
205     void taskQTBUG_10169_sizeHintForRow();
206     void taskQTBUG_30653_doItemsLayout();
207 
208     void mouseWheel_data();
209     void mouseWheel();
210 
211     void addColumnWhileEditing();
212     void task234926_setHeaderSorting();
213 
214     void changeHeaderData();
215 };
216 
217 // Testing get/set functions
getSetCheck()218 void tst_QTableView::getSetCheck()
219 {
220     QTableView obj1;
221 
222     obj1.setSortingEnabled(false);
223     QCOMPARE(false, obj1.isSortingEnabled());
224     obj1.setSortingEnabled(true);
225     QCOMPARE(true, obj1.isSortingEnabled());
226 
227     obj1.setShowGrid(false);
228     QCOMPARE(false, obj1.showGrid());
229     obj1.setShowGrid(true);
230     QCOMPARE(true, obj1.showGrid());
231 
232     obj1.setGridStyle(Qt::NoPen);
233     QCOMPARE(Qt::NoPen, obj1.gridStyle());
234     obj1.setGridStyle(Qt::SolidLine);
235     QCOMPARE(Qt::SolidLine, obj1.gridStyle());
236 
237     obj1.setRootIndex(QModelIndex());
238     QCOMPARE(QModelIndex(), obj1.rootIndex());
239     QStandardItemModel model(10, 10);
240     obj1.setModel(&model);
241     QModelIndex index = model.index(0, 0);
242     obj1.setRootIndex(index);
243     QCOMPARE(index, obj1.rootIndex());
244 
245     QHeaderView *var1 = new QHeaderView(Qt::Horizontal);
246     obj1.setHorizontalHeader(var1);
247     QCOMPARE(var1, obj1.horizontalHeader());
248     obj1.setHorizontalHeader((QHeaderView *)0);
249     QCOMPARE(var1, obj1.horizontalHeader());
250     delete var1;
251 
252     QHeaderView *var2 = new QHeaderView(Qt::Vertical);
253     obj1.setVerticalHeader(var2);
254     QCOMPARE(var2, obj1.verticalHeader());
255     obj1.setVerticalHeader((QHeaderView *)0);
256     QCOMPARE(var2, obj1.verticalHeader());
257     delete var2;
258 
259     QCOMPARE(obj1.isCornerButtonEnabled(), true);
260     obj1.setCornerButtonEnabled(false);
261     QCOMPARE(obj1.isCornerButtonEnabled(), false);
262 }
263 
264 class QtTestTableModel: public QAbstractTableModel
265 {
266     Q_OBJECT
267 
268 signals:
269     void invalidIndexEncountered() const;
270 
271 public:
QtTestTableModel(int rows=0,int columns=0,QObject * parent=0)272     QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = 0)
273         : QAbstractTableModel(parent),
274           row_count(rows),
275           column_count(columns),
276           can_fetch_more(false),
277           fetch_more_count(0),
278           disabled_rows(),
279           disabled_columns() {}
280 
rowCount(const QModelIndex &=QModelIndex ()) const281     int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; }
columnCount(const QModelIndex &=QModelIndex ()) const282     int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; }
isEditable(const QModelIndex &) const283     bool isEditable(const QModelIndex &) const { return true; }
284 
flags(const QModelIndex & index) const285     Qt::ItemFlags flags(const QModelIndex &index) const
286     {
287         Qt::ItemFlags index_flags = QAbstractTableModel::flags(index);
288         if (disabled_rows.contains(index.row())
289             || disabled_columns.contains(index.column()))
290             index_flags &= ~Qt::ItemIsEnabled;
291         return index_flags;
292     }
293 
disableRow(int row)294     void disableRow(int row)
295     {
296         disabled_rows.insert(row);
297     }
298 
enableRow(int row)299     void enableRow(int row)
300     {
301         disabled_rows.remove(row);
302     }
303 
disableColumn(int column)304     void disableColumn(int column)
305     {
306         disabled_columns.insert(column);
307     }
308 
enableColumn(int column)309     void enableColumn(int column)
310     {
311         disabled_columns.remove(column);
312     }
313 
data(const QModelIndex & idx,int role) const314     QVariant data(const QModelIndex &idx, int role) const
315     {
316         if (!idx.isValid() || idx.row() >= row_count || idx.column() >= column_count) {
317             qWarning() << "Invalid modelIndex [%d,%d,%p]" << idx;
318             emit invalidIndexEncountered();
319             return QVariant();
320         }
321 
322         if (role == Qt::DisplayRole || role == Qt::EditRole)
323             return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);
324 
325         return QVariant();
326     }
327 
insertRows(int start,int count,const QModelIndex & parent=QModelIndex ())328     bool insertRows(int start, int count, const QModelIndex &parent = QModelIndex())
329     {
330         if (start < 0 || start > row_count)
331             return false;
332 
333         beginInsertRows(parent, start, start + count - 1);
334         row_count += count;
335         endInsertRows();
336         return true;
337     }
338 
removeRows(int start,int count,const QModelIndex & parent=QModelIndex ())339     bool removeRows(int start, int count, const QModelIndex &parent = QModelIndex())
340     {
341         if (start < 0 || start >= row_count || row_count < count)
342             return false;
343 
344         beginRemoveRows(parent, start, start + count - 1);
345         row_count -= count;
346         endRemoveRows();
347         return true;
348     }
349 
removeLastRow()350     void removeLastRow()
351     {
352         beginRemoveRows(QModelIndex(), row_count - 1, row_count - 1);
353         --row_count;
354         endRemoveRows();
355     }
356 
removeAllRows()357     void removeAllRows()
358     {
359         beginRemoveRows(QModelIndex(), 0, row_count - 1);
360         row_count = 0;
361         endRemoveRows();
362     }
363 
insertColumns(int start,int count,const QModelIndex & parent=QModelIndex ())364     bool insertColumns(int start, int count, const QModelIndex &parent = QModelIndex())
365     {
366         if (start < 0 || start > column_count)
367             return false;
368 
369         beginInsertColumns(parent, start, start + count - 1);
370         column_count += count;
371         endInsertColumns();
372         return true;
373     }
374 
removeColumns(int start,int count,const QModelIndex & parent=QModelIndex ())375     bool removeColumns(int start, int count, const QModelIndex &parent = QModelIndex())
376     {
377         if (start < 0 || start >= column_count || column_count < count)
378             return false;
379 
380         beginRemoveColumns(parent, start, start + count - 1);
381         column_count -= count;
382         endRemoveColumns();
383         return true;
384     }
385 
removeLastColumn()386     void removeLastColumn()
387     {
388         beginRemoveColumns(QModelIndex(), column_count - 1, column_count - 1);
389         --column_count;
390         endRemoveColumns();
391     }
392 
removeAllColumns()393     void removeAllColumns()
394     {
395         beginRemoveColumns(QModelIndex(), 0, column_count - 1);
396         column_count = 0;
397         endRemoveColumns();
398     }
399 
canFetchMore(const QModelIndex &) const400     bool canFetchMore(const QModelIndex &) const
401     {
402         return can_fetch_more;
403     }
404 
fetchMore(const QModelIndex &)405     void fetchMore(const QModelIndex &)
406     {
407         ++fetch_more_count;
408     }
409 
reset()410     void reset()
411     {
412         QAbstractTableModel::reset();
413     }
414 
415     int row_count;
416     int column_count;
417     bool can_fetch_more;
418     int fetch_more_count;
419     QSet<int> disabled_rows;
420     QSet<int> disabled_columns;
421 };
422 
423 class QtTestTableView : public QTableView
424 {
425 Q_OBJECT
426 
427 public:
QtTestTableView(QWidget * parent=0)428     QtTestTableView(QWidget *parent = 0) : QTableView(parent), checkSignalOrder(false), hasCurrentChanged(0), hasSelectionChanged(0) {}
429 
setModel(QAbstractItemModel * model)430     void setModel(QAbstractItemModel *model)
431     {
432         QTableView::setModel(model);
433         connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
434                      this, SLOT(currentChanged(QModelIndex,QModelIndex)));
435         connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
436                      this, SLOT(itemSelectionChanged(QItemSelection,QItemSelection)));
437     }
438 
439     enum CursorAction {
440         MoveUp       = QAbstractItemView::MoveUp,
441         MoveDown     = QAbstractItemView::MoveDown,
442         MoveLeft     = QAbstractItemView::MoveLeft,
443         MoveRight    = QAbstractItemView::MoveRight,
444         MoveHome     = QAbstractItemView::MoveHome,
445         MoveEnd      = QAbstractItemView::MoveEnd,
446         MovePageUp   = QAbstractItemView::MovePageUp,
447         MovePageDown = QAbstractItemView::MovePageDown,
448         MoveNext     = QAbstractItemView::MoveNext,
449         MovePrevious = QAbstractItemView::MovePrevious
450     };
451 
moveCursor(QtTestTableView::CursorAction cursorAction,Qt::KeyboardModifiers modifiers)452     QModelIndex moveCursor(QtTestTableView::CursorAction cursorAction,
453                            Qt::KeyboardModifiers modifiers)
454     {
455         return QTableView::moveCursor((QAbstractItemView::CursorAction)cursorAction, modifiers);
456     }
457 
columnWidthHint(int column) const458     int columnWidthHint(int column) const
459     {
460         return sizeHintForColumn(column);
461     }
462 
rowHeightHint(int row) const463     int rowHeightHint(int row) const
464     {
465         return sizeHintForRow(row);
466     }
467 
isIndexHidden(const QModelIndex & index) const468     bool isIndexHidden(const QModelIndex &index) const
469     {
470         return QTableView::isIndexHidden(index);
471     }
472 
setSelection(const QRect & rect,QItemSelectionModel::SelectionFlags command)473     void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
474     {
475         QTableView::setSelection(rect, command);
476     }
477 
selectedIndexes() const478     QModelIndexList selectedIndexes() const
479     {
480         return QTableView::selectedIndexes();
481     }
482 
sizeHintForRow(int row) const483     int sizeHintForRow(int row) const
484     {
485         return QTableView::sizeHintForRow(row);
486     }
487 
488     bool checkSignalOrder;
489 public slots:
currentChanged(QModelIndex,QModelIndex)490     void currentChanged(QModelIndex , QModelIndex ) {
491         hasCurrentChanged++;
492         if (checkSignalOrder)
493             QVERIFY(hasCurrentChanged > hasSelectionChanged);
494     }
495 
itemSelectionChanged(QItemSelection,QItemSelection)496     void itemSelectionChanged(QItemSelection , QItemSelection ) {
497         hasSelectionChanged++;
498         if (checkSignalOrder)
499             QVERIFY(hasCurrentChanged >= hasSelectionChanged);
500     }
501 private:
502     int hasCurrentChanged;
503     int hasSelectionChanged;
504 
505 };
506 
507 class QtTestItemDelegate : public QItemDelegate
508 {
509 public:
sizeHint(const QStyleOptionViewItem &,const QModelIndex &) const510     QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const
511     {
512         return hint;
513     }
514 
515     QSize hint;
516 };
517 
tst_QTableView()518 tst_QTableView::tst_QTableView()
519 {
520 }
521 
~tst_QTableView()522 tst_QTableView::~tst_QTableView()
523 {
524 }
525 
initTestCase()526 void tst_QTableView::initTestCase()
527 {
528 #ifdef Q_OS_WINCE //disable magic for WindowsCE
529     qApp->setAutoMaximizeThreshold(-1);
530 #endif
531 }
532 
cleanupTestCase()533 void tst_QTableView::cleanupTestCase()
534 {
535 }
536 
init()537 void tst_QTableView::init()
538 {
539 }
540 
cleanup()541 void tst_QTableView::cleanup()
542 {
543 }
544 
noDelegate()545 void tst_QTableView::noDelegate()
546 {
547     QtTestTableModel model(3, 3);
548     QTableView view;
549     view.setModel(&model);
550     view.setItemDelegate(0);
551     view.show();
552 }
553 
noModel()554 void tst_QTableView::noModel()
555 {
556     QTableView view;
557     view.show();
558 }
559 
emptyModel()560 void tst_QTableView::emptyModel()
561 {
562     QtTestTableModel model;
563     QTableView view;
564     QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
565     view.setModel(&model);
566     view.show();
567     QCOMPARE(spy.count(), 0);
568 }
569 
removeRows_data()570 void tst_QTableView::removeRows_data()
571 {
572     QTest::addColumn<int>("rowCount");
573     QTest::addColumn<int>("columnCount");
574 
575     QTest::newRow("2x2") << 2 << 2;
576     QTest::newRow("10x10") << 10  << 10;
577 }
578 
removeRows()579 void tst_QTableView::removeRows()
580 {
581     QFETCH(int, rowCount);
582     QFETCH(int, columnCount);
583 
584     QtTestTableModel model(rowCount, columnCount);
585     QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
586 
587     QTableView view;
588     view.setModel(&model);
589     view.show();
590 
591     model.removeLastRow();
592     QCOMPARE(spy.count(), 0);
593 
594     model.removeAllRows();
595     QCOMPARE(spy.count(), 0);
596 }
597 
removeColumns_data()598 void tst_QTableView::removeColumns_data()
599 {
600     QTest::addColumn<int>("rowCount");
601     QTest::addColumn<int>("columnCount");
602 
603     QTest::newRow("2x2") << 2 << 2;
604     QTest::newRow("10x10") << 10  << 10;
605 }
606 
removeColumns()607 void tst_QTableView::removeColumns()
608 {
609     QFETCH(int, rowCount);
610     QFETCH(int, columnCount);
611 
612     QtTestTableModel model(rowCount, columnCount);
613     QSignalSpy spy(&model, SIGNAL(invalidIndexEncountered()));
614 
615     QTableView view;
616     view.setModel(&model);
617     view.show();
618 
619     model.removeLastColumn();
620     QCOMPARE(spy.count(), 0);
621 
622     model.removeAllColumns();
623     QCOMPARE(spy.count(), 0);
624 }
625 
keyboardNavigation_data()626 void tst_QTableView::keyboardNavigation_data()
627 {
628     QTest::addColumn<int>("rowCount");
629     QTest::addColumn<int>("columnCount");
630     QTest::addColumn<bool>("tabKeyNavigation");
631     QTest::addColumn<IntList>("keyPresses");
632 
633     QTest::newRow("16x16 model") << 16  << 16 << true
634                                  << (IntList()
635                                      << Qt::Key_Up
636                                      << Qt::Key_Up
637                                      << Qt::Key_Right
638                                      << Qt::Key_Right
639                                      << Qt::Key_Up
640                                      << Qt::Key_Left
641                                      << Qt::Key_Left
642                                      << Qt::Key_Up
643                                      << Qt::Key_Down
644                                      << Qt::Key_Up
645                                      << Qt::Key_Up
646                                      << Qt::Key_Up
647                                      << Qt::Key_Up
648                                      << Qt::Key_Up
649                                      << Qt::Key_Up
650                                      << Qt::Key_Left
651                                      << Qt::Key_Left
652                                      << Qt::Key_Up
653                                      << Qt::Key_Down
654                                      << Qt::Key_Down
655                                      << Qt::Key_Tab
656                                      << Qt::Key_Backtab);
657 
658 
659     QTest::newRow("no tab") << 8  << 8 <<  false
660                                  << (IntList()
661                                      << Qt::Key_Up
662                                      << Qt::Key_Up
663                                      << Qt::Key_Right
664                                      << Qt::Key_Right
665                                      << Qt::Key_Up
666                                      << Qt::Key_Left
667                                      << Qt::Key_Left
668                                      << Qt::Key_Up
669                                      << Qt::Key_Down
670                                      << Qt::Key_Up
671                                      << Qt::Key_Up
672                                      << Qt::Key_Up
673                                      << Qt::Key_Up
674                                      << Qt::Key_Up
675                                      << Qt::Key_Up
676                                      << Qt::Key_Left
677                                      << Qt::Key_Left
678                                      << Qt::Key_Up
679                                      << Qt::Key_Down
680                                      << Qt::Key_Down
681                                      << Qt::Key_Tab
682                                      << Qt::Key_Backtab);
683 }
684 
keyboardNavigation()685 void tst_QTableView::keyboardNavigation()
686 {
687     QFETCH(int, rowCount);
688     QFETCH(int, columnCount);
689     QFETCH(bool, tabKeyNavigation);
690     QFETCH(IntList, keyPresses);
691 
692     QtTestTableModel model(rowCount, columnCount);
693     QTableView view;
694     view.setModel(&model);
695 
696     view.setTabKeyNavigation(tabKeyNavigation);
697     QModelIndex index = model.index(rowCount - 1, columnCount - 1);
698     view.setCurrentIndex(index);
699 
700     view.show();
701     QTest::qWaitForWindowShown(&view);
702     qApp->setActiveWindow(&view);
703 
704     int row = rowCount - 1;
705     int column = columnCount - 1;
706     for (int i = 0; i < keyPresses.count(); ++i) {
707 
708         Qt::Key key = (Qt::Key)keyPresses.at(i);
709 
710         switch (key) {
711         case Qt::Key_Up:
712             row = qMax(0, row - 1);
713             break;
714         case Qt::Key_Down:
715             row = qMin(rowCount - 1, row + 1);
716             break;
717         case Qt::Key_Backtab:
718             if (!tabKeyNavigation)
719                 break;
720         case Qt::Key_Left:
721             column = qMax(0, column - 1);
722             break;
723         case Qt::Key_Tab:
724             if (!tabKeyNavigation)
725                 break;
726         case Qt::Key_Right:
727             column = qMin(columnCount - 1, column + 1);
728             break;
729         default:
730             break;
731         }
732 
733         QTest::keyClick(&view, key);
734         QApplication::processEvents();
735 
736         QModelIndex index = model.index(row, column);
737         QCOMPARE(view.currentIndex(), index);
738     }
739 }
740 
headerSections_data()741 void tst_QTableView::headerSections_data()
742 {
743     QTest::addColumn<int>("rowCount");
744     QTest::addColumn<int>("columnCount");
745     QTest::addColumn<int>("row");
746     QTest::addColumn<int>("column");
747     QTest::addColumn<int>("rowHeight");
748     QTest::addColumn<int>("columnWidth");
749 
750     QTest::newRow("") << 10 << 10 << 5 << 5 << 30 << 30;
751 }
752 
headerSections()753 void tst_QTableView::headerSections()
754 {
755     QFETCH(int, rowCount);
756     QFETCH(int, columnCount);
757     QFETCH(int, row);
758     QFETCH(int, column);
759     QFETCH(int, rowHeight);
760     QFETCH(int, columnWidth);
761 
762     QtTestTableModel model(rowCount, columnCount);
763 
764     QTableView view;
765     QHeaderView *hheader = view.horizontalHeader();
766     QHeaderView *vheader = view.verticalHeader();
767 
768     view.setModel(&model);
769     view.show();
770 
771     hheader->doItemsLayout();
772     vheader->doItemsLayout();
773 
774     QCOMPARE(hheader->count(), model.columnCount());
775     QCOMPARE(vheader->count(), model.rowCount());
776 
777     view.setRowHeight(row, rowHeight);
778     QCOMPARE(view.rowHeight(row), rowHeight);
779     view.hideRow(row);
780     QCOMPARE(view.rowHeight(row), 0);
781     view.showRow(row);
782     QCOMPARE(view.rowHeight(row), rowHeight);
783 
784     view.setColumnWidth(column, columnWidth);
785     QCOMPARE(view.columnWidth(column), columnWidth);
786     view.hideColumn(column);
787     QCOMPARE(view.columnWidth(column), 0);
788     view.showColumn(column);
789     QCOMPARE(view.columnWidth(column), columnWidth);
790 }
791 
792 typedef QPair<int,int> IntPair;
Q_DECLARE_METATYPE(IntPair)793 Q_DECLARE_METATYPE(IntPair)
794 
795 void tst_QTableView::moveCursor_data()
796 {
797     QTest::addColumn<int>("rowCount");
798     QTest::addColumn<int>("columnCount");
799     QTest::addColumn<int>("hideRow");
800     QTest::addColumn<int>("hideColumn");
801 
802     QTest::addColumn<int>("startRow");
803     QTest::addColumn<int>("startColumn");
804 
805     QTest::addColumn<int>("cursorMoveAction");
806     QTest::addColumn<int>("modifier");
807 
808     QTest::addColumn<int>("expectedRow");
809     QTest::addColumn<int>("expectedColumn");
810     QTest::addColumn<IntPair>("moveRow");
811     QTest::addColumn<IntPair>("moveColumn");
812 
813     // MoveRight
814     QTest::newRow("MoveRight (0,0)")
815         << 4 << 4 << -1 << -1
816         << 0 << 0
817         << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
818         << 0 << 1 << IntPair(0,0) << IntPair(0,0);
819 
820     QTest::newRow("MoveRight (3,0)")
821         << 4 << 4 << -1 << -1
822         << 3 << 0
823         << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
824         << 3 << 1 << IntPair(0,0) << IntPair(0,0);
825 
826     QTest::newRow("MoveRight (3,3)")
827         << 4 << 4 << -1 << -1
828         << 3 << 3
829         << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
830         << 3 << 3 << IntPair(0,0) << IntPair(0,0); // ###
831 
832     QTest::newRow("MoveRight, hidden column 1 (0,0)")
833         << 4 << 4 << -1 << 1
834         << 0 << 0
835         << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
836         << 0 << 2 << IntPair(0,0) << IntPair(0,0);
837 
838     QTest::newRow("MoveRight, hidden column 3 (0,2)")
839         << 4 << 4 << -1 << 3
840         << 0 << 2
841         << int(QtTestTableView::MoveRight) << int(Qt::NoModifier)
842         << 0 << 2 << IntPair(0,0) << IntPair(0,0); // ###
843 
844     // MoveNext should in addition wrap
845     QTest::newRow("MoveNext (0,0)")
846         << 4 << 4 << -1 << -1
847         << 0 << 0
848         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
849         << 0 << 1 << IntPair(0,0) << IntPair(0,0);
850 
851     QTest::newRow("MoveNext (0,2)")
852         << 4 << 4 << -1 << -1
853         << 0 << 2
854         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
855         << 0 << 3 << IntPair(0,0) << IntPair(0,0);
856 
857     QTest::newRow("MoveNext, wrap (0,3)")
858         << 4 << 4 << -1 << -1
859         << 0 << 3
860         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
861         << 1 << 0 << IntPair(0,0) << IntPair(0,0);
862 
863     QTest::newRow("MoveNext, wrap (3,3)")
864         << 4 << 4 << -1 << -1
865         << 3 << 3
866         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
867         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
868 
869     QTest::newRow("MoveNext, hidden column 1 (0,0)")
870         << 4 << 4 << -1 << 1
871         << 0 << 0
872         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
873         << 0 << 2 << IntPair(0,0) << IntPair(0,0);
874 
875     QTest::newRow("MoveNext, wrap, hidden column 3 (0,2)")
876         << 4 << 4 << -1 << 3
877         << 0 << 2
878         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
879         << 1 << 0 << IntPair(0,0) << IntPair(0,0);
880 
881     QTest::newRow("MoveNext, wrap, hidden column 3 (3,2)")
882         << 4 << 4 << -1 << 3
883         << 3 << 2
884         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
885         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
886 
887     QTest::newRow("MoveNext, wrapy, wrapx, hidden column 3, hidden row 3 (2,2)")
888         << 4 << 4 << 3 << 3
889         << 2 << 2
890         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
891         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
892 
893     QTest::newRow("MoveNext, wrap, hidden column 2, moved column from 3 to 0. (0,2)")
894         << 4 << 4 << -1 << 2
895         << 0 << 2
896         << int(QtTestTableView::MoveNext) << int(Qt::NoModifier)
897         << 1 << 3 << IntPair(0,0) << IntPair(3,0);
898 
899     // MoveLeft
900     QTest::newRow("MoveLeft (0,0)")
901         << 4 << 4 << -1 << -1
902         << 0 << 0
903         << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
904         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
905 
906     QTest::newRow("MoveLeft (0,3)")
907         << 4 << 4 << -1 << -1
908         << 0 << 3
909         << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
910         << 0 << 2 << IntPair(0,0) << IntPair(0,0);
911 
912     QTest::newRow("MoveLeft (1,0)")
913         << 4 << 4 << -1 << -1
914         << 1 << 0
915         << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
916         << 1 << 0 << IntPair(0,0) << IntPair(0,0);
917 
918     QTest::newRow("MoveLeft, hidden column 0 (0,2)")
919         << 4 << 4 << -1 << 1
920         << 0 << 2
921         << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
922         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
923 
924     QTest::newRow("MoveLeft, hidden column 0 (0,1)")
925         << 4 << 4 << -1 << 0
926         << 0 << 1
927         << int(QtTestTableView::MoveLeft) << int(Qt::NoModifier)
928         << 0 << 1 << IntPair(0,0) << IntPair(0,0);
929 
930     // MovePrevious should in addition wrap
931     QTest::newRow("MovePrevious (0,3)")
932         << 4 << 4 << -1 << -1
933         << 0 << 3
934         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
935         << 0 << 2 << IntPair(0,0) << IntPair(0,0);
936 
937     QTest::newRow("MovePrevious (0,1)")
938         << 4 << 4 << -1 << -1
939         << 0 << 1
940         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
941         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
942 
943     QTest::newRow("MovePrevious, wrap (1,0)")
944         << 4 << 4 << -1 << -1
945         << 1 << 0
946         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
947         << 0 << 3 << IntPair(0,0) << IntPair(0,0);
948 
949     QTest::newRow("MovePrevious, wrap, (0,0)")
950         << 4 << 4 << -1 << -1
951         << 0 << 0
952         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
953         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
954 
955     QTest::newRow("MovePrevious, hidden column 1 (0,2)")
956         << 4 << 4 << -1 << 1
957         << 0 << 2
958         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
959         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
960 
961     QTest::newRow("MovePrevious, wrap, hidden column 3 (0,2)")
962         << 4 << 4 << -1 << 3
963         << 0 << 2
964         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
965         << 0 << 1 << IntPair(0,0) << IntPair(0,0);
966 
967     QTest::newRow("MovePrevious, wrapy, hidden column 0 (0,1)")
968         << 4 << 4 << -1 << 0
969         << 0 << 1
970         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
971         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
972 
973     QTest::newRow("MovePrevious, wrap, hidden column 0, hidden row 0 (1,1)")
974         << 4 << 4 << 0 << 0
975         << 1 << 1
976         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
977         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
978 
979     QTest::newRow("MovePrevious, wrap, hidden column 1, moved column from 0 to 3. (1,2)")
980         << 4 << 4 << -1 << 1
981         << 1 << 2
982         << int(QtTestTableView::MovePrevious) << int(Qt::NoModifier)
983         << 0 << 0 << IntPair(0,0) << IntPair(0,3);
984 
985     // MoveDown
986     QTest::newRow("MoveDown (0,0)")
987         << 4 << 4 << -1 << -1
988         << 0 << 0
989         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
990         << 1 << 0 << IntPair(0,0) << IntPair(0,0);
991 
992     QTest::newRow("MoveDown (3,0)")
993         << 4 << 4 << -1 << -1
994         << 3 << 0
995         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
996         << 3 << 0 << IntPair(0,0) << IntPair(0,0);
997 
998     QTest::newRow("MoveDown (3,3)")
999         << 4 << 4 << -1 << -1
1000         << 3 << 3
1001         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
1002         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1003 
1004     QTest::newRow("MoveDown, hidden row 1 (0,0)")
1005         << 4 << 4 << 1 << -1
1006         << 0 << 0
1007         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
1008         << 2 << 0 << IntPair(0,0) << IntPair(0,0);
1009 
1010     QTest::newRow("MoveDown, hidden row 3 (2,0)")
1011         << 4 << 4 << 3 << -1
1012         << 2 << 0
1013         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
1014         << 2 << 0 << IntPair(0,0) << IntPair(0,0);
1015 
1016     QTest::newRow("MoveDown, hidden row 0 hidden column 0 (0,0)")
1017         << 4 << 4 << 0 << 0
1018         << 0 << 0
1019         << int(QtTestTableView::MoveDown) << int(Qt::NoModifier)
1020         << 1 << 1 << IntPair(0,0) << IntPair(0,0);
1021 
1022     // MoveUp
1023     QTest::newRow("MoveUp (0,0)")
1024         << 4 << 4 << -1 << -1
1025         << 0 << 0
1026         << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
1027         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1028 
1029     QTest::newRow("MoveUp (3, 0)")
1030         << 4 << 4 << -1 << -1
1031         << 3 << 0
1032         << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
1033         << 2 << 0 << IntPair(0,0) << IntPair(0,0);
1034 
1035     QTest::newRow("MoveUp (0,1)")
1036         << 4 << 4 << -1 << -1
1037         << 0 << 1
1038         << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
1039         << 0 << 1 << IntPair(0,0) << IntPair(0,0);
1040 
1041     QTest::newRow("MoveUp, hidden row 1 (2,0)")
1042         << 4 << 4 << 1 << -1
1043         << 2 << 0
1044         << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
1045         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1046 
1047     QTest::newRow("MoveUp, hidden row (1,0)")
1048         << 4 << 4 << 0 << -1
1049         << 1 << 0
1050         << int(QtTestTableView::MoveUp) << int(Qt::NoModifier)
1051         << 1 << 0 << IntPair(0,0) << IntPair(0,0);
1052 
1053     // MoveHome
1054     QTest::newRow("MoveHome (0,0)")
1055         << 4 << 4 << -1 << -1
1056         << 0 << 0
1057         << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
1058         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1059 
1060     QTest::newRow("MoveHome (3,3)")
1061         << 4 << 4 << -1 << -1
1062         << 3 << 3
1063         << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
1064         << 3 << 0 << IntPair(0,0) << IntPair(0,0);
1065 
1066     QTest::newRow("MoveHome, hidden column 0 (3,3)")
1067         << 4 << 4 << -1 << 0
1068         << 3 << 3
1069         << int(QtTestTableView::MoveHome) << int(Qt::NoModifier)
1070         << 3 << 1 << IntPair(0,0) << IntPair(0,0);
1071 
1072     // Use Ctrl modifier
1073     QTest::newRow("MoveHome + Ctrl (0,0)")
1074         << 4 << 4 << -1 << -1
1075         << 0 << 0
1076         << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
1077         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1078 
1079     QTest::newRow("MoveHome + Ctrl (3,3)")
1080         << 4 << 4 << -1 << -1
1081         << 3 << 3
1082         << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
1083         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1084 
1085     QTest::newRow("MoveHome + Ctrl, hidden column 0, hidden row 0 (3,3)")
1086         << 4 << 4 << 0 << 0
1087         << 3 << 3
1088         << int(QtTestTableView::MoveHome) << int(Qt::ControlModifier)
1089         << 1 << 1 << IntPair(0,0) << IntPair(0,0);
1090 
1091     // MoveEnd
1092     QTest::newRow("MoveEnd (0,0)")
1093         << 4 << 4 << -1 << -1
1094         << 0 << 0
1095         << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
1096         << 0 << 3 << IntPair(0,0) << IntPair(0,0);
1097 
1098     QTest::newRow("MoveEnd (3,3)")
1099         << 4 << 4 << -1 << -1
1100         << 3 << 3
1101         << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
1102         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1103 
1104     QTest::newRow("MoveEnd, hidden column (0,0)")
1105         << 4 << 4 << -1 << 3
1106         << 0 << 0
1107         << int(QtTestTableView::MoveEnd) << int(Qt::NoModifier)
1108         << 0<< 2 << IntPair(0,0) << IntPair(0,0);
1109 
1110     // Use Ctrl modifier
1111     QTest::newRow("MoveEnd + Ctrl (0,0)")
1112         << 4 << 4 << -1 << -1
1113         << 0 << 0
1114         << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
1115         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1116 
1117     QTest::newRow("MoveEnd + Ctrl (3,3)")
1118         << 4 << 4 << -1 << -1
1119         << 3 << 3
1120         << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
1121         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1122 
1123     QTest::newRow("MoveEnd + Ctrl, hidden column 3 (0,0)")
1124         << 4 << 4 << -1 << 3
1125         << 0 << 0
1126         << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
1127         << 3 << 2 << IntPair(0,0) << IntPair(0,0);
1128 
1129     QTest::newRow("MoveEnd + Ctrl, hidden column 3, hidden row 3 (0,0)")
1130         << 4 << 4 << 3 << 3
1131         << 0 << 0
1132         << int(QtTestTableView::MoveEnd) << int(Qt::ControlModifier)
1133         << 2 << 2 << IntPair(0,0) << IntPair(0,0);
1134 
1135     QTest::newRow("MovePageUp (0,0)")
1136         << 4 << 4 << -1 << -1
1137         << 0 << 0
1138         << int(QtTestTableView::MovePageUp) << 0
1139         << 0 << 0 << IntPair(0,0) << IntPair(0,0);
1140 
1141     QTest::newRow("MovePageUp (3,3)")
1142         << 4 << 4 << -1 << -1
1143         << 3 << 3
1144         << int(QtTestTableView::MovePageUp) << 0
1145         << 0 << 3 << IntPair(0,0) << IntPair(0,0);
1146 
1147     QTest::newRow("MovePageDown (3, 3)")
1148         << 4 << 4 << -1 << -1
1149         << 3 << 3
1150         << int(QtTestTableView::MovePageDown) << 0
1151         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1152 
1153     QTest::newRow("MovePageDown (0, 3)")
1154         << 4 << 4 << -1 << -1
1155         << 0 << 3
1156         << int(QtTestTableView::MovePageDown) << 0
1157         << 3 << 3 << IntPair(0,0) << IntPair(0,0);
1158 }
1159 
moveCursor()1160 void tst_QTableView::moveCursor()
1161 {
1162     QFETCH(int, rowCount);
1163     QFETCH(int, columnCount);
1164     QFETCH(int, hideRow);
1165     QFETCH(int, hideColumn);
1166     QFETCH(int, startRow);
1167     QFETCH(int, startColumn);
1168     QFETCH(int, cursorMoveAction);
1169     QFETCH(int, modifier);
1170     QFETCH(int, expectedRow);
1171     QFETCH(int, expectedColumn);
1172     QFETCH(IntPair, moveRow);
1173     QFETCH(IntPair, moveColumn);
1174 
1175     QtTestTableModel model(rowCount, columnCount);
1176     QtTestTableView view;
1177 
1178     view.setModel(&model);
1179     view.hideRow(hideRow);
1180     view.hideColumn(hideColumn);
1181     if (moveColumn.first != moveColumn.second)
1182         view.horizontalHeader()->moveSection(moveColumn.first, moveColumn.second);
1183     if (moveRow.first != moveRow.second)
1184         view.verticalHeader()->moveSection(moveRow.first, moveRow.second);
1185 
1186     view.show();
1187 
1188     QModelIndex index = model.index(startRow, startColumn);
1189     view.setCurrentIndex(index);
1190 
1191     QModelIndex newIndex = view.moveCursor((QtTestTableView::CursorAction)cursorMoveAction,
1192                                            (Qt::KeyboardModifiers)modifier);
1193     // expected fails, task 119433
1194     if(newIndex.row() == -1)
1195         return;
1196     QCOMPARE(newIndex.row(), expectedRow);
1197     QCOMPARE(newIndex.column(), expectedColumn);
1198 }
1199 
moveCursorStrikesBack_data()1200 void tst_QTableView::moveCursorStrikesBack_data()
1201 {
1202     QTest::addColumn<int>("hideRow");
1203     QTest::addColumn<int>("hideColumn");
1204     QTest::addColumn<IntList>("disableRows");
1205     QTest::addColumn<IntList>("disableColumns");
1206     QTest::addColumn<QRect>("span");
1207 
1208     QTest::addColumn<int>("startRow");
1209     QTest::addColumn<int>("startColumn");
1210     QTest::addColumn<IntList>("cursorMoveActions");
1211     QTest::addColumn<int>("expectedRow");
1212     QTest::addColumn<int>("expectedColumn");
1213 
1214     QTest::newRow("Last column disabled. Task QTBUG-3878") << -1 << -1
1215             << IntList()
1216             << (IntList() << 6)
1217             << QRect()
1218             << 0 << 5 << (IntList() << int(QtTestTableView::MoveNext))
1219             << 1 << 0;
1220 
1221     QTest::newRow("Last column disabled. Task QTBUG-3878") << -1 << -1
1222             << IntList()
1223             << (IntList() << 6)
1224             << QRect()
1225             << 1 << 0 << (IntList() << int(QtTestTableView::MovePrevious))
1226             << 0 << 5;
1227 
1228     QTest::newRow("Span, anchor column hidden") << -1 << 1
1229             << IntList()
1230             << IntList()
1231             << QRect(1, 2, 2, 3)
1232             << 2 << 0 << (IntList() << int(QtTestTableView::MoveNext))
1233             << 2 << 2;
1234 
1235     QTest::newRow("Span, anchor column disabled") << -1 << -1
1236             << IntList()
1237             << (IntList() << 1)
1238             << QRect(1, 2, 2, 3)
1239             << 2 << 0 << (IntList() << int(QtTestTableView::MoveNext))
1240             << 2 << 2;
1241 
1242     QTest::newRow("Span, anchor row hidden") << 2 << -1
1243             << IntList()
1244             << IntList()
1245             << QRect(1, 2, 2, 3)
1246             << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown))
1247             << 3 << 2;
1248 
1249     QTest::newRow("Span, anchor row disabled") << -1 << -1
1250             << (IntList() << 2)
1251             << IntList()
1252             << QRect(1, 2, 2, 3)
1253             << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown))
1254             << 3 << 2;
1255 
1256     QTest::newRow("Move through span right") << -1 << -1
1257             << IntList()
1258             << IntList()
1259             << QRect(1, 2, 2, 3)
1260             << 3 << 0 << (IntList() << int(QtTestTableView::MoveRight) << int(QtTestTableView::MoveRight))
1261             << 3 << 3;
1262 
1263     QTest::newRow("Move through span left") << -1 << -1
1264             << IntList()
1265             << IntList()
1266             << QRect(1, 2, 2, 3)
1267             << 3 << 3 << (IntList() << int(QtTestTableView::MoveLeft) << int(QtTestTableView::MoveLeft))
1268             << 3 << 0;
1269 
1270     QTest::newRow("Move through span down") << -1 << -1
1271             << IntList()
1272             << IntList()
1273             << QRect(1, 2, 2, 3)
1274             << 1 << 2 << (IntList() << int(QtTestTableView::MoveDown) << int(QtTestTableView::MoveDown))
1275             << 5 << 2;
1276 
1277     QTest::newRow("Move through span up") << -1 << -1
1278             << IntList()
1279             << IntList()
1280             << QRect(1, 2, 2, 3)
1281             << 5 << 2 << (IntList() << int(QtTestTableView::MoveUp) << int(QtTestTableView::MoveUp))
1282             << 1 << 2;
1283 
1284     IntList fullList;
1285     for (int i = 0; i < 7; ++i)
1286         fullList << i;
1287 
1288     QTest::newRow("All disabled, wrap forward. Timeout => FAIL") << -1 << -1
1289             << fullList
1290             << fullList
1291             << QRect()
1292             << 1 << 0 << (IntList() << int(QtTestTableView::MoveNext))
1293             << 1 << 0;
1294 
1295     QTest::newRow("All disabled, wrap backwards. Timeout => FAIL") << -1 << -1
1296             << fullList
1297             << fullList
1298             << QRect()
1299             << 1 << 0 << (IntList() << int(QtTestTableView::MovePrevious))
1300             << 1 << 0;
1301 }
1302 
moveCursorStrikesBack()1303 void tst_QTableView::moveCursorStrikesBack()
1304 {
1305     QFETCH(int, hideRow);
1306     QFETCH(int, hideColumn);
1307     QFETCH(IntList, disableRows);
1308     QFETCH(IntList, disableColumns);
1309     QFETCH(QRect, span);
1310 
1311     QFETCH(int, startRow);
1312     QFETCH(int, startColumn);
1313     QFETCH(IntList, cursorMoveActions);
1314     QFETCH(int, expectedRow);
1315     QFETCH(int, expectedColumn);
1316 
1317     QtTestTableModel model(7, 7);
1318     QtTestTableView view;
1319     view.setModel(&model);
1320     view.hideRow(hideRow);
1321     view.hideColumn(hideColumn);
1322 
1323     if (span.height() && span.width())
1324         view.setSpan(span.top(), span.left(), span.height(), span.width());
1325     view.show();
1326 
1327     QModelIndex index = model.index(startRow, startColumn);
1328     view.setCurrentIndex(index);
1329 
1330     foreach (int row, disableRows)
1331         model.disableRow(row);
1332     foreach (int column, disableColumns)
1333         model.disableColumn(column);
1334 
1335     int newRow = -1;
1336     int newColumn = -1;
1337     foreach (int cursorMoveAction, cursorMoveActions) {
1338         QModelIndex newIndex = view.moveCursor((QtTestTableView::CursorAction)cursorMoveAction, 0);
1339         view.setCurrentIndex(newIndex);
1340         newRow = newIndex.row();
1341         newColumn = newIndex.column();
1342     }
1343 
1344     // expected fails, task 119433
1345     if(newRow == -1)
1346         return;
1347     QCOMPARE(newRow, expectedRow);
1348     QCOMPARE(newColumn, expectedColumn);
1349 }
1350 
hideRows_data()1351 void tst_QTableView::hideRows_data()
1352 {
1353     QTest::addColumn<int>("rowCount");
1354     QTest::addColumn<int>("columnCount");
1355     QTest::addColumn<int>("showRow"); // hide, then show
1356     QTest::addColumn<int>("hideRow"); // hide only
1357     QTest::addColumn<int>("row");
1358     QTest::addColumn<int>("column");
1359     QTest::addColumn<int>("rowSpan");
1360     QTest::addColumn<int>("columnSpan");
1361 
1362     QTest::newRow("show row 0, hide row 3, no span")
1363       << 10 << 10
1364       << 0
1365       << 3
1366       << -1 << -1
1367       << 1 << 1;
1368 
1369     QTest::newRow("show row 0, hide row 3, span")
1370       << 10 << 10
1371       << 0
1372       << 3
1373       << 0 << 0
1374       << 3 << 2;
1375 }
1376 
hideRows()1377 void tst_QTableView::hideRows()
1378 {
1379     QFETCH(int, rowCount);
1380     QFETCH(int, columnCount);
1381     QFETCH(int, showRow);
1382     QFETCH(int, hideRow);
1383     QFETCH(int, row);
1384     QFETCH(int, column);
1385     QFETCH(int, rowSpan);
1386     QFETCH(int, columnSpan);
1387 
1388     QtTestTableModel model(rowCount, columnCount);
1389     QTableView view;
1390 
1391     view.setModel(&model);
1392     view.setSpan(row, column, rowSpan, columnSpan);
1393 
1394     view.hideRow(showRow);
1395     QVERIFY(view.isRowHidden(showRow));
1396 
1397     view.hideRow(hideRow);
1398     QVERIFY(view.isRowHidden(hideRow));
1399 
1400     view.showRow(showRow);
1401     QVERIFY(!view.isRowHidden(showRow));
1402     QVERIFY(view.isRowHidden(hideRow));
1403 }
1404 
hideColumns_data()1405 void tst_QTableView::hideColumns_data()
1406 {
1407     QTest::addColumn<int>("rowCount");
1408     QTest::addColumn<int>("columnCount");
1409     QTest::addColumn<int>("showColumn"); // hide, then show
1410     QTest::addColumn<int>("hideColumn"); // hide only
1411     QTest::addColumn<int>("row");
1412     QTest::addColumn<int>("column");
1413     QTest::addColumn<int>("rowSpan");
1414     QTest::addColumn<int>("columnSpan");
1415 
1416     QTest::newRow("show col 0, hide col 3, no span")
1417       << 10 << 10
1418       << 0
1419       << 3
1420       << -1 << -1
1421       << 1 << 1;
1422 
1423     QTest::newRow("show col 0, hide col 3, span")
1424       << 10 << 10
1425       << 0
1426       << 3
1427       << 0 << 0
1428       << 3 << 2;
1429 }
1430 
hideColumns()1431 void tst_QTableView::hideColumns()
1432 {
1433     QFETCH(int, rowCount);
1434     QFETCH(int, columnCount);
1435     QFETCH(int, showColumn);
1436     QFETCH(int, hideColumn);
1437     QFETCH(int, row);
1438     QFETCH(int, column);
1439     QFETCH(int, rowSpan);
1440     QFETCH(int, columnSpan);
1441 
1442     QtTestTableModel model(rowCount, columnCount);
1443 
1444     QTableView view;
1445     view.setModel(&model);
1446     view.setSpan(row, column, rowSpan, columnSpan);
1447 
1448     view.hideColumn(showColumn);
1449     QVERIFY(view.isColumnHidden(showColumn));
1450 
1451     view.hideColumn(hideColumn);
1452     QVERIFY(view.isColumnHidden(hideColumn));
1453 
1454     view.showColumn(showColumn);
1455     QVERIFY(!view.isColumnHidden(showColumn));
1456     QVERIFY(view.isColumnHidden(hideColumn));
1457 }
1458 
selection_data()1459 void tst_QTableView::selection_data()
1460 {
1461     QTest::addColumn<int>("rowCount");
1462     QTest::addColumn<int>("columnCount");
1463     QTest::addColumn<int>("row");
1464     QTest::addColumn<int>("column");
1465     QTest::addColumn<int>("rowSpan");
1466     QTest::addColumn<int>("columnSpan");
1467     QTest::addColumn<int>("hideRow");
1468     QTest::addColumn<int>("hideColumn");
1469     QTest::addColumn<int>("moveRowFrom");
1470     QTest::addColumn<int>("moveRowTo");
1471     QTest::addColumn<int>("moveColumnFrom");
1472     QTest::addColumn<int>("moveColumnTo");
1473     QTest::addColumn<int>("rowHeight");
1474     QTest::addColumn<int>("columnWidth");
1475     QTest::addColumn<int>("x");
1476     QTest::addColumn<int>("y");
1477     QTest::addColumn<int>("width");
1478     QTest::addColumn<int>("height");
1479     QTest::addColumn<int>("command");
1480     QTest::addColumn<int>("selectedCount"); // ### make this more detailed
1481 
1482     QTest::newRow("no span, no hidden, no moved, 3x3 select")
1483       << 10 << 10                          // dim
1484       << -1 << -1                          // pos
1485       << 1 << 1                            // span
1486       << -1 << -1                          // hide
1487       << -1 << -1                          // move row
1488       << -1 << -1                          // move col
1489       << 40 << 40                          // cell size
1490       << 20 << 20 << 80 << 80              // rect
1491       << int(QItemSelectionModel::Select)  // command
1492       << 9;                                // selected count
1493 
1494     QTest::newRow("row span, no hidden, no moved, 3x3 select")
1495       << 10 << 10                          // dim
1496       << 1 << 1                            // pos
1497       << 2 << 1                            // span
1498       << -1 << -1                          // hide
1499       << -1 << -1                          // move row
1500       << -1 << -1                          // move col
1501       << 40 << 40                          // cell size
1502       << 20 << 20 << 80 << 80              // rect
1503       << int(QItemSelectionModel::Select)  // command
1504       << 8;                                // selected count
1505 
1506     QTest::newRow("col span, no hidden, no moved, 3x3 select")
1507       << 10 << 10                          // dim
1508       << 1 << 1                            // pos
1509       << 1 << 2                            // span
1510       << -1 << -1                          // hide
1511       << -1 << -1                          // move row
1512       << -1 << -1                          // move col
1513       << 40 << 40                          // cell size
1514       << 20 << 20 << 80 << 80              // rect
1515       << int(QItemSelectionModel::Select)  // command
1516       << 8;                                // selected count
1517 
1518     QTest::newRow("no span, row hidden, no moved, 3x3 select")
1519       << 10 << 10                          // dim
1520       << -1 << -1                          // pos
1521       << 1 << 1                            // span
1522       << 1 << -1                           // hide
1523       << -1 << -1                          // move row
1524       << -1 << -1                          // move col
1525       << 40 << 40                          // cell size
1526       << 20 << 20 << 80 << 80              // rect
1527       << int(QItemSelectionModel::Select)  // command
1528       << 9;                                // selected count
1529 
1530     QTest::newRow("no span, col hidden, no moved, 3x3 select")
1531       << 10 << 10                          // dim
1532       << -1 << -1                          // pos
1533       << 1 << 1                            // span
1534       << -1 << 1                           // hide
1535       << -1 << -1                          // move row
1536       << -1 << -1                          // move col
1537       << 40 << 40                          // cell size
1538       << 20 << 20 << 80 << 80              // rect
1539       << int(QItemSelectionModel::Select)  // command
1540       << 9;                                // selected count
1541 
1542     QTest::newRow("no span, no hidden, row moved, 3x3 select")
1543       << 10 << 10                          // dim
1544       << -1 << -1                          // pos
1545       << 1 << 1                            // span
1546       << -1 << -1                          // hide
1547       << 1 << 3                            // move row
1548       << -1 << -1                          // move col
1549       << 40 << 40                          // cell size
1550       << 20 << 20 << 80 << 80              // rect
1551       << int(QItemSelectionModel::Select)  // command
1552       << 9;                                // selected count
1553 
1554     QTest::newRow("no span, no hidden, col moved, 3x3 select")
1555       << 10 << 10                          // dim
1556       << -1 << -1                          // pos
1557       << 1 << 1                            // span
1558       << -1 << -1                          // hide
1559       << -1 << -1                          // move row
1560       << 1 << 3                            // move col
1561       << 40 << 40                          // cell size
1562       << 20 << 20 << 80 << 80              // rect
1563       << int(QItemSelectionModel::Select)  // command
1564       << 9;                                // selected count
1565 }
1566 
selection()1567 void tst_QTableView::selection()
1568 {
1569     QFETCH(int, rowCount);
1570     QFETCH(int, columnCount);
1571     QFETCH(int, row);
1572     QFETCH(int, column);
1573     QFETCH(int, rowSpan);
1574     QFETCH(int, columnSpan);
1575     QFETCH(int, hideRow);
1576     QFETCH(int, hideColumn);
1577     QFETCH(int, moveRowFrom);
1578     QFETCH(int, moveRowTo);
1579     QFETCH(int, moveColumnFrom);
1580     QFETCH(int, moveColumnTo);
1581     QFETCH(int, rowHeight);
1582     QFETCH(int, columnWidth);
1583     QFETCH(int, x);
1584     QFETCH(int, y);
1585     QFETCH(int, width);
1586     QFETCH(int, height);
1587     QFETCH(int, command);
1588     QFETCH(int, selectedCount);
1589 
1590     QtTestTableModel model(rowCount, columnCount);
1591 
1592     QtTestTableView view;
1593     view.show();
1594     view.setModel(&model);
1595 
1596     view.setSpan(row, column, rowSpan, columnSpan);
1597 
1598     view.hideRow(hideRow);
1599     view.hideColumn(hideColumn);
1600 
1601     view.verticalHeader()->moveSection(moveRowFrom, moveRowTo);
1602     view.horizontalHeader()->moveSection(moveColumnFrom, moveColumnTo);
1603 
1604     for (int r = 0; r < rowCount; ++r)
1605         view.setRowHeight(r, rowHeight);
1606     for (int c = 0; c < columnCount; ++c)
1607         view.setColumnWidth(c, columnWidth);
1608 
1609     view.setSelection(QRect(x, y, width, height),
1610 		      QItemSelectionModel::SelectionFlags(command));
1611 
1612     QCOMPARE(view.selectedIndexes().count(), selectedCount);
1613 }
1614 
selectRow_data()1615 void tst_QTableView::selectRow_data()
1616 {
1617     QTest::addColumn<int>("rowCount");
1618     QTest::addColumn<int>("columnCount");
1619     QTest::addColumn<int>("row");
1620     QTest::addColumn<int>("mode");
1621     QTest::addColumn<int>("behavior");
1622     QTest::addColumn<int>("selectedItems");
1623 
1624     QTest::newRow("SingleSelection and SelectItems")
1625         << 10 << 10
1626         << 0
1627         << (int)QAbstractItemView::SingleSelection
1628         << (int)QAbstractItemView::SelectItems
1629         << 0;
1630 
1631     QTest::newRow("SingleSelection and SelectRows")
1632         << 10 << 10
1633         << 0
1634         << (int)QAbstractItemView::SingleSelection
1635         << (int)QAbstractItemView::SelectRows
1636         << 10;
1637 
1638     QTest::newRow("SingleSelection and SelectColumns")
1639         << 10 << 10
1640         << 0
1641         << (int)QAbstractItemView::SingleSelection
1642         << (int)QAbstractItemView::SelectColumns
1643         << 0;
1644 
1645     QTest::newRow("MultiSelection and SelectItems")
1646         << 10 << 10
1647         << 0
1648         << (int)QAbstractItemView::MultiSelection
1649         << (int)QAbstractItemView::SelectItems
1650         << 10;
1651 
1652     QTest::newRow("MultiSelection and SelectRows")
1653         << 10 << 10
1654         << 0
1655         << (int)QAbstractItemView::MultiSelection
1656         << (int)QAbstractItemView::SelectRows
1657         << 10;
1658 
1659     QTest::newRow("MultiSelection and SelectColumns")
1660         << 10 << 10
1661         << 0
1662         << (int)QAbstractItemView::MultiSelection
1663         << (int)QAbstractItemView::SelectColumns
1664         << 0;
1665 
1666     QTest::newRow("ExtendedSelection and SelectItems")
1667         << 10 << 10
1668         << 0
1669         << (int)QAbstractItemView::ExtendedSelection
1670         << (int)QAbstractItemView::SelectItems
1671         << 10;
1672 
1673     QTest::newRow("ExtendedSelection and SelectRows")
1674         << 10 << 10
1675         << 0
1676         << (int)QAbstractItemView::ExtendedSelection
1677         << (int)QAbstractItemView::SelectRows
1678         << 10;
1679 
1680     QTest::newRow("ExtendedSelection and SelectColumns")
1681         << 10 << 10
1682         << 0
1683         << (int)QAbstractItemView::ExtendedSelection
1684         << (int)QAbstractItemView::SelectColumns
1685         << 0;
1686 
1687     QTest::newRow("ContiguousSelection and SelectItems")
1688         << 10 << 10
1689         << 0
1690         << (int)QAbstractItemView::ContiguousSelection
1691         << (int)QAbstractItemView::SelectItems
1692         << 10;
1693 
1694     QTest::newRow("ContiguousSelection and SelectRows")
1695         << 10 << 10
1696         << 0
1697         << (int)QAbstractItemView::ContiguousSelection
1698         << (int)QAbstractItemView::SelectRows
1699         << 10;
1700 
1701     QTest::newRow("ContiguousSelection and SelectColumns")
1702         << 10 << 10
1703         << 0
1704         << (int)QAbstractItemView::ContiguousSelection
1705         << (int)QAbstractItemView::SelectColumns
1706         << 0;
1707 }
1708 
selectRow()1709 void tst_QTableView::selectRow()
1710 {
1711     QFETCH(int, rowCount);
1712     QFETCH(int, columnCount);
1713     QFETCH(int, row);
1714     QFETCH(int, mode);
1715     QFETCH(int, behavior);
1716     QFETCH(int, selectedItems);
1717 
1718     QtTestTableModel model(rowCount, columnCount);
1719     QTableView view;
1720 
1721     view.setModel(&model);
1722     view.setSelectionMode((QAbstractItemView::SelectionMode)mode);
1723     view.setSelectionBehavior((QAbstractItemView::SelectionBehavior)behavior);
1724 
1725     QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0);
1726 
1727     view.selectRow(row);
1728 
1729     //test we have 10 items selected
1730     QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems);
1731     //test that all 10 items are in the same row
1732     for (int i = 0; selectedItems > 0 && i < rowCount; ++i)
1733         QCOMPARE(view.selectionModel()->selectedIndexes().at(i).row(), row);
1734 }
1735 
selectColumn_data()1736 void tst_QTableView::selectColumn_data()
1737 {
1738     QTest::addColumn<int>("rowCount");
1739     QTest::addColumn<int>("columnCount");
1740     QTest::addColumn<int>("column");
1741     QTest::addColumn<int>("mode");
1742     QTest::addColumn<int>("behavior");
1743     QTest::addColumn<int>("selectedItems");
1744 
1745         QTest::newRow("SingleSelection and SelectItems")
1746             << 10 << 10
1747             << 0
1748             << (int)QAbstractItemView::SingleSelection
1749             << (int)QAbstractItemView::SelectItems
1750             << 0;
1751 
1752         QTest::newRow("SingleSelection and SelectRows")
1753             << 10 << 10
1754             << 0
1755             << (int)QAbstractItemView::SingleSelection
1756             << (int)QAbstractItemView::SelectRows
1757             << 0;
1758 
1759         QTest::newRow("SingleSelection and SelectColumns")
1760             << 10 << 10
1761             << 0
1762             << (int)QAbstractItemView::SingleSelection
1763             << (int)QAbstractItemView::SelectColumns
1764             << 10;
1765 
1766         QTest::newRow("MultiSelection and SelectItems")
1767             << 10 << 10
1768             << 0
1769             << (int)QAbstractItemView::MultiSelection
1770             << (int)QAbstractItemView::SelectItems
1771             << 10;
1772 
1773         QTest::newRow("MultiSelection and SelectRows")
1774             << 10 << 10
1775             << 0
1776             << (int)QAbstractItemView::MultiSelection
1777             << (int)QAbstractItemView::SelectRows
1778             << 0;
1779 
1780         QTest::newRow("MultiSelection and SelectColumns")
1781             << 10 << 10
1782             << 0
1783             << (int)QAbstractItemView::MultiSelection
1784             << (int)QAbstractItemView::SelectColumns
1785             << 10;
1786 
1787         QTest::newRow("ExtendedSelection and SelectItems")
1788             << 10 << 10
1789             << 0
1790             << (int)QAbstractItemView::ExtendedSelection
1791             << (int)QAbstractItemView::SelectItems
1792             << 10;
1793 
1794         QTest::newRow("ExtendedSelection and SelectRows")
1795             << 10 << 10
1796             << 0
1797             << (int)QAbstractItemView::ExtendedSelection
1798             << (int)QAbstractItemView::SelectRows
1799             << 0;
1800 
1801         QTest::newRow("ExtendedSelection and SelectColumns")
1802             << 10 << 10
1803             << 0
1804             << (int)QAbstractItemView::ExtendedSelection
1805             << (int)QAbstractItemView::SelectColumns
1806             << 10;
1807 
1808         QTest::newRow("ContiguousSelection and SelectItems")
1809             << 10 << 10
1810             << 0
1811             << (int)QAbstractItemView::ContiguousSelection
1812             << (int)QAbstractItemView::SelectItems
1813             << 10;
1814 
1815         QTest::newRow("ContiguousSelection and SelectRows")
1816             << 10 << 10
1817             << 0
1818             << (int)QAbstractItemView::ContiguousSelection
1819             << (int)QAbstractItemView::SelectRows
1820             << 0;
1821 
1822         QTest::newRow("ContiguousSelection and SelectColumns")
1823             << 10 << 10
1824             << 0
1825             << (int)QAbstractItemView::ContiguousSelection
1826             << (int)QAbstractItemView::SelectColumns
1827             << 10;
1828 }
1829 
selectColumn()1830 void tst_QTableView::selectColumn()
1831 {
1832     QFETCH(int, rowCount);
1833     QFETCH(int, columnCount);
1834     QFETCH(int, column);
1835     QFETCH(int, mode);
1836     QFETCH(int, behavior);
1837     QFETCH(int, selectedItems);
1838 
1839     QtTestTableModel model(rowCount, columnCount);
1840 
1841     QTableView view;
1842     view.setModel(&model);
1843     view.setSelectionMode((QAbstractItemView::SelectionMode)mode);
1844     view.setSelectionBehavior((QAbstractItemView::SelectionBehavior)behavior);
1845 
1846     QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0);
1847 
1848     view.selectColumn(column);
1849 
1850     QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems);
1851     for (int i = 0; selectedItems > 0 && i < columnCount; ++i)
1852         QCOMPARE(view.selectionModel()->selectedIndexes().at(i).column(), column);
1853 }
1854 
Q_DECLARE_METATYPE(QRect)1855 Q_DECLARE_METATYPE(QRect)
1856 void tst_QTableView::visualRect_data()
1857 {
1858     QTest::addColumn<int>("rowCount");
1859     QTest::addColumn<int>("columnCount");
1860     QTest::addColumn<int>("hideRow");
1861     QTest::addColumn<int>("hideColumn");
1862     QTest::addColumn<int>("row");
1863     QTest::addColumn<int>("column");
1864     QTest::addColumn<int>("rowHeight");
1865     QTest::addColumn<int>("columnWidth");
1866     QTest::addColumn<QRect>("expectedRect");
1867 
1868     QTest::newRow("(0,0)")
1869         << 10 << 10
1870         << -1 << -1
1871         << 0 << 0
1872         << 20 << 30
1873         << QRect(0, 0, 29, 19);
1874 
1875     QTest::newRow("(0,0) hidden row")
1876         << 10 << 10
1877         << 0 << -1
1878         << 0 << 0
1879         << 20 << 30
1880         << QRect();
1881 
1882     QTest::newRow("(0,0) hidden column")
1883         << 10 << 10
1884         << -1 << 0
1885         << 0 << 0
1886         << 20 << 30
1887         << QRect();
1888 
1889     QTest::newRow("(0,0) hidden row and column")
1890         << 10 << 10
1891         << 0 << 0
1892         << 0 << 0
1893         << 20 << 30
1894         << QRect();
1895 
1896     QTest::newRow("(0,0) out of bounds")
1897         << 10 << 10
1898         << -1 << -1
1899         << 20 << 20
1900         << 20 << 30
1901         << QRect();
1902 
1903     QTest::newRow("(5,5), hidden row")
1904         << 10 << 10
1905         << 5 << -1
1906         << 5 << 5
1907         << 20 << 30
1908         << QRect();
1909 
1910     QTest::newRow("(9,9)")
1911         << 10 << 10
1912         << -1 << -1
1913         << 9 << 9
1914         << 20 << 30
1915         << QRect(30*9, 20*9, 29, 19);
1916 }
1917 
visualRect()1918 void tst_QTableView::visualRect()
1919 {
1920     QFETCH(int, rowCount);
1921     QFETCH(int, columnCount);
1922     QFETCH(int, hideRow);
1923     QFETCH(int, hideColumn);
1924     QFETCH(int, row);
1925     QFETCH(int, column);
1926     QFETCH(int, rowHeight);
1927     QFETCH(int, columnWidth);
1928     QFETCH(QRect, expectedRect);
1929 
1930     QtTestTableModel model(rowCount, columnCount);
1931 
1932     QTableView view;
1933     view.setModel(&model);
1934     // Make sure that it has 1 pixel between each cell.
1935     view.setGridStyle(Qt::SolidLine);
1936     for (int i = 0; i < view.verticalHeader()->count(); ++i)
1937         view.verticalHeader()->resizeSection(i, rowHeight);
1938     for (int i = 0; i < view.horizontalHeader()->count(); ++i)
1939         view.horizontalHeader()->resizeSection(i, columnWidth);
1940 
1941     view.hideRow(hideRow);
1942     view.hideColumn(hideColumn);
1943 
1944     QRect rect = view.visualRect(model.index(row, column));
1945     QCOMPARE(rect, expectedRect);
1946 }
1947 
fetchMore()1948 void tst_QTableView::fetchMore()
1949 {
1950     QtTestTableModel model(64, 64);
1951 
1952     model.can_fetch_more = true;
1953 
1954     QTableView view;
1955     view.setModel(&model);
1956     view.show();
1957 
1958     QCOMPARE(model.fetch_more_count, 0);
1959     view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
1960     QVERIFY(model.fetch_more_count > 0);
1961 
1962     model.fetch_more_count = 0; //reset
1963     view.scrollToTop();
1964     QCOMPARE(model.fetch_more_count, 0);
1965 
1966     view.scrollToBottom();
1967     QVERIFY(model.fetch_more_count > 0);
1968 
1969     model.fetch_more_count = 0; //reset
1970     view.scrollToTop();
1971     view.setCurrentIndex(model.index(0, 0));
1972     QCOMPARE(model.fetch_more_count, 0);
1973 
1974     for (int i = 0; i < 64; ++i)
1975         QTest::keyClick(&view, Qt::Key_Down);
1976     QCOMPARE(view.currentIndex(), model.index(63, 0));
1977     QVERIFY(model.fetch_more_count > 0);
1978 }
1979 
setHeaders()1980 void tst_QTableView::setHeaders()
1981 {
1982     QTableView view;
1983 
1984     // Make sure we don't delete ourselves
1985     view.setVerticalHeader(view.verticalHeader());
1986     view.verticalHeader()->count();
1987     view.setHorizontalHeader(view.horizontalHeader());
1988     view.horizontalHeader()->count();
1989 
1990     // Try passing around a header without it being deleted
1991     QTableView view2;
1992     view2.setVerticalHeader(view.verticalHeader());
1993     view2.setHorizontalHeader(view.horizontalHeader());
1994     view.setHorizontalHeader(new QHeaderView(Qt::Horizontal));
1995     view.setVerticalHeader(new QHeaderView(Qt::Vertical));
1996     view2.verticalHeader()->count();
1997     view2.horizontalHeader()->count();
1998 
1999 }
2000 
resizeRowsToContents_data()2001 void tst_QTableView::resizeRowsToContents_data()
2002 {
2003     QTest::addColumn<int>("rowCount");
2004     QTest::addColumn<int>("columnCount");
2005     QTest::addColumn<bool>("showGrid");
2006     QTest::addColumn<int>("cellWidth");
2007     QTest::addColumn<int>("cellHeight");
2008     QTest::addColumn<int>("rowHeight");
2009     QTest::addColumn<int>("columnWidth");
2010 
2011     QTest::newRow("10x10 grid shown 40x40")
2012         << 10 << 10 << false << 40 << 40 << 40 << 40;
2013 
2014     QTest::newRow("10x10 grid not shown 40x40")
2015         << 10 << 10 << true << 40 << 40 << 41 << 41;
2016 }
2017 
resizeRowsToContents()2018 void tst_QTableView::resizeRowsToContents()
2019 {
2020     QFETCH(int, rowCount);
2021     QFETCH(int, columnCount);
2022     QFETCH(bool, showGrid);
2023     QFETCH(int, cellWidth);
2024     QFETCH(int, cellHeight);
2025     QFETCH(int, rowHeight);
2026     QFETCH(int, columnWidth);
2027     Q_UNUSED(columnWidth);
2028 
2029     QtTestTableModel model(rowCount, columnCount);
2030     QtTestTableView view;
2031     QtTestItemDelegate delegate;
2032 
2033     view.setModel(&model);
2034     view.setItemDelegate(&delegate);
2035     view.setShowGrid(showGrid); // the grid will add to the row height
2036 
2037     delegate.hint = QSize(cellWidth, cellHeight);
2038 
2039     QSignalSpy resizedSpy(view.verticalHeader(), SIGNAL(sectionResized(int, int, int)));
2040     view.resizeRowsToContents();
2041 
2042     QCOMPARE(resizedSpy.count(), model.rowCount());
2043     for (int r = 0; r < model.rowCount(); ++r) {
2044         QCOMPARE(view.rowHeight(r), rowHeight);
2045     }
2046 }
2047 
resizeColumnsToContents_data()2048 void tst_QTableView::resizeColumnsToContents_data()
2049 {
2050     QTest::addColumn<int>("rowCount");
2051     QTest::addColumn<int>("columnCount");
2052     QTest::addColumn<bool>("showGrid");
2053     QTest::addColumn<int>("cellWidth");
2054     QTest::addColumn<int>("cellHeight");
2055     QTest::addColumn<int>("rowHeight");
2056     QTest::addColumn<int>("columnWidth");
2057 
2058     QTest::newRow("10x10 grid shown 40x40")
2059         << 10 << 10 << false << 40 << 40 << 40 << 40;
2060 
2061     QTest::newRow("10x10 grid not shown 40x40")
2062         << 10 << 10 << true << 40 << 40 << 41 << 41;
2063 }
2064 
resizeColumnsToContents()2065 void tst_QTableView::resizeColumnsToContents()
2066 {
2067     QFETCH(int, rowCount);
2068     QFETCH(int, columnCount);
2069     QFETCH(bool, showGrid);
2070     QFETCH(int, cellWidth);
2071     QFETCH(int, cellHeight);
2072     QFETCH(int, rowHeight);
2073     QFETCH(int, columnWidth);
2074     Q_UNUSED(rowHeight);
2075 
2076     QtTestTableModel model(rowCount, columnCount);
2077     QtTestTableView view;
2078     QtTestItemDelegate delegate;
2079 
2080     view.setModel(&model);
2081     view.setItemDelegate(&delegate);
2082     view.setShowGrid(showGrid); // the grid will add to the row height
2083 
2084     delegate.hint = QSize(cellWidth, cellHeight);
2085 
2086     QSignalSpy resizedSpy(view.horizontalHeader(), SIGNAL(sectionResized(int, int, int)));
2087     view.resizeColumnsToContents();
2088 
2089     QCOMPARE(resizedSpy.count(), model.columnCount());
2090     for (int c = 0; c < model.columnCount(); ++c)
2091         QCOMPARE(view.columnWidth(c), columnWidth);
2092 }
2093 
rowViewportPosition_data()2094 void tst_QTableView::rowViewportPosition_data()
2095 {
2096     QTest::addColumn<int>("rowCount");
2097     QTest::addColumn<int>("rowHeight");
2098     QTest::addColumn<int>("row");
2099     QTest::addColumn<int>("verticalScrollMode");
2100     QTest::addColumn<int>("verticalScrollValue");
2101     QTest::addColumn<int>("rowViewportPosition");
2102 
2103     QTest::newRow("row 0, scroll per item 0")
2104         << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerItem) << 0 << 0;
2105 
2106     QTest::newRow("row 1, scroll per item, 0")
2107         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 0 << 1 * 40;
2108 
2109     QTest::newRow("row 1, scroll per item, 1")
2110         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 1 << 0;
2111 
2112     QTest::newRow("row 5, scroll per item, 0")
2113         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 0 << 5 * 40;
2114 
2115     QTest::newRow("row 5, scroll per item, 5")
2116         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 5 << 0;
2117 
2118     QTest::newRow("row 9, scroll per item, 0")
2119         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 0 << 9 * 40;
2120 
2121     QTest::newRow("row 9, scroll per item, 5")
2122         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 5 << 4 * 40;
2123 
2124     QTest::newRow("row 0, scroll per pixel 0")
2125         << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerPixel) << 0 << 0;
2126 
2127     QTest::newRow("row 1, scroll per pixel, 0")
2128         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 0 << 1 * 40;
2129 
2130     QTest::newRow("row 1, scroll per pixel, 1")
2131         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 1 * 40 << 0;
2132 
2133     QTest::newRow("row 5, scroll per pixel, 0")
2134         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 0 << 5 * 40;
2135 
2136     QTest::newRow("row 5, scroll per pixel, 5")
2137         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 0;
2138 
2139     QTest::newRow("row 9, scroll per pixel, 0")
2140         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 0 << 9 * 40;
2141 
2142     QTest::newRow("row 9, scroll per pixel, 5")
2143         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 4 * 40;
2144 }
2145 
rowViewportPosition()2146 void tst_QTableView::rowViewportPosition()
2147 {
2148     QFETCH(int, rowCount);
2149     QFETCH(int, rowHeight);
2150     QFETCH(int, row);
2151     QFETCH(int, verticalScrollMode);
2152     QFETCH(int, verticalScrollValue);
2153     QFETCH(int, rowViewportPosition);
2154 
2155     QtTestTableModel model(rowCount, 1);
2156     QtTestTableView view;
2157     view.resize(100, 2 * rowHeight);
2158     view.show();
2159 
2160     view.setModel(&model);
2161     for (int r = 0; r < rowCount; ++r)
2162         view.setRowHeight(r, rowHeight);
2163 
2164     view.setVerticalScrollMode((QAbstractItemView::ScrollMode)verticalScrollMode);
2165     view.verticalScrollBar()->setValue(verticalScrollValue);
2166 
2167     QCOMPARE(view.rowViewportPosition(row), rowViewportPosition);
2168 }
2169 
rowAt_data()2170 void tst_QTableView::rowAt_data()
2171 {
2172     QTest::addColumn<int>("rowCount");
2173     QTest::addColumn<int>("rowHeight");
2174     QTest::addColumn<IntList>("hiddenRows");
2175     QTest::addColumn<int>("coordinate");
2176     QTest::addColumn<int>("row");
2177 
2178     QTest::newRow("row at 100") << 5 << 40 << IntList() << 100 << 2;
2179     QTest::newRow("row at 180") << 5 << 40 << IntList() << 180 << 4;
2180     QTest::newRow("row at 20")  << 5 << 40 << IntList() <<  20 << 0;
2181 
2182     // ### expand the dataset to include hidden rows
2183 }
2184 
rowAt()2185 void tst_QTableView::rowAt()
2186 {
2187     QFETCH(int, rowCount);
2188     QFETCH(int, rowHeight);
2189     QFETCH(IntList, hiddenRows);
2190     QFETCH(int, coordinate);
2191     QFETCH(int, row);
2192 
2193     QtTestTableModel model(rowCount, 1);
2194     QtTestTableView view;
2195     view.resize(100, 2 * rowHeight);
2196 
2197     view.setModel(&model);
2198 
2199     for (int r = 0; r < rowCount; ++r)
2200         view.setRowHeight(r, rowHeight);
2201 
2202     for (int i = 0; i < hiddenRows.count(); ++i)
2203         view.hideRow(hiddenRows.at(i));
2204 
2205     QCOMPARE(view.rowAt(coordinate), row);
2206 }
2207 
rowHeight_data()2208 void tst_QTableView::rowHeight_data()
2209 {
2210     QTest::addColumn<int>("rowCount");
2211     QTest::addColumn<IntList>("rowHeights");
2212     QTest::addColumn<BoolList>("hiddenRows");
2213 
2214     QTest::newRow("increasing")
2215       << 5
2216       << (IntList() << 20 << 30 << 40 << 50 << 60)
2217       << (BoolList() << false << false << false << false << false);
2218 
2219     QTest::newRow("decreasing")
2220       << 5
2221       << (IntList() << 60 << 50 << 40 << 30 << 20)
2222       << (BoolList() << false << false << false << false << false);
2223 
2224     QTest::newRow("random")
2225       << 5
2226       << (IntList() << 87 << 34 << 68 << 91 << 27)
2227       << (BoolList() << false << false << false << false << false);
2228 
2229     // ### expand the dataset to include hidden rows
2230 }
2231 
rowHeight()2232 void tst_QTableView::rowHeight()
2233 {
2234     QFETCH(int, rowCount);
2235     QFETCH(IntList, rowHeights);
2236     QFETCH(BoolList, hiddenRows);
2237 
2238     QtTestTableModel model(rowCount, 1);
2239     QtTestTableView view;
2240 
2241     view.setModel(&model);
2242 
2243     for (int r = 0; r < rowCount; ++r) {
2244         view.setRowHeight(r, rowHeights.at(r));
2245         view.setRowHidden(r, hiddenRows.at(r));
2246     }
2247 
2248     for (int r = 0; r < rowCount; ++r) {
2249         if (hiddenRows.at(r))
2250             QCOMPARE(view.rowHeight(r), 0);
2251         else
2252             QCOMPARE(view.rowHeight(r), rowHeights.at(r));
2253     }
2254 }
2255 
columnViewportPosition_data()2256 void tst_QTableView::columnViewportPosition_data()
2257 {
2258     QTest::addColumn<int>("columnCount");
2259     QTest::addColumn<int>("columnWidth");
2260     QTest::addColumn<int>("column");
2261     QTest::addColumn<int>("horizontalScrollMode");
2262     QTest::addColumn<int>("horizontalScrollValue");
2263     QTest::addColumn<int>("columnViewportPosition");
2264 
2265     QTest::newRow("column 0, scroll per item 0")
2266         << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerItem) << 0 << 0;
2267 
2268     QTest::newRow("column 1, scroll per item, 0")
2269         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 0 << 1 * 40;
2270 
2271     QTest::newRow("column 1, scroll per item, 1")
2272         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerItem) << 1 << 0;
2273 
2274     QTest::newRow("column 5, scroll per item, 0")
2275         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 0 << 5 * 40;
2276 
2277     QTest::newRow("column 5, scroll per item, 5")
2278         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerItem) << 5 << 0;
2279 
2280     QTest::newRow("column 9, scroll per item, 0")
2281         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 0 << 9 * 40;
2282 
2283     QTest::newRow("column 9, scroll per item, 5")
2284         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerItem) << 5 << 4 * 40;
2285 
2286     QTest::newRow("column 0, scroll per pixel 0")
2287         << 10 << 40 << 0 << int(QAbstractItemView::ScrollPerPixel) << 0 << 0;
2288 
2289     QTest::newRow("column 1, scroll per pixel 0")
2290         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 0 << 1 * 40;
2291 
2292     QTest::newRow("column 1, scroll per pixel 1")
2293         << 10 << 40 << 1 << int(QAbstractItemView::ScrollPerPixel) << 1 * 40 << 0;
2294 
2295     QTest::newRow("column 5, scroll per pixel 0")
2296         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 0 << 5 * 40;
2297 
2298     QTest::newRow("column 5, scroll per pixel 5")
2299         << 10 << 40 << 5 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 0;
2300 
2301     QTest::newRow("column 9, scroll per pixel 0")
2302         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 0 << 9 * 40;
2303 
2304     QTest::newRow("column 9, scroll per pixel 5")
2305         << 10 << 40 << 9 << int(QAbstractItemView::ScrollPerPixel) << 5 * 40 << 4 * 40;
2306 }
2307 
columnViewportPosition()2308 void tst_QTableView::columnViewportPosition()
2309 {
2310     QFETCH(int, columnCount);
2311     QFETCH(int, columnWidth);
2312     QFETCH(int, column);
2313     QFETCH(int, horizontalScrollMode);
2314     QFETCH(int, horizontalScrollValue);
2315     QFETCH(int, columnViewportPosition);
2316 
2317     QtTestTableModel model(1, columnCount);
2318     QtTestTableView view;
2319     view.resize(2 * columnWidth, 100);
2320     view.show();
2321 
2322     view.setModel(&model);
2323     for (int c = 0; c < columnCount; ++c)
2324         view.setColumnWidth(c, columnWidth);
2325 
2326     view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)horizontalScrollMode);
2327     view.horizontalScrollBar()->setValue(horizontalScrollValue);
2328 
2329     QCOMPARE(view.columnViewportPosition(column), columnViewportPosition);
2330 }
2331 
columnAt_data()2332 void tst_QTableView::columnAt_data()
2333 {
2334     QTest::addColumn<int>("columnCount");
2335     QTest::addColumn<int>("columnWidth");
2336     QTest::addColumn<IntList>("hiddenColumns");
2337     QTest::addColumn<int>("coordinate");
2338     QTest::addColumn<int>("column");
2339 
2340     QTest::newRow("column at 100") << 5 << 40 << IntList() << 100 << 2;
2341     QTest::newRow("column at 180") << 5 << 40 << IntList() << 180 << 4;
2342     QTest::newRow("column at 20")  << 5 << 40 << IntList() <<  20 << 0;
2343 
2344     // ### expand the dataset to include hidden coumns
2345 }
2346 
columnAt()2347 void tst_QTableView::columnAt()
2348 {
2349     QFETCH(int, columnCount);
2350     QFETCH(int, columnWidth);
2351     QFETCH(IntList, hiddenColumns);
2352     QFETCH(int, coordinate);
2353     QFETCH(int, column);
2354 
2355     QtTestTableModel model(1, columnCount);
2356     QtTestTableView view;
2357     view.resize(2 * columnWidth, 100);
2358 
2359     view.setModel(&model);
2360 
2361     for (int c = 0; c < columnCount; ++c)
2362         view.setColumnWidth(c, columnWidth);
2363 
2364     for (int i = 0; i < hiddenColumns.count(); ++i)
2365         view.hideColumn(hiddenColumns.at(i));
2366 
2367     QCOMPARE(view.columnAt(coordinate), column);
2368 }
2369 
columnWidth_data()2370 void tst_QTableView::columnWidth_data()
2371 {
2372     QTest::addColumn<int>("columnCount");
2373     QTest::addColumn<IntList>("columnWidths");
2374     QTest::addColumn<BoolList>("hiddenColumns");
2375 
2376     QTest::newRow("increasing")
2377       << 5
2378       << (IntList() << 20 << 30 << 40 << 50 << 60)
2379       << (BoolList() << false << false << false << false << false);
2380 
2381     QTest::newRow("decreasing")
2382       << 5
2383       << (IntList() << 60 << 50 << 40 << 30 << 20)
2384       << (BoolList() << false << false << false << false << false);
2385 
2386     QTest::newRow("random")
2387       << 5
2388       << (IntList() << 87 << 34 << 68 << 91 << 27)
2389       << (BoolList() << false << false << false << false << false);
2390 
2391     // ### expand the dataset to include hidden columns
2392 }
2393 
columnWidth()2394 void tst_QTableView::columnWidth()
2395 {
2396     QFETCH(int, columnCount);
2397     QFETCH(IntList, columnWidths);
2398     QFETCH(BoolList, hiddenColumns);
2399 
2400     QtTestTableModel model(1, columnCount);
2401     QtTestTableView view;
2402 
2403     view.setModel(&model);
2404 
2405     for (int c = 0; c < columnCount; ++c) {
2406         view.setColumnWidth(c, columnWidths.at(c));
2407         view.setColumnHidden(c, hiddenColumns.at(c));
2408     }
2409 
2410     for (int c = 0; c < columnCount; ++c) {
2411         if (hiddenColumns.at(c))
2412             QCOMPARE(view.columnWidth(c), 0);
2413         else
2414             QCOMPARE(view.columnWidth(c), columnWidths.at(c));
2415     }
2416 }
2417 
hiddenRow_data()2418 void tst_QTableView::hiddenRow_data()
2419 {
2420     QTest::addColumn<int>("rowCount");
2421     QTest::addColumn<BoolList>("hiddenRows");
2422 
2423     QTest::newRow("first hidden")
2424       << 5 << (BoolList() << true << false << false << false << false);
2425 
2426     QTest::newRow("last hidden")
2427       << 5 << (BoolList() << false << false << false << false << true);
2428 
2429     QTest::newRow("none hidden")
2430       << 5 << (BoolList() << false << false << false << false << false);
2431 
2432     QTest::newRow("all hidden")
2433       << 5 << (BoolList() << true << true << true << true << true);
2434  }
2435 
hiddenRow()2436 void tst_QTableView::hiddenRow()
2437 {
2438     QFETCH(int, rowCount);
2439     QFETCH(BoolList, hiddenRows);
2440 
2441 
2442     QtTestTableModel model(rowCount, 1);
2443     QtTestTableView view;
2444 
2445     view.setModel(&model);
2446 
2447     for (int r = 0; r < rowCount; ++r)
2448         QVERIFY(!view.isRowHidden(r));
2449 
2450     for (int r = 0; r < rowCount; ++r)
2451         view.setRowHidden(r, hiddenRows.at(r));
2452 
2453     for (int r = 0; r < rowCount; ++r)
2454         QCOMPARE(view.isRowHidden(r), hiddenRows.at(r));
2455 
2456     for (int r = 0; r < rowCount; ++r)
2457         view.setRowHidden(r, false);
2458 
2459     for (int r = 0; r < rowCount; ++r)
2460         QVERIFY(!view.isRowHidden(r));
2461 }
2462 
hiddenColumn_data()2463 void tst_QTableView::hiddenColumn_data()
2464 {
2465     QTest::addColumn<int>("columnCount");
2466     QTest::addColumn<BoolList>("hiddenColumns");
2467 
2468     QTest::newRow("first hidden")
2469       << 5 << (BoolList() << true << false << false << false << false);
2470 
2471     QTest::newRow("last hidden")
2472       << 5 << (BoolList() << false << false << false << false << true);
2473 
2474     QTest::newRow("none hidden")
2475       << 5 << (BoolList() << false << false << false << false << false);
2476 
2477     QTest::newRow("all hidden")
2478       << 5 << (BoolList() << true << true << true << true << true);
2479 }
2480 
hiddenColumn()2481 void tst_QTableView::hiddenColumn()
2482 {
2483     QFETCH(int, columnCount);
2484     QFETCH(BoolList, hiddenColumns);
2485 
2486     QtTestTableModel model(1, columnCount);
2487     QtTestTableView view;
2488 
2489     view.setModel(&model);
2490 
2491     for (int c = 0; c < columnCount; ++c)
2492         QVERIFY(!view.isColumnHidden(c));
2493 
2494     for (int c = 0; c < columnCount; ++c)
2495         view.setColumnHidden(c, hiddenColumns.at(c));
2496 
2497     for (int c = 0; c < columnCount; ++c)
2498         QCOMPARE(view.isColumnHidden(c), hiddenColumns.at(c));
2499 
2500     for (int c = 0; c < columnCount; ++c)
2501         view.setColumnHidden(c, false);
2502 
2503     for (int c = 0; c < columnCount; ++c)
2504         QVERIFY(!view.isColumnHidden(c));
2505 }
2506 
sortingEnabled_data()2507 void tst_QTableView::sortingEnabled_data()
2508 {
2509 //    QTest::addColumn<int>("columnCount");
2510 }
2511 
sortingEnabled()2512 void tst_QTableView::sortingEnabled()
2513 {
2514 //    QFETCH(int, columnCount);
2515 }
2516 
scrollTo_data()2517 void tst_QTableView::scrollTo_data()
2518 {
2519     QTest::addColumn<int>("verticalScrollMode");
2520     QTest::addColumn<int>("horizontalScrollMode");
2521     QTest::addColumn<int>("rowCount");
2522     QTest::addColumn<int>("columnCount");
2523     QTest::addColumn<int>("rowHeight");
2524     QTest::addColumn<int>("columnWidth");
2525     QTest::addColumn<int>("hiddenRow");
2526     QTest::addColumn<int>("hiddenColumn");
2527     QTest::addColumn<int>("row");
2528     QTest::addColumn<int>("column");
2529     QTest::addColumn<int>("rowSpan");
2530     QTest::addColumn<int>("columnSpan");
2531     QTest::addColumn<int>("horizontalScroll");
2532     QTest::addColumn<int>("verticalScroll");
2533     QTest::addColumn<int>("scrollHint");
2534     QTest::addColumn<int>("expectedHorizontalScroll");
2535     QTest::addColumn<int>("expectedVerticalScroll");
2536 
2537     QTest::newRow("no hidden, no span, no scroll, per item")
2538         << (int)QAbstractItemView::ScrollPerItem
2539         << (int)QAbstractItemView::ScrollPerItem
2540         << 10 << 10  // table
2541         << 80 << 80  // size
2542         << -1 << -1  // hide
2543         << 0 << 0    // cell
2544         << 1 << 1    // span
2545         << 0 << 0    // scroll
2546         << (int)QAbstractItemView::PositionAtTop
2547         << 0 << 0;   // expected
2548 
2549     QTest::newRow("no hidden, no span, no scroll, per pixel")
2550         << (int)QAbstractItemView::ScrollPerPixel
2551         << (int)QAbstractItemView::ScrollPerPixel
2552         << 10 << 10  // table
2553         << 80 << 80  // size
2554         << -1 << -1  // hide
2555         << 0 << 0    // cell
2556         << 1 << 1    // span
2557         << 0 << 0    // scroll
2558         << (int)QAbstractItemView::PositionAtTop
2559         << 0 << 0;   // expected
2560 
2561     QTest::newRow("hidden, no span, no scroll, per item")
2562         << (int)QAbstractItemView::ScrollPerItem
2563         << (int)QAbstractItemView::ScrollPerItem
2564         << 10 << 10  // table
2565         << 80 << 80  // size
2566         << 3 << 3    // hide
2567         << 5 << 5    // cell
2568         << 1 << 1    // span
2569         << 0 << 0    // scroll
2570         << (int)QAbstractItemView::PositionAtTop
2571         << 4 << 4;   // expected
2572 }
2573 
scrollTo()2574 void tst_QTableView::scrollTo()
2575 {
2576     QFETCH(int, horizontalScrollMode);
2577     QFETCH(int, verticalScrollMode);
2578     QFETCH(int, rowCount);
2579     QFETCH(int, columnCount);
2580     QFETCH(int, rowHeight);
2581     QFETCH(int, columnWidth);
2582     QFETCH(int, hiddenRow);
2583     QFETCH(int, hiddenColumn);
2584     QFETCH(int, row);
2585     QFETCH(int, column);
2586     QFETCH(int, rowSpan);
2587     QFETCH(int, columnSpan);
2588     QFETCH(int, horizontalScroll);
2589     QFETCH(int, verticalScroll);
2590     QFETCH(int, scrollHint);
2591     QFETCH(int, expectedHorizontalScroll);
2592     QFETCH(int, expectedVerticalScroll);
2593 
2594     QtTestTableModel model(rowCount, columnCount);
2595     QWidget toplevel;
2596     QtTestTableView view(&toplevel);
2597 
2598     toplevel.show();
2599     // resizing to this size will ensure that there can ONLY_BE_ONE_CELL inside the view.
2600     QSize forcedSize(columnWidth * 2, rowHeight * 2);
2601     view.resize(forcedSize);
2602     QTest::qWaitForWindowShown(&view);
2603     QTest::qWait(50);
2604     QTRY_COMPARE(view.size(), forcedSize);
2605 
2606     view.setModel(&model);
2607     view.setSpan(row, column, rowSpan, columnSpan);
2608     view.hideRow(hiddenRow);
2609     view.hideColumn(hiddenColumn);
2610     view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)horizontalScrollMode);
2611     view.setVerticalScrollMode((QAbstractItemView::ScrollMode)verticalScrollMode);
2612 
2613     for (int r = 0; r < rowCount; ++r)
2614         view.setRowHeight(r, rowHeight);
2615     for (int c = 0; c < columnCount; ++c)
2616         view.setColumnWidth(c, columnWidth);
2617 
2618     QTest::qWait(150); // ### needed to pass the test
2619     view.horizontalScrollBar()->setValue(horizontalScroll);
2620     view.verticalScrollBar()->setValue(verticalScroll);
2621 
2622     QModelIndex index = model.index(row, column);
2623     QVERIFY(index.isValid());
2624     view.scrollTo(index, (QAbstractItemView::ScrollHint)scrollHint);
2625     QCOMPARE(view.verticalScrollBar()->value(), expectedVerticalScroll);
2626     QCOMPARE(view.horizontalScrollBar()->value(), expectedHorizontalScroll);
2627 }
2628 
indexAt_data()2629 void tst_QTableView::indexAt_data()
2630 {
2631     QTest::addColumn<int>("rowCount");
2632     QTest::addColumn<int>("columnCount");
2633 
2634     QTest::addColumn<int>("rowHeight");
2635     QTest::addColumn<int>("columnWidth");
2636 
2637     QTest::addColumn<int>("hiddenRow");
2638     QTest::addColumn<int>("hiddenColumn");
2639 
2640     QTest::addColumn<int>("row");
2641     QTest::addColumn<int>("column");
2642     QTest::addColumn<int>("rowSpan");
2643     QTest::addColumn<int>("columnSpan");
2644     QTest::addColumn<int>("horizontalScroll");
2645     QTest::addColumn<int>("verticalScroll");
2646     QTest::addColumn<int>("x");
2647     QTest::addColumn<int>("y");
2648     QTest::addColumn<int>("expectedRow");
2649     QTest::addColumn<int>("expectedColumn");
2650 
2651     QTest::newRow("no hidden, no span, no scroll, (20,20)")
2652       << 10 << 10  // dim
2653       << 40 << 40  // size
2654       << -1 << -1  // hide
2655       << -1 << -1  // pos
2656       << 1 << 1    // span
2657       << 0 << 0    // scroll
2658       << 20 << 20  // point
2659       << 0 << 0;   // expected
2660 
2661     QTest::newRow("row hidden, no span, no scroll, at (20,20)")
2662       << 10 << 10  // dim
2663       << 40 << 40  // size
2664       << 0 << -1   // hide
2665       << -1 << -1  // pos
2666       << 1 << 1    // span
2667       << 0 << 0    // scroll
2668       << 20 << 20  // point
2669       << 1 << 0;   // expected
2670 
2671     QTest::newRow("col hidden, no span, no scroll, at (20,20)")
2672       << 10 << 10  // dim
2673       << 40 << 40  // size
2674       << -1 << 0   // hide
2675       << -1 << -1  // pos
2676       << 1 << 1    // span
2677       << 0 << 0    // scroll
2678       << 20 << 20  // point
2679       << 0 << 1;   // expected
2680 
2681     QTest::newRow("no hidden, row span, no scroll, at (60,20)")
2682       << 10 << 10  // dim
2683       << 40 << 40  // size
2684       << -1 << -1  // hide
2685       << 0 << 0    // pos
2686       << 2 << 1    // span
2687       << 0 << 0    // scroll
2688       << 20 << 60  // point
2689       << 0 << 0;   // expected
2690 
2691 
2692     QTest::newRow("no hidden, col span, no scroll, at (60,20)")
2693       << 10 << 10  // dim
2694       << 40 << 40  // size
2695       << -1 << -1  // hide
2696       << 0 << 0    // pos
2697       << 1 << 2    // span
2698       << 0 << 0    // scroll
2699       << 60 << 20  // point
2700       << 0 << 0;   // expected
2701 
2702     QTest::newRow("no hidden, no span, scroll (5,0), at (20,20)")
2703       << 10 << 10  // dim
2704       << 40 << 40  // size
2705       << -1 << -1  // hide
2706       << -1 << -1  // pos
2707       << 1 << 1    // span
2708       << 5 << 0    // scroll
2709       << 20 << 20  // point
2710       << 0 << 5;   // expected
2711 
2712     QTest::newRow("no hidden, no span, scroll (0,5), at (20,20)")
2713       << 10 << 10  // dim
2714       << 40 << 40  // size
2715       << -1 << -1  // hide
2716       << -1 << -1  // pos
2717       << 1 << 1    // span
2718       << 0 << 5    // scroll
2719       << 20 << 20  // point
2720       << 5 << 0;   // expected
2721 
2722     QTest::newRow("no hidden, no span, scroll (5,5), at (20,20)")
2723       << 10 << 10  // dim
2724       << 40 << 40  // size
2725       << -1 << -1  // hide
2726       << -1 << -1  // pos
2727       << 1 << 1    // span
2728       << 5 << 5    // scroll
2729       << 20 << 20  // point
2730       << 5 << 5;   // expected
2731 }
2732 
indexAt()2733 void tst_QTableView::indexAt()
2734 {
2735     QFETCH(int, rowCount);
2736     QFETCH(int, columnCount);
2737     QFETCH(int, rowHeight);
2738     QFETCH(int, columnWidth);
2739     QFETCH(int, hiddenRow);
2740     QFETCH(int, hiddenColumn);
2741     QFETCH(int, row);
2742     QFETCH(int, column);
2743     QFETCH(int, rowSpan);
2744     QFETCH(int, columnSpan);
2745     QFETCH(int, horizontalScroll);
2746     QFETCH(int, verticalScroll);
2747     QFETCH(int, x);
2748     QFETCH(int, y);
2749     QFETCH(int, expectedRow);
2750     QFETCH(int, expectedColumn);
2751 
2752     QtTestTableModel model(rowCount, columnCount);
2753     QWidget toplevel;
2754     QtTestTableView view(&toplevel);
2755 
2756     toplevel.show();
2757     QTest::qWaitForWindowShown(&toplevel);
2758 
2759     //some styles change the scroll mode in their polish
2760     view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
2761     view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
2762 
2763     view.setModel(&model);
2764     view.setSpan(row, column, rowSpan, columnSpan);
2765     view.hideRow(hiddenRow);
2766     view.hideColumn(hiddenColumn);
2767 
2768     for (int r = 0; r < rowCount; ++r)
2769         view.setRowHeight(r, rowHeight);
2770     for (int c = 0; c < columnCount; ++c)
2771         view.setColumnWidth(c, columnWidth);
2772 
2773     QTest::qWait(20);
2774     view.horizontalScrollBar()->setValue(horizontalScroll);
2775     view.verticalScrollBar()->setValue(verticalScroll);
2776     QTest::qWait(20);
2777 
2778     QModelIndex index = view.indexAt(QPoint(x, y));
2779     QCOMPARE(index.row(), expectedRow);
2780     QCOMPARE(index.column(), expectedColumn);
2781 }
2782 
span_data()2783 void tst_QTableView::span_data()
2784 {
2785     QTest::addColumn<int>("rowCount");
2786     QTest::addColumn<int>("columnCount");
2787     QTest::addColumn<int>("hiddenRow");
2788     QTest::addColumn<int>("hiddenColumn");
2789     QTest::addColumn<int>("row");
2790     QTest::addColumn<int>("column");
2791     QTest::addColumn<int>("rowSpan");
2792     QTest::addColumn<int>("columnSpan");
2793     QTest::addColumn<int>("expectedRowSpan");
2794     QTest::addColumn<int>("expectedColumnSpan");
2795     QTest::addColumn<bool>("clear");
2796 
2797     QTest::newRow("top left 2x2")
2798       << 10 << 10
2799       << -1 << -1
2800       << 0 << 0
2801       << 2 << 2
2802       << 2 << 2
2803       << false;
2804 
2805     QTest::newRow("top left 1x2")
2806       << 10 << 10
2807       << 3 << 3
2808       << 0 << 0
2809       << 1 << 2
2810       << 1 << 2
2811       << false;
2812 
2813     QTest::newRow("top left 2x1")
2814       << 10 << 10
2815       << -1 << -1
2816       << 0 << 0
2817       << 2 << 1
2818       << 2 << 1
2819       << false;
2820 
2821   /* This makes no sens.
2822     QTest::newRow("top left 2x0")
2823       << 10 << 10
2824       << -1 << -1
2825       << 0 << 0
2826       << 2 << 0
2827       << 2 << 0
2828       << false;
2829 
2830     QTest::newRow("top left 0x2")
2831       << 10 << 10
2832       << -1 << -1
2833       << 0 << 0
2834       << 0 << 2
2835       << 0 << 2
2836       << false;*/
2837 
2838     QTest::newRow("invalid 2x2")
2839       << 10 << 10
2840       << -1 << -1
2841       << -1 << -1
2842       << 2 << 2
2843       << 1 << 1
2844       << false;
2845 
2846     QTest::newRow("top left 2x2")
2847       << 10 << 10
2848       << -1 << -1
2849       << 0 << 0
2850       << 2 << 2
2851       << 2 << 2
2852       << false;
2853 
2854     QTest::newRow("bottom right 2x2")
2855       << 10 << 10
2856       << -1 << -1
2857       << 8 << 8
2858       << 2 << 2
2859       << 2 << 2
2860       << false;
2861 
2862     QTest::newRow("invalid span 2x2")
2863       << 10 << 10
2864       << -1 << -1
2865       << 8 << 8
2866       << 2 << 2
2867       << 2 << 2
2868       << false;
2869 
2870     QTest::newRow("invalid span 3x3")
2871       << 10 << 10
2872       << -1 << -1
2873       << 6 << 6
2874       << 3 << 3
2875       << 2 << 3
2876       << true;
2877 
2878 }
2879 
span()2880 void tst_QTableView::span()
2881 {
2882     QFETCH(int, rowCount);
2883     QFETCH(int, columnCount);
2884     QFETCH(int, hiddenRow);
2885     QFETCH(int, hiddenColumn);
2886     QFETCH(int, row);
2887     QFETCH(int, column);
2888     QFETCH(int, rowSpan);
2889     QFETCH(int, columnSpan);
2890     QFETCH(int, expectedRowSpan);
2891     QFETCH(int, expectedColumnSpan);
2892     QFETCH(bool, clear);
2893 
2894     QtTestTableModel model(rowCount, columnCount);
2895     QtTestTableView view;
2896 
2897     view.setModel(&model);
2898     view.show();
2899 
2900     view.setSpan(row, column, rowSpan, columnSpan);
2901     if (clear) {
2902         model.removeLastRow();
2903         model.removeLastRow();
2904         view.update();
2905     }
2906 
2907     view.hideRow(hiddenRow);
2908     view.hideColumn(hiddenColumn);
2909     view.show();
2910 
2911     QCOMPARE(view.rowSpan(row, column), expectedRowSpan);
2912     QCOMPARE(view.columnSpan(row, column), expectedColumnSpan);
2913 
2914     if (hiddenRow > -1) {
2915         QModelIndex hidden = model.index(hiddenRow, columnCount - 1);
2916 	QVERIFY(view.isIndexHidden(hidden));
2917     }
2918 
2919     if (hiddenColumn > -1) {
2920         QModelIndex hidden = model.index(rowCount - 1, hiddenColumn);
2921         QVERIFY(view.isIndexHidden(hidden));
2922     }
2923 
2924     view.clearSpans();
2925     QCOMPARE(view.rowSpan(row, column), 1);
2926     QCOMPARE(view.columnSpan(row, column), 1);
2927 
2928     VERIFY_SPANS_CONSISTENCY(&view);
2929 }
2930 
2931 typedef QVector<QRect> SpanList;
Q_DECLARE_METATYPE(SpanList)2932 Q_DECLARE_METATYPE(SpanList)
2933 
2934 void tst_QTableView::spans_data()
2935 {
2936     QTest::addColumn<int>("rows");
2937     QTest::addColumn<int>("columns");
2938     QTest::addColumn<SpanList>("spans");
2939     QTest::addColumn<bool>("hideRowLastRowOfFirstSpan");
2940     QTest::addColumn<QPoint>("pos");
2941     QTest::addColumn<int>("expectedRowSpan");
2942     QTest::addColumn<int>("expectedColumnSpan");
2943 
2944     QTest::newRow("1x3 span, query 3,0")
2945       << 5 << 5
2946       << (SpanList() << QRect(3, 0, 1, 3))
2947       << false //no hidden row
2948       << QPoint(3, 0)
2949       << 1
2950       << 3;
2951 
2952     QTest::newRow("1x3 span, query 3,1")
2953       << 5 << 5
2954       << (SpanList() << QRect(3, 0, 1, 3))
2955       << false //no hidden row
2956       << QPoint(3, 1)
2957       << 1
2958       << 3;
2959 
2960     QTest::newRow("1x3 span, query 3,2")
2961       << 5 << 5
2962       << (SpanList() << QRect(3, 0, 1, 3))
2963       << false //no hidden row
2964       << QPoint(3, 2)
2965       << 1
2966       << 3;
2967 
2968     QTest::newRow("two 1x2 spans at the same column, query at 3,0")
2969       << 5 << 5
2970       << (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
2971       << false //no hidden row
2972       << QPoint(3, 0)
2973       << 1
2974       << 2;
2975 
2976     QTest::newRow("two 1x2 spans at the same column, query at 4,0")
2977       << 5 << 5
2978       << (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
2979       << false //no hidden row
2980       << QPoint(4, 0)
2981       << 1
2982       << 2;
2983 
2984     QTest::newRow("how to order spans (1,1)")
2985       << 5 << 5
2986       << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
2987       << false //no hidden row
2988       << QPoint(1, 1)
2989       << 3
2990       << 1;
2991 
2992     QTest::newRow("how to order spans (2,1)")
2993       << 5 << 5
2994       << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
2995       << false //no hidden row
2996       << QPoint(2, 1)
2997       << 3
2998       << 1;
2999 
3000     QTest::newRow("how to order spans (3,1)")
3001       << 5 << 5
3002       << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
3003       << false //no hidden row
3004       << QPoint(3, 1)
3005       << 3
3006       << 1;
3007 
3008     QTest::newRow("how to order spans (1,2)")
3009       << 5 << 5
3010       << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
3011       << false //no hidden row
3012       << QPoint(1, 2)
3013       << 2
3014       << 1;
3015 
3016     QTest::newRow("how to order spans (2,2)")
3017       << 5 << 5
3018       << (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
3019       << false //no hidden row
3020       << QPoint(2, 2)
3021       << 2
3022       << 1;
3023 
3024     QTest::newRow("spans with hidden rows")
3025       << 3 << 2
3026       << (SpanList() << QRect(0, 0, 2, 2) << QRect(2, 0, 1, 2))
3027       << true //we hide the last row of the first span
3028       << QPoint(2, 0)
3029       << 1
3030       << 2;
3031 
3032     QTest::newRow("QTBUG-6004: No failing assertion, then it passes.")
3033       << 5 << 5
3034       << (SpanList() << QRect(0, 0, 2, 2) << QRect(0, 0, 1, 1))
3035       << false
3036       << QPoint(0, 0)
3037       << 1
3038       << 1;
3039 
3040     QTest::newRow("QTBUG-6004 (follow-up): No failing assertion, then it passes.")
3041       << 10 << 10
3042       << (SpanList() << QRect(2, 2, 1, 3) << QRect(2, 2, 1, 1))
3043       << false
3044       << QPoint(0, 0)
3045       << 1
3046       << 1;
3047 
3048     QTest::newRow("QTBUG-9631: remove one span")
3049       << 10 << 10
3050       << (SpanList() << QRect(1, 1, 2, 1) << QRect(2, 2, 2, 2) << QRect(1, 1, 1, 1))
3051       << false
3052       << QPoint(1, 1)
3053       << 1
3054       << 1;
3055 }
3056 
spans()3057 void tst_QTableView::spans()
3058 {
3059     QFETCH(int, rows);
3060     QFETCH(int, columns);
3061     QFETCH(SpanList, spans);
3062     QFETCH(bool, hideRowLastRowOfFirstSpan);
3063     QFETCH(QPoint, pos);
3064     QFETCH(int, expectedRowSpan);
3065     QFETCH(int, expectedColumnSpan);
3066 
3067     QtTestTableModel model(rows, columns);
3068     QtTestTableView view;
3069 
3070     view.setModel(&model);
3071     view.show();
3072 
3073     for (int i = 0; i < spans.count(); ++i) {
3074         QRect sp = spans.at(i);
3075         view.setSpan(sp.x(), sp.y(), sp.width(), sp.height());
3076     }
3077 
3078     if (hideRowLastRowOfFirstSpan) {
3079         view.setRowHidden(spans.at(0).bottom(), true);
3080         //we check that the span didn't break the visual rects of the model indexes
3081         QRect first = view.visualRect( model.index(spans.at(0).top(), 0));
3082         QRect next = view.visualRect( model.index(spans.at(0).bottom() + 1, 0));
3083         QVERIFY(first.intersected(next).isEmpty());
3084     }
3085 
3086     QCOMPARE(view.columnSpan(pos.x(), pos.y()), expectedColumnSpan);
3087     QCOMPARE(view.rowSpan(pos.x(), pos.y()), expectedRowSpan);
3088 
3089     VERIFY_SPANS_CONSISTENCY(&view);
3090 }
3091 
spansAfterRowInsertion()3092 void tst_QTableView::spansAfterRowInsertion()
3093 {
3094     QtTestTableModel model(10, 10);
3095     QtTestTableView view;
3096     view.setModel(&model);
3097     view.setSpan(3, 3, 3, 3);
3098     view.show();
3099     QTest::qWait(50);
3100 
3101     // Insertion before the span only shifts the span.
3102     view.model()->insertRows(0, 2);
3103     QCOMPARE(view.rowSpan(3, 3), 1);
3104     QCOMPARE(view.columnSpan(3, 3), 1);
3105     QCOMPARE(view.rowSpan(5, 3), 3);
3106     QCOMPARE(view.columnSpan(5, 3), 3);
3107 
3108     // Insertion happens before the given row, so it only shifts the span also.
3109     view.model()->insertRows(5, 2);
3110     QCOMPARE(view.rowSpan(5, 3), 1);
3111     QCOMPARE(view.columnSpan(5, 3), 1);
3112     QCOMPARE(view.rowSpan(7, 3), 3);
3113     QCOMPARE(view.columnSpan(7, 3), 3);
3114 
3115     // Insertion inside the span expands it.
3116     view.model()->insertRows(8, 2);
3117     QCOMPARE(view.rowSpan(7, 3), 5);
3118     QCOMPARE(view.columnSpan(7, 3), 3);
3119 
3120     // Insertion after the span does nothing to it.
3121     view.model()->insertRows(12, 2);
3122     QCOMPARE(view.rowSpan(7, 3), 5);
3123     QCOMPARE(view.columnSpan(7, 3), 3);
3124 
3125     VERIFY_SPANS_CONSISTENCY(&view);
3126 }
3127 
spansAfterColumnInsertion()3128 void tst_QTableView::spansAfterColumnInsertion()
3129 {
3130     QtTestTableModel model(10, 10);
3131     QtTestTableView view;
3132     view.setModel(&model);
3133     view.setSpan(3, 3, 3, 3);
3134     view.show();
3135     QTest::qWait(50);
3136 
3137     // Insertion before the span only shifts the span.
3138     view.model()->insertColumns(0, 2);
3139     QCOMPARE(view.rowSpan(3, 3), 1);
3140     QCOMPARE(view.columnSpan(3, 3), 1);
3141     QCOMPARE(view.rowSpan(3, 5), 3);
3142     QCOMPARE(view.columnSpan(3, 5), 3);
3143 
3144     // Insertion happens before the given column, so it only shifts the span also.
3145     view.model()->insertColumns(5, 2);
3146     QCOMPARE(view.rowSpan(3, 5), 1);
3147     QCOMPARE(view.columnSpan(3, 5), 1);
3148     QCOMPARE(view.rowSpan(3, 7), 3);
3149     QCOMPARE(view.columnSpan(3, 7), 3);
3150 
3151     // Insertion inside the span expands it.
3152     view.model()->insertColumns(8, 2);
3153     QCOMPARE(view.rowSpan(3, 7), 3);
3154     QCOMPARE(view.columnSpan(3, 7), 5);
3155 
3156     // Insertion after the span does nothing to it.
3157     view.model()->insertColumns(12, 2);
3158     QCOMPARE(view.rowSpan(3, 7), 3);
3159     QCOMPARE(view.columnSpan(3, 7), 5);
3160 
3161     VERIFY_SPANS_CONSISTENCY(&view);
3162 }
3163 
spansAfterRowRemoval()3164 void tst_QTableView::spansAfterRowRemoval()
3165 {
3166     QtTestTableModel model(10, 10);
3167     QtTestTableView view;
3168     view.setModel(&model);
3169 
3170     QList<QRect> spans;
3171     spans << QRect(0, 1, 1, 2)
3172           << QRect(1, 2, 1, 2)
3173           << QRect(2, 2, 1, 5)
3174           << QRect(2, 8, 1, 2)
3175           << QRect(3, 4, 1, 2)
3176           << QRect(4, 4, 1, 4)
3177           << QRect(5, 6, 1, 3)
3178           << QRect(6, 7, 1, 3);
3179     foreach (QRect span, spans)
3180         view.setSpan(span.top(), span.left(), span.height(), span.width());
3181 
3182     view.show();
3183     QTest::qWait(100);
3184     view.model()->removeRows(3, 3);
3185 
3186     QList<QRect> expectedSpans;
3187     expectedSpans << QRect(0, 1, 1, 2)
3188           << QRect(1, 2, 1, 1)
3189           << QRect(2, 2, 1, 2)
3190           << QRect(2, 5, 1, 2)
3191           << QRect(3, 4, 1, 1)
3192           << QRect(4, 3, 1, 2)
3193           << QRect(5, 3, 1, 3)
3194           << QRect(6, 4, 1, 3);
3195     foreach (QRect span, expectedSpans) {
3196         QCOMPARE(view.columnSpan(span.top(), span.left()), span.width());
3197         QCOMPARE(view.rowSpan(span.top(), span.left()), span.height());
3198     }
3199 
3200     VERIFY_SPANS_CONSISTENCY(&view);
3201 }
3202 
spansAfterColumnRemoval()3203 void tst_QTableView::spansAfterColumnRemoval()
3204 {
3205     QtTestTableModel model(10, 10);
3206     QtTestTableView view;
3207     view.setModel(&model);
3208 
3209     // Same set as above just swapping columns and rows.
3210     QList<QRect> spans;
3211     spans << QRect(0, 1, 1, 2)
3212           << QRect(1, 2, 1, 2)
3213           << QRect(2, 2, 1, 5)
3214           << QRect(2, 8, 1, 2)
3215           << QRect(3, 4, 1, 2)
3216           << QRect(4, 4, 1, 4)
3217           << QRect(5, 6, 1, 3)
3218           << QRect(6, 7, 1, 3);
3219     foreach (QRect span, spans)
3220         view.setSpan(span.left(), span.top(), span.width(), span.height());
3221 
3222     view.show();
3223     QTest::qWait(100);
3224     view.model()->removeColumns(3, 3);
3225 
3226     QList<QRect> expectedSpans;
3227     expectedSpans << QRect(0, 1, 1, 2)
3228           << QRect(1, 2, 1, 1)
3229           << QRect(2, 2, 1, 2)
3230           << QRect(2, 5, 1, 2)
3231           << QRect(3, 4, 1, 1)
3232           << QRect(4, 3, 1, 2)
3233           << QRect(5, 3, 1, 3)
3234           << QRect(6, 4, 1, 3);
3235     foreach (QRect span, expectedSpans) {
3236         QCOMPARE(view.columnSpan(span.left(), span.top()), span.height());
3237         QCOMPARE(view.rowSpan(span.left(), span.top()), span.width());
3238     }
3239 
3240     VERIFY_SPANS_CONSISTENCY(&view);
3241 }
3242 
3243 class Model : public QAbstractTableModel {
3244 
3245 Q_OBJECT
3246 
3247 public:
Model(QObject * parent=0)3248     Model(QObject * parent = 0) : QAbstractTableModel(parent) {
3249     }
3250 
rowCount(const QModelIndex &) const3251     int rowCount(const QModelIndex &) const {
3252         return rows;
3253     }
columnCount(const QModelIndex &) const3254     int columnCount(const QModelIndex &) const {
3255         return columns;
3256     }
data(const QModelIndex &,int) const3257     QVariant data(const QModelIndex &, int) const
3258     {
3259         return QVariant();
3260     }
res()3261     void res() { reset(); }
3262 
3263     int rows;
3264     int columns;
3265 };
3266 
checkHeaderReset()3267 void tst_QTableView::checkHeaderReset()
3268 {
3269     QTableView view;
3270     Model m;
3271     m.rows = 3;
3272     m.columns = 3;
3273     view.setModel(&m);
3274 
3275     m.rows = 4;
3276     m.columns = 4;
3277     m.res();
3278     QCOMPARE(view.horizontalHeader()->count(), 4);
3279 }
3280 
checkHeaderMinSize()3281 void tst_QTableView::checkHeaderMinSize()
3282 {
3283     //tests if the minimumsize is of a header is taken into account
3284     //while computing QTableView geometry. For that we test the position of the
3285     //viewport.
3286     QTableView view;
3287     QStringListModel m;
3288     m.setStringList( QStringList() << QLatin1String("one cell is enough"));
3289     view.setModel(&m);
3290 
3291     //setting the minimum height on the horizontal header
3292     //and the minimum width on the vertical header
3293     view.horizontalHeader()->setMinimumHeight(50);
3294     view.verticalHeader()->setMinimumWidth(100);
3295 
3296     view.show();
3297 
3298     QVERIFY( view.verticalHeader()->y() >= view.horizontalHeader()->minimumHeight());
3299     QVERIFY( view.horizontalHeader()->x() >= view.verticalHeader()->minimumWidth());
3300 }
3301 
resizeToContents()3302 void tst_QTableView::resizeToContents()
3303 {
3304     //checks that the resize to contents is consistent
3305     QTableWidget table(2,3);
3306     QTableWidget table2(2,3);
3307     QTableWidget table3(2,3);
3308 
3309 
3310     table.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
3311     table2.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
3312     table3.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
3313     table.horizontalHeader()->setVisible(false);
3314     table2.horizontalHeader()->setVisible(false);
3315     table.verticalHeader()->setVisible(false);
3316     table2.verticalHeader()->setVisible(false);
3317 
3318 
3319     for(int i = 0;i<table.columnCount();i++) {
3320         table.resizeColumnToContents(i);
3321     }
3322     for(int i = 0;i<table.rowCount();i++) {
3323         table.resizeRowToContents(i);
3324     }
3325     table2.resizeColumnsToContents();
3326     table2.resizeRowsToContents();
3327     table3.resizeColumnsToContents();
3328     table3.resizeRowsToContents();
3329 
3330     //now let's check the row/col sizes
3331     for(int i = 0;i<table.columnCount();i++) {
3332         QCOMPARE( table.columnWidth(i), table2.columnWidth(i));
3333         QCOMPARE( table2.columnWidth(i), table3.columnWidth(i));
3334     }
3335     for(int i = 0;i<table.rowCount();i++) {
3336         QCOMPARE( table.rowHeight(i), table2.rowHeight(i));
3337         QCOMPARE( table2.rowHeight(i), table3.rowHeight(i));
3338     }
3339 
3340 }
3341 
3342 QT_BEGIN_NAMESPACE
3343 extern bool Q_GUI_EXPORT qt_tab_all_widgets; // qapplication.cpp
3344 QT_END_NAMESPACE
3345 
tabFocus()3346 void tst_QTableView::tabFocus()
3347 {
3348     if (!qt_tab_all_widgets)
3349         QSKIP("This test requires full keyboard control to be enabled.", SkipAll);
3350 
3351     // QTableView enables tabKeyNavigation by default, but you should be able
3352     // to change focus on an empty table view, or on a table view that doesn't
3353     // have this property set.
3354     QWidget window;
3355 
3356     QTableView *view = new QTableView(&window);
3357     QLineEdit *edit = new QLineEdit(&window);
3358 
3359     window.show();
3360     QApplication::setActiveWindow(&window);
3361     QTest::qWaitForWindowShown(&window);
3362     window.setFocus();
3363     QTest::qWait(100);
3364     window.activateWindow();
3365     QTest::qWait(100);
3366 
3367     qApp->processEvents();
3368 
3369     WAIT_FOR_CONDITION(window.hasFocus(), true);
3370 
3371     qApp->processEvents();
3372 
3373     // window
3374     QVERIFY(window.hasFocus());
3375     QVERIFY(!view->hasFocus());
3376     QVERIFY(!edit->hasFocus());
3377 
3378     for (int i = 0; i < 2; ++i) {
3379         // tab to view
3380         QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
3381         QTRY_VERIFY(!window.hasFocus());
3382         QVERIFY(view->hasFocus());
3383         QVERIFY(!edit->hasFocus());
3384 
3385         // tab to edit
3386         QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
3387         QTRY_VERIFY(edit->hasFocus());
3388         QVERIFY(!window.hasFocus());
3389         QVERIFY(!view->hasFocus());
3390     }
3391 
3392     // backtab to view
3393     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3394     QTRY_VERIFY(view->hasFocus());
3395     QVERIFY(!window.hasFocus());
3396     QVERIFY(!edit->hasFocus());
3397 
3398     // backtab to edit
3399     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3400     QTRY_VERIFY(edit->hasFocus());
3401     QVERIFY(!window.hasFocus());
3402     QVERIFY(!view->hasFocus());
3403 
3404     QStandardItemModel *model = new QStandardItemModel;
3405     view->setModel(model);
3406 
3407     // backtab to view
3408     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3409     QTRY_VERIFY(view->hasFocus());
3410     QVERIFY(!window.hasFocus());
3411     QVERIFY(!edit->hasFocus());
3412 
3413     // backtab to edit
3414     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3415     QTRY_VERIFY(edit->hasFocus());
3416     QVERIFY(!window.hasFocus());
3417     QVERIFY(!view->hasFocus());
3418 
3419     model->insertRow(0, new QStandardItem("Hei"));
3420     model->insertRow(0, new QStandardItem("Hei"));
3421     model->insertRow(0, new QStandardItem("Hei"));
3422 
3423     // backtab to view
3424     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3425     QTRY_VERIFY(view->hasFocus());
3426     QVERIFY(!window.hasFocus());
3427     QVERIFY(!edit->hasFocus());
3428 
3429     // backtab to edit doesn't work
3430     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3431     QVERIFY(!window.hasFocus());
3432     QVERIFY(view->hasFocus());
3433     QVERIFY(!edit->hasFocus());
3434 
3435     view->setTabKeyNavigation(false);
3436 
3437     // backtab to edit
3438     QTest::keyPress(qApp->focusWidget(), Qt::Key_Backtab);
3439     QTRY_VERIFY(edit->hasFocus());
3440     QVERIFY(!window.hasFocus());
3441     QVERIFY(!view->hasFocus());
3442 
3443     QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
3444     QTRY_VERIFY(view->hasFocus());
3445     QTest::keyPress(qApp->focusWidget(), Qt::Key_Tab);
3446     QTRY_VERIFY(edit->hasFocus());
3447 
3448     delete model;
3449 }
3450 
3451 class BigModel : public QAbstractTableModel
3452 {
3453     Q_OBJECT
3454 public:
data(const QModelIndex & index,int role=Qt::DisplayRole) const3455     virtual QVariant data(const QModelIndex &index,
3456                           int role = Qt::DisplayRole) const
3457     {
3458         if (role == Qt::DisplayRole)
3459             return QString("%1 - %2").arg(index.column()).arg(index.row());
3460         return QVariant();
3461     }
3462 
3463 
rowCount(const QModelIndex & parent=QModelIndex ()) const3464     int rowCount(const QModelIndex & parent = QModelIndex()) const
3465     {
3466         Q_UNUSED(parent);
3467         return 10000000;
3468     }
3469 
columnCount(const QModelIndex & parent=QModelIndex ()) const3470     int columnCount(const QModelIndex & parent = QModelIndex()) const
3471     {
3472         Q_UNUSED(parent);
3473         return 20000000;
3474     }
3475 };
3476 
bigModel()3477 void tst_QTableView::bigModel()
3478 {
3479     //should not crash
3480     QTableView view;
3481     BigModel model;
3482     view.setModel(&model);
3483     view.show();
3484     view.setSpan(10002,10002,6,6);
3485     QTest::qWait(100);
3486     view.resize(1000,1000);
3487     QTest::qWait(100);
3488     view.scrollTo(model.index(10010,10010));
3489     QTest::qWait(100);
3490 }
3491 
selectionSignal()3492 void tst_QTableView::selectionSignal()
3493 {
3494     QtTestTableModel model(10, 10);
3495     QtTestTableView view;
3496     view.checkSignalOrder = true;
3497     view.setModel(&model);
3498     view.resize(200, 200);
3499     view.show();
3500     QTest::qWaitForWindowShown(&view);
3501     QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(model.index(2, 0)).center());
3502 }
3503 
3504 class task173773_EventFilter : public QObject
3505 {
3506     int paintEventCount_;
3507 public:
task173773_EventFilter()3508     task173773_EventFilter() : paintEventCount_(0) {}
paintEventCount() const3509     int paintEventCount() const { return paintEventCount_; }
3510 private:
eventFilter(QObject * obj,QEvent * e)3511     bool eventFilter(QObject *obj, QEvent *e)
3512     {
3513         Q_UNUSED(obj);
3514         if (e->type() == QEvent::Paint)
3515             ++paintEventCount_;
3516         return false;
3517     }
3518 };
3519 
task173773_updateVerticalHeader()3520 void tst_QTableView::task173773_updateVerticalHeader()
3521 {
3522     QStandardItemModel model(2, 1);
3523     model.setData(model.index(0, 0), 0);
3524     model.setData(model.index(1, 0), 1);
3525 
3526     QSortFilterProxyModel proxyModel;
3527     proxyModel.setSourceModel(&model);
3528 
3529     QTableView view;
3530     view.setModel(&proxyModel);
3531     view.setSortingEnabled(true);
3532     view.show();
3533     QTest::qWaitForWindowShown(&view);
3534 
3535     view.sortByColumn(0, Qt::AscendingOrder);
3536     QTest::qWait(100);
3537 
3538     task173773_EventFilter eventFilter;
3539     view.verticalHeader()->viewport()->installEventFilter(&eventFilter);
3540 
3541     view.sortByColumn(0, Qt::DescendingOrder);
3542     QTest::qWait(100);
3543 
3544     // ### note: this test may occasionally pass even if the bug is present!
3545     QVERIFY(eventFilter.paintEventCount() > 0);
3546 }
3547 
task227953_setRootIndex()3548 void tst_QTableView::task227953_setRootIndex()
3549 {
3550 	QTableView tableView;
3551 
3552     //model = tree with two items with tables as children
3553     QStandardItemModel model;
3554     QStandardItem item1, item2;
3555     model.appendColumn(QList<QStandardItem*>() << &item1 << &item2);
3556 
3557 
3558     //setup the first table as a child of the first item
3559     for ( int row = 0; row < 40; ++row ) {
3560         item1.appendRow(QList<QStandardItem*>() << new QStandardItem(QString("row %0").arg(row)));
3561     }
3562 
3563     //setup the second table as a child of the second item
3564     for ( int row = 0; row < 10; ++row ) {
3565         item2.appendRow(QList<QStandardItem*>() << new QStandardItem(QString("row %0").arg(row)));
3566     }
3567 
3568     tableView.setModel(&model);
3569 
3570     //show the first 10 rows of the first table
3571     QModelIndex root = model.indexFromItem(&item1);
3572 	tableView.setRootIndex(root);
3573 	for (int i = 10; i != 40; ++i) {
3574 		tableView.setRowHidden(i, true);
3575 	}
3576 
3577     QCOMPARE(tableView.verticalHeader()->count(), 40);
3578     QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 30);
3579 
3580 	//show the first 10 rows of the second table
3581 	tableView.setRootIndex(model.indexFromItem(&item2));
3582 
3583     QCOMPARE(tableView.verticalHeader()->count(), 10);
3584     QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 0);
3585     QVERIFY(!tableView.verticalHeader()->isHidden());
3586 }
3587 
task240266_veryBigColumn()3588 void tst_QTableView::task240266_veryBigColumn()
3589 {
3590     QTableView table;
3591     table.setFixedSize(500, 300); //just to make sure we have the 2 first columns visible
3592     QStandardItemModel model(1, 3);
3593     table.setModel(&model);
3594     table.setColumnWidth(0, 100); //normal column
3595     table.setColumnWidth(1, 100); //normal column
3596     table.setColumnWidth(2, 9000); //very big column
3597     table.show();
3598     QTest::qWaitForWindowShown(&table);
3599 
3600     //some styles change the scroll mode in their polish
3601     table.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
3602     table.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
3603 
3604     QScrollBar *scroll = table.horizontalScrollBar();
3605     QCOMPARE(scroll->minimum(), 0);
3606     QCOMPARE(scroll->maximum(), model.columnCount() - 1);
3607     QCOMPARE(scroll->singleStep(), 1);
3608 
3609     //1 is not always a very correct value for pageStep. Ideally this should be dynamic.
3610     //Maybe something for Qt 5 ;-)
3611     QCOMPARE(scroll->pageStep(), 1);
3612 
3613 }
3614 
task248688_autoScrollNavigation()3615 void tst_QTableView::task248688_autoScrollNavigation()
3616 {
3617     //we make sure that when navigating with the keyboard the view is correctly scrolled
3618     //to the current item
3619     QStandardItemModel model(16, 16);
3620     QTableView view;
3621     view.setModel(&model);
3622 
3623 	view.hideColumn(8);
3624 	view.hideRow(8);
3625     view.show();
3626     for (int r = 0; r < model.rowCount(); ++r) {
3627         if (view.isRowHidden(r))
3628             continue;
3629         for (int c = 0; c < model.columnCount(); ++c) {
3630             if (view.isColumnHidden(c))
3631                 continue;
3632             QModelIndex index = model.index(r, c);
3633             view.setCurrentIndex(index);
3634             QVERIFY(view.viewport()->rect().contains(view.visualRect(index)));
3635         }
3636     }
3637 }
3638 
3639 
mouseWheel_data()3640 void tst_QTableView::mouseWheel_data()
3641 {
3642     QTest::addColumn<int>("scrollMode");
3643     QTest::addColumn<int>("delta");
3644     QTest::addColumn<int>("horizontalPositon");
3645     QTest::addColumn<int>("verticalPosition");
3646 
3647     QTest::newRow("scroll up per item")
3648             << int(QAbstractItemView::ScrollPerItem) << 120
3649             << 10 - qApp->wheelScrollLines() << 10 - qApp->wheelScrollLines();
3650     QTest::newRow("scroll down per item")
3651             << int(QAbstractItemView::ScrollPerItem) << -120
3652             << 10 + qApp->wheelScrollLines() << 10 + qApp->wheelScrollLines();
3653     QTest::newRow("scroll down per pixel")
3654             << int(QAbstractItemView::ScrollPerPixel) << -120
3655             << 10 + qApp->wheelScrollLines() * 89 << 10 + qApp->wheelScrollLines() * 28;
3656 }
3657 
mouseWheel()3658 void tst_QTableView::mouseWheel()
3659 {
3660 #ifdef Q_OS_WINCE
3661     QSKIP("Since different Windows CE versions sport different taskbars, we skip this test", SkipAll);
3662 #endif
3663 
3664     QFETCH(int, scrollMode);
3665     QFETCH(int, delta);
3666     QFETCH(int, horizontalPositon);
3667     QFETCH(int, verticalPosition);
3668 
3669     QtTestTableModel model(100, 100);
3670     QWidget topLevel;
3671     QtTestTableView view(&topLevel);
3672     view.resize(500, 500);
3673     for (int r = 0; r < 100; ++r)
3674         view.setRowHeight(r, 50);
3675     for (int c = 0; c < 100; ++c)
3676         view.setColumnWidth(c, 100);
3677     topLevel.show();
3678 
3679     QTest::qWaitForWindowShown(&topLevel);
3680 
3681     view.setModel(&model);
3682 
3683     view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
3684     view.setVerticalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
3685     view.horizontalScrollBar()->setValue(10);
3686     view.verticalScrollBar()->setValue(10);
3687 
3688     QPoint pos = view.viewport()->geometry().center();
3689     QWheelEvent verticalEvent(pos, delta, 0, 0, Qt::Vertical);
3690     QWheelEvent horizontalEvent(pos, delta, 0, 0, Qt::Horizontal);
3691     QApplication::sendEvent(view.viewport(), &horizontalEvent);
3692     QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 10);
3693     QApplication::sendEvent(view.viewport(), &verticalEvent);
3694     QVERIFY(qAbs(view.verticalScrollBar()->value() - verticalPosition) < 10);
3695 }
3696 
addColumnWhileEditing()3697 void tst_QTableView::addColumnWhileEditing()
3698 {
3699     QTableView view;
3700     QStandardItemModel model(1, 10);
3701     view.setModel(&model);
3702     QModelIndex last = model.index(0,9);
3703     view.show();
3704 
3705     view.openPersistentEditor(last);
3706     view.scrollTo(last);
3707 
3708     //let's see if the editor is moved to the right location
3709     //after adding a column
3710     model.setColumnCount(model.columnCount() + 1);
3711     QPointer<QLineEdit> editor = qFindChild<QLineEdit*>(&view);
3712     QVERIFY(editor);
3713     QCOMPARE(editor->geometry(), view.visualRect(last));
3714 
3715     //let's see if the editor is moved to the right location
3716     //after removing a column
3717     view.scrollTo(model.index(0, model.columnCount()-1));
3718     model.setColumnCount(model.columnCount() - 1);
3719     QVERIFY(editor);
3720     QCOMPARE(editor->geometry(), view.visualRect(last));
3721 }
3722 
task259308_scrollVerticalHeaderSwappedSections()3723 void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections()
3724 {
3725     QStandardItemModel model;
3726     model.setRowCount(50);
3727     model.setColumnCount(2);
3728     for (int row = 0; row < model.rowCount(); ++row)
3729         for (int col = 0; col < model.columnCount(); ++col) {
3730             const QModelIndex &idx = model.index(row, col);
3731             model.setData(idx, QVariant(row), Qt::EditRole);
3732         }
3733 
3734     QTableView tv;
3735     tv.setModel(&model);
3736     tv.show();
3737     tv.verticalHeader()->swapSections(0, model.rowCount() - 1);
3738     tv.setCurrentIndex(model.index(model.rowCount() - 1, 0));
3739 
3740     QTest::qWaitForWindowShown(&tv);
3741     QTest::keyClick(&tv, Qt::Key_PageUp);   // PageUp won't scroll when at top
3742     QTRY_COMPARE(tv.rowAt(0), tv.verticalHeader()->logicalIndex(0));
3743 
3744     int newRow = tv.rowAt(tv.viewport()->height());
3745     if (newRow == tv.rowAt(tv.viewport()->height() - 1)) // Overlapping row
3746         newRow++;
3747     QTest::keyClick(&tv, Qt::Key_PageDown); // Scroll down and check current
3748     QTRY_COMPARE(tv.currentIndex().row(), newRow);
3749 
3750     tv.setCurrentIndex(model.index(0, 0));
3751     QTest::qWait(60);
3752     QTest::keyClick(&tv, Qt::Key_PageDown); // PageDown won't scroll when at the bottom
3753     QTRY_COMPARE(tv.rowAt(tv.viewport()->height() - 1), tv.verticalHeader()->logicalIndex(model.rowCount() - 1));
3754 }
3755 
3756 template <typename T>
3757 struct ValueSaver {
3758     T &var, value;
ValueSaverValueSaver3759     ValueSaver(T &v) : var(v), value(v) { }
~ValueSaverValueSaver3760     ~ValueSaver() { var = value; }
3761 };
3762 
task191545_dragSelectRows()3763 void tst_QTableView::task191545_dragSelectRows()
3764 {
3765     QStandardItemModel model(10, 10);
3766     QTableView table;
3767     table.setModel(&model);
3768     table.setSelectionBehavior(QAbstractItemView::SelectItems);
3769     table.setSelectionMode(QAbstractItemView::ExtendedSelection);
3770     table.setMinimumSize(1000, 400);
3771     table.show();
3772     QTest::qWait(200);
3773 
3774     ValueSaver<Qt::KeyboardModifiers> saver(QApplicationPrivate::modifier_buttons);
3775     QApplicationPrivate::modifier_buttons = Qt::ControlModifier;
3776 
3777     {
3778         QRect cellRect = table.visualRect(model.index(3, 0));
3779         QHeaderView *vHeader = table.verticalHeader();
3780         QWidget *vHeaderVp = vHeader->viewport();
3781         QPoint rowPos(cellRect.center());
3782         QMouseEvent rowPressEvent(QEvent::MouseButtonPress, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3783         qApp->sendEvent(vHeaderVp, &rowPressEvent);
3784 
3785         for (int i = 0; i < 4; ++i) {
3786             rowPos.setY(rowPos.y() + cellRect.height());
3787             QMouseEvent moveEvent(QEvent::MouseMove, rowPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
3788             qApp->sendEvent(vHeaderVp, &moveEvent);
3789         }
3790         QMouseEvent rowReleaseEvent(QEvent::MouseButtonRelease, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3791         qApp->sendEvent(vHeaderVp, &rowReleaseEvent);
3792 
3793         for (int i = 0; i < 4; ++i) {
3794             QModelIndex index = model.index(3 + i, 0, table.rootIndex());
3795             QVERIFY(vHeader->selectionModel()->selectedRows().contains(index));
3796         }
3797     }
3798 
3799     {
3800         QRect cellRect = table.visualRect(model.index(0, 3));
3801         QHeaderView *hHeader = table.horizontalHeader();
3802         QWidget *hHeaderVp = hHeader->viewport();
3803         QPoint colPos((cellRect.left() + cellRect.right()) / 2, 5);
3804         QMouseEvent colPressEvent(QEvent::MouseButtonPress, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3805         qApp->sendEvent(hHeaderVp, &colPressEvent);
3806 
3807         for (int i = 0; i < 4; ++i) {
3808             colPos.setX(colPos.x() + cellRect.width());
3809             QMouseEvent moveEvent(QEvent::MouseMove, colPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
3810             qApp->sendEvent(hHeaderVp, &moveEvent);
3811         }
3812         QMouseEvent colReleaseEvent(QEvent::MouseButtonRelease, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3813         qApp->sendEvent(hHeaderVp, &colReleaseEvent);
3814 
3815         for (int i = 0; i < 4; ++i) {
3816             QModelIndex index = model.index(0, 3 + i, table.rootIndex());
3817             QVERIFY(hHeader->selectionModel()->selectedColumns().contains(index));
3818         }
3819     }
3820 
3821     {
3822         QRect cellRect = table.visualRect(model.index(2, 2));
3823         QWidget *tableVp = table.viewport();
3824         QPoint cellPos = cellRect.center();
3825         QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3826         qApp->sendEvent(tableVp, &cellPressEvent);
3827 
3828         for (int i = 0; i < 6; ++i) {
3829             cellPos.setX(cellPos.x() + cellRect.width());
3830             cellPos.setY(cellPos.y() + cellRect.height());
3831             QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
3832             qApp->sendEvent(tableVp, &moveEvent);
3833         }
3834         QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3835         qApp->sendEvent(tableVp, &cellReleaseEvent);
3836 
3837         for (int i = 0; i < 6; ++i)
3838             for (int j = 0; j < 6; ++j) {
3839                 QModelIndex index = model.index(2 + i, 2 + j, table.rootIndex());
3840                 QVERIFY(table.selectionModel()->isSelected(index));
3841             }
3842     }
3843 
3844     {
3845         QRect cellRect = table.visualRect(model.index(3, 3));
3846         QWidget *tableVp = table.viewport();
3847         QPoint cellPos = cellRect.center();
3848         QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3849         qApp->sendEvent(tableVp, &cellPressEvent);
3850 
3851         for (int i = 0; i < 6; ++i) {
3852             cellPos.setX(cellPos.x() + cellRect.width());
3853             cellPos.setY(cellPos.y() + cellRect.height());
3854             QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
3855             qApp->sendEvent(tableVp, &moveEvent);
3856         }
3857         QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
3858         qApp->sendEvent(tableVp, &cellReleaseEvent);
3859 
3860         QTest::qWait(200);
3861         for (int i = 0; i < 6; ++i)
3862             for (int j = 0; j < 6; ++j) {
3863                 QModelIndex index = model.index(3 + i, 3 + j, table.rootIndex());
3864                 QVERIFY(!table.selectionModel()->isSelected(index));
3865             }
3866     }
3867 }
3868 
task234926_setHeaderSorting()3869 void tst_QTableView::task234926_setHeaderSorting()
3870 {
3871     QStringListModel model;
3872     QStringList data;
3873     data << "orange" << "apple" << "banana" << "lemon" << "pumpkin";
3874     QStringList sortedDataA = data;
3875     QStringList sortedDataD = data;
3876     qSort(sortedDataA);
3877     qSort(sortedDataD.begin(), sortedDataD.end(), qGreater<QString>());
3878     model.setStringList(data);
3879     QTableView view;
3880     view.setModel(&model);
3881 //    view.show();
3882     QTest::qWait(20);
3883     QCOMPARE(model.stringList(), data);
3884     view.setSortingEnabled(true);
3885     view.sortByColumn(0, Qt::AscendingOrder);
3886     QApplication::processEvents();
3887     QCOMPARE(model.stringList() , sortedDataA);
3888 
3889     view.horizontalHeader()->setSortIndicator(0, Qt::DescendingOrder);
3890     QApplication::processEvents();
3891     QCOMPARE(model.stringList() , sortedDataD);
3892 
3893     QHeaderView *h = new QHeaderView(Qt::Horizontal);
3894     h->setModel(&model);
3895     view.setHorizontalHeader(h);
3896     h->setSortIndicator(0, Qt::AscendingOrder);
3897     QApplication::processEvents();
3898     QCOMPARE(model.stringList() , sortedDataA);
3899 
3900     h->setSortIndicator(0, Qt::DescendingOrder);
3901     QApplication::processEvents();
3902     QCOMPARE(model.stringList() , sortedDataD);
3903 }
3904 
taskQTBUG_5062_spansInconsistency()3905 void tst_QTableView::taskQTBUG_5062_spansInconsistency()
3906 {
3907     const int nRows = 5;
3908     const int nColumns = 5;
3909 
3910     QtTestTableModel model(nRows, nColumns);
3911     QtTestTableView view;
3912     view.setModel(&model);
3913 
3914     for (int i = 0; i < nRows; ++i)
3915        view.setSpan(i, 0, 1, nColumns);
3916     view.setSpan(2, 0, 1, 1);
3917     view.setSpan(3, 0, 1, 1);
3918 
3919     VERIFY_SPANS_CONSISTENCY(&view);
3920 }
3921 
taskQTBUG_4516_clickOnRichTextLabel()3922 void tst_QTableView::taskQTBUG_4516_clickOnRichTextLabel()
3923 {
3924     QTableView view;
3925     QStandardItemModel model(5,5);
3926     view.setModel(&model);
3927     QLabel label("rich text");
3928     label.setTextFormat(Qt::RichText);
3929     view.setIndexWidget(model.index(1,1), &label);
3930     view.setCurrentIndex(model.index(0,0));
3931     QCOMPARE(view.currentIndex(), model.index(0,0));
3932 
3933     QTest::mouseClick(&label, Qt::LeftButton);
3934     QCOMPARE(view.currentIndex(), model.index(1,1));
3935 
3936 
3937 }
3938 
3939 
changeHeaderData()3940 void tst_QTableView::changeHeaderData()
3941 {
3942     QTableView view;
3943     QStandardItemModel model(5,5);
3944     view.setModel(&model);
3945     view.show();
3946     QTest::qWaitForWindowShown(&view);
3947 
3948     QString text = "long long long text";
3949     const int textWidth = view.verticalHeader()->fontMetrics().width(text);
3950     QVERIFY(view.verticalHeader()->width() < textWidth);
3951 
3952     model.setHeaderData(2, Qt::Vertical, text);
3953     QTest::qWait(100); //leave time for layout
3954 
3955     QVERIFY(view.verticalHeader()->width() > textWidth);
3956 }
3957 
taskQTBUG_5237_wheelEventOnHeader()3958 void tst_QTableView::taskQTBUG_5237_wheelEventOnHeader()
3959 {
3960     QTableView view;
3961     QStandardItemModel model(500,5);
3962     view.setModel(&model);
3963     view.show();
3964     QTest::qWaitForWindowShown(&view);
3965 
3966     int sbValueBefore = view.verticalScrollBar()->value();
3967     QHeaderView *header = view.verticalHeader();
3968     QTest::mouseMove(header);
3969     QWheelEvent wheelEvent(header->geometry().center(), -720, 0, 0);
3970     QApplication::sendEvent(header->viewport(), &wheelEvent);
3971     int sbValueAfter = view.verticalScrollBar()->value();
3972     QVERIFY(sbValueBefore != sbValueAfter);
3973 }
3974 
3975 class TestTableView : public QTableView {
3976 Q_OBJECT
3977 public:
TestTableView(QWidget * parent=0)3978     TestTableView(QWidget *parent = 0) : QTableView(parent)
3979     {
3980         connect(this, SIGNAL(entered(const QModelIndex&)), this, SLOT(openEditor(const QModelIndex&)));
3981     }
~TestTableView()3982     ~TestTableView(){}
3983 public slots:
onDataChanged()3984     void onDataChanged()
3985     {
3986         for (int i = 0; i < model()->rowCount(); i++) {
3987             setRowHidden(i, model()->data(model()->index(i, 0)).toBool());
3988         }
3989     }
3990 
openEditor(const QModelIndex & index)3991     void openEditor(const QModelIndex& index)
3992     { openPersistentEditor(index); }
3993 };
3994 
3995 
taskQTBUG_8585_crashForNoGoodReason()3996 void tst_QTableView::taskQTBUG_8585_crashForNoGoodReason()
3997 {
3998     QStandardItemModel model;
3999     model.insertColumn(0, QModelIndex());
4000     for(int i = 0; i < 20; i++)
4001     {
4002         model.insertRow(i);
4003     }
4004 
4005     TestTableView w;
4006     w.setMouseTracking(true);
4007     w.setModel(&model);
4008     connect(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), &w, SLOT(onDataChanged()));
4009     w.show();
4010     QTest::qWaitForWindowShown(&w);
4011     for (int i = 0; i < 10; i++)
4012     {
4013         QTest::mouseMove(w.viewport(), QPoint(50, 20));
4014         w.model()->setData(w.indexAt(QPoint(50, 20)), true);
4015         QTest::mouseMove(w.viewport(), QPoint(50, 25));
4016     }
4017 }
4018 
4019 class TableView7774 : public QTableView
4020 {
4021 public:
visualRegionForSelection(const QItemSelection & selection) const4022     QRegion visualRegionForSelection(const QItemSelection &selection) const
4023     {
4024         return QTableView::visualRegionForSelection(selection);
4025     }
4026 };
4027 
taskQTBUG_7774_RtoLVisualRegionForSelection()4028 void tst_QTableView::taskQTBUG_7774_RtoLVisualRegionForSelection()
4029 {
4030     TableView7774 view;
4031     QStandardItemModel model(5,5);
4032     view.setModel(&model);
4033     view.setLayoutDirection(Qt::RightToLeft);
4034     view.show();
4035     QTest::qWaitForWindowShown(&view);
4036 
4037     QItemSelectionRange range(model.index(2, 0), model.index(2, model.columnCount() - 1));
4038     QItemSelection selection;
4039     selection << range;
4040     QRegion region = view.visualRegionForSelection(selection);
4041     QCOMPARE(region.rects().at(0), view.visualRect(range.topLeft()) | view.visualRect(range.bottomRight()));
4042 }
4043 
taskQTBUG_8777_scrollToSpans()4044 void tst_QTableView::taskQTBUG_8777_scrollToSpans()
4045 {
4046     QTableWidget table(75,5);
4047     for (int i=0; i<50; i++)
4048         table.setSpan(2+i, 0, 1, 5);
4049     table.setCurrentCell(0,2);
4050     table.show();
4051 
4052     for (int i = 0; i < 45; ++i)
4053         QTest::keyClick(&table, Qt::Key_Down);
4054 
4055     QVERIFY(table.verticalScrollBar()->value() > 10);
4056 }
4057 
taskQTBUG_10169_sizeHintForRow()4058 void tst_QTableView::taskQTBUG_10169_sizeHintForRow()
4059 {
4060     QtTestTableView tableView;
4061     QStandardItemModel model(1, 3);
4062     model.setData(model.index(0, 0), "Word wrapping text goes here.");
4063     tableView.setModel(&model);
4064     tableView.verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
4065     const int orderedHeight = tableView.sizeHintForRow(0);
4066     tableView.horizontalHeader()->moveSection(2, 0);
4067     const int reorderedHeight = tableView.sizeHintForRow(0);
4068 
4069     //the order of the columns shouldn't matter.
4070     QCOMPARE(orderedHeight, reorderedHeight);
4071 }
4072 
taskQTBUG_30653_doItemsLayout()4073 void tst_QTableView::taskQTBUG_30653_doItemsLayout()
4074 {
4075     QWidget topLevel;
4076     QtTestTableView view(&topLevel);
4077 
4078     QtTestTableModel model(5, 5);
4079     view.setModel(&model);
4080 
4081     QtTestItemDelegate delegate;
4082     delegate.hint = QSize(50, 50);
4083     view.setItemDelegate(&delegate);
4084 
4085     view.resizeRowsToContents();
4086     view.resizeColumnsToContents();
4087 
4088     // show two and half rows/cols
4089     int extraWidth = view.verticalHeader()->sizeHint().width() + view.verticalScrollBar()->sizeHint().width();
4090     int extraHeight = view.horizontalHeader()->sizeHint().height() + view.horizontalScrollBar()->sizeHint().height();
4091     view.resize(125 + extraWidth, 125 + extraHeight);
4092 
4093     topLevel.show();
4094     QVERIFY(QTest::qWaitForWindowShown(&topLevel));
4095 
4096     // the offset after scrollToBottom() and doItemsLayout() should not differ
4097     // as the view content should stay aligned to the last section
4098     view.scrollToBottom();
4099     int scrollToBottomOffset = view.verticalHeader()->offset();
4100     view.doItemsLayout();
4101     int doItemsLayoutOffset = view.verticalHeader()->offset();
4102 
4103     QCOMPARE(scrollToBottomOffset, doItemsLayoutOffset);
4104 }
4105 
4106 QTEST_MAIN(tst_QTableView)
4107 #include "tst_qtableview.moc"
4108