1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 
43 #include <QtTest/QtTest>
44 #include <QStandardItemModel>
45 #include <QStringListModel>
46 #include <QSortFilterProxyModel>
47 #include <QTableView>
48 
49 #include <qabstractitemmodel.h>
50 #include <qapplication.h>
51 #include <qheaderview.h>
52 #include <private/qheaderview_p.h>
53 #include <qitemdelegate.h>
54 #include <qtreewidget.h>
55 #include <qdebug.h>
56 
57 typedef QList<int> IntList;
58 Q_DECLARE_METATYPE(IntList)
59 
60 typedef QList<bool> BoolList;
61 Q_DECLARE_METATYPE(BoolList)
62 
63 //TESTED_CLASS=
64 //TESTED_FILES=
65 
66 // Will try to wait for the condition while allowing event processing
67 // for a maximum of 2 seconds.
68 #define WAIT_FOR_CONDITION(expr, expected) \
69     do { \
70         const int step = 100; \
71         for (int i = 0; i < 2000 && expr != expected; i+=step) { \
72             QTest::qWait(step); \
73         } \
74     } while(0)
75 
76 class protected_QHeaderView : public QHeaderView
77 {
78     Q_OBJECT
79 public:
protected_QHeaderView(Qt::Orientation orientation)80     protected_QHeaderView(Qt::Orientation orientation) : QHeaderView(orientation) {
81         resizeSections();
82     };
83 
84     void testEvent();
85     void testhorizontalOffset();
86     void testverticalOffset();
87     friend class tst_QHeaderView;
88 };
89 
90 class tst_QHeaderView : public QObject
91 {
92     Q_OBJECT
93 
94 public:
95     tst_QHeaderView();
96     virtual ~tst_QHeaderView();
97 
98 public slots:
99     void initTestCase();
100     void cleanupTestCase();
101     void init();
102     void cleanup();
103 
104 private slots:
105     void getSetCheck();
106     void visualIndex();
107 
108     void visualIndexAt_data();
109     void visualIndexAt();
110 
111     void noModel();
112     void emptyModel();
113     void removeRows();
114     void removeCols();
115 
116     void clickable();
117     void movable();
118     void hidden();
119     void stretch();
120 
121     void sectionSize_data();
122     void sectionSize();
123 
124     void length();
125     void offset();
126     void sectionSizeHint();
127     void logicalIndex();
128     void logicalIndexAt();
129     void swapSections();
130 
131     void moveSection_data();
132     void moveSection();
133 
134     void resizeMode();
135 
136     void resizeSection_data();
137     void resizeSection();
138 
139     void resizeAndMoveSection_data();
140     void resizeAndMoveSection();
141     void resizeHiddenSection_data();
142     void resizeHiddenSection();
143     void resizeAndInsertSection_data();
144     void resizeAndInsertSection();
145     void resizeWithResizeModes_data();
146     void resizeWithResizeModes();
147     void moveAndInsertSection_data();
148     void moveAndInsertSection();
149     void highlightSections();
150     void showSortIndicator();
151     void sortIndicatorTracking();
152     void removeAndInsertRow();
153     void unhideSection();
154     void event();
155     void headerDataChanged();
156     void currentChanged();
157     void horizontalOffset();
158     void verticalOffset();
159     void stretchSectionCount();
160     void hiddenSectionCount();
161     void focusPolicy();
162     void moveSectionAndReset();
163     void moveSectionAndRemove();
164     void saveRestore();
165 
166     void defaultAlignment_data();
167     void defaultAlignment();
168 
169     void globalResizeMode_data();
170     void globalResizeMode();
171 
172     void sectionPressedSignal_data();
173     void sectionPressedSignal();
sectionClickedSignal_data()174     void sectionClickedSignal_data() { sectionPressedSignal_data(); }
175     void sectionClickedSignal();
176 
177     void defaultSectionSize_data();
178     void defaultSectionSize();
179 
180     void oneSectionSize();
181 
182     void hideAndInsert_data();
183     void hideAndInsert();
184 
185     void removeSection();
186     void preserveHiddenSectionWidth();
187     void invisibleStretchLastSection();
188 
189     void emptySectionSpan();
190     void task236450_hidden_data();
191     void task236450_hidden();
192     void task248050_hideRow();
193     void QTBUG6058_reset();
194     void QTBUG7833_sectionClicked();
195     void QTBUG8650_crashOnInsertSections();
196     void QTBUG12268_hiddenMovedSectionSorting();
197     void QTBUG14242_hideSectionAutoSize();
198 
199     void initialSortOrderRole();
200     void ensureNoIndexAtLength();
201 
202 protected:
203     QWidget *topLevel;
204     QHeaderView *view;
205     QStandardItemModel *model;
206 };
207 
208 class QtTestModel: public QAbstractTableModel
209 {
210 
211 Q_OBJECT
212 
213 public:
QtTestModel(QObject * parent=0)214     QtTestModel(QObject *parent = 0): QAbstractTableModel(parent),
215        cols(0), rows(0), wrongIndex(false) {}
rowCount(const QModelIndex &) const216     int rowCount(const QModelIndex&) const { return rows; }
columnCount(const QModelIndex &) const217     int columnCount(const QModelIndex&) const { return cols; }
isEditable(const QModelIndex &) const218     bool isEditable(const QModelIndex &) const { return true; }
219 
data(const QModelIndex & idx,int) const220     QVariant data(const QModelIndex &idx, int) const
221     {
222         if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
223             wrongIndex = true;
224             qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), idx.internalPointer());
225         }
226         return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);//idx.data());
227     }
228 
insertOneColumn(int col)229     void insertOneColumn(int col)
230     {
231         beginInsertColumns(QModelIndex(), col, col);
232         --cols;
233         endInsertColumns();
234     }
235 
removeLastRow()236     void removeLastRow()
237     {
238         beginRemoveRows(QModelIndex(), rows - 1, rows - 1);
239         --rows;
240         endRemoveRows();
241     }
242 
removeAllRows()243     void removeAllRows()
244     {
245         beginRemoveRows(QModelIndex(), 0, rows - 1);
246         rows = 0;
247         endRemoveRows();
248     }
249 
removeOneColumn(int col)250     void removeOneColumn(int col)
251     {
252         beginRemoveColumns(QModelIndex(), col, col);
253         --cols;
254         endRemoveColumns();
255     }
256 
removeLastColumn()257     void removeLastColumn()
258     {
259         beginRemoveColumns(QModelIndex(), cols - 1, cols - 1);
260         --cols;
261         endRemoveColumns();
262     }
263 
removeAllColumns()264     void removeAllColumns()
265     {
266         beginRemoveColumns(QModelIndex(), 0, cols - 1);
267         cols = 0;
268         endRemoveColumns();
269     }
270 
cleanup()271     void cleanup()
272     {
273         cols = 3;
274         rows = 3;
275         emit layoutChanged();
276     }
277 
278     int cols, rows;
279     mutable bool wrongIndex;
280 };
281 
282 // Testing get/set functions
getSetCheck()283 void tst_QHeaderView::getSetCheck()
284 {
285     protected_QHeaderView obj1(Qt::Horizontal);
286     // bool QHeaderView::highlightSections()
287     // void QHeaderView::setHighlightSections(bool)
288     obj1.setHighlightSections(false);
289     QCOMPARE(false, obj1.highlightSections());
290     obj1.setHighlightSections(true);
291     QCOMPARE(true, obj1.highlightSections());
292 
293     // bool QHeaderView::stretchLastSection()
294     // void QHeaderView::setStretchLastSection(bool)
295     obj1.setStretchLastSection(false);
296     QCOMPARE(false, obj1.stretchLastSection());
297     obj1.setStretchLastSection(true);
298     QCOMPARE(true, obj1.stretchLastSection());
299 
300     // int QHeaderView::defaultSectionSize()
301     // void QHeaderView::setDefaultSectionSize(int)
302     obj1.setDefaultSectionSize(0);
303     QCOMPARE(0, obj1.defaultSectionSize());
304     obj1.setDefaultSectionSize(INT_MIN);
305     QCOMPARE(INT_MIN, obj1.defaultSectionSize());
306     obj1.setDefaultSectionSize(INT_MAX);
307     QCOMPARE(INT_MAX, obj1.defaultSectionSize());
308     // ### the test above does not make sense for values below 0
309 
310     // int QHeaderView::minimumSectionSize()
311     // void QHeaderView::setMinimumSectionSize(int)
312     obj1.setMinimumSectionSize(0);
313     QCOMPARE(0, obj1.minimumSectionSize());
314     obj1.setMinimumSectionSize(INT_MIN);
315     QCOMPARE(INT_MIN, obj1.minimumSectionSize());
316     obj1.setMinimumSectionSize(INT_MAX);
317     QCOMPARE(INT_MAX, obj1.minimumSectionSize());
318     // ### the test above does not make sense for values below 0
319 
320     // int QHeaderView::offset()
321     // void QHeaderView::setOffset(int)
322     obj1.setOffset(0);
323     QCOMPARE(0, obj1.offset());
324     obj1.setOffset(INT_MIN);
325     QCOMPARE(INT_MIN, obj1.offset());
326     obj1.setOffset(INT_MAX);
327     QCOMPARE(INT_MAX, obj1.offset());
328 
329 }
330 
tst_QHeaderView()331 tst_QHeaderView::tst_QHeaderView()
332 {
333     qRegisterMetaType<int>("Qt::SortOrder");
334 }
335 
~tst_QHeaderView()336 tst_QHeaderView::~tst_QHeaderView()
337 {
338 }
339 
initTestCase()340 void tst_QHeaderView::initTestCase()
341 {
342 #ifdef Q_OS_WINCE //disable magic for WindowsCE
343     qApp->setAutoMaximizeThreshold(-1);
344 #endif
345 }
346 
cleanupTestCase()347 void tst_QHeaderView::cleanupTestCase()
348 {
349 }
350 
init()351 void tst_QHeaderView::init()
352 {
353     topLevel = new QWidget();
354     view = new QHeaderView(Qt::Vertical,topLevel);
355     // Some initial value tests before a model is added
356     QCOMPARE(view->length(), 0);
357     QVERIFY(view->sizeHint() == QSize(0,0));
358     QCOMPARE(view->sectionSizeHint(0), -1);
359 
360     /*
361     model = new QStandardItemModel(1, 1);
362     view->setModel(model);
363     //qDebug() << view->count();
364     view->sizeHint();
365     */
366 
367     int rows = 4;
368     int columns = 4;
369     model = new QStandardItemModel(rows, columns);
370     /*
371     for (int row = 0; row < rows; ++row) {
372         for (int column = 0; column < columns; ++column) {
373             QModelIndex index = model->index(row, column, QModelIndex());
374             model->setData(index, QVariant((row+1) * (column+1)));
375         }
376     }
377     */
378 
379     QSignalSpy spy(view, SIGNAL(sectionCountChanged(int, int)));
380     view->setModel(model);
381     QCOMPARE(spy.count(), 1);
382     view->resize(200,200);
383     topLevel->show();
384 }
385 
cleanup()386 void tst_QHeaderView::cleanup()
387 {
388     delete view;
389     view = 0;
390     delete model;
391     model = 0;
392 }
393 
noModel()394 void tst_QHeaderView::noModel()
395 {
396     QHeaderView emptyView(Qt::Vertical);
397     QCOMPARE(emptyView.count(), 0);
398 }
399 
emptyModel()400 void tst_QHeaderView::emptyModel()
401 {
402     QtTestModel testmodel;
403     view->setModel(&testmodel);
404     QVERIFY(!testmodel.wrongIndex);
405     QCOMPARE(view->count(), testmodel.rows);
406     view->setModel(model);
407 }
408 
removeRows()409 void tst_QHeaderView::removeRows()
410 {
411     QtTestModel model;
412     model.rows = model.cols = 10;
413 
414     QHeaderView vertical(Qt::Vertical);
415     QHeaderView horizontal(Qt::Horizontal);
416 
417     vertical.setModel(&model);
418     horizontal.setModel(&model);
419     vertical.show();
420     horizontal.show();
421     QCOMPARE(vertical.count(), model.rows);
422     QCOMPARE(horizontal.count(), model.cols);
423 
424     model.removeLastRow();
425     QVERIFY(!model.wrongIndex);
426     QCOMPARE(vertical.count(), model.rows);
427     QCOMPARE(horizontal.count(), model.cols);
428 
429     model.removeAllRows();
430     QVERIFY(!model.wrongIndex);
431     QCOMPARE(vertical.count(), model.rows);
432     QCOMPARE(horizontal.count(), model.cols);
433 }
434 
435 
removeCols()436 void tst_QHeaderView::removeCols()
437 {
438     QtTestModel model;
439     model.rows = model.cols = 10;
440 
441     QHeaderView vertical(Qt::Vertical);
442     QHeaderView horizontal(Qt::Horizontal);
443     vertical.setModel(&model);
444     horizontal.setModel(&model);
445     vertical.show();
446     horizontal.show();
447     QCOMPARE(vertical.count(), model.rows);
448     QCOMPARE(horizontal.count(), model.cols);
449 
450     model.removeLastColumn();
451     QVERIFY(!model.wrongIndex);
452     QCOMPARE(vertical.count(), model.rows);
453     QCOMPARE(horizontal.count(), model.cols);
454 
455     model.removeAllColumns();
456     QVERIFY(!model.wrongIndex);
457     QCOMPARE(vertical.count(), model.rows);
458     QCOMPARE(horizontal.count(), model.cols);
459 }
460 
movable()461 void tst_QHeaderView::movable()
462 {
463     QCOMPARE(view->isMovable(), false);
464     view->setMovable(false);
465     QCOMPARE(view->isMovable(), false);
466     view->setMovable(true);
467     QCOMPARE(view->isMovable(), true);
468 }
469 
clickable()470 void tst_QHeaderView::clickable()
471 {
472     QCOMPARE(view->isClickable(), false);
473     view->setClickable(false);
474     QCOMPARE(view->isClickable(), false);
475     view->setClickable(true);
476     QCOMPARE(view->isClickable(), true);
477 }
478 
hidden()479 void tst_QHeaderView::hidden()
480 {
481     //hideSection() & showSection call setSectionHidden
482     // Test bad arguments
483     QCOMPARE(view->isSectionHidden(-1), false);
484     QCOMPARE(view->isSectionHidden(view->count()), false);
485     QCOMPARE(view->isSectionHidden(999999), false);
486 
487     view->setSectionHidden(-1, true);
488     view->setSectionHidden(view->count(), true);
489     view->setSectionHidden(999999, true);
490     view->setSectionHidden(-1, false);
491     view->setSectionHidden(view->count(), false);
492     view->setSectionHidden(999999, false);
493 
494     // Hidden sections shouldn't have visual properties (except position)
495     int pos = view->defaultSectionSize();
496     view->setSectionHidden(1, true);
497     QCOMPARE(view->sectionSize(1), 0);
498     QCOMPARE(view->sectionPosition(1), pos);
499     view->resizeSection(1, 100);
500     QCOMPARE(view->sectionViewportPosition(1), pos);
501     QCOMPARE(view->sectionSize(1), 0);
502     view->setSectionHidden(1, false);
503     QCOMPARE(view->isSectionHidden(0), false);
504     QCOMPARE(view->sectionSize(0), view->defaultSectionSize());
505 }
506 
stretch()507 void tst_QHeaderView::stretch()
508 {
509     // Show before resize and setStrechLastSection
510 #if defined(Q_OS_WINCE)
511     QSize viewSize(200,300);
512 #else
513     QSize viewSize(500, 500);
514 #endif
515     view->resize(viewSize);
516     view->setStretchLastSection(true);
517     QCOMPARE(view->stretchLastSection(), true);
518     topLevel->show();
519     QCOMPARE(view->width(), viewSize.width());
520     QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 3);
521 
522     view->setSectionHidden(3, true);
523     QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 2);
524 
525     view->setStretchLastSection(false);
526     QCOMPARE(view->stretchLastSection(), false);
527 }
528 
oneSectionSize()529 void tst_QHeaderView::oneSectionSize()
530 {
531     //this ensures that if there is only one section, it gets a correct width (more than 0)
532     QHeaderView view (Qt::Vertical);
533     QtTestModel model;
534     model.cols = 1;
535     model.rows = 1;
536 
537     view.setResizeMode(QHeaderView::Interactive);
538     view.setModel(&model);
539 
540     view.show();
541 
542     QVERIFY(view.sectionSize(0) > 0);
543 }
544 
545 
sectionSize_data()546 void tst_QHeaderView::sectionSize_data()
547 {
548     QTest::addColumn<QList<int> >("boundsCheck");
549     QTest::addColumn<QList<int> >("defaultSizes");
550     QTest::addColumn<int>("initialDefaultSize");
551     QTest::addColumn<int>("lastVisibleSectionSize");
552     QTest::addColumn<int>("persistentSectionSize");
553 
554     QTest::newRow("data set one")
555         << (QList<int>() << -1 << 0 << 4 << 9999)
556         << (QList<int>() << 10 << 30 << 30)
557         << 30
558         << 300
559         << 20;
560 }
561 
sectionSize()562 void tst_QHeaderView::sectionSize()
563 {
564     QFETCH(QList<int>, boundsCheck);
565     QFETCH(QList<int>, defaultSizes);
566     QFETCH(int, initialDefaultSize);
567     QFETCH(int, lastVisibleSectionSize);
568     QFETCH(int, persistentSectionSize);
569 
570 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
571     // We test on a device with doubled pixels. Therefore we need to specify
572     // different boundaries.
573     initialDefaultSize = qMax(view->minimumSectionSize(), 30);
574 #endif
575 
576     // bounds check
577     foreach (int val, boundsCheck)
578         view->sectionSize(val);
579 
580     // default size
581     QCOMPARE(view->defaultSectionSize(), initialDefaultSize);
582     foreach (int def, defaultSizes) {
583         view->setDefaultSectionSize(def);
584         QCOMPARE(view->defaultSectionSize(), def);
585     }
586 
587     view->setDefaultSectionSize(initialDefaultSize);
588     for (int s = 0; s < view->count(); ++s)
589         QCOMPARE(view->sectionSize(s), initialDefaultSize);
590     view->doItemsLayout();
591 
592     // stretch last section
593     view->setStretchLastSection(true);
594     int lastSection = view->count() - 1;
595 
596     //test that when hiding the last column,
597     //resizing the new last visible columns still works
598     view->hideSection(lastSection);
599     view->resizeSection(lastSection - 1, lastVisibleSectionSize);
600     QCOMPARE(view->sectionSize(lastSection - 1), lastVisibleSectionSize);
601     view->showSection(lastSection);
602 
603     // turn off stretching
604     view->setStretchLastSection(false);
605     QCOMPARE(view->sectionSize(lastSection), initialDefaultSize);
606 
607     // test persistence
608     int sectionCount = view->count();
609     for (int i = 0; i < sectionCount; ++i)
610         view->resizeSection(i, persistentSectionSize);
611     QtTestModel model;
612     model.cols = sectionCount * 2;
613     model.rows = sectionCount * 2;
614     view->setModel(&model);
615     for (int j = 0; j < sectionCount; ++j)
616         QCOMPARE(view->sectionSize(j), persistentSectionSize);
617     for (int k = sectionCount; k < view->count(); ++k)
618         QCOMPARE(view->sectionSize(k), initialDefaultSize);
619 }
620 
visualIndex()621 void tst_QHeaderView::visualIndex()
622 {
623     // Test bad arguments
624     QCOMPARE(view->visualIndex(999999), -1);
625     QCOMPARE(view->visualIndex(-1), -1);
626     QCOMPARE(view->visualIndex(1), 1);
627     view->setSectionHidden(1, true);
628     QCOMPARE(view->visualIndex(1), 1);
629     QCOMPARE(view->visualIndex(2), 2);
630 
631     view->setSectionHidden(1, false);
632     QCOMPARE(view->visualIndex(1), 1);
633     QCOMPARE(view->visualIndex(2), 2);
634 }
635 
visualIndexAt_data()636 void tst_QHeaderView::visualIndexAt_data()
637 {
638     QTest::addColumn<QList<int> >("hidden");
639     QTest::addColumn<QList<int> >("from");
640     QTest::addColumn<QList<int> >("to");
641     QTest::addColumn<QList<int> >("coordinate");
642     QTest::addColumn<QList<int> >("visual");
643 
644     QList<int> coordinateList;
645 #ifndef Q_OS_WINCE
646     coordinateList << -1 << 0 << 31 << 91 << 99999;
647 #else
648     // We test on a device with doubled pixels. Therefore we need to specify
649     // different boundaries.
650     coordinateList << -1 << 0 << 33 << 97 << 99999;
651 #endif
652 
653     QTest::newRow("no hidden, no moved sections")
654         << QList<int>()
655         << QList<int>()
656         << QList<int>()
657         << coordinateList
658         << (QList<int>() << -1 << 0 << 1 << 3 << -1);
659 
660     QTest::newRow("no hidden, moved sections")
661         << QList<int>()
662         << (QList<int>() << 0)
663         << (QList<int>() << 1)
664         << coordinateList
665         << (QList<int>() << -1 << 0 << 1 << 3 << -1);
666 
667     QTest::newRow("hidden, no moved sections")
668         << (QList<int>() << 0)
669         << QList<int>()
670         << QList<int>()
671         << coordinateList
672         << (QList<int>() << -1 << 1 << 2 << 3 << -1);
673 }
674 
visualIndexAt()675 void tst_QHeaderView::visualIndexAt()
676 {
677     QFETCH(QList<int>, hidden);
678     QFETCH(QList<int>, from);
679     QFETCH(QList<int>, to);
680     QFETCH(QList<int>, coordinate);
681     QFETCH(QList<int>, visual);
682 
683 #ifdef Q_OS_SYMBIAN
684     // Some Symbian devices have larger minimum section size than what is expected.
685     // Need to do this here instead of visualIndexAt_data() as view pointer doesn't
686     // seem to be valid there.
687     int minSize = view->minimumSectionSize();
688     if (minSize > 30) {
689         coordinate.clear();
690         coordinate << -1 << 0 << minSize + 1 << (minSize * 3) + 1 << 99999;
691     }
692 #endif
693     view->setStretchLastSection(true);
694     topLevel->show();
695 
696     for (int i = 0; i < hidden.count(); ++i)
697         view->setSectionHidden(hidden.at(i), true);
698 
699     for (int j = 0; j < from.count(); ++j)
700         view->moveSection(from.at(j), to.at(j));
701 
702     QTest::qWait(100);
703 
704     for (int k = 0; k < coordinate.count(); ++k)
705         QCOMPARE(view->visualIndexAt(coordinate.at(k)), visual.at(k));
706 }
707 
length()708 void tst_QHeaderView::length()
709 {
710 #if defined(Q_OS_WINCE)
711     QFont font(QLatin1String("Tahoma"), 7);
712     view->setFont(font);
713 #elif defined(Q_OS_SYMBIAN)
714     QFont font(QLatin1String("Series 60 Sans"), 6);
715     view->setFont(font);
716 #endif
717     view->setStretchLastSection(true);
718     topLevel->show();
719 
720     //minimumSectionSize should be the size of the last section of the widget is not tall enough
721     int length = view->minimumSectionSize();
722     for (int i=0; i < view->count()-1; i++) {
723         length += view->sectionSize(i);
724     }
725 
726     length = qMax(length, view->viewport()->height());
727     QCOMPARE(length, view->length());
728 
729     view->setStretchLastSection(false);
730     topLevel->show();
731 
732     QVERIFY(length != view->length());
733 
734     // layoutChanged might mean rows have been removed
735     QtTestModel model;
736     model.cols = 10;
737     model.rows = 10;
738     view->setModel(&model);
739     int oldLength = view->length();
740     model.cleanup();
741     QCOMPARE(model.rows, view->count());
742     QVERIFY(oldLength != view->length());
743 }
744 
offset()745 void tst_QHeaderView::offset()
746 {
747     QCOMPARE(view->offset(), 0);
748     view->setOffset(10);
749     QCOMPARE(view->offset(), 10);
750     view->setOffset(0);
751     QCOMPARE(view->offset(), 0);
752 
753     // Test odd arguments
754     view->setOffset(-1);
755 }
756 
sectionSizeHint()757 void tst_QHeaderView::sectionSizeHint()
758 {
759     // Test bad arguments
760     view->sectionSizeHint(-1);
761     view->sectionSizeHint(99999);
762 
763     // TODO how to test the return value?
764 }
765 
logicalIndex()766 void tst_QHeaderView::logicalIndex()
767 {
768     // Test bad arguments
769     QCOMPARE(view->logicalIndex(-1), -1);
770     QCOMPARE(view->logicalIndex(99999), -1);
771 }
772 
logicalIndexAt()773 void tst_QHeaderView::logicalIndexAt()
774 {
775     // Test bad arguments
776     view->logicalIndexAt(-1);
777     view->logicalIndexAt(99999);
778     QCOMPARE(view->logicalIndexAt(0), 0);
779     QCOMPARE(view->logicalIndexAt(1), 0);
780 
781     topLevel->show();
782     view->setStretchLastSection(true);
783     // First item
784     QCOMPARE(view->logicalIndexAt(0), 0);
785     QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 0);
786     QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 1);
787     // Last item
788     int last = view->length() - 1;//view->viewport()->height() - 10;
789     QCOMPARE(view->logicalIndexAt(last), 3);
790     // Not in widget
791     int outofbounds = view->length() + 1;//view->viewport()->height() + 1;
792     QCOMPARE(view->logicalIndexAt(outofbounds), -1);
793 
794     view->moveSection(0,1);
795     // First item
796     QCOMPARE(view->logicalIndexAt(0), 1);
797     QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 1);
798     QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 0);
799     // Last item
800     QCOMPARE(view->logicalIndexAt(last), 3);
801     view->moveSection(1,0);
802 
803 }
804 
swapSections()805 void tst_QHeaderView::swapSections()
806 {
807     view->swapSections(-1, 1);
808     view->swapSections(99999, 1);
809     view->swapSections(1, -1);
810     view->swapSections(1, 99999);
811 
812     QVector<int> logical = (QVector<int>() << 0 << 1 << 2 << 3);
813 
814     QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int)));
815 
816     QCOMPARE(view->sectionsMoved(), false);
817     view->swapSections(1, 1);
818     QCOMPARE(view->sectionsMoved(), false);
819     view->swapSections(1, 2);
820     QCOMPARE(view->sectionsMoved(), true);
821     view->swapSections(2, 1);
822     QCOMPARE(view->sectionsMoved(), true);
823     for (int i = 0; i < view->count(); ++i)
824         QCOMPARE(view->logicalIndex(i), logical.at(i));
825     QCOMPARE(spy1.count(), 4);
826 
827     logical = (QVector<int>()  << 3 << 1 << 2 << 0);
828     view->swapSections(3, 0);
829     QCOMPARE(view->sectionsMoved(), true);
830     for (int j = 0; j < view->count(); ++j)
831         QCOMPARE(view->logicalIndex(j), logical.at(j));
832     QCOMPARE(spy1.count(), 6);
833 }
834 
moveSection_data()835 void tst_QHeaderView::moveSection_data()
836 {
837     QTest::addColumn<QList<int> >("hidden");
838     QTest::addColumn<QList<int> >("from");
839     QTest::addColumn<QList<int> >("to");
840     QTest::addColumn<QList<bool> >("moved");
841     QTest::addColumn<QList<int> >("logical");
842     QTest::addColumn<int>("count");
843 
844     QTest::newRow("bad args, no hidden")
845         << QList<int>()
846         << (QList<int>() << -1 << 1 << 99999 << 1)
847         << (QList<int>() << 1 << -1 << 1 << 99999)
848         << (QList<bool>() << false << false << false << false)
849         << (QList<int>() << 0 << 1 << 2 << 3)
850         << 0;
851 
852     QTest::newRow("good args, no hidden")
853         << QList<int>()
854         << (QList<int>() << 1 << 1 << 2 << 1)
855         << (QList<int>() << 1 << 2 << 1 << 2)
856         << (QList<bool>() << false << true << true << true)
857         << (QList<int>() << 0 << 2 << 1 << 3)
858         << 3;
859 
860     QTest::newRow("hidden sections")
861         << (QList<int>() << 0 << 3)
862         << (QList<int>() << 1 << 1 << 2 << 1)
863         << (QList<int>() << 1 << 2 << 1 << 2)
864         << (QList<bool>() << false << true << true << true)
865         << (QList<int>() << 0 << 2 << 1 << 3)
866         << 3;
867 }
868 
moveSection()869 void tst_QHeaderView::moveSection()
870 {
871     QFETCH(QList<int>, hidden);
872     QFETCH(QList<int>, from);
873     QFETCH(QList<int>, to);
874     QFETCH(QList<bool>, moved);
875     QFETCH(QList<int>, logical);
876     QFETCH(int, count);
877 
878     QVERIFY(from.count() == to.count());
879     QVERIFY(from.count() == moved.count());
880     QVERIFY(view->count() == logical.count());
881 
882     QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int)));
883     QCOMPARE(view->sectionsMoved(), false);
884 
885     for (int h = 0; h < hidden.count(); ++h)
886         view->setSectionHidden(hidden.at(h), true);
887 
888     for (int i = 0; i < from.count(); ++i) {
889         view->moveSection(from.at(i), to.at(i));
890         QCOMPARE(view->sectionsMoved(), moved.at(i));
891     }
892 
893     for (int j = 0; j < view->count(); ++j)
894         QCOMPARE(view->logicalIndex(j), logical.at(j));
895 
896     QCOMPARE(spy1.count(), count);
897 }
898 
resizeAndMoveSection_data()899 void tst_QHeaderView::resizeAndMoveSection_data()
900 {
901     QTest::addColumn<IntList>("logicalIndexes");
902     QTest::addColumn<IntList>("sizes");
903     QTest::addColumn<int>("logicalFrom");
904     QTest::addColumn<int>("logicalTo");
905 
906     QTest::newRow("resizeAndMove-1")
907         << (IntList() << 0 << 1)
908         << (IntList() << 20 << 40)
909         << 0 << 1;
910 
911     QTest::newRow("resizeAndMove-2")
912         << (IntList() << 0 << 1 << 2 << 3)
913         << (IntList() << 20 << 60 << 10 << 80)
914         << 0 << 2;
915 
916     QTest::newRow("resizeAndMove-3")
917         << (IntList() << 0 << 1 << 2 << 3)
918         << (IntList() << 100 << 60 << 40 << 10)
919         << 0 << 3;
920 
921     QTest::newRow("resizeAndMove-4")
922         << (IntList() << 0 << 1 << 2 << 3)
923         << (IntList() << 10 << 40 << 80 << 30)
924         << 1 << 2;
925 
926     QTest::newRow("resizeAndMove-5")
927         << (IntList() << 2 << 3)
928         << (IntList() << 100 << 200)
929         << 3 << 2;
930 }
931 
resizeAndMoveSection()932 void tst_QHeaderView::resizeAndMoveSection()
933 {
934     QFETCH(IntList, logicalIndexes);
935     QFETCH(IntList, sizes);
936     QFETCH(int, logicalFrom);
937     QFETCH(int, logicalTo);
938 
939     // Save old visual indexes and sizes
940     IntList oldVisualIndexes;
941     IntList oldSizes;
942     foreach (int logical, logicalIndexes) {
943         oldVisualIndexes.append(view->visualIndex(logical));
944         oldSizes.append(view->sectionSize(logical));
945     }
946 
947     // Resize sections
948     for (int i = 0; i < logicalIndexes.size(); ++i) {
949         int logical = logicalIndexes.at(i);
950         view->resizeSection(logical, sizes.at(i));
951     }
952 
953     // Move sections
954     int visualFrom = view->visualIndex(logicalFrom);
955     int visualTo = view->visualIndex(logicalTo);
956     view->moveSection(visualFrom, visualTo);
957     QCOMPARE(view->visualIndex(logicalFrom), visualTo);
958 
959     // Check that sizes are still correct
960     for (int i = 0; i < logicalIndexes.size(); ++i) {
961         int logical = logicalIndexes.at(i);
962         QCOMPARE(view->sectionSize(logical), sizes.at(i));
963     }
964 
965     // Move sections back
966     view->moveSection(visualTo, visualFrom);
967 
968     // Check that sizes are still correct
969     for (int i = 0; i < logicalIndexes.size(); ++i) {
970         int logical = logicalIndexes.at(i);
971         QCOMPARE(view->sectionSize(logical), sizes.at(i));
972     }
973 
974     // Put everything back as it was
975     for (int i = 0; i < logicalIndexes.size(); ++i) {
976         int logical = logicalIndexes.at(i);
977         view->resizeSection(logical, oldSizes.at(i));
978         QCOMPARE(view->visualIndex(logical), oldVisualIndexes.at(i));
979     }
980 }
981 
resizeHiddenSection_data()982 void tst_QHeaderView::resizeHiddenSection_data()
983 {
984     QTest::addColumn<int>("section");
985     QTest::addColumn<int>("initialSize");
986     QTest::addColumn<int>("finalSize");
987 
988     QTest::newRow("section 0 resize 50 to 20")
989         << 0 << 50 << 20;
990 
991     QTest::newRow("section 1 resize 50 to 20")
992         << 1 << 50 << 20;
993 
994     QTest::newRow("section 2 resize 50 to 20")
995         << 2 << 50 << 20;
996 
997     QTest::newRow("section 3 resize 50 to 20")
998         << 3 << 50 << 20;
999 }
1000 
resizeHiddenSection()1001 void tst_QHeaderView::resizeHiddenSection()
1002 {
1003     QFETCH(int, section);
1004     QFETCH(int, initialSize);
1005     QFETCH(int, finalSize);
1006 
1007     view->resizeSection(section, initialSize);
1008     view->setSectionHidden(section, true);
1009     QCOMPARE(view->sectionSize(section), 0);
1010 
1011     view->resizeSection(section, finalSize);
1012     QCOMPARE(view->sectionSize(section), 0);
1013 
1014     view->setSectionHidden(section, false);
1015     QCOMPARE(view->sectionSize(section), finalSize);
1016 }
1017 
resizeAndInsertSection_data()1018 void tst_QHeaderView::resizeAndInsertSection_data()
1019 {
1020     QTest::addColumn<int>("section");
1021     QTest::addColumn<int>("size");
1022     QTest::addColumn<int>("insert");
1023     QTest::addColumn<int>("compare");
1024     QTest::addColumn<int>("expected");
1025 
1026     QTest::newRow("section 0 size 50 insert 0")
1027         << 0 << 50 << 0 << 1 << 50;
1028 
1029     QTest::newRow("section 1 size 50 insert 1")
1030         << 0 << 50 << 1 << 0 << 50;
1031 
1032     QTest::newRow("section 1 size 50 insert 0")
1033         << 1 << 50 << 0 << 2 << 50;
1034 
1035 }
1036 
resizeAndInsertSection()1037 void tst_QHeaderView::resizeAndInsertSection()
1038 {
1039     QFETCH(int, section);
1040     QFETCH(int, size);
1041     QFETCH(int, insert);
1042     QFETCH(int, compare);
1043     QFETCH(int, expected);
1044 
1045     view->setStretchLastSection(false);
1046 
1047     view->resizeSection(section, size);
1048     QCOMPARE(view->sectionSize(section), size);
1049 
1050     model->insertRow(insert);
1051 
1052     QCOMPARE(view->sectionSize(compare), expected);
1053 }
1054 
resizeWithResizeModes_data()1055 void tst_QHeaderView::resizeWithResizeModes_data()
1056 {
1057     QTest::addColumn<int>("size");
1058     QTest::addColumn<QList<int> >("sections");
1059     QTest::addColumn<QList<int> >("modes");
1060     QTest::addColumn<QList<int> >("expected");
1061 
1062     QTest::newRow("stretch first section")
1063         << 600
1064         << (QList<int>() << 100 << 100 << 100 << 100)
1065         << (QList<int>() << ((int)QHeaderView::Stretch)
1066                          << ((int)QHeaderView::Interactive)
1067                          << ((int)QHeaderView::Interactive)
1068                          << ((int)QHeaderView::Interactive))
1069         << (QList<int>() << 300 << 100 << 100 << 100);
1070 }
1071 
resizeWithResizeModes()1072 void  tst_QHeaderView::resizeWithResizeModes()
1073 {
1074     QFETCH(int, size);
1075     QFETCH(QList<int>, sections);
1076     QFETCH(QList<int>, modes);
1077     QFETCH(QList<int>, expected);
1078 
1079     view->setStretchLastSection(false);
1080     for (int i = 0; i < sections.count(); ++i) {
1081         view->resizeSection(i, sections.at(i));
1082         view->setResizeMode(i, (QHeaderView::ResizeMode)modes.at(i));
1083     }
1084     topLevel->show();
1085     view->resize(size, size);
1086     for (int j = 0; j < expected.count(); ++j)
1087         QCOMPARE(view->sectionSize(j), expected.at(j));
1088 }
1089 
moveAndInsertSection_data()1090 void tst_QHeaderView::moveAndInsertSection_data()
1091 {
1092     QTest::addColumn<int>("from");
1093     QTest::addColumn<int>("to");
1094     QTest::addColumn<int>("insert");
1095     QTest::addColumn<QList<int> >("mapping");
1096 
1097     QTest::newRow("move from 1 to 3, insert 0")
1098         << 1 << 3 << 0 <<(QList<int>() << 0 << 1 << 3 << 4 << 2);
1099 
1100 }
1101 
moveAndInsertSection()1102 void tst_QHeaderView::moveAndInsertSection()
1103 {
1104     QFETCH(int, from);
1105     QFETCH(int, to);
1106     QFETCH(int, insert);
1107     QFETCH(QList<int>, mapping);
1108 
1109     view->setStretchLastSection(false);
1110 
1111     view->moveSection(from, to);
1112 
1113     model->insertRow(insert);
1114 
1115     for (int i = 0; i < mapping.count(); ++i)
1116         QCOMPARE(view->logicalIndex(i), mapping.at(i));
1117 }
1118 
resizeMode()1119 void tst_QHeaderView::resizeMode()
1120 {
1121     // resizeMode must not be called with an invalid index
1122     int last = view->count() - 1;
1123     view->setResizeMode(QHeaderView::Interactive);
1124     QCOMPARE(view->resizeMode(last), QHeaderView::Interactive);
1125     QCOMPARE(view->resizeMode(1), QHeaderView::Interactive);
1126     view->setResizeMode(QHeaderView::Stretch);
1127     QCOMPARE(view->resizeMode(last), QHeaderView::Stretch);
1128     QCOMPARE(view->resizeMode(1), QHeaderView::Stretch);
1129     view->setResizeMode(QHeaderView::Custom);
1130     QCOMPARE(view->resizeMode(last), QHeaderView::Custom);
1131     QCOMPARE(view->resizeMode(1), QHeaderView::Custom);
1132 
1133     // test when sections have been moved
1134     view->setStretchLastSection(false);
1135     for (int i=0; i < (view->count() - 1); ++i)
1136         view->setResizeMode(i, QHeaderView::Interactive);
1137     int logicalIndex = view->count() / 2;
1138     view->setResizeMode(logicalIndex, QHeaderView::Stretch);
1139     view->moveSection(view->visualIndex(logicalIndex), 0);
1140     for (int i=0; i < (view->count() - 1); ++i) {
1141         if (i == logicalIndex)
1142             QCOMPARE(view->resizeMode(i), QHeaderView::Stretch);
1143         else
1144             QCOMPARE(view->resizeMode(i), QHeaderView::Interactive);
1145     }
1146 }
1147 
resizeSection_data()1148 void tst_QHeaderView::resizeSection_data()
1149 {
1150     QTest::addColumn<int>("initial");
1151     QTest::addColumn<QList<int> >("logical");
1152     QTest::addColumn<QList<int> >("size");
1153     QTest::addColumn<QList<int> >("mode");
1154     QTest::addColumn<int>("resized");
1155     QTest::addColumn<QList<int> >("expected");
1156 
1157     QTest::newRow("bad args")
1158         << 100
1159         << (QList<int>() << -1 << -1 << 99999 << 99999 << 4)
1160         << (QList<int>() << -1 << 0 << 99999 << -1 << -1)
1161         << (QList<int>()
1162             << int(QHeaderView::Interactive)
1163             << int(QHeaderView::Interactive)
1164             << int(QHeaderView::Interactive)
1165             << int(QHeaderView::Interactive))
1166         << 0
1167         << (QList<int>() << 0 << 0 << 0 << 0 << 0);
1168 }
1169 
resizeSection()1170 void tst_QHeaderView::resizeSection()
1171 {
1172 
1173     QFETCH(int, initial);
1174     QFETCH(QList<int>, logical);
1175     QFETCH(QList<int>, size);
1176     QFETCH(QList<int>, mode);
1177     QFETCH(int, resized);
1178     QFETCH(QList<int>, expected);
1179 
1180     view->resize(400, 400);
1181 
1182     topLevel->show();
1183     view->setMovable(true);
1184     view->setStretchLastSection(false);
1185 
1186     for (int i = 0; i < logical.count(); ++i)
1187         if (logical.at(i) > -1 && logical.at(i) < view->count()) // for now
1188             view->setResizeMode(logical.at(i), (QHeaderView::ResizeMode)mode.at(i));
1189 
1190     for (int j = 0; j < logical.count(); ++j)
1191         view->resizeSection(logical.at(j), initial);
1192 
1193     QSignalSpy spy(view, SIGNAL(sectionResized(int, int, int)));
1194 
1195     for (int k = 0; k < logical.count(); ++k)
1196         view->resizeSection(logical.at(k), size.at(k));
1197 
1198     QCOMPARE(spy.count(), resized);
1199 
1200     for (int l = 0; l < logical.count(); ++l)
1201         QCOMPARE(view->sectionSize(logical.at(l)), expected.at(l));
1202 }
1203 
highlightSections()1204 void tst_QHeaderView::highlightSections()
1205 {
1206     view->setHighlightSections(true);
1207     QCOMPARE(view->highlightSections(), true);
1208     view->setHighlightSections(false);
1209     QCOMPARE(view->highlightSections(), false);
1210 }
1211 
showSortIndicator()1212 void tst_QHeaderView::showSortIndicator()
1213 {
1214     view->setSortIndicatorShown(true);
1215     QCOMPARE(view->isSortIndicatorShown(), true);
1216     QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder);
1217     view->setSortIndicator(1, Qt::AscendingOrder);
1218     QCOMPARE(view->sortIndicatorOrder(), Qt::AscendingOrder);
1219     view->setSortIndicator(1, Qt::DescendingOrder);
1220     QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder);
1221     view->setSortIndicatorShown(false);
1222     QCOMPARE(view->isSortIndicatorShown(), false);
1223 
1224     view->setSortIndicator(999999, Qt::DescendingOrder);
1225     // Don't segfault baby :)
1226     view->setSortIndicatorShown(true);
1227 
1228     view->setSortIndicator(0, Qt::DescendingOrder);
1229     // Don't assert baby :)
1230 }
1231 
sortIndicatorTracking()1232 void tst_QHeaderView::sortIndicatorTracking()
1233 {
1234     QtTestModel model;
1235     model.rows = model.cols = 10;
1236 
1237     QHeaderView hv(Qt::Horizontal);
1238 
1239     hv.setModel(&model);
1240     hv.show();
1241     hv.setSortIndicatorShown(true);
1242     hv.setSortIndicator(1, Qt::DescendingOrder);
1243 
1244     model.removeOneColumn(8);
1245     QCOMPARE(hv.sortIndicatorSection(), 1);
1246 
1247     model.removeOneColumn(2);
1248     QCOMPARE(hv.sortIndicatorSection(), 1);
1249 
1250     model.insertOneColumn(2);
1251     QCOMPARE(hv.sortIndicatorSection(), 1);
1252 
1253     model.insertOneColumn(1);
1254     QCOMPARE(hv.sortIndicatorSection(), 2);
1255 
1256     model.removeOneColumn(0);
1257     QCOMPARE(hv.sortIndicatorSection(), 1);
1258 
1259     model.removeOneColumn(1);
1260     QCOMPARE(hv.sortIndicatorSection(), -1);
1261 }
1262 
removeAndInsertRow()1263 void tst_QHeaderView::removeAndInsertRow()
1264 {
1265     // Check if logicalIndex returns the correct value after we have removed a row
1266     // we might as well te
1267     for (int i = 0; i < model->rowCount(); ++i) {
1268         QCOMPARE(i, view->logicalIndex(i));
1269     }
1270 
1271     while (model->removeRow(0)) {
1272         for (int i = 0; i < model->rowCount(); ++i) {
1273             QCOMPARE(i, view->logicalIndex(i));
1274         }
1275     }
1276 
1277     int pass = 0;
1278     for (pass = 0; pass < 5; pass++) {
1279         for (int i = 0; i < model->rowCount(); ++i) {
1280             QCOMPARE(i, view->logicalIndex(i));
1281         }
1282         model->insertRow(0);
1283     }
1284 
1285     while (model->removeRows(0, 2)) {
1286         for (int i = 0; i < model->rowCount(); ++i) {
1287             QCOMPARE(i, view->logicalIndex(i));
1288         }
1289     }
1290 
1291     for (pass = 0; pass < 3; pass++) {
1292         model->insertRows(0, 2);
1293         for (int i = 0; i < model->rowCount(); ++i) {
1294             QCOMPARE(i, view->logicalIndex(i));
1295         }
1296     }
1297 
1298     for (pass = 0; pass < 3; pass++) {
1299         model->insertRows(3, 2);
1300         for (int i = 0; i < model->rowCount(); ++i) {
1301             QCOMPARE(i, view->logicalIndex(i));
1302         }
1303     }
1304 
1305     // Insert at end
1306     for (pass = 0; pass < 3; pass++) {
1307         int rowCount = model->rowCount();
1308         model->insertRows(rowCount, 1);
1309         for (int i = 0; i < rowCount; ++i) {
1310             QCOMPARE(i, view->logicalIndex(i));
1311         }
1312     }
1313 
1314 }
unhideSection()1315 void tst_QHeaderView::unhideSection()
1316 {
1317     // You should not necessarily expect the same size back again, so the best test we can do is to test if it is larger than 0 after a unhide.
1318     QCOMPARE(view->sectionsHidden(), false);
1319     view->setSectionHidden(0, true);
1320     QCOMPARE(view->sectionsHidden(), true);
1321     QVERIFY(view->sectionSize(0) == 0);
1322     view->setResizeMode(QHeaderView::Interactive);
1323     view->setSectionHidden(0, false);
1324     QVERIFY(view->sectionSize(0) > 0);
1325 
1326     view->setSectionHidden(0, true);
1327     QVERIFY(view->sectionSize(0) == 0);
1328     view->setSectionHidden(0, true);
1329     QVERIFY(view->sectionSize(0) == 0);
1330     view->setResizeMode(QHeaderView::Stretch);
1331     view->setSectionHidden(0, false);
1332     QVERIFY(view->sectionSize(0) > 0);
1333 
1334 }
1335 
event()1336 void tst_QHeaderView::event()
1337 {
1338     protected_QHeaderView x(Qt::Vertical);
1339     x.testEvent();
1340     protected_QHeaderView y(Qt::Horizontal);
1341     y.testEvent();
1342 }
1343 
1344 
testEvent()1345 void protected_QHeaderView::testEvent()
1346 {
1347     // No crashy please
1348     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint());
1349     event(&enterEvent);
1350     QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint());
1351     event(&eventLeave);
1352     QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint());
1353     event(&eventMove);
1354 }
1355 
headerDataChanged()1356 void tst_QHeaderView::headerDataChanged()
1357 {
1358     // This shouldn't asserver because view is Vertical
1359     view->headerDataChanged(Qt::Horizontal, -1, -1);
1360 #if 0
1361     // This will assert
1362     view->headerDataChanged(Qt::Vertical, -1, -1);
1363 #endif
1364 
1365     // No crashing please
1366     view->headerDataChanged(Qt::Horizontal, 0, 1);
1367     view->headerDataChanged(Qt::Vertical, 0, 1);
1368 }
1369 
currentChanged()1370 void tst_QHeaderView::currentChanged()
1371 {
1372     view->setCurrentIndex(QModelIndex());
1373 }
1374 
horizontalOffset()1375 void tst_QHeaderView::horizontalOffset()
1376 {
1377     protected_QHeaderView x(Qt::Vertical);
1378     x.testhorizontalOffset();
1379     protected_QHeaderView y(Qt::Horizontal);
1380     y.testhorizontalOffset();
1381 }
1382 
verticalOffset()1383 void tst_QHeaderView::verticalOffset()
1384 {
1385     protected_QHeaderView x(Qt::Vertical);
1386     x.testverticalOffset();
1387     protected_QHeaderView y(Qt::Horizontal);
1388     y.testverticalOffset();
1389 }
1390 
testhorizontalOffset()1391 void  protected_QHeaderView::testhorizontalOffset()
1392 {
1393     if(orientation() == Qt::Horizontal){
1394         QCOMPARE(horizontalOffset(), 0);
1395         setOffset(10);
1396         QCOMPARE(horizontalOffset(), 10);
1397     }
1398     else
1399         QCOMPARE(horizontalOffset(), 0);
1400 
1401 }
1402 
testverticalOffset()1403 void  protected_QHeaderView::testverticalOffset()
1404 {
1405     if(orientation() == Qt::Vertical){
1406         QCOMPARE(verticalOffset(), 0);
1407         setOffset(10);
1408         QCOMPARE(verticalOffset(), 10);
1409     }
1410     else
1411         QCOMPARE(verticalOffset(), 0);
1412 }
1413 
stretchSectionCount()1414 void tst_QHeaderView::stretchSectionCount()
1415 {
1416     view->setStretchLastSection(false);
1417     QCOMPARE(view->stretchSectionCount(), 0);
1418     view->setStretchLastSection(true);
1419     QCOMPARE(view->stretchSectionCount(), 0);
1420 
1421     view->setResizeMode(0, QHeaderView::Stretch);
1422     QCOMPARE(view->stretchSectionCount(), 1);
1423 }
1424 
hiddenSectionCount()1425 void tst_QHeaderView::hiddenSectionCount()
1426 {
1427     model->clear();
1428     model->insertRows(0, 10);
1429     // Hide every other one
1430     for (int i=0; i<10; i++)
1431         view->setSectionHidden(i, (i & 1) == 0);
1432 
1433     QCOMPARE(view->hiddenSectionCount(), 5);
1434 
1435     view->setResizeMode(QHeaderView::Stretch);
1436     QCOMPARE(view->hiddenSectionCount(), 5);
1437 
1438     // Remove some rows and make sure they are now still counted
1439     model->removeRow(9);
1440     model->removeRow(8);
1441     model->removeRow(7);
1442     model->removeRow(6);
1443     QCOMPARE(view->count(), 6);
1444     QCOMPARE(view->hiddenSectionCount(), 3);
1445     model->removeRows(0,5);
1446     QCOMPARE(view->count(), 1);
1447     QCOMPARE(view->hiddenSectionCount(), 0);
1448     QVERIFY(view->count() >=  view->hiddenSectionCount());
1449 }
1450 
focusPolicy()1451 void tst_QHeaderView::focusPolicy()
1452 {
1453     QHeaderView view(Qt::Horizontal);
1454     QCOMPARE(view.focusPolicy(), Qt::NoFocus);
1455 
1456     QTreeWidget widget;
1457     QCOMPARE(widget.header()->focusPolicy(), Qt::NoFocus);
1458     QVERIFY(!widget.focusProxy());
1459     QVERIFY(!widget.hasFocus());
1460     QVERIFY(!widget.header()->focusProxy());
1461     QVERIFY(!widget.header()->hasFocus());
1462 
1463     widget.show();
1464     widget.setFocus(Qt::OtherFocusReason);
1465     QApplication::setActiveWindow(&widget);
1466     QTest::qWaitForWindowShown(&widget);
1467     widget.activateWindow();
1468     QTest::qWait(100);
1469 
1470     qApp->processEvents();
1471 
1472     WAIT_FOR_CONDITION(widget.hasFocus(), true);
1473 
1474     QVERIFY(widget.hasFocus());
1475     QVERIFY(!widget.header()->hasFocus());
1476 
1477     widget.setFocusPolicy(Qt::NoFocus);
1478     widget.clearFocus();
1479 
1480     qApp->processEvents();
1481     qApp->processEvents();
1482 
1483     WAIT_FOR_CONDITION(widget.hasFocus(), false);
1484     QVERIFY(!widget.hasFocus());
1485     QVERIFY(!widget.header()->hasFocus());
1486 
1487     QTest::keyPress(&widget, Qt::Key_Tab);
1488 
1489     qApp->processEvents();
1490     qApp->processEvents();
1491 
1492     QVERIFY(!widget.hasFocus());
1493     QVERIFY(!widget.header()->hasFocus());
1494 }
1495 
1496 class SimpleModel : public QAbstractItemModel
1497 {
1498     Q_OBJECT
1499 public:
1500 
SimpleModel(QObject * parent=0)1501     SimpleModel( QObject* parent=0)
1502         : QAbstractItemModel(parent),
1503         m_col_count(3) {}
1504 
parent(const QModelIndex &) const1505     QModelIndex parent(const QModelIndex &/*child*/) const
1506     {
1507         return QModelIndex();
1508     }
index(int row,int column,const QModelIndex & parent=QModelIndex ()) const1509     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
1510     {
1511         return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
1512     }
rowCount(const QModelIndex &) const1513     int rowCount(const QModelIndex & /* parent */) const
1514     {
1515         return 8;
1516     }
columnCount(const QModelIndex &) const1517     int columnCount(const QModelIndex &/*parent= QModelIndex()*/) const
1518     {
1519         return m_col_count;
1520     }
1521 
data(const QModelIndex & index,int role) const1522     QVariant data(const QModelIndex &index, int role) const
1523     {
1524         if (!index.isValid())
1525         {
1526             return QVariant();
1527         }
1528         if (role == Qt::DisplayRole) {
1529             return QString::fromAscii("%1,%2").arg(index.row()).arg(index.column());
1530         }
1531         return QVariant();
1532     }
1533 
setColumnCount(int c)1534     void setColumnCount( int c )
1535     {
1536         m_col_count = c;
1537     }
1538 
1539 private:
1540     int m_col_count;
1541 };
1542 
moveSectionAndReset()1543 void tst_QHeaderView::moveSectionAndReset()
1544 {
1545     SimpleModel m;
1546     QHeaderView v(Qt::Horizontal);
1547     v.setModel(&m);
1548     int cc = 2;
1549     for (cc = 2; cc < 4; ++cc) {
1550         m.setColumnCount(cc);
1551         int movefrom = 0;
1552         int moveto;
1553         for (moveto = 1; moveto < cc; ++moveto) {
1554             v.moveSection(movefrom, moveto);
1555             m.setColumnCount(cc - 1);
1556             v.reset();
1557             for (int i = 0; i < cc - 1; ++i) {
1558                 QCOMPARE(v.logicalIndex(v.visualIndex(i)), i);
1559             }
1560         }
1561     }
1562 }
1563 
moveSectionAndRemove()1564 void tst_QHeaderView::moveSectionAndRemove()
1565 {
1566     QStandardItemModel m;
1567     QHeaderView v(Qt::Horizontal);
1568 
1569     v.setModel(&m);
1570     v.model()->insertColumns(0, 3);
1571     v.moveSection(0, 1);
1572 
1573     QCOMPARE(v.count(), 3);
1574     v.model()->removeColumns(0, v.model()->columnCount());
1575     QCOMPARE(v.count(), 0);
1576 }
1577 
saveRestore()1578 void tst_QHeaderView::saveRestore()
1579 {
1580     SimpleModel m;
1581     QHeaderView h1(Qt::Horizontal);
1582     h1.setModel(&m);
1583     h1.swapSections(0, 2);
1584     h1.resizeSection(1, 10);
1585     h1.setSortIndicatorShown(true);
1586     h1.setSortIndicator(1,Qt::DescendingOrder);
1587     QByteArray s1 = h1.saveState();
1588 
1589     QHeaderView h2(Qt::Vertical);
1590     QSignalSpy spy(&h2, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)));
1591 
1592     h2.setModel(&m);
1593     h2.restoreState(s1);
1594 
1595     QCOMPARE(spy.count(), 1);
1596     QCOMPARE(spy.at(0).at(0).toInt(), 1);
1597 
1598     QCOMPARE(h2.logicalIndex(0), 2);
1599     QCOMPARE(h2.logicalIndex(2), 0);
1600     QCOMPARE(h2.sectionSize(1), 10);
1601     QCOMPARE(h2.sortIndicatorSection(), 1);
1602     QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder);
1603     QCOMPARE(h2.isSortIndicatorShown(), true);
1604 
1605     QByteArray s2 = h2.saveState();
1606 
1607     QVERIFY(s1 == s2);
1608 }
1609 
defaultAlignment_data()1610 void tst_QHeaderView::defaultAlignment_data()
1611 {
1612     QTest::addColumn<int>("direction");
1613     QTest::addColumn<int>("initial");
1614     QTest::addColumn<int>("alignment");
1615 
1616     QTest::newRow("horizontal right aligned")
1617         << int(Qt::Horizontal)
1618         << int(Qt::AlignCenter)
1619         << int(Qt::AlignRight);
1620 
1621     QTest::newRow("horizontal left aligned")
1622         << int(Qt::Horizontal)
1623         << int(Qt::AlignCenter)
1624         << int(Qt::AlignLeft);
1625 
1626     QTest::newRow("vertical right aligned")
1627         << int(Qt::Vertical)
1628         << int(Qt::AlignLeft|Qt::AlignVCenter)
1629         << int(Qt::AlignRight);
1630 
1631     QTest::newRow("vertical left aligned")
1632         << int(Qt::Vertical)
1633         << int(Qt::AlignLeft|Qt::AlignVCenter)
1634         << int(Qt::AlignLeft);
1635 }
1636 
defaultAlignment()1637 void tst_QHeaderView::defaultAlignment()
1638 {
1639     QFETCH(int, direction);
1640     QFETCH(int, initial);
1641     QFETCH(int, alignment);
1642 
1643     SimpleModel m;
1644 
1645     QHeaderView header((Qt::Orientation)direction);
1646     header.setModel(&m);
1647 
1648     QCOMPARE(header.defaultAlignment(), (Qt::Alignment)initial);
1649     header.setDefaultAlignment((Qt::Alignment)alignment);
1650     QCOMPARE(header.defaultAlignment(), (Qt::Alignment)alignment);
1651 }
1652 
globalResizeMode_data()1653 void tst_QHeaderView::globalResizeMode_data()
1654 {
1655     QTest::addColumn<int>("direction");
1656     QTest::addColumn<int>("mode");
1657     QTest::addColumn<int>("insert");
1658 
1659     QTest::newRow("horizontal ResizeToContents 0")
1660         << int(Qt::Horizontal)
1661         << int(QHeaderView::ResizeToContents)
1662         << 0;
1663 }
1664 
globalResizeMode()1665 void tst_QHeaderView::globalResizeMode()
1666 {
1667     QFETCH(int, direction);
1668     QFETCH(int, mode);
1669     QFETCH(int, insert);
1670 
1671     QStandardItemModel m(4, 4);
1672     QHeaderView h((Qt::Orientation)direction);
1673     h.setModel(&m);
1674 
1675     h.setResizeMode((QHeaderView::ResizeMode)mode);
1676     m.insertRow(insert);
1677     for (int i = 0; i < h.count(); ++i)
1678         QCOMPARE(h.resizeMode(i), (QHeaderView::ResizeMode)mode);
1679 }
1680 
1681 
sectionPressedSignal_data()1682 void tst_QHeaderView::sectionPressedSignal_data()
1683 {
1684     QTest::addColumn<int>("direction");
1685     QTest::addColumn<bool>("clickable");
1686     QTest::addColumn<int>("count");
1687 
1688     QTest::newRow("horizontal unclickable 0")
1689         << int(Qt::Horizontal)
1690         << false
1691         << 0;
1692 
1693     QTest::newRow("horizontal clickable 1")
1694         << int(Qt::Horizontal)
1695         << true
1696         << 1;
1697 }
1698 
sectionPressedSignal()1699 void tst_QHeaderView::sectionPressedSignal()
1700 {
1701     QFETCH(int, direction);
1702     QFETCH(bool, clickable);
1703     QFETCH(int, count);
1704 
1705     QStandardItemModel m(4, 4);
1706     QHeaderView h((Qt::Orientation)direction);
1707 
1708     h.setModel(&m);
1709     h.show();
1710     h.setClickable(clickable);
1711 
1712     QSignalSpy spy(&h, SIGNAL(sectionPressed(int)));
1713 
1714     QCOMPARE(spy.count(), 0);
1715     QTest::mousePress(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
1716     QCOMPARE(spy.count(), count);
1717 }
1718 
sectionClickedSignal()1719 void tst_QHeaderView::sectionClickedSignal()
1720 {
1721     QFETCH(int, direction);
1722     QFETCH(bool, clickable);
1723     QFETCH(int, count);
1724 
1725     QStandardItemModel m(4, 4);
1726     QHeaderView h((Qt::Orientation)direction);
1727 
1728     h.setModel(&m);
1729     h.show();
1730     h.setClickable(clickable);
1731     h.setSortIndicatorShown(true);
1732 
1733     QSignalSpy spy(&h, SIGNAL(sectionClicked(int)));
1734     QSignalSpy spy2(&h, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)));
1735 
1736     QCOMPARE(spy.count(), 0);
1737     QCOMPARE(spy2.count(), 0);
1738     QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
1739     QCOMPARE(spy.count(), count);
1740     QCOMPARE(spy2.count(), count);
1741 
1742     //now let's try with the sort indicator hidden (the result should be the same
1743     spy.clear();
1744     spy2.clear();
1745     h.setSortIndicatorShown(false);
1746     QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
1747     QCOMPARE(spy.count(), count);
1748     QCOMPARE(spy2.count(), count);
1749 }
1750 
defaultSectionSize_data()1751 void tst_QHeaderView::defaultSectionSize_data()
1752 {
1753     QTest::addColumn<int>("direction");
1754     QTest::addColumn<int>("oldDefaultSize");
1755     QTest::addColumn<int>("newDefaultSize");
1756 
1757     //QTest::newRow("horizontal,-5") << int(Qt::Horizontal) << 100 << -5;
1758     QTest::newRow("horizontal, 0") << int(Qt::Horizontal) << 100 << 0;
1759     QTest::newRow("horizontal, 5") << int(Qt::Horizontal) << 100 << 5;
1760     QTest::newRow("horizontal,25") << int(Qt::Horizontal) << 100 << 5;
1761 }
1762 
defaultSectionSize()1763 void tst_QHeaderView::defaultSectionSize()
1764 {
1765     QFETCH(int, direction);
1766     QFETCH(int, oldDefaultSize);
1767     QFETCH(int, newDefaultSize);
1768 
1769     QStandardItemModel m(4, 4);
1770     QHeaderView h((Qt::Orientation)direction);
1771 
1772     h.setModel(&m);
1773 
1774     QCOMPARE(h.defaultSectionSize(), oldDefaultSize);
1775     h.setDefaultSectionSize(newDefaultSize);
1776     QCOMPARE(h.defaultSectionSize(), newDefaultSize);
1777     h.reset();
1778     for (int i = 0; i < h.count(); ++i)
1779         QCOMPARE(h.sectionSize(i), newDefaultSize);
1780 }
1781 
hideAndInsert_data()1782 void tst_QHeaderView::hideAndInsert_data()
1783 {
1784     QTest::addColumn<int>("direction");
1785     QTest::addColumn<int>("hide");
1786     QTest::addColumn<int>("insert");
1787     QTest::addColumn<int>("hidden");
1788 
1789     QTest::newRow("horizontal, 0, 0") << int(Qt::Horizontal) << 0 << 0 << 1;
1790 }
1791 
hideAndInsert()1792 void tst_QHeaderView::hideAndInsert()
1793 {
1794     QFETCH(int, direction);
1795     QFETCH(int, hide);
1796     QFETCH(int, insert);
1797     QFETCH(int, hidden);
1798 
1799     QStandardItemModel m(4, 4);
1800     QHeaderView h((Qt::Orientation)direction);
1801 
1802     h.setModel(&m);
1803 
1804     h.setSectionHidden(hide, true);
1805 
1806     if (direction == Qt::Vertical)
1807         m.insertRow(insert);
1808     else
1809         m.insertColumn(insert);
1810 
1811     for (int i = 0; i < h.count(); ++i)
1812         if (i != hidden)
1813             QCOMPARE(h.isSectionHidden(i), false);
1814         else
1815             QCOMPARE(h.isSectionHidden(i), true);
1816 }
1817 
removeSection()1818 void tst_QHeaderView::removeSection()
1819 {
1820 //test that removing a hidden section gives the expected result: the next row should be hidden
1821 //(see task
1822     const int hidden = 3; //section that will be hidden
1823     const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5" << "6";
1824 
1825     QStringListModel model( list );
1826     QHeaderView view(Qt::Vertical);
1827     view.setModel(&model);
1828     view.hideSection(hidden);
1829     view.hideSection(1);
1830     model.removeRow(1);
1831     view.show();
1832 
1833     for(int i = 0; i < view.count(); i++) {
1834         if (i == (hidden-1)) { //-1 because we removed a row in the meantime
1835             QCOMPARE(view.sectionSize(i), 0);
1836             QVERIFY(view.isSectionHidden(i));
1837         } else {
1838             QCOMPARE(view.sectionSize(i), view.defaultSectionSize() );
1839             QVERIFY(!view.isSectionHidden(i));
1840         }
1841     }
1842 }
1843 
preserveHiddenSectionWidth()1844 void tst_QHeaderView::preserveHiddenSectionWidth()
1845 {
1846     const QStringList list = QStringList() << "0" << "1" << "2" << "3";
1847 
1848     QStringListModel model( list );
1849     QHeaderView view(Qt::Vertical);
1850     view.setModel(&model);
1851     view.resizeSection(0, 100);
1852     view.resizeSection(1, 10);
1853     view.resizeSection(2, 50);
1854     view.setResizeMode(3, QHeaderView::Stretch);
1855     view.show();
1856 
1857     view.hideSection(2);
1858     model.removeRow(1);
1859     view.showSection(1);
1860     QCOMPARE(view.sectionSize(0), 100);
1861     QCOMPARE(view.sectionSize(1), 50);
1862 
1863     view.hideSection(1);
1864     model.insertRow(1);
1865     view.showSection(2);
1866     QCOMPARE(view.sectionSize(0), 100);
1867     QCOMPARE(view.sectionSize(1), view.defaultSectionSize());
1868     QCOMPARE(view.sectionSize(2), 50);
1869 }
1870 
invisibleStretchLastSection()1871 void tst_QHeaderView::invisibleStretchLastSection()
1872 {
1873     int count = 6;
1874     QStandardItemModel model(1, count);
1875     QHeaderView view(Qt::Horizontal);
1876     view.setModel(&model);
1877     int height = view.height();
1878 
1879     view.resize(view.defaultSectionSize() * (count / 2), height); // don't show all sections
1880     view.show();
1881     view.setStretchLastSection(true);
1882     // stretch section is not visible; it should not be stretched
1883     for (int i = 0; i < count; ++i)
1884         QCOMPARE(view.sectionSize(i), view.defaultSectionSize());
1885 
1886     view.resize(view.defaultSectionSize() * (count + 1), height); // give room to stretch
1887 
1888     // stretch section is visible; it should be stretched
1889     for (int i = 0; i < count - 1; ++i)
1890         QCOMPARE(view.sectionSize(i), view.defaultSectionSize());
1891     QCOMPARE(view.sectionSize(count - 1), view.defaultSectionSize() * 2);
1892 }
1893 
emptySectionSpan()1894 void tst_QHeaderView::emptySectionSpan()
1895 {
1896     QHeaderViewPrivate::SectionSpan span;
1897     QCOMPARE(span.sectionSize(), 0);
1898 }
1899 
task236450_hidden_data()1900 void tst_QHeaderView::task236450_hidden_data()
1901 {
1902     QTest::addColumn<QList<int> >("hide1");
1903     QTest::addColumn<QList<int> >("hide2");
1904 
1905     QTest::newRow("set 1") << (QList<int>() << 1 << 3)
1906                            << (QList<int>() << 1 << 5);
1907 
1908     QTest::newRow("set 2") << (QList<int>() << 2 << 3)
1909                            << (QList<int>() << 1 << 5);
1910 
1911     QTest::newRow("set 3") << (QList<int>() << 0 << 2 << 4)
1912                            << (QList<int>() << 2 << 3 << 5);
1913 
1914 }
1915 
task236450_hidden()1916 void tst_QHeaderView::task236450_hidden()
1917 {
1918     QFETCH(QList<int>, hide1);
1919     QFETCH(QList<int>, hide2);
1920     const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5";
1921 
1922     QStringListModel model( list );
1923     protected_QHeaderView view(Qt::Vertical);
1924     view.setModel(&model);
1925     view.show();
1926 
1927     foreach (int i, hide1)
1928         view.hideSection(i);
1929 
1930     QCOMPARE(view.hiddenSectionCount(), hide1.count());
1931     for (int i = 0; i < 6; i++) {
1932         QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i));
1933     }
1934 
1935     view.setDefaultSectionSize(2);
1936     view.scheduleDelayedItemsLayout();
1937     view.executeDelayedItemsLayout(); //force to do a relayout
1938 
1939     QCOMPARE(view.hiddenSectionCount(), hide1.count());
1940     for (int i = 0; i < 6; i++) {
1941         QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i));
1942         view.setSectionHidden(i, hide2.contains(i));
1943     }
1944 
1945     QCOMPARE(view.hiddenSectionCount(), hide2.count());
1946     for (int i = 0; i < 6; i++) {
1947         QCOMPARE(!view.isSectionHidden(i), !hide2.contains(i));
1948     }
1949 
1950 }
1951 
task248050_hideRow()1952 void tst_QHeaderView::task248050_hideRow()
1953 {
1954     //this is the sequence of events that make the task fail
1955     protected_QHeaderView header(Qt::Vertical);
1956     QStandardItemModel model(0, 1);
1957     header.setStretchLastSection(false);
1958     header.setDefaultSectionSize(17);
1959     header.setModel(&model);
1960     header.doItemsLayout();
1961 
1962     model.setRowCount(3);
1963 
1964     QCOMPARE(header.sectionPosition(2), 17*2);
1965 
1966     header.hideSection(1);
1967     QCOMPARE(header.sectionPosition(2), 17);
1968 
1969     QTest::qWait(100);
1970     //the size of the section shouldn't have changed
1971     QCOMPARE(header.sectionPosition(2), 17);
1972 }
1973 
1974 
1975 //returns 0 if everything is fine.
checkHeaderViewOrder(QHeaderView * view,const QVector<int> & expected)1976 static int checkHeaderViewOrder(QHeaderView *view, const QVector<int> &expected)
1977 {
1978     if (view->count() != expected.count())
1979         return 1;
1980 
1981     for (int i = 0; i < expected.count(); i++) {
1982         if (view->logicalIndex(i) != expected.at(i))
1983             return i + 10;
1984         if (view->visualIndex(expected.at(i)) != i)
1985             return i + 100;
1986     }
1987     return 0;
1988 }
1989 
1990 
QTBUG6058_reset()1991 void tst_QHeaderView::QTBUG6058_reset()
1992 {
1993     QStringListModel model1( QStringList() << "0" << "1" << "2" << "3" << "4" << "5" );
1994     QStringListModel model2( QStringList() << "a" << "b" << "c" );
1995     QSortFilterProxyModel proxy;
1996 
1997     QHeaderView view(Qt::Vertical);
1998     view.setModel(&proxy);
1999     view.show();
2000     QTest::qWait(20);
2001 
2002     proxy.setSourceModel(&model1);
2003     QApplication::processEvents();
2004     view.swapSections(0,2);
2005     view.swapSections(1,4);
2006     QApplication::processEvents();
2007     QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 4 << 0 << 3 << 1 << 5) , 0);
2008 
2009     proxy.setSourceModel(&model2);
2010     QApplication::processEvents();
2011     QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 0 << 1 ) , 0);
2012 
2013     proxy.setSourceModel(&model1);
2014     QApplication::processEvents();
2015     QCOMPARE(checkHeaderViewOrder(&view, QVector<int>() << 2 << 0 << 1 << 3 << 4 << 5 ) , 0);
2016 }
2017 
QTBUG7833_sectionClicked()2018 void tst_QHeaderView::QTBUG7833_sectionClicked()
2019 {
2020 
2021 
2022 
2023 
2024     QTableView tv;
2025     QStandardItemModel *sim = new QStandardItemModel(&tv);
2026     QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&tv);
2027     proxyModel->setSourceModel(sim);
2028     proxyModel->setDynamicSortFilter(true);
2029     proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
2030 
2031     QList<QStandardItem *> row;
2032     for (int i = 0; i < 12; i++)
2033         row.append(new QStandardItem(QString(QLatin1Char('A' + i))));
2034     sim->appendRow(row);
2035     row.clear();
2036     for (int i = 12; i > 0; i--)
2037         row.append(new QStandardItem(QString(QLatin1Char('A' + i))));
2038     sim->appendRow(row);
2039 
2040     tv.setSortingEnabled(true);
2041     tv.horizontalHeader()->setSortIndicatorShown(true);
2042     tv.horizontalHeader()->setClickable(true);
2043     tv.horizontalHeader()->setStretchLastSection(true);
2044     tv.horizontalHeader()->setResizeMode(QHeaderView::Interactive);
2045 
2046     tv.setModel(proxyModel);
2047     tv.setColumnHidden(5, true);
2048     tv.setColumnHidden(6, true);
2049     tv.horizontalHeader()->swapSections(8, 10);
2050     tv.sortByColumn(1, Qt::AscendingOrder);
2051 
2052     QSignalSpy clickedSpy(tv.horizontalHeader(), SIGNAL(sectionClicked(int)));
2053     QSignalSpy pressedSpy(tv.horizontalHeader(), SIGNAL(sectionPressed(int)));
2054 
2055 
2056     QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
2057                       QPoint(tv.horizontalHeader()->sectionViewportPosition(11) + tv.horizontalHeader()->sectionSize(11)/2, 5));
2058     QCOMPARE(clickedSpy.count(), 1);
2059     QCOMPARE(pressedSpy.count(), 1);
2060     QCOMPARE(clickedSpy.at(0).at(0).toInt(), 11);
2061     QCOMPARE(pressedSpy.at(0).at(0).toInt(), 11);
2062 
2063     QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
2064                       QPoint(tv.horizontalHeader()->sectionViewportPosition(8) + tv.horizontalHeader()->sectionSize(0)/2, 5));
2065 
2066     QCOMPARE(clickedSpy.count(), 2);
2067     QCOMPARE(pressedSpy.count(), 2);
2068     QCOMPARE(clickedSpy.at(1).at(0).toInt(), 8);
2069     QCOMPARE(pressedSpy.at(1).at(0).toInt(), 8);
2070 
2071     QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier,
2072                       QPoint(tv.horizontalHeader()->sectionViewportPosition(0) + tv.horizontalHeader()->sectionSize(0)/2, 5));
2073 
2074     QCOMPARE(clickedSpy.count(), 3);
2075     QCOMPARE(pressedSpy.count(), 3);
2076     QCOMPARE(clickedSpy.at(2).at(0).toInt(), 0);
2077     QCOMPARE(pressedSpy.at(2).at(0).toInt(), 0);
2078 }
2079 
QTBUG8650_crashOnInsertSections()2080 void tst_QHeaderView::QTBUG8650_crashOnInsertSections()
2081 {
2082     QStringList headerLabels;
2083     QHeaderView view(Qt::Horizontal);
2084     QStandardItemModel model(2,2);
2085     view.setModel(&model);
2086     view.moveSection(1, 0);
2087     view.hideSection(0);
2088 
2089     QList<QStandardItem *> items;
2090     items << new QStandardItem("c");
2091     model.insertColumn(0, items);
2092 }
2093 
QTBUG12268_hiddenMovedSectionSorting()2094 void tst_QHeaderView::QTBUG12268_hiddenMovedSectionSorting()
2095 {
2096     QTableView view;
2097     QStandardItemModel *model = new QStandardItemModel(4,3, &view);
2098     for (int i = 0; i< model->rowCount(); ++i)
2099         for (int j = 0; j< model->columnCount(); ++j)
2100             model->setData(model->index(i,j), QString("item [%1,%2]").arg(i).arg(j));
2101     view.setModel(model);
2102     view.horizontalHeader()->setMovable(true);
2103     view.setSortingEnabled(true);
2104     view.sortByColumn(1, Qt::AscendingOrder);
2105     view.horizontalHeader()->moveSection(0,2);
2106     view.setColumnHidden(1, true);
2107     view.show();
2108     QTest::qWaitForWindowShown(&view);
2109     QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1);
2110     QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton);
2111     QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1);
2112 }
2113 
QTBUG14242_hideSectionAutoSize()2114 void tst_QHeaderView::QTBUG14242_hideSectionAutoSize()
2115 {
2116     QTableView qtv;
2117     QStandardItemModel amodel(4, 4);
2118     qtv.setModel(&amodel);
2119     QHeaderView *hv = qtv.verticalHeader();
2120     hv->setDefaultSectionSize(25);
2121     hv->setResizeMode(QHeaderView::ResizeToContents);
2122     qtv.show();
2123     hv->hideSection(0);
2124     int afterlength = hv->length();
2125     int calced_length = 0;
2126     for (int u = 0; u < hv->count(); ++u)
2127         calced_length += hv->sectionSize(u);
2128     QVERIFY(calced_length == afterlength);
2129 }
2130 
initialSortOrderRole()2131 void tst_QHeaderView::initialSortOrderRole()
2132 {
2133     QTableView view;
2134     QStandardItemModel *model = new QStandardItemModel(4, 3, &view);
2135     for (int i = 0; i< model->rowCount(); ++i)
2136         for (int j = 0; j< model->columnCount(); ++j)
2137             model->setData(model->index(i,j), QString("item [%1,%2]").arg(i).arg(j));
2138     QStandardItem *ascendingItem = new QStandardItem();
2139     QStandardItem *descendingItem = new QStandardItem();
2140     ascendingItem->setData(Qt::AscendingOrder, Qt::InitialSortOrderRole);
2141     descendingItem->setData(Qt::DescendingOrder, Qt::InitialSortOrderRole);
2142     model->setHorizontalHeaderItem(1, ascendingItem);
2143     model->setHorizontalHeaderItem(2, descendingItem);
2144     view.setModel(model);
2145     view.setSortingEnabled(true);
2146     view.sortByColumn(0, Qt::AscendingOrder);
2147     view.show();
2148     QTest::qWaitForWindowShown(&view);
2149 
2150     const int column1Pos = view.horizontalHeader()->sectionViewportPosition(1) + 5; // +5 not to be on the handle
2151     QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column1Pos, 0));
2152     QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 1);
2153     QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder);
2154 
2155     const int column2Pos = view.horizontalHeader()->sectionViewportPosition(2) + 5; // +5 not to be on the handle
2156     QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column2Pos, 0));
2157     QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 2);
2158     QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::DescendingOrder);
2159 
2160     const int column0Pos = view.horizontalHeader()->sectionViewportPosition(0) + 5; // +5 not to be on the handle
2161     QTest::mouseClick(view.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(column0Pos, 0));
2162     QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 0);
2163     QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder);
2164 }
2165 
ensureNoIndexAtLength()2166 void tst_QHeaderView::ensureNoIndexAtLength()
2167 {
2168     QTableView qtv;
2169     QStandardItemModel amodel(4, 4);
2170     qtv.setModel(&amodel);
2171     QHeaderView *hv = qtv.verticalHeader();
2172     QVERIFY(hv->visualIndexAt(hv->length()) == -1);
2173     hv->resizeSection(hv->count() - 1, 0);
2174     QVERIFY(hv->visualIndexAt(hv->length()) == -1);
2175 }
2176 
2177 
2178 QTEST_MAIN(tst_QHeaderView)
2179 #include "tst_qheaderview.moc"
2180