diff options
Diffstat (limited to 'tests/auto/qheaderview/tst_qheaderview.cpp')
-rw-r--r-- | tests/auto/qheaderview/tst_qheaderview.cpp | 1923 |
1 files changed, 1923 insertions, 0 deletions
diff --git a/tests/auto/qheaderview/tst_qheaderview.cpp b/tests/auto/qheaderview/tst_qheaderview.cpp new file mode 100644 index 0000000..0867e48 --- /dev/null +++ b/tests/auto/qheaderview/tst_qheaderview.cpp @@ -0,0 +1,1923 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QStandardItemModel> +#include <QStringListModel> + +#include <qabstractitemmodel.h> +#include <qapplication.h> +#include <qheaderview.h> +#include <private/qheaderview_p.h> +#include <qitemdelegate.h> +#include <qtreewidget.h> +#include <qdebug.h> + +typedef QList<int> IntList; +Q_DECLARE_METATYPE(IntList) + +typedef QList<bool> BoolList; +Q_DECLARE_METATYPE(BoolList) + +//TESTED_CLASS= +//TESTED_FILES= + +// Will try to wait for the condition while allowing event processing +// for a maximum of 2 seconds. +#define WAIT_FOR_CONDITION(expr, expected) \ + do { \ + const int step = 100; \ + for (int i = 0; i < 2000 && expr != expected; i+=step) { \ + QTest::qWait(step); \ + } \ + } while(0) + +class protected_QHeaderView : public QHeaderView +{ + Q_OBJECT +public: + protected_QHeaderView(Qt::Orientation orientation) : QHeaderView(orientation) { + resizeSections(); + }; + + void testEvent(); + void testhorizontalOffset(); + void testverticalOffset(); + friend class tst_QHeaderView; +}; + +class tst_QHeaderView : public QObject +{ + Q_OBJECT + +public: + tst_QHeaderView(); + virtual ~tst_QHeaderView(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void getSetCheck(); + void visualIndex(); + + void visualIndexAt_data(); + void visualIndexAt(); + + void noModel(); + void emptyModel(); + void removeRows(); + void removeCols(); + + void clickable(); + void movable(); + void hidden(); + void stretch(); + + void sectionSize_data(); + void sectionSize(); + + void length(); + void offset(); + void sectionSizeHint(); + void logicalIndex(); + void logicalIndexAt(); + void swapSections(); + + void moveSection_data(); + void moveSection(); + + void resizeMode(); + + void resizeSection_data(); + void resizeSection(); + + void resizeAndMoveSection_data(); + void resizeAndMoveSection(); + void resizeHiddenSection_data(); + void resizeHiddenSection(); + void resizeAndInsertSection_data(); + void resizeAndInsertSection(); + void resizeWithResizeModes_data(); + void resizeWithResizeModes(); + void moveAndInsertSection_data(); + void moveAndInsertSection(); + void highlightSections(); + void showSortIndicator(); + void sortIndicatorTracking(); + void removeAndInsertRow(); + void unhideSection(); + void event(); + void headerDataChanged(); + void currentChanged(); + void horizontalOffset(); + void verticalOffset(); + void stretchSectionCount(); + void hiddenSectionCount(); + void focusPolicy(); + void moveSectionAndReset(); + void moveSectionAndRemove(); + void saveRestore(); + + void defaultAlignment_data(); + void defaultAlignment(); + + void globalResizeMode_data(); + void globalResizeMode(); + + void sectionPressedSignal_data(); + void sectionPressedSignal(); + void sectionClickedSignal_data() { sectionPressedSignal_data(); } + void sectionClickedSignal(); + + void defaultSectionSize_data(); + void defaultSectionSize(); + + void oneSectionSize(); + + void hideAndInsert_data(); + void hideAndInsert(); + + void removeSection(); + void preserveHiddenSectionWidth(); + void invisibleStretchLastSection(); + + void emptySectionSpan(); + void task236450_hidden_data(); + void task236450_hidden(); + +protected: + QHeaderView *view; + QStandardItemModel *model; +}; + +class QtTestModel: public QAbstractTableModel +{ + +Q_OBJECT + +public: + QtTestModel(QObject *parent = 0): QAbstractTableModel(parent), + cols(0), rows(0), wrongIndex(false) {} + int rowCount(const QModelIndex&) const { return rows; } + int columnCount(const QModelIndex&) const { return cols; } + bool isEditable(const QModelIndex &) const { return true; } + + QVariant data(const QModelIndex &idx, int) const + { + if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) { + wrongIndex = true; + qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), idx.internalPointer()); + } + return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);//idx.data()); + } + + void insertOneColumn(int col) + { + beginInsertColumns(QModelIndex(), col, col); + --cols; + endInsertColumns(); + } + + void removeLastRow() + { + beginRemoveRows(QModelIndex(), rows - 1, rows - 1); + --rows; + endRemoveRows(); + } + + void removeAllRows() + { + beginRemoveRows(QModelIndex(), 0, rows - 1); + rows = 0; + endRemoveRows(); + } + + void removeOneColumn(int col) + { + beginRemoveColumns(QModelIndex(), col, col); + --cols; + endRemoveColumns(); + } + + void removeLastColumn() + { + beginRemoveColumns(QModelIndex(), cols - 1, cols - 1); + --cols; + endRemoveColumns(); + } + + void removeAllColumns() + { + beginRemoveColumns(QModelIndex(), 0, cols - 1); + cols = 0; + endRemoveColumns(); + } + + void cleanup() + { + cols = 3; + rows = 3; + emit layoutChanged(); + } + + int cols, rows; + mutable bool wrongIndex; +}; + +// Testing get/set functions +void tst_QHeaderView::getSetCheck() +{ + protected_QHeaderView obj1(Qt::Horizontal); + // bool QHeaderView::highlightSections() + // void QHeaderView::setHighlightSections(bool) + obj1.setHighlightSections(false); + QCOMPARE(false, obj1.highlightSections()); + obj1.setHighlightSections(true); + QCOMPARE(true, obj1.highlightSections()); + + // bool QHeaderView::stretchLastSection() + // void QHeaderView::setStretchLastSection(bool) + obj1.setStretchLastSection(false); + QCOMPARE(false, obj1.stretchLastSection()); + obj1.setStretchLastSection(true); + QCOMPARE(true, obj1.stretchLastSection()); + + // int QHeaderView::defaultSectionSize() + // void QHeaderView::setDefaultSectionSize(int) + obj1.setDefaultSectionSize(0); + QCOMPARE(0, obj1.defaultSectionSize()); + obj1.setDefaultSectionSize(INT_MIN); + QCOMPARE(INT_MIN, obj1.defaultSectionSize()); + obj1.setDefaultSectionSize(INT_MAX); + QCOMPARE(INT_MAX, obj1.defaultSectionSize()); + // ### the test above does not make sense for values below 0 + + // int QHeaderView::minimumSectionSize() + // void QHeaderView::setMinimumSectionSize(int) + obj1.setMinimumSectionSize(0); + QCOMPARE(0, obj1.minimumSectionSize()); + obj1.setMinimumSectionSize(INT_MIN); + QCOMPARE(INT_MIN, obj1.minimumSectionSize()); + obj1.setMinimumSectionSize(INT_MAX); + QCOMPARE(INT_MAX, obj1.minimumSectionSize()); + // ### the test above does not make sense for values below 0 + + // int QHeaderView::offset() + // void QHeaderView::setOffset(int) + obj1.setOffset(0); + QCOMPARE(0, obj1.offset()); + obj1.setOffset(INT_MIN); + QCOMPARE(INT_MIN, obj1.offset()); + obj1.setOffset(INT_MAX); + QCOMPARE(INT_MAX, obj1.offset()); + +} + +tst_QHeaderView::tst_QHeaderView() +{ + qRegisterMetaType<int>("Qt::SortOrder"); +} + +tst_QHeaderView::~tst_QHeaderView() +{ +} + +void tst_QHeaderView::initTestCase() +{ +#ifdef Q_OS_WINCE //disable magic for WindowsCE + qApp->setAutoMaximizeThreshold(-1); +#endif +} + +void tst_QHeaderView::cleanupTestCase() +{ +} + +void tst_QHeaderView::init() +{ + view = new QHeaderView(Qt::Vertical); + // Some initial value tests before a model is added + QCOMPARE(view->length(), 0); + QVERIFY(view->sizeHint() == QSize(0,0)); + QCOMPARE(view->sectionSizeHint(0), -1); + + /* + model = new QStandardItemModel(1, 1); + view->setModel(model); + //qDebug() << view->count(); + view->sizeHint(); + */ + + int rows = 4; + int columns = 4; + model = new QStandardItemModel(rows, columns); + /* + for (int row = 0; row < rows; ++row) { + for (int column = 0; column < columns; ++column) { + QModelIndex index = model->index(row, column, QModelIndex()); + model->setData(index, QVariant((row+1) * (column+1))); + } + } + */ + + QSignalSpy spy(view, SIGNAL(sectionCountChanged(int, int))); + view->setModel(model); + QCOMPARE(spy.count(), 1); + view->show(); +} + +void tst_QHeaderView::cleanup() +{ + delete view; + view = 0; + delete model; + model = 0; +} + +void tst_QHeaderView::noModel() +{ + QHeaderView emptyView(Qt::Vertical); + QCOMPARE(emptyView.count(), 0); +} + +void tst_QHeaderView::emptyModel() +{ + QtTestModel testmodel; + view->setModel(&testmodel); + QVERIFY(!testmodel.wrongIndex); + QCOMPARE(view->count(), testmodel.rows); + view->setModel(model); +} + +void tst_QHeaderView::removeRows() +{ + QtTestModel model; + model.rows = model.cols = 10; + + QHeaderView vertical(Qt::Vertical); + QHeaderView horizontal(Qt::Horizontal); + + vertical.setModel(&model); + horizontal.setModel(&model); + vertical.show(); + horizontal.show(); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); + + model.removeLastRow(); + QVERIFY(!model.wrongIndex); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); + + model.removeAllRows(); + QVERIFY(!model.wrongIndex); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); +} + + +void tst_QHeaderView::removeCols() +{ + QtTestModel model; + model.rows = model.cols = 10; + + QHeaderView vertical(Qt::Vertical); + QHeaderView horizontal(Qt::Horizontal); + vertical.setModel(&model); + horizontal.setModel(&model); + vertical.show(); + horizontal.show(); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); + + model.removeLastColumn(); + QVERIFY(!model.wrongIndex); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); + + model.removeAllColumns(); + QVERIFY(!model.wrongIndex); + QCOMPARE(vertical.count(), model.rows); + QCOMPARE(horizontal.count(), model.cols); +} + +void tst_QHeaderView::movable() +{ + QCOMPARE(view->isMovable(), false); + view->setMovable(false); + QCOMPARE(view->isMovable(), false); + view->setMovable(true); + QCOMPARE(view->isMovable(), true); +} + +void tst_QHeaderView::clickable() +{ + QCOMPARE(view->isClickable(), false); + view->setClickable(false); + QCOMPARE(view->isClickable(), false); + view->setClickable(true); + QCOMPARE(view->isClickable(), true); +} + +void tst_QHeaderView::hidden() +{ + //hideSection() & showSection call setSectionHidden + // Test bad arguments + QCOMPARE(view->isSectionHidden(-1), false); + QCOMPARE(view->isSectionHidden(view->count()), false); + QCOMPARE(view->isSectionHidden(999999), false); + + view->setSectionHidden(-1, true); + view->setSectionHidden(view->count(), true); + view->setSectionHidden(999999, true); + view->setSectionHidden(-1, false); + view->setSectionHidden(view->count(), false); + view->setSectionHidden(999999, false); + + // Hidden sections shouldn't have visual properties (except position) + int pos = view->defaultSectionSize(); + view->setSectionHidden(1, true); + QCOMPARE(view->sectionSize(1), 0); + QCOMPARE(view->sectionPosition(1), pos); + view->resizeSection(1, 100); + QCOMPARE(view->sectionViewportPosition(1), pos); + QCOMPARE(view->sectionSize(1), 0); + view->setSectionHidden(1, false); + QCOMPARE(view->isSectionHidden(0), false); + QCOMPARE(view->sectionSize(0), view->defaultSectionSize()); +} + +void tst_QHeaderView::stretch() +{ + // Show before resize and setStrechLastSection +#if defined(Q_OS_WINCE) + QSize viewSize(200,300); +#else + QSize viewSize(500, 500); +#endif + view->resize(viewSize); + view->setStretchLastSection(true); + QCOMPARE(view->stretchLastSection(), true); + view->show(); + QCOMPARE(view->width(), viewSize.width()); + QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 3); + + view->setSectionHidden(3, true); + QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 2); + + view->setStretchLastSection(false); + QCOMPARE(view->stretchLastSection(), false); +} + +void tst_QHeaderView::oneSectionSize() +{ + //this ensures that if there is only one section, it gets a correct width (more than 0) + QHeaderView view (Qt::Vertical); + QtTestModel model; + model.cols = 1; + model.rows = 1; + + view.setResizeMode(QHeaderView::Interactive); + view.setModel(&model); + + view.show(); + + QVERIFY(view.sectionSize(0) > 0); +} + + +void tst_QHeaderView::sectionSize_data() +{ + QTest::addColumn<QList<int> >("boundsCheck"); + QTest::addColumn<QList<int> >("defaultSizes"); + QTest::addColumn<int>("initialDefaultSize"); + QTest::addColumn<int>("lastVisibleSectionSize"); + QTest::addColumn<int>("persistentSectionSize"); + + QTest::newRow("data set one") + << (QList<int>() << -1 << 0 << 4 << 9999) + << (QList<int>() << 10 << 30 << 30) + << 30 + << 300 + << 20; +} + +void tst_QHeaderView::sectionSize() +{ + QFETCH(QList<int>, boundsCheck); + QFETCH(QList<int>, defaultSizes); + QFETCH(int, initialDefaultSize); + QFETCH(int, lastVisibleSectionSize); + QFETCH(int, persistentSectionSize); + +#ifdef Q_OS_WINCE + // We test on a device with doubled pixels. Therefore we need to specify + // different boundaries. + initialDefaultSize = qMax(view->minimumSectionSize(), 30); +#endif + + // bounds check + foreach (int val, boundsCheck) + view->sectionSize(val); + + // default size + QCOMPARE(view->defaultSectionSize(), initialDefaultSize); + foreach (int def, defaultSizes) { + view->setDefaultSectionSize(def); + QCOMPARE(view->defaultSectionSize(), def); + } + + view->setDefaultSectionSize(initialDefaultSize); + for (int s = 0; s < view->count(); ++s) + QCOMPARE(view->sectionSize(s), initialDefaultSize); + view->doItemsLayout(); + + // stretch last section + view->setStretchLastSection(true); + int lastSection = view->count() - 1; + + //test that when hiding the last column, + //resizing the new last visible columns still works + view->hideSection(lastSection); + view->resizeSection(lastSection - 1, lastVisibleSectionSize); + QCOMPARE(view->sectionSize(lastSection - 1), lastVisibleSectionSize); + view->showSection(lastSection); + + // turn off stretching + view->setStretchLastSection(false); + QCOMPARE(view->sectionSize(lastSection), initialDefaultSize); + + // test persistence + int sectionCount = view->count(); + for (int i = 0; i < sectionCount; ++i) + view->resizeSection(i, persistentSectionSize); + QtTestModel model; + model.cols = sectionCount * 2; + model.rows = sectionCount * 2; + view->setModel(&model); + for (int j = 0; j < sectionCount; ++j) + QCOMPARE(view->sectionSize(j), persistentSectionSize); + for (int k = sectionCount; k < view->count(); ++k) + QCOMPARE(view->sectionSize(k), initialDefaultSize); +} + +void tst_QHeaderView::visualIndex() +{ + // Test bad arguments + QCOMPARE(view->visualIndex(999999), -1); + QCOMPARE(view->visualIndex(-1), -1); + QCOMPARE(view->visualIndex(1), 1); + view->setSectionHidden(1, true); + QCOMPARE(view->visualIndex(1), 1); + QCOMPARE(view->visualIndex(2), 2); + + view->setSectionHidden(1, false); + QCOMPARE(view->visualIndex(1), 1); + QCOMPARE(view->visualIndex(2), 2); +} + +void tst_QHeaderView::visualIndexAt_data() +{ + QTest::addColumn<QList<int> >("hidden"); + QTest::addColumn<QList<int> >("from"); + QTest::addColumn<QList<int> >("to"); + QTest::addColumn<QList<int> >("coordinate"); + QTest::addColumn<QList<int> >("visual"); + + QList<int> coordinateList; +#ifndef Q_OS_WINCE + coordinateList << -1 << 0 << 31 << 91 << 99999; +#else + // We test on a device with doubled pixels. Therefore we need to specify + // different boundaries. + coordinateList << -1 << 0 << 33 << 97 << 99999; +#endif + + QTest::newRow("no hidden, no moved sections") + << QList<int>() + << QList<int>() + << QList<int>() + << coordinateList + << (QList<int>() << -1 << 0 << 1 << 3 << -1); + + QTest::newRow("no hidden, moved sections") + << QList<int>() + << (QList<int>() << 0) + << (QList<int>() << 1) + << coordinateList + << (QList<int>() << -1 << 0 << 1 << 3 << -1); + + QTest::newRow("hidden, no moved sections") + << (QList<int>() << 0) + << QList<int>() + << QList<int>() + << coordinateList + << (QList<int>() << -1 << 1 << 2 << 3 << -1); +} + +void tst_QHeaderView::visualIndexAt() +{ + QFETCH(QList<int>, hidden); + QFETCH(QList<int>, from); + QFETCH(QList<int>, to); + QFETCH(QList<int>, coordinate); + QFETCH(QList<int>, visual); + + view->setStretchLastSection(true); + view->show(); + + for (int i = 0; i < hidden.count(); ++i) + view->setSectionHidden(hidden.at(i), true); + + for (int j = 0; j < from.count(); ++j) + view->moveSection(from.at(j), to.at(j)); + + for (int k = 0; k < coordinate.count(); ++k) + QCOMPARE(view->visualIndexAt(coordinate.at(k)), visual.at(k)); +} + +void tst_QHeaderView::length() +{ +#ifdef Q_OS_WINCE + QFont font(QLatin1String("Tahoma"), 7); + view->setFont(font); +#endif + view->setStretchLastSection(true); + view->show(); + + //minimumSectionSize should be the size of the last section of the widget is not tall enough + int length = view->minimumSectionSize(); + for (int i=0; i < view->count()-1; i++) { + length += view->sectionSize(i); + } + + length = qMax(length, view->viewport()->height()); + QCOMPARE(length, view->length()); + + view->setStretchLastSection(false); + view->show(); + + QVERIFY(length != view->length()); + + // layoutChanged might mean rows have been removed + QtTestModel model; + model.cols = 10; + model.rows = 10; + view->setModel(&model); + int oldLength = view->length(); + model.cleanup(); + QCOMPARE(model.rows, view->count()); + QVERIFY(oldLength != view->length()); +} + +void tst_QHeaderView::offset() +{ + QCOMPARE(view->offset(), 0); + view->setOffset(10); + QCOMPARE(view->offset(), 10); + view->setOffset(0); + QCOMPARE(view->offset(), 0); + + // Test odd arguments + view->setOffset(-1); +} + +void tst_QHeaderView::sectionSizeHint() +{ + // Test bad arguments + view->sectionSizeHint(-1); + view->sectionSizeHint(99999); + + // TODO how to test the return value? +} + +void tst_QHeaderView::logicalIndex() +{ + // Test bad arguments + QCOMPARE(view->logicalIndex(-1), -1); + QCOMPARE(view->logicalIndex(99999), -1); +} + +void tst_QHeaderView::logicalIndexAt() +{ + // Test bad arguments + view->logicalIndexAt(-1); + view->logicalIndexAt(99999); + QCOMPARE(view->logicalIndexAt(0), 0); + QCOMPARE(view->logicalIndexAt(1), 0); + + view->show(); + view->setStretchLastSection(true); + // First item + QCOMPARE(view->logicalIndexAt(0), 0); + QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 0); + QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 1); + // Last item + int last = view->length() - 1;//view->viewport()->height() - 10; + QCOMPARE(view->logicalIndexAt(last), 3); + // Not in widget + int outofbounds = view->length() + 1;//view->viewport()->height() + 1; + QCOMPARE(view->logicalIndexAt(outofbounds), -1); + + view->moveSection(0,1); + // First item + QCOMPARE(view->logicalIndexAt(0), 1); + QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 1); + QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 0); + // Last item + QCOMPARE(view->logicalIndexAt(last), 3); + view->moveSection(1,0); + +} + +void tst_QHeaderView::swapSections() +{ + view->swapSections(-1, 1); + view->swapSections(99999, 1); + view->swapSections(1, -1); + view->swapSections(1, 99999); + + QVector<int> logical = (QVector<int>() << 0 << 1 << 2 << 3); + + QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int))); + + QCOMPARE(view->sectionsMoved(), false); + view->swapSections(1, 1); + QCOMPARE(view->sectionsMoved(), false); + view->swapSections(1, 2); + QCOMPARE(view->sectionsMoved(), true); + view->swapSections(2, 1); + QCOMPARE(view->sectionsMoved(), true); + for (int i = 0; i < view->count(); ++i) + QCOMPARE(view->logicalIndex(i), logical.at(i)); + QCOMPARE(spy1.count(), 4); + + logical = (QVector<int>() << 3 << 1 << 2 << 0); + view->swapSections(3, 0); + QCOMPARE(view->sectionsMoved(), true); + for (int j = 0; j < view->count(); ++j) + QCOMPARE(view->logicalIndex(j), logical.at(j)); + QCOMPARE(spy1.count(), 6); +} + +void tst_QHeaderView::moveSection_data() +{ + QTest::addColumn<QList<int> >("hidden"); + QTest::addColumn<QList<int> >("from"); + QTest::addColumn<QList<int> >("to"); + QTest::addColumn<QList<bool> >("moved"); + QTest::addColumn<QList<int> >("logical"); + QTest::addColumn<int>("count"); + + QTest::newRow("bad args, no hidden") + << QList<int>() + << (QList<int>() << -1 << 1 << 99999 << 1) + << (QList<int>() << 1 << -1 << 1 << 99999) + << (QList<bool>() << false << false << false << false) + << (QList<int>() << 0 << 1 << 2 << 3) + << 0; + + QTest::newRow("good args, no hidden") + << QList<int>() + << (QList<int>() << 1 << 1 << 2 << 1) + << (QList<int>() << 1 << 2 << 1 << 2) + << (QList<bool>() << false << true << true << true) + << (QList<int>() << 0 << 2 << 1 << 3) + << 3; + + QTest::newRow("hidden sections") + << (QList<int>() << 0 << 3) + << (QList<int>() << 1 << 1 << 2 << 1) + << (QList<int>() << 1 << 2 << 1 << 2) + << (QList<bool>() << false << true << true << true) + << (QList<int>() << 0 << 2 << 1 << 3) + << 3; +} + +void tst_QHeaderView::moveSection() +{ + QFETCH(QList<int>, hidden); + QFETCH(QList<int>, from); + QFETCH(QList<int>, to); + QFETCH(QList<bool>, moved); + QFETCH(QList<int>, logical); + QFETCH(int, count); + + QVERIFY(from.count() == to.count()); + QVERIFY(from.count() == moved.count()); + QVERIFY(view->count() == logical.count()); + + QSignalSpy spy1(view, SIGNAL(sectionMoved(int, int, int))); + QCOMPARE(view->sectionsMoved(), false); + + for (int h = 0; h < hidden.count(); ++h) + view->setSectionHidden(hidden.at(h), true); + + for (int i = 0; i < from.count(); ++i) { + view->moveSection(from.at(i), to.at(i)); + QCOMPARE(view->sectionsMoved(), moved.at(i)); + } + + for (int j = 0; j < view->count(); ++j) + QCOMPARE(view->logicalIndex(j), logical.at(j)); + + QCOMPARE(spy1.count(), count); +} + +void tst_QHeaderView::resizeAndMoveSection_data() +{ + QTest::addColumn<IntList>("logicalIndexes"); + QTest::addColumn<IntList>("sizes"); + QTest::addColumn<int>("logicalFrom"); + QTest::addColumn<int>("logicalTo"); + + QTest::newRow("resizeAndMove-1") + << (IntList() << 0 << 1) + << (IntList() << 20 << 40) + << 0 << 1; + + QTest::newRow("resizeAndMove-2") + << (IntList() << 0 << 1 << 2 << 3) + << (IntList() << 20 << 60 << 10 << 80) + << 0 << 2; + + QTest::newRow("resizeAndMove-3") + << (IntList() << 0 << 1 << 2 << 3) + << (IntList() << 100 << 60 << 40 << 10) + << 0 << 3; + + QTest::newRow("resizeAndMove-4") + << (IntList() << 0 << 1 << 2 << 3) + << (IntList() << 10 << 40 << 80 << 30) + << 1 << 2; + + QTest::newRow("resizeAndMove-5") + << (IntList() << 2 << 3) + << (IntList() << 100 << 200) + << 3 << 2; +} + +void tst_QHeaderView::resizeAndMoveSection() +{ + QFETCH(IntList, logicalIndexes); + QFETCH(IntList, sizes); + QFETCH(int, logicalFrom); + QFETCH(int, logicalTo); + + // Save old visual indexes and sizes + IntList oldVisualIndexes; + IntList oldSizes; + foreach (int logical, logicalIndexes) { + oldVisualIndexes.append(view->visualIndex(logical)); + oldSizes.append(view->sectionSize(logical)); + } + + // Resize sections + for (int i = 0; i < logicalIndexes.size(); ++i) { + int logical = logicalIndexes.at(i); + view->resizeSection(logical, sizes.at(i)); + } + + // Move sections + int visualFrom = view->visualIndex(logicalFrom); + int visualTo = view->visualIndex(logicalTo); + view->moveSection(visualFrom, visualTo); + QCOMPARE(view->visualIndex(logicalFrom), visualTo); + + // Check that sizes are still correct + for (int i = 0; i < logicalIndexes.size(); ++i) { + int logical = logicalIndexes.at(i); + QCOMPARE(view->sectionSize(logical), sizes.at(i)); + } + + // Move sections back + view->moveSection(visualTo, visualFrom); + + // Check that sizes are still correct + for (int i = 0; i < logicalIndexes.size(); ++i) { + int logical = logicalIndexes.at(i); + QCOMPARE(view->sectionSize(logical), sizes.at(i)); + } + + // Put everything back as it was + for (int i = 0; i < logicalIndexes.size(); ++i) { + int logical = logicalIndexes.at(i); + view->resizeSection(logical, oldSizes.at(i)); + QCOMPARE(view->visualIndex(logical), oldVisualIndexes.at(i)); + } +} + +void tst_QHeaderView::resizeHiddenSection_data() +{ + QTest::addColumn<int>("section"); + QTest::addColumn<int>("initialSize"); + QTest::addColumn<int>("finalSize"); + + QTest::newRow("section 0 resize 50 to 20") + << 0 << 50 << 20; + + QTest::newRow("section 1 resize 50 to 20") + << 1 << 50 << 20; + + QTest::newRow("section 2 resize 50 to 20") + << 2 << 50 << 20; + + QTest::newRow("section 3 resize 50 to 20") + << 3 << 50 << 20; +} + +void tst_QHeaderView::resizeHiddenSection() +{ + QFETCH(int, section); + QFETCH(int, initialSize); + QFETCH(int, finalSize); + + view->resizeSection(section, initialSize); + view->setSectionHidden(section, true); + QCOMPARE(view->sectionSize(section), 0); + + view->resizeSection(section, finalSize); + QCOMPARE(view->sectionSize(section), 0); + + view->setSectionHidden(section, false); + QCOMPARE(view->sectionSize(section), finalSize); +} + +void tst_QHeaderView::resizeAndInsertSection_data() +{ + QTest::addColumn<int>("section"); + QTest::addColumn<int>("size"); + QTest::addColumn<int>("insert"); + QTest::addColumn<int>("compare"); + QTest::addColumn<int>("expected"); + + QTest::newRow("section 0 size 50 insert 0") + << 0 << 50 << 0 << 1 << 50; + + QTest::newRow("section 1 size 50 insert 1") + << 0 << 50 << 1 << 0 << 50; + + QTest::newRow("section 1 size 50 insert 0") + << 1 << 50 << 0 << 2 << 50; + +} + +void tst_QHeaderView::resizeAndInsertSection() +{ + QFETCH(int, section); + QFETCH(int, size); + QFETCH(int, insert); + QFETCH(int, compare); + QFETCH(int, expected); + + view->setStretchLastSection(false); + + view->resizeSection(section, size); + QCOMPARE(view->sectionSize(section), size); + + model->insertRow(insert); + + QCOMPARE(view->sectionSize(compare), expected); +} + +void tst_QHeaderView::resizeWithResizeModes_data() +{ + QTest::addColumn<int>("size"); + QTest::addColumn<QList<int> >("sections"); + QTest::addColumn<QList<int> >("modes"); + QTest::addColumn<QList<int> >("expected"); + + QTest::newRow("stretch first section") + << 600 + << (QList<int>() << 100 << 100 << 100 << 100) + << (QList<int>() << ((int)QHeaderView::Stretch) + << ((int)QHeaderView::Interactive) + << ((int)QHeaderView::Interactive) + << ((int)QHeaderView::Interactive)) + << (QList<int>() << 300 << 100 << 100 << 100); +} + +void tst_QHeaderView::resizeWithResizeModes() +{ + QFETCH(int, size); + QFETCH(QList<int>, sections); + QFETCH(QList<int>, modes); + QFETCH(QList<int>, expected); + + view->setStretchLastSection(false); + for (int i = 0; i < sections.count(); ++i) { + view->resizeSection(i, sections.at(i)); + view->setResizeMode(i, (QHeaderView::ResizeMode)modes.at(i)); + } + view->show(); + view->resize(size, size); + for (int j = 0; j < expected.count(); ++j) + QCOMPARE(view->sectionSize(j), expected.at(j)); +} + +void tst_QHeaderView::moveAndInsertSection_data() +{ + QTest::addColumn<int>("from"); + QTest::addColumn<int>("to"); + QTest::addColumn<int>("insert"); + QTest::addColumn<QList<int> >("mapping"); + + QTest::newRow("move from 1 to 3, insert 0") + << 1 << 3 << 0 <<(QList<int>() << 0 << 1 << 3 << 4 << 2); + +} + +void tst_QHeaderView::moveAndInsertSection() +{ + QFETCH(int, from); + QFETCH(int, to); + QFETCH(int, insert); + QFETCH(QList<int>, mapping); + + view->setStretchLastSection(false); + + view->moveSection(from, to); + + model->insertRow(insert); + + for (int i = 0; i < mapping.count(); ++i) + QCOMPARE(view->logicalIndex(i), mapping.at(i)); +} + +void tst_QHeaderView::resizeMode() +{ + // Q_ASSERT's when resizeMode is called with an invalid index + int last = view->count() - 1; + view->setResizeMode(QHeaderView::Interactive); + QCOMPARE(view->resizeMode(last), QHeaderView::Interactive); + QCOMPARE(view->resizeMode(1), QHeaderView::Interactive); + view->setResizeMode(QHeaderView::Stretch); + QCOMPARE(view->resizeMode(last), QHeaderView::Stretch); + QCOMPARE(view->resizeMode(1), QHeaderView::Stretch); + view->setResizeMode(QHeaderView::Custom); + QCOMPARE(view->resizeMode(last), QHeaderView::Custom); + QCOMPARE(view->resizeMode(1), QHeaderView::Custom); + + // test when sections have been moved + view->setStretchLastSection(false); + for (int i=0; i < (view->count() - 1); ++i) + view->setResizeMode(i, QHeaderView::Interactive); + int logicalIndex = view->count() / 2; + view->setResizeMode(logicalIndex, QHeaderView::Stretch); + view->moveSection(view->visualIndex(logicalIndex), 0); + for (int i=0; i < (view->count() - 1); ++i) { + if (i == logicalIndex) + QCOMPARE(view->resizeMode(i), QHeaderView::Stretch); + else + QCOMPARE(view->resizeMode(i), QHeaderView::Interactive); + } +} + +void tst_QHeaderView::resizeSection_data() +{ + QTest::addColumn<int>("initial"); + QTest::addColumn<QList<int> >("logical"); + QTest::addColumn<QList<int> >("size"); + QTest::addColumn<QList<int> >("mode"); + QTest::addColumn<int>("resized"); + QTest::addColumn<QList<int> >("expected"); + + QTest::newRow("bad args") + << 100 + << (QList<int>() << -1 << -1 << 99999 << 99999 << 4) + << (QList<int>() << -1 << 0 << 99999 << -1 << -1) + << (QList<int>() + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive) + << int(QHeaderView::Interactive)) + << 0 + << (QList<int>() << 0 << 0 << 0 << 0 << 0); +} + +void tst_QHeaderView::resizeSection() +{ + + QFETCH(int, initial); + QFETCH(QList<int>, logical); + QFETCH(QList<int>, size); + QFETCH(QList<int>, mode); + QFETCH(int, resized); + QFETCH(QList<int>, expected); + + view->resize(400, 400); + + view->show(); + view->setMovable(true); + view->setStretchLastSection(false); + + for (int i = 0; i < logical.count(); ++i) + if (logical.at(i) > -1 && logical.at(i) < view->count()) // for now + view->setResizeMode(logical.at(i), (QHeaderView::ResizeMode)mode.at(i)); + + for (int j = 0; j < logical.count(); ++j) + view->resizeSection(logical.at(j), initial); + + QSignalSpy spy(view, SIGNAL(sectionResized(int, int, int))); + + for (int k = 0; k < logical.count(); ++k) + view->resizeSection(logical.at(k), size.at(k)); + + QCOMPARE(spy.count(), resized); + + for (int l = 0; l < logical.count(); ++l) + QCOMPARE(view->sectionSize(logical.at(l)), expected.at(l)); +} + +void tst_QHeaderView::highlightSections() +{ + view->setHighlightSections(true); + QCOMPARE(view->highlightSections(), true); + view->setHighlightSections(false); + QCOMPARE(view->highlightSections(), false); +} + +void tst_QHeaderView::showSortIndicator() +{ + view->setSortIndicatorShown(true); + QCOMPARE(view->isSortIndicatorShown(), true); + QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder); + view->setSortIndicator(1, Qt::AscendingOrder); + QCOMPARE(view->sortIndicatorOrder(), Qt::AscendingOrder); + view->setSortIndicator(1, Qt::DescendingOrder); + QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder); + view->setSortIndicatorShown(false); + QCOMPARE(view->isSortIndicatorShown(), false); + + view->setSortIndicator(999999, Qt::DescendingOrder); + // Don't segfault baby :) + view->setSortIndicatorShown(true); + + view->setSortIndicator(0, Qt::DescendingOrder); + // Don't assert baby :) +} + +void tst_QHeaderView::sortIndicatorTracking() +{ + QtTestModel model; + model.rows = model.cols = 10; + + QHeaderView hv(Qt::Horizontal); + + hv.setModel(&model); + hv.show(); + hv.setSortIndicatorShown(true); + hv.setSortIndicator(1, Qt::DescendingOrder); + + model.removeOneColumn(8); + QCOMPARE(hv.sortIndicatorSection(), 1); + + model.removeOneColumn(2); + QCOMPARE(hv.sortIndicatorSection(), 1); + + model.insertOneColumn(2); + QCOMPARE(hv.sortIndicatorSection(), 1); + + model.insertOneColumn(1); + QCOMPARE(hv.sortIndicatorSection(), 2); + + model.removeOneColumn(0); + QCOMPARE(hv.sortIndicatorSection(), 1); + + model.removeOneColumn(1); + QCOMPARE(hv.sortIndicatorSection(), -1); +} + +void tst_QHeaderView::removeAndInsertRow() +{ + // Check if logicalIndex returns the correct value after we have removed a row + // we might as well te + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + + while (model->removeRow(0)) { + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + } + + int pass = 0; + for (pass = 0; pass < 5; pass++) { + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + model->insertRow(0); + } + + while (model->removeRows(0, 2)) { + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + } + + for (pass = 0; pass < 3; pass++) { + model->insertRows(0, 2); + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + } + + for (pass = 0; pass < 3; pass++) { + model->insertRows(3, 2); + for (int i = 0; i < model->rowCount(); ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + } + + // Insert at end + for (pass = 0; pass < 3; pass++) { + int rowCount = model->rowCount(); + model->insertRows(rowCount, 1); + for (int i = 0; i < rowCount; ++i) { + QCOMPARE(i, view->logicalIndex(i)); + } + } + +} +void tst_QHeaderView::unhideSection() +{ + // 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. + QCOMPARE(view->sectionsHidden(), false); + view->setSectionHidden(0, true); + QCOMPARE(view->sectionsHidden(), true); + QVERIFY(view->sectionSize(0) == 0); + view->setResizeMode(QHeaderView::Interactive); + view->setSectionHidden(0, false); + QVERIFY(view->sectionSize(0) > 0); + + view->setSectionHidden(0, true); + QVERIFY(view->sectionSize(0) == 0); + view->setSectionHidden(0, true); + QVERIFY(view->sectionSize(0) == 0); + view->setResizeMode(QHeaderView::Stretch); + view->setSectionHidden(0, false); + QVERIFY(view->sectionSize(0) > 0); + +} + +void tst_QHeaderView::event() +{ + protected_QHeaderView x(Qt::Vertical); + x.testEvent(); + protected_QHeaderView y(Qt::Horizontal); + y.testEvent(); +} + + +void protected_QHeaderView::testEvent() +{ + // No crashy please + QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint()); + event(&enterEvent); + QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint()); + event(&eventLeave); + QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint()); + event(&eventMove); +} + +void tst_QHeaderView::headerDataChanged() +{ + // This shouldn't asserver because view is Vertical + view->headerDataChanged(Qt::Horizontal, -1, -1); +#if 0 + // This will assert + view->headerDataChanged(Qt::Vertical, -1, -1); +#endif + + // No crashing please + view->headerDataChanged(Qt::Horizontal, 0, 1); + view->headerDataChanged(Qt::Vertical, 0, 1); +} + +void tst_QHeaderView::currentChanged() +{ + view->setCurrentIndex(QModelIndex()); +} + +void tst_QHeaderView::horizontalOffset() +{ + protected_QHeaderView x(Qt::Vertical); + x.testhorizontalOffset(); + protected_QHeaderView y(Qt::Horizontal); + y.testhorizontalOffset(); +} + +void tst_QHeaderView::verticalOffset() +{ + protected_QHeaderView x(Qt::Vertical); + x.testverticalOffset(); + protected_QHeaderView y(Qt::Horizontal); + y.testverticalOffset(); +} + +void protected_QHeaderView::testhorizontalOffset() +{ + if(orientation() == Qt::Horizontal){ + QCOMPARE(horizontalOffset(), 0); + setOffset(10); + QCOMPARE(horizontalOffset(), 10); + } + else + QCOMPARE(horizontalOffset(), 0); + +} + +void protected_QHeaderView::testverticalOffset() +{ + if(orientation() == Qt::Vertical){ + QCOMPARE(verticalOffset(), 0); + setOffset(10); + QCOMPARE(verticalOffset(), 10); + } + else + QCOMPARE(verticalOffset(), 0); +} + +void tst_QHeaderView::stretchSectionCount() +{ + view->setStretchLastSection(false); + QCOMPARE(view->stretchSectionCount(), 0); + view->setStretchLastSection(true); + QCOMPARE(view->stretchSectionCount(), 0); + + view->setResizeMode(0, QHeaderView::Stretch); + QCOMPARE(view->stretchSectionCount(), 1); +} + +void tst_QHeaderView::hiddenSectionCount() +{ + model->clear(); + model->insertRows(0, 10); + // Hide every other one + for (int i=0; i<10; i++) + view->setSectionHidden(i, (i & 1) == 0); + + QCOMPARE(view->hiddenSectionCount(), 5); + + view->setResizeMode(QHeaderView::Stretch); + QCOMPARE(view->hiddenSectionCount(), 5); + + // Remove some rows and make sure they are now still counted + model->removeRow(9); + model->removeRow(8); + model->removeRow(7); + model->removeRow(6); + QCOMPARE(view->count(), 6); + QCOMPARE(view->hiddenSectionCount(), 3); + model->removeRows(0,5); + QCOMPARE(view->count(), 1); + QCOMPARE(view->hiddenSectionCount(), 0); + QVERIFY(view->count() >= view->hiddenSectionCount()); +} + +void tst_QHeaderView::focusPolicy() +{ + QHeaderView view(Qt::Horizontal); + QCOMPARE(view.focusPolicy(), Qt::NoFocus); + + QTreeWidget widget; + QCOMPARE(widget.header()->focusPolicy(), Qt::NoFocus); + QVERIFY(!widget.focusProxy()); + QVERIFY(!widget.hasFocus()); + QVERIFY(!widget.header()->focusProxy()); + QVERIFY(!widget.header()->hasFocus()); + + widget.show(); + widget.setFocus(Qt::OtherFocusReason); + QTest::qWait(100); + widget.activateWindow(); + QTest::qWait(100); + + qApp->processEvents(); + + WAIT_FOR_CONDITION(widget.hasFocus(), true); + + QVERIFY(widget.hasFocus()); + QVERIFY(!widget.header()->hasFocus()); + + widget.setFocusPolicy(Qt::NoFocus); + widget.clearFocus(); + + qApp->processEvents(); + qApp->processEvents(); + + WAIT_FOR_CONDITION(widget.hasFocus(), false); + QVERIFY(!widget.hasFocus()); + QVERIFY(!widget.header()->hasFocus()); + + QTest::keyPress(&widget, Qt::Key_Tab); + + qApp->processEvents(); + qApp->processEvents(); + + QVERIFY(!widget.hasFocus()); + QVERIFY(!widget.header()->hasFocus()); +} + +class SimpleModel : public QAbstractItemModel +{ + Q_OBJECT +public: + + SimpleModel( QObject* parent=0) + : QAbstractItemModel(parent), + m_col_count(3) {} + + QModelIndex parent(const QModelIndex &/*child*/) const + { + return QModelIndex(); + } + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const + { + return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex(); + } + int rowCount(const QModelIndex & /* parent */) const + { + return 8; + } + int columnCount(const QModelIndex &/*parent= QModelIndex()*/) const + { + return m_col_count; + } + + QVariant data(const QModelIndex &index, int role) const + { + if (!index.isValid()) + { + return QVariant(); + } + if (role == Qt::DisplayRole) { + return QString::fromAscii("%1,%2").arg(index.row()).arg(index.column()); + } + return QVariant(); + } + + void setColumnCount( int c ) + { + m_col_count = c; + } + +private: + int m_col_count; +}; + +void tst_QHeaderView::moveSectionAndReset() +{ + SimpleModel m; + QHeaderView v(Qt::Horizontal); + v.setModel(&m); + int cc = 2; + for (cc = 2; cc < 4; ++cc) { + m.setColumnCount(cc); + int movefrom = 0; + int moveto; + for (moveto = 1; moveto < cc; ++moveto) { + v.moveSection(movefrom, moveto); + m.setColumnCount(cc - 1); + v.reset(); + for (int i = 0; i < cc - 1; ++i) { + QCOMPARE(v.logicalIndex(v.visualIndex(i)), i); + } + } + } +} + +void tst_QHeaderView::moveSectionAndRemove() +{ + QStandardItemModel m; + QHeaderView v(Qt::Horizontal); + + v.setModel(&m); + v.model()->insertColumns(0, 3); + v.moveSection(0, 1); + + QCOMPARE(v.count(), 3); + v.model()->removeColumns(0, v.model()->columnCount()); + QCOMPARE(v.count(), 0); +} + +void tst_QHeaderView::saveRestore() +{ + SimpleModel m; + QHeaderView h1(Qt::Horizontal); + h1.setModel(&m); + h1.swapSections(0, 2); + h1.resizeSection(1, 10); + h1.setSortIndicatorShown(true); + h1.setSortIndicator(1,Qt::DescendingOrder); + QByteArray s1 = h1.saveState(); + + QHeaderView h2(Qt::Vertical); + QSignalSpy spy(&h2, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder))); + + h2.setModel(&m); + h2.restoreState(s1); + + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toInt(), 1); + + QCOMPARE(h2.logicalIndex(0), 2); + QCOMPARE(h2.logicalIndex(2), 0); + QCOMPARE(h2.sectionSize(1), 10); + QCOMPARE(h2.sortIndicatorSection(), 1); + QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder); + QCOMPARE(h2.isSortIndicatorShown(), true); + + QByteArray s2 = h2.saveState(); + + QVERIFY(s1 == s2); +} + +void tst_QHeaderView::defaultAlignment_data() +{ + QTest::addColumn<int>("direction"); + QTest::addColumn<int>("initial"); + QTest::addColumn<int>("alignment"); + + QTest::newRow("horizontal right aligned") + << int(Qt::Horizontal) + << int(Qt::AlignCenter) + << int(Qt::AlignRight); + + QTest::newRow("horizontal left aligned") + << int(Qt::Horizontal) + << int(Qt::AlignCenter) + << int(Qt::AlignLeft); + + QTest::newRow("vertical right aligned") + << int(Qt::Vertical) + << int(Qt::AlignLeft|Qt::AlignVCenter) + << int(Qt::AlignRight); + + QTest::newRow("vertical left aligned") + << int(Qt::Vertical) + << int(Qt::AlignLeft|Qt::AlignVCenter) + << int(Qt::AlignLeft); +} + +void tst_QHeaderView::defaultAlignment() +{ + QFETCH(int, direction); + QFETCH(int, initial); + QFETCH(int, alignment); + + SimpleModel m; + + QHeaderView header((Qt::Orientation)direction); + header.setModel(&m); + + QCOMPARE(header.defaultAlignment(), (Qt::Alignment)initial); + header.setDefaultAlignment((Qt::Alignment)alignment); + QCOMPARE(header.defaultAlignment(), (Qt::Alignment)alignment); +} + +void tst_QHeaderView::globalResizeMode_data() +{ + QTest::addColumn<int>("direction"); + QTest::addColumn<int>("mode"); + QTest::addColumn<int>("insert"); + + QTest::newRow("horizontal ResizeToContents 0") + << int(Qt::Horizontal) + << int(QHeaderView::ResizeToContents) + << 0; +} + +void tst_QHeaderView::globalResizeMode() +{ + QFETCH(int, direction); + QFETCH(int, mode); + QFETCH(int, insert); + + QStandardItemModel m(4, 4); + QHeaderView h((Qt::Orientation)direction); + h.setModel(&m); + + h.setResizeMode((QHeaderView::ResizeMode)mode); + m.insertRow(insert); + for (int i = 0; i < h.count(); ++i) + QCOMPARE(h.resizeMode(i), (QHeaderView::ResizeMode)mode); +} + + +void tst_QHeaderView::sectionPressedSignal_data() +{ + QTest::addColumn<int>("direction"); + QTest::addColumn<bool>("clickable"); + QTest::addColumn<int>("count"); + + QTest::newRow("horizontal unclickable 0") + << int(Qt::Horizontal) + << false + << 0; + + QTest::newRow("horizontal clickable 1") + << int(Qt::Horizontal) + << true + << 1; +} + +void tst_QHeaderView::sectionPressedSignal() +{ + QFETCH(int, direction); + QFETCH(bool, clickable); + QFETCH(int, count); + + QStandardItemModel m(4, 4); + QHeaderView h((Qt::Orientation)direction); + + h.setModel(&m); + h.show(); + h.setClickable(clickable); + + QSignalSpy spy(&h, SIGNAL(sectionPressed(int))); + + QCOMPARE(spy.count(), 0); + QTest::mousePress(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(spy.count(), count); +} + +void tst_QHeaderView::sectionClickedSignal() +{ + QFETCH(int, direction); + QFETCH(bool, clickable); + QFETCH(int, count); + + QStandardItemModel m(4, 4); + QHeaderView h((Qt::Orientation)direction); + + h.setModel(&m); + h.show(); + h.setClickable(clickable); + h.setSortIndicatorShown(true); + + QSignalSpy spy(&h, SIGNAL(sectionClicked(int))); + QSignalSpy spy2(&h, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder))); + + QCOMPARE(spy.count(), 0); + QCOMPARE(spy2.count(), 0); + QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(spy.count(), count); + QCOMPARE(spy2.count(), count); + + //now let's try with the sort indicator hidden (the result should be the same + spy.clear(); + spy2.clear(); + h.setSortIndicatorShown(false); + QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(spy.count(), count); + QCOMPARE(spy2.count(), count); +} + +void tst_QHeaderView::defaultSectionSize_data() +{ + QTest::addColumn<int>("direction"); + QTest::addColumn<int>("oldDefaultSize"); + QTest::addColumn<int>("newDefaultSize"); + + //QTest::newRow("horizontal,-5") << int(Qt::Horizontal) << 100 << -5; + QTest::newRow("horizontal, 0") << int(Qt::Horizontal) << 100 << 0; + QTest::newRow("horizontal, 5") << int(Qt::Horizontal) << 100 << 5; + QTest::newRow("horizontal,25") << int(Qt::Horizontal) << 100 << 5; +} + +void tst_QHeaderView::defaultSectionSize() +{ + QFETCH(int, direction); + QFETCH(int, oldDefaultSize); + QFETCH(int, newDefaultSize); + + QStandardItemModel m(4, 4); + QHeaderView h((Qt::Orientation)direction); + + h.setModel(&m); + + QCOMPARE(h.defaultSectionSize(), oldDefaultSize); + h.setDefaultSectionSize(newDefaultSize); + QCOMPARE(h.defaultSectionSize(), newDefaultSize); + h.reset(); + for (int i = 0; i < h.count(); ++i) + QCOMPARE(h.sectionSize(i), newDefaultSize); +} + +void tst_QHeaderView::hideAndInsert_data() +{ + QTest::addColumn<int>("direction"); + QTest::addColumn<int>("hide"); + QTest::addColumn<int>("insert"); + QTest::addColumn<int>("hidden"); + + QTest::newRow("horizontal, 0, 0") << int(Qt::Horizontal) << 0 << 0 << 1; +} + +void tst_QHeaderView::hideAndInsert() +{ + QFETCH(int, direction); + QFETCH(int, hide); + QFETCH(int, insert); + QFETCH(int, hidden); + + QStandardItemModel m(4, 4); + QHeaderView h((Qt::Orientation)direction); + + h.setModel(&m); + + h.setSectionHidden(hide, true); + + if (direction == Qt::Vertical) + m.insertRow(insert); + else + m.insertColumn(insert); + + for (int i = 0; i < h.count(); ++i) + if (i != hidden) + QCOMPARE(h.isSectionHidden(i), false); + else + QCOMPARE(h.isSectionHidden(i), true); +} + +void tst_QHeaderView::removeSection() +{ +//test that removing a hidden section gives the expected result: the next row should be hidden +//(see task + const int hidden = 3; //section that will be hidden + const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5" << "6"; + + QStringListModel model( list ); + QHeaderView view(Qt::Vertical); + view.setModel(&model); + view.hideSection(hidden); + view.hideSection(1); + model.removeRow(1); + view.show(); + + for(int i = 0; i < view.count(); i++) { + if (i == (hidden-1)) { //-1 because we removed a row in the meantime + QCOMPARE(view.sectionSize(i), 0); + QVERIFY(view.isSectionHidden(i)); + } else { + QCOMPARE(view.sectionSize(i), view.defaultSectionSize() ); + QVERIFY(!view.isSectionHidden(i)); + } + } +} + +void tst_QHeaderView::preserveHiddenSectionWidth() +{ + const QStringList list = QStringList() << "0" << "1" << "2" << "3"; + + QStringListModel model( list ); + QHeaderView view(Qt::Vertical); + view.setModel(&model); + view.resizeSection(0, 100); + view.resizeSection(1, 10); + view.resizeSection(2, 50); + view.setResizeMode(3, QHeaderView::Stretch); + view.show(); + + view.hideSection(2); + model.removeRow(1); + view.showSection(1); + QCOMPARE(view.sectionSize(0), 100); + QCOMPARE(view.sectionSize(1), 50); + + view.hideSection(1); + model.insertRow(1); + view.showSection(2); + QCOMPARE(view.sectionSize(0), 100); + QCOMPARE(view.sectionSize(1), 30); + QCOMPARE(view.sectionSize(2), 50); +} + +void tst_QHeaderView::invisibleStretchLastSection() +{ + int count = 10; + QStandardItemModel model(1, count); + QHeaderView view(Qt::Horizontal); + view.setModel(&model); + view.setStretchLastSection(true); + int height = view.height(); + + view.resize(view.defaultSectionSize() * (count / 2), height); // don't show all sections + view.show(); + // stretch section is not visible; it should not be stretched + for (int i = 0; i < count; ++i) + QCOMPARE(view.sectionSize(i), view.defaultSectionSize()); + + view.resize(view.defaultSectionSize() * (count + 1), height); // give room to stretch + + // stretch section is visible; it should be stretched + for (int i = 0; i < count - 1; ++i) + QCOMPARE(view.sectionSize(i), view.defaultSectionSize()); + QCOMPARE(view.sectionSize(count - 1), view.defaultSectionSize() * 2); +} + +void tst_QHeaderView::emptySectionSpan() +{ + QHeaderViewPrivate::SectionSpan span; + QCOMPARE(span.sectionSize(), 0); +} + +void tst_QHeaderView::task236450_hidden_data() +{ + QTest::addColumn<QList<int> >("hide1"); + QTest::addColumn<QList<int> >("hide2"); + + QTest::newRow("set 1") << (QList<int>() << 1 << 3) + << (QList<int>() << 1 << 5); + + QTest::newRow("set 2") << (QList<int>() << 2 << 3) + << (QList<int>() << 1 << 5); + + QTest::newRow("set 3") << (QList<int>() << 0 << 2 << 4) + << (QList<int>() << 2 << 3 << 5); + +} + +void tst_QHeaderView::task236450_hidden() +{ + QFETCH(QList<int>, hide1); + QFETCH(QList<int>, hide2); + const QStringList list = QStringList() << "0" << "1" << "2" << "3" << "4" << "5"; + + QStringListModel model( list ); + protected_QHeaderView view(Qt::Vertical); + view.setModel(&model); + view.show(); + + foreach (int i, hide1) + view.hideSection(i); + + QCOMPARE(view.hiddenSectionCount(), hide1.count()); + for (int i = 0; i < 6; i++) { + QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); + } + + view.setDefaultSectionSize(2); + view.scheduleDelayedItemsLayout(); + view.executeDelayedItemsLayout(); //force to do a relayout + + QCOMPARE(view.hiddenSectionCount(), hide1.count()); + for (int i = 0; i < 6; i++) { + QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); + view.setSectionHidden(i, hide2.contains(i)); + } + + QCOMPARE(view.hiddenSectionCount(), hide2.count()); + for (int i = 0; i < 6; i++) { + QCOMPARE(!view.isSectionHidden(i), !hide2.contains(i)); + } + +} + +QTEST_MAIN(tst_QHeaderView) +#include "tst_qheaderview.moc" |