mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-11-26 14:17:05 +08:00
4955 lines
154 KiB
C++
4955 lines
154 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include <QIdentityProxyModel>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QScrollBar>
|
|
#include <QSignalSpy>
|
|
#include <QSortFilterProxyModel>
|
|
#include <QStandardItemModel>
|
|
#include <QStringListModel>
|
|
#include <QStyledItemDelegate>
|
|
#include <QTableView>
|
|
#include <QTest>
|
|
#include <private/qapplication_p.h>
|
|
#include <private/qtablewidget_p.h>
|
|
#include <private/qtesthelpers_p.h>
|
|
#if QT_CONFIG(textmarkdownwriter)
|
|
#include <private/qtextmarkdownwriter_p.h>
|
|
#endif
|
|
|
|
|
|
using namespace QTestPrivate;
|
|
|
|
#ifdef QT_BUILD_INTERNAL
|
|
#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) \
|
|
QVERIFY(static_cast<QTableViewPrivate*>(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency())
|
|
#else
|
|
#define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) (void)false
|
|
#endif
|
|
|
|
Q_DECLARE_METATYPE(Qt::Key);
|
|
Q_DECLARE_METATYPE(Qt::KeyboardModifier);
|
|
Q_DECLARE_METATYPE(QItemSelectionModel::SelectionFlag);
|
|
using BoolList = QList<bool>;
|
|
using IntList = QList<int>;
|
|
using KeyList = QList<Qt::Key>;
|
|
using SpanList = QList<QRect>;
|
|
|
|
class QtTestTableModel: public QAbstractTableModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
signals:
|
|
void invalidIndexEncountered() const;
|
|
|
|
public slots:
|
|
bool submit() override { ++submit_count; return QAbstractTableModel::submit(); }
|
|
|
|
public:
|
|
QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = nullptr)
|
|
: QAbstractTableModel(parent), row_count(rows), column_count(columns)
|
|
{}
|
|
|
|
void insertRows(int rows)
|
|
{
|
|
beginInsertRows(QModelIndex(), row_count, row_count + rows - 1);
|
|
row_count += rows;
|
|
endInsertRows();
|
|
}
|
|
|
|
int rowCount(const QModelIndex& = QModelIndex()) const override
|
|
{
|
|
return row_count;
|
|
}
|
|
|
|
int columnCount(const QModelIndex& = QModelIndex()) const override
|
|
{
|
|
return column_count;
|
|
}
|
|
|
|
bool isEditable(const QModelIndex &) const { return true; }
|
|
|
|
Qt::ItemFlags flags(const QModelIndex &index) const override
|
|
{
|
|
Qt::ItemFlags index_flags = QAbstractTableModel::flags(index);
|
|
if (disabled_rows.contains(index.row())
|
|
|| disabled_columns.contains(index.column()))
|
|
index_flags &= ~Qt::ItemIsEnabled;
|
|
return index_flags;
|
|
}
|
|
|
|
void disableRow(int row)
|
|
{
|
|
disabled_rows.insert(row);
|
|
}
|
|
|
|
void enableRow(int row)
|
|
{
|
|
disabled_rows.remove(row);
|
|
}
|
|
|
|
void disableColumn(int column)
|
|
{
|
|
disabled_columns.insert(column);
|
|
}
|
|
|
|
void enableColumn(int column)
|
|
{
|
|
disabled_columns.remove(column);
|
|
}
|
|
|
|
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
|
|
{
|
|
if (!idx.isValid() || idx.row() >= row_count || idx.column() >= column_count) {
|
|
qWarning() << "Invalid modelIndex [%d,%d,%p]" << idx;
|
|
emit invalidIndexEncountered();
|
|
return QVariant();
|
|
}
|
|
|
|
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
|
return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',')
|
|
+ QString::number(idx.column()) + QLatin1String(",0]");
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
bool insertRows(int start, int count, const QModelIndex &parent = QModelIndex()) override
|
|
{
|
|
if (start < 0 || start > row_count)
|
|
return false;
|
|
|
|
beginInsertRows(parent, start, start + count - 1);
|
|
row_count += count;
|
|
endInsertRows();
|
|
return true;
|
|
}
|
|
|
|
bool removeRows(int start, int count, const QModelIndex &parent = QModelIndex()) override
|
|
{
|
|
if (start < 0 || start >= row_count || row_count < count)
|
|
return false;
|
|
|
|
beginRemoveRows(parent, start, start + count - 1);
|
|
row_count -= count;
|
|
endRemoveRows();
|
|
return true;
|
|
}
|
|
|
|
void removeLastRow()
|
|
{
|
|
beginRemoveRows(QModelIndex(), row_count - 1, row_count - 1);
|
|
--row_count;
|
|
endRemoveRows();
|
|
}
|
|
|
|
void removeAllRows()
|
|
{
|
|
beginRemoveRows(QModelIndex(), 0, row_count - 1);
|
|
row_count = 0;
|
|
endRemoveRows();
|
|
}
|
|
|
|
bool insertColumns(int start, int count, const QModelIndex &parent = QModelIndex()) override
|
|
{
|
|
if (start < 0 || start > column_count)
|
|
return false;
|
|
|
|
beginInsertColumns(parent, start, start + count - 1);
|
|
column_count += count;
|
|
endInsertColumns();
|
|
return true;
|
|
}
|
|
|
|
bool removeColumns(int start, int count, const QModelIndex &parent = QModelIndex()) override
|
|
{
|
|
if (start < 0 || start >= column_count || column_count < count)
|
|
return false;
|
|
|
|
beginRemoveColumns(parent, start, start + count - 1);
|
|
column_count -= count;
|
|
endRemoveColumns();
|
|
return true;
|
|
}
|
|
|
|
void removeLastColumn()
|
|
{
|
|
beginRemoveColumns(QModelIndex(), column_count - 1, column_count - 1);
|
|
--column_count;
|
|
endRemoveColumns();
|
|
}
|
|
|
|
void removeAllColumns()
|
|
{
|
|
beginRemoveColumns(QModelIndex(), 0, column_count - 1);
|
|
column_count = 0;
|
|
endRemoveColumns();
|
|
}
|
|
|
|
bool canFetchMore(const QModelIndex &) const override
|
|
{
|
|
return can_fetch_more;
|
|
}
|
|
|
|
void fetchMore(const QModelIndex &) override
|
|
{
|
|
++fetch_more_count;
|
|
}
|
|
|
|
QSet<int> disabled_rows;
|
|
QSet<int> disabled_columns;
|
|
int row_count;
|
|
int column_count;
|
|
int submit_count = 0;
|
|
int fetch_more_count = 0;
|
|
bool can_fetch_more = false;
|
|
};
|
|
|
|
class QtTestTableView : public QTableView
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
using QTableView::QTableView;
|
|
|
|
void setModel(QAbstractItemModel *model) override
|
|
{
|
|
QTableView::setModel(model);
|
|
connect(selectionModel(), &QItemSelectionModel::currentChanged,
|
|
this, &QtTestTableView::slotCurrentChanged);
|
|
connect(selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
this, &QtTestTableView::itemSelectionChanged);
|
|
// Allow small sections in this test, since this test was made before we correctly enforced minimum sizes.
|
|
horizontalHeader()->setMinimumSectionSize(0);
|
|
verticalHeader()->setMinimumSectionSize(0);
|
|
}
|
|
|
|
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
|
const QList<int> &roles = QList<int>()) override
|
|
{
|
|
QTableView::dataChanged(topLeft, bottomRight, roles);
|
|
QTableViewPrivate *av = static_cast<QTableViewPrivate*>(qt_widget_private(this));
|
|
m_intersectecRect = av->intersectedRect(av->viewport->rect(), topLeft, bottomRight);
|
|
}
|
|
mutable QRect m_intersectecRect;
|
|
|
|
using QTableView::moveCursor;
|
|
using QTableView::isIndexHidden;
|
|
using QTableView::setSelection;
|
|
using QTableView::selectedIndexes;
|
|
using QTableView::sizeHintForRow;
|
|
using QTableView::initViewItemOption;
|
|
|
|
bool checkSignalOrder = false;
|
|
public slots:
|
|
void slotCurrentChanged(QModelIndex, QModelIndex) {
|
|
hasCurrentChanged++;
|
|
if (checkSignalOrder)
|
|
QVERIFY(hasCurrentChanged > hasSelectionChanged);
|
|
}
|
|
|
|
void itemSelectionChanged(QItemSelection , QItemSelection ) {
|
|
hasSelectionChanged++;
|
|
if (checkSignalOrder)
|
|
QVERIFY(hasCurrentChanged >= hasSelectionChanged);
|
|
}
|
|
private:
|
|
int hasCurrentChanged = 0;
|
|
int hasSelectionChanged = 0;
|
|
|
|
friend class tst_QTableView;
|
|
friend struct QMetaTypeId<QtTestTableView::CursorAction>;
|
|
};
|
|
Q_DECLARE_METATYPE(QtTestTableView::CursorAction);
|
|
|
|
class QtTestItemDelegate : public QStyledItemDelegate
|
|
{
|
|
public:
|
|
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override
|
|
{
|
|
return hint;
|
|
}
|
|
|
|
QSize hint;
|
|
};
|
|
|
|
class tst_QTableView : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private:
|
|
using CursorActionList = QList<QtTestTableView::CursorAction>;
|
|
private slots:
|
|
void getSetCheck();
|
|
|
|
void noDelegate();
|
|
void noModel();
|
|
void emptyModel();
|
|
|
|
void removeRows_data();
|
|
void removeRows();
|
|
|
|
void removeColumns_data();
|
|
void removeColumns();
|
|
|
|
void keyboardNavigation_data();
|
|
void keyboardNavigation();
|
|
|
|
void headerSections_data();
|
|
void headerSections();
|
|
|
|
void moveCursor_data();
|
|
void moveCursor();
|
|
|
|
void moveCursorStrikesBack_data();
|
|
void moveCursorStrikesBack();
|
|
|
|
void moveCursorBiggerJump();
|
|
|
|
void hideRows_data();
|
|
void hideRows();
|
|
|
|
void hideColumns_data();
|
|
void hideColumns();
|
|
|
|
void selection_data();
|
|
void selection();
|
|
|
|
void selectRow_data();
|
|
void selectRow();
|
|
|
|
void selectColumn_data();
|
|
void selectColumn();
|
|
|
|
#if QT_CONFIG(shortcut)
|
|
void selectall_data();
|
|
void selectall();
|
|
#endif
|
|
|
|
void visualRect_data();
|
|
void visualRect();
|
|
|
|
void fetchMore();
|
|
void setHeaders();
|
|
|
|
void resizeRowsToContents_data();
|
|
void resizeRowsToContents();
|
|
|
|
void resizeColumnsToContents_data();
|
|
void resizeColumnsToContents();
|
|
|
|
void rowViewportPosition_data();
|
|
void rowViewportPosition();
|
|
|
|
void rowAt_data();
|
|
void rowAt();
|
|
|
|
void rowHeight_data();
|
|
void rowHeight();
|
|
|
|
void columnViewportPosition_data();
|
|
void columnViewportPosition();
|
|
|
|
void columnAt_data();
|
|
void columnAt();
|
|
|
|
void columnWidth_data();
|
|
void columnWidth();
|
|
|
|
void hiddenRow_data();
|
|
void hiddenRow();
|
|
|
|
void hiddenColumn_data();
|
|
void hiddenColumn();
|
|
|
|
void sortingEnabled_data();
|
|
void sortingEnabled();
|
|
|
|
void sortByColumn_data();
|
|
void sortByColumn();
|
|
|
|
void scrollTo_data();
|
|
void scrollTo();
|
|
|
|
void indexAt_data();
|
|
void indexAt();
|
|
|
|
void span_data();
|
|
void span();
|
|
void spans();
|
|
void spans_data();
|
|
void spansAfterRowInsertion();
|
|
void spansAfterColumnInsertion();
|
|
void spansAfterRowRemoval();
|
|
void spansAfterColumnRemoval();
|
|
void editSpanFromDirections_data();
|
|
void editSpanFromDirections();
|
|
|
|
void checkHeaderReset();
|
|
void checkHeaderMinSize();
|
|
|
|
void resizeToContents();
|
|
void resizeToContentsSpans();
|
|
|
|
void tabFocus();
|
|
void bigModel();
|
|
void selectionSignal();
|
|
void setCurrentIndex();
|
|
|
|
void checkIntersectedRect_data();
|
|
void checkIntersectedRect();
|
|
|
|
// task-specific tests:
|
|
void task173773_updateVerticalHeader();
|
|
void task227953_setRootIndex();
|
|
void task240266_veryBigColumn();
|
|
void task248688_autoScrollNavigation();
|
|
void task259308_scrollVerticalHeaderSwappedSections();
|
|
void task191545_dragSelectRows();
|
|
void taskQTBUG_5062_spansInconsistency();
|
|
void taskQTBUG_4516_clickOnRichTextLabel();
|
|
#if QT_CONFIG(wheelevent)
|
|
void taskQTBUG_5237_wheelEventOnHeader();
|
|
#endif
|
|
void taskQTBUG_8585_crashForNoGoodReason();
|
|
void taskQTBUG_7774_RtoLVisualRegionForSelection();
|
|
void taskQTBUG_8777_scrollToSpans();
|
|
void taskQTBUG_10169_sizeHintForRow();
|
|
void taskQTBUG_30653_doItemsLayout();
|
|
void taskQTBUG_50171_selectRowAfterSwapColumns();
|
|
void deselectRow();
|
|
void selectRowsAndCells();
|
|
void selectColumnsAndCells();
|
|
void selectWithHeader_data();
|
|
void selectWithHeader();
|
|
|
|
#if QT_CONFIG(wheelevent)
|
|
void mouseWheel_data();
|
|
void mouseWheel();
|
|
#endif
|
|
|
|
void addColumnWhileEditing();
|
|
void task234926_setHeaderSorting();
|
|
|
|
void changeHeaderData();
|
|
void viewOptions();
|
|
|
|
void taskQTBUG_7232_AllowUserToControlSingleStep();
|
|
void rowsInVerticalHeader();
|
|
|
|
#if QT_CONFIG(textmarkdownwriter)
|
|
void markdownWriter();
|
|
#endif
|
|
};
|
|
|
|
// Testing get/set functions
|
|
void tst_QTableView::getSetCheck()
|
|
{
|
|
QTableView obj1;
|
|
|
|
obj1.setSortingEnabled(false);
|
|
QCOMPARE(false, obj1.isSortingEnabled());
|
|
obj1.setSortingEnabled(true);
|
|
QCOMPARE(true, obj1.isSortingEnabled());
|
|
|
|
obj1.setShowGrid(false);
|
|
QCOMPARE(false, obj1.showGrid());
|
|
obj1.setShowGrid(true);
|
|
QCOMPARE(true, obj1.showGrid());
|
|
|
|
obj1.setGridStyle(Qt::NoPen);
|
|
QCOMPARE(Qt::NoPen, obj1.gridStyle());
|
|
obj1.setGridStyle(Qt::SolidLine);
|
|
QCOMPARE(Qt::SolidLine, obj1.gridStyle());
|
|
|
|
obj1.setRootIndex(QModelIndex());
|
|
QCOMPARE(QModelIndex(), obj1.rootIndex());
|
|
QStandardItemModel model(10, 10);
|
|
obj1.setModel(&model);
|
|
QModelIndex index = model.index(0, 0);
|
|
obj1.setRootIndex(index);
|
|
QCOMPARE(index, obj1.rootIndex());
|
|
|
|
QHeaderView *var1 = new QHeaderView(Qt::Horizontal);
|
|
obj1.setHorizontalHeader(var1);
|
|
QCOMPARE(var1, obj1.horizontalHeader());
|
|
obj1.setHorizontalHeader(nullptr);
|
|
QCOMPARE(var1, obj1.horizontalHeader());
|
|
delete var1;
|
|
|
|
QHeaderView *var2 = new QHeaderView(Qt::Vertical);
|
|
obj1.setVerticalHeader(var2);
|
|
QCOMPARE(var2, obj1.verticalHeader());
|
|
obj1.setVerticalHeader(nullptr);
|
|
QCOMPARE(var2, obj1.verticalHeader());
|
|
delete var2;
|
|
|
|
QCOMPARE(obj1.isCornerButtonEnabled(), true);
|
|
obj1.setCornerButtonEnabled(false);
|
|
QCOMPARE(obj1.isCornerButtonEnabled(), false);
|
|
}
|
|
void tst_QTableView::noDelegate()
|
|
{
|
|
QtTestTableModel model(3, 3);
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.setItemDelegate(nullptr);
|
|
view.show();
|
|
}
|
|
|
|
void tst_QTableView::noModel()
|
|
{
|
|
QTableView view;
|
|
view.show();
|
|
}
|
|
|
|
void tst_QTableView::emptyModel()
|
|
{
|
|
QtTestTableModel model;
|
|
QTableView view;
|
|
QSignalSpy spy(&model, &QtTestTableModel::invalidIndexEncountered);
|
|
view.setModel(&model);
|
|
view.show();
|
|
QCOMPARE(spy.size(), 0);
|
|
}
|
|
|
|
void tst_QTableView::removeRows_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
|
|
QTest::newRow("2x2") << 2 << 2;
|
|
QTest::newRow("10x10") << 10 << 10;
|
|
}
|
|
|
|
void tst_QTableView::removeRows()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QSignalSpy spy(&model, &QtTestTableModel::invalidIndexEncountered);
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.show();
|
|
|
|
model.removeLastRow();
|
|
QCOMPARE(spy.size(), 0);
|
|
|
|
model.removeAllRows();
|
|
QCOMPARE(spy.size(), 0);
|
|
}
|
|
|
|
void tst_QTableView::removeColumns_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
|
|
QTest::newRow("2x2") << 2 << 2;
|
|
QTest::newRow("10x10") << 10 << 10;
|
|
}
|
|
|
|
void tst_QTableView::removeColumns()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QSignalSpy spy(&model, &QtTestTableModel::invalidIndexEncountered);
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.show();
|
|
|
|
model.removeLastColumn();
|
|
QCOMPARE(spy.size(), 0);
|
|
|
|
model.removeAllColumns();
|
|
QCOMPARE(spy.size(), 0);
|
|
}
|
|
|
|
void tst_QTableView::keyboardNavigation_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<bool>("tabKeyNavigation");
|
|
QTest::addColumn<KeyList>("keyPresses");
|
|
|
|
const KeyList keyList {
|
|
Qt::Key_Up, Qt::Key_Up, Qt::Key_Right, Qt::Key_Right,
|
|
Qt::Key_Up, Qt::Key_Left, Qt::Key_Left, Qt::Key_Up,
|
|
Qt::Key_Down, Qt::Key_Up, Qt::Key_Up, Qt::Key_Up,
|
|
Qt::Key_Up, Qt::Key_Up, Qt::Key_Up, Qt::Key_Left,
|
|
Qt::Key_Left, Qt::Key_Up, Qt::Key_Down, Qt::Key_Down,
|
|
Qt::Key_Tab, Qt::Key_Backtab};
|
|
|
|
QTest::newRow("16x16 model") << 16 << 16 << true << keyList;
|
|
QTest::newRow("no tab") << 8 << 8 << false << keyList;
|
|
}
|
|
|
|
void tst_QTableView::keyboardNavigation()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(bool, tabKeyNavigation);
|
|
QFETCH(const KeyList, keyPresses);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
|
|
view.setTabKeyNavigation(tabKeyNavigation);
|
|
QModelIndex index = model.index(rowCount - 1, columnCount - 1);
|
|
view.setCurrentIndex(index);
|
|
|
|
view.show();
|
|
QApplicationPrivate::setActiveWindow(&view);
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
|
|
int row = rowCount - 1;
|
|
int column = columnCount - 1;
|
|
for (Qt::Key key : keyPresses) {
|
|
|
|
switch (key) {
|
|
case Qt::Key_Up:
|
|
row = qMax(0, row - 1);
|
|
break;
|
|
case Qt::Key_Down:
|
|
row = qMin(rowCount - 1, row + 1);
|
|
break;
|
|
case Qt::Key_Backtab:
|
|
if (!tabKeyNavigation)
|
|
break;
|
|
Q_FALLTHROUGH();
|
|
case Qt::Key_Left:
|
|
column = qMax(0, column - 1);
|
|
break;
|
|
case Qt::Key_Tab:
|
|
if (!tabKeyNavigation)
|
|
break;
|
|
Q_FALLTHROUGH();
|
|
case Qt::Key_Right:
|
|
column = qMin(columnCount - 1, column + 1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
QTest::keyClick(&view, key);
|
|
QApplication::processEvents();
|
|
|
|
QModelIndex index = model.index(row, column);
|
|
QCOMPARE(view.currentIndex(), index);
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::headerSections_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
|
|
QTest::newRow("") << 10 << 10 << 5 << 5 << 30 << 30;
|
|
}
|
|
|
|
void tst_QTableView::headerSections()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QTableView view;
|
|
QHeaderView *hheader = view.horizontalHeader();
|
|
QHeaderView *vheader = view.verticalHeader();
|
|
|
|
view.setModel(&model);
|
|
hheader->setMinimumSectionSize(columnWidth);
|
|
vheader->setMinimumSectionSize(rowHeight);
|
|
view.show();
|
|
|
|
hheader->doItemsLayout();
|
|
vheader->doItemsLayout();
|
|
|
|
QCOMPARE(hheader->count(), model.columnCount());
|
|
QCOMPARE(vheader->count(), model.rowCount());
|
|
|
|
view.setRowHeight(row, rowHeight);
|
|
QCOMPARE(view.rowHeight(row), rowHeight);
|
|
view.hideRow(row);
|
|
QCOMPARE(view.rowHeight(row), 0);
|
|
view.showRow(row);
|
|
QCOMPARE(view.rowHeight(row), rowHeight);
|
|
|
|
view.setColumnWidth(column, columnWidth);
|
|
QCOMPARE(view.columnWidth(column), columnWidth);
|
|
view.hideColumn(column);
|
|
QCOMPARE(view.columnWidth(column), 0);
|
|
view.showColumn(column);
|
|
QCOMPARE(view.columnWidth(column), columnWidth);
|
|
}
|
|
|
|
typedef QPair<int,int> IntPair;
|
|
|
|
void tst_QTableView::moveCursor_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("hideRow");
|
|
QTest::addColumn<int>("hideColumn");
|
|
|
|
QTest::addColumn<int>("startRow");
|
|
QTest::addColumn<int>("startColumn");
|
|
|
|
QTest::addColumn<QtTestTableView::CursorAction>("cursorMoveAction");
|
|
QTest::addColumn<Qt::KeyboardModifier>("modifier");
|
|
|
|
QTest::addColumn<int>("expectedRow");
|
|
QTest::addColumn<int>("expectedColumn");
|
|
QTest::addColumn<IntPair>("moveRow");
|
|
QTest::addColumn<IntPair>("moveColumn");
|
|
|
|
// MoveRight
|
|
QTest::newRow("MoveRight (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveRight << Qt::NoModifier
|
|
<< 0 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveRight (3,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 0
|
|
<< QtTestTableView::MoveRight << Qt::NoModifier
|
|
<< 3 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveRight (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveRight << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0); // ###
|
|
|
|
QTest::newRow("MoveRight, hidden column 1 (0,0)")
|
|
<< 4 << 4 << -1 << 1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveRight << Qt::NoModifier
|
|
<< 0 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveRight, hidden column 3 (0,2)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 0 << 2
|
|
<< QtTestTableView::MoveRight << Qt::NoModifier
|
|
<< 0 << 2 << IntPair(0,0) << IntPair(0,0); // ###
|
|
|
|
// MoveNext should in addition wrap
|
|
QTest::newRow("MoveNext (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext (0,2)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 2
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrap (0,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 3
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 1 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrap (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, hidden column 1 (0,0)")
|
|
<< 4 << 4 << -1 << 1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrap, hidden column 3 (0,2)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 0 << 2
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 1 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrap, hidden column 3 (3,2)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 3 << 2
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrapy, wrapx, hidden column 3, hidden row 3 (2,2)")
|
|
<< 4 << 4 << 3 << 3
|
|
<< 2 << 2
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveNext, wrap, hidden column 2, moved column from 3 to 0. (0,2)")
|
|
<< 4 << 4 << -1 << 2
|
|
<< 0 << 2
|
|
<< QtTestTableView::MoveNext << Qt::NoModifier
|
|
<< 1 << 3 << IntPair(0,0) << IntPair(3,0);
|
|
|
|
// MoveLeft
|
|
QTest::newRow("MoveLeft (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveLeft << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveLeft (0,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 3
|
|
<< QtTestTableView::MoveLeft << Qt::NoModifier
|
|
<< 0 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveLeft (1,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 1 << 0
|
|
<< QtTestTableView::MoveLeft << Qt::NoModifier
|
|
<< 1 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveLeft, hidden column 0 (0,2)")
|
|
<< 4 << 4 << -1 << 1
|
|
<< 0 << 2
|
|
<< QtTestTableView::MoveLeft << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveLeft, hidden column 0 (0,1)")
|
|
<< 4 << 4 << -1 << 0
|
|
<< 0 << 1
|
|
<< QtTestTableView::MoveLeft << Qt::NoModifier
|
|
<< 0 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// MovePrevious should in addition wrap
|
|
QTest::newRow("MovePrevious (0,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 3
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious (0,1)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 1
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrap (1,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 1 << 0
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrap, (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, hidden column 1 (0,2)")
|
|
<< 4 << 4 << -1 << 1
|
|
<< 0 << 2
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrap, hidden column 3 (0,2)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 0 << 2
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrapy, hidden column 0 (0,1)")
|
|
<< 4 << 4 << -1 << 0
|
|
<< 0 << 1
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrap, hidden column 0, hidden row 0 (1,1)")
|
|
<< 4 << 4 << 0 << 0
|
|
<< 1 << 1
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePrevious, wrap, hidden column 1, moved column from 0 to 3. (1,2)")
|
|
<< 4 << 4 << -1 << 1
|
|
<< 1 << 2
|
|
<< QtTestTableView::MovePrevious << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,3);
|
|
|
|
// MoveDown
|
|
QTest::newRow("MoveDown (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 1 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveDown (3,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 0
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 3 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveDown (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveDown, hidden row 1 (0,0)")
|
|
<< 4 << 4 << 1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 2 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveDown, hidden row 3 (2,0)")
|
|
<< 4 << 4 << 3 << -1
|
|
<< 2 << 0
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 2 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveDown, hidden row 0 hidden column 0 (0,0)")
|
|
<< 4 << 4 << 0 << 0
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveDown << Qt::NoModifier
|
|
<< 1 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// MoveUp
|
|
QTest::newRow("MoveUp (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveUp << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveUp (3, 0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 0
|
|
<< QtTestTableView::MoveUp << Qt::NoModifier
|
|
<< 2 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveUp (0,1)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 1
|
|
<< QtTestTableView::MoveUp << Qt::NoModifier
|
|
<< 0 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveUp, hidden row 1 (2,0)")
|
|
<< 4 << 4 << 1 << -1
|
|
<< 2 << 0
|
|
<< QtTestTableView::MoveUp << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveUp, hidden row (1,0)")
|
|
<< 4 << 4 << 0 << -1
|
|
<< 1 << 0
|
|
<< QtTestTableView::MoveUp << Qt::NoModifier
|
|
<< 1 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// MoveHome
|
|
QTest::newRow("MoveHome (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveHome << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveHome (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveHome << Qt::NoModifier
|
|
<< 3 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveHome, hidden column 0 (3,3)")
|
|
<< 4 << 4 << -1 << 0
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveHome << Qt::NoModifier
|
|
<< 3 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// Use Ctrl modifier
|
|
QTest::newRow("MoveHome + Ctrl (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveHome << Qt::ControlModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveHome + Ctrl (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveHome << Qt::ControlModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveHome + Ctrl, hidden column 0, hidden row 0 (3,3)")
|
|
<< 4 << 4 << 0 << 0
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveHome << Qt::ControlModifier
|
|
<< 1 << 1 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// MoveEnd
|
|
QTest::newRow("MoveEnd (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveEnd << Qt::NoModifier
|
|
<< 0 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveEnd (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveEnd << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveEnd, hidden column (0,0)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveEnd << Qt::NoModifier
|
|
<< 0<< 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
// Use Ctrl modifier
|
|
QTest::newRow("MoveEnd + Ctrl (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveEnd << Qt::ControlModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveEnd + Ctrl (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MoveEnd << Qt::ControlModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveEnd + Ctrl, hidden column 3 (0,0)")
|
|
<< 4 << 4 << -1 << 3
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveEnd << Qt::ControlModifier
|
|
<< 3 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MoveEnd + Ctrl, hidden column 3, hidden row 3 (0,0)")
|
|
<< 4 << 4 << 3 << 3
|
|
<< 0 << 0
|
|
<< QtTestTableView::MoveEnd << Qt::ControlModifier
|
|
<< 2 << 2 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePageUp (0,0)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 0
|
|
<< QtTestTableView::MovePageUp << Qt::NoModifier
|
|
<< 0 << 0 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePageUp (3,3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MovePageUp << Qt::NoModifier
|
|
<< 0 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePageDown (3, 3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 3 << 3
|
|
<< QtTestTableView::MovePageDown << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
|
|
QTest::newRow("MovePageDown (0, 3)")
|
|
<< 4 << 4 << -1 << -1
|
|
<< 0 << 3
|
|
<< QtTestTableView::MovePageDown << Qt::NoModifier
|
|
<< 3 << 3 << IntPair(0,0) << IntPair(0,0);
|
|
}
|
|
|
|
void tst_QTableView::moveCursor()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(int, startRow);
|
|
QFETCH(int, startColumn);
|
|
QFETCH(QtTestTableView::CursorAction, cursorMoveAction);
|
|
QFETCH(Qt::KeyboardModifier, modifier);
|
|
QFETCH(int, expectedRow);
|
|
QFETCH(int, expectedColumn);
|
|
QFETCH(IntPair, moveRow);
|
|
QFETCH(IntPair, moveColumn);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
// we have to make sure that PgUp/PgDown can scroll to the bottom/top
|
|
view.resize(view.horizontalHeader()->length() + 50,
|
|
view.verticalHeader()->length() + 50);
|
|
view.hideRow(hideRow);
|
|
view.hideColumn(hideColumn);
|
|
if (moveColumn.first != moveColumn.second)
|
|
view.horizontalHeader()->moveSection(moveColumn.first, moveColumn.second);
|
|
if (moveRow.first != moveRow.second)
|
|
view.verticalHeader()->moveSection(moveRow.first, moveRow.second);
|
|
|
|
view.show();
|
|
|
|
QModelIndex index = model.index(startRow, startColumn);
|
|
view.setCurrentIndex(index);
|
|
|
|
QModelIndex newIndex = view.moveCursor(cursorMoveAction, modifier);
|
|
// expected fails, task 119433
|
|
if(newIndex.row() == -1)
|
|
return;
|
|
QCOMPARE(newIndex.row(), expectedRow);
|
|
QCOMPARE(newIndex.column(), expectedColumn);
|
|
}
|
|
|
|
void tst_QTableView::moveCursorStrikesBack_data()
|
|
{
|
|
QTest::addColumn<int>("hideRow");
|
|
QTest::addColumn<int>("hideColumn");
|
|
QTest::addColumn<IntList>("disableRows");
|
|
QTest::addColumn<IntList>("disableColumns");
|
|
QTest::addColumn<QRect>("span");
|
|
|
|
QTest::addColumn<int>("startRow");
|
|
QTest::addColumn<int>("startColumn");
|
|
QTest::addColumn<CursorActionList>("cursorMoveActions");
|
|
QTest::addColumn<int>("expectedRow");
|
|
QTest::addColumn<int>("expectedColumn");
|
|
|
|
QTest::newRow("Last column disabled. Task QTBUG-3878") << -1 << -1
|
|
<< IntList()
|
|
<< (IntList() << 6)
|
|
<< QRect()
|
|
<< 0 << 5
|
|
<< CursorActionList{QtTestTableView::MoveNext}
|
|
<< 1 << 0;
|
|
|
|
QTest::newRow("Last column disabled 2. Task QTBUG-3878") << -1 << -1
|
|
<< IntList()
|
|
<< (IntList() << 6)
|
|
<< QRect()
|
|
<< 1 << 0
|
|
<< CursorActionList{QtTestTableView::MovePrevious}
|
|
<< 0 << 5;
|
|
|
|
QTest::newRow("Span, anchor column hidden") << -1 << 1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 2 << 0
|
|
<< CursorActionList{QtTestTableView::MoveNext}
|
|
<< 2 << 1;
|
|
|
|
QTest::newRow("Span, anchor column disabled") << -1 << -1
|
|
<< IntList()
|
|
<< (IntList() << 1)
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 2 << 0
|
|
<< CursorActionList{QtTestTableView::MoveNext}
|
|
<< 2 << 1;
|
|
|
|
QTest::newRow("Span, anchor row hidden") << 2 << -1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 1 << 2
|
|
<< CursorActionList{QtTestTableView::MoveDown}
|
|
<< 2 << 1;
|
|
|
|
QTest::newRow("Span, anchor row disabled") << -1 << -1
|
|
<< (IntList() << 2)
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 1 << 2
|
|
<< CursorActionList{QtTestTableView::MoveDown}
|
|
<< 2 << 1;
|
|
|
|
QTest::newRow("Move through span right") << -1 << -1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 3 << 0
|
|
<< CursorActionList{QtTestTableView::MoveRight,
|
|
QtTestTableView::MoveRight}
|
|
<< 3 << 3;
|
|
|
|
QTest::newRow("Move through span left") << -1 << -1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 3 << 3
|
|
<< CursorActionList{QtTestTableView::MoveLeft,
|
|
QtTestTableView::MoveLeft}
|
|
<< 3 << 0;
|
|
|
|
QTest::newRow("Move through span down") << -1 << -1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 1 << 2
|
|
<< CursorActionList{QtTestTableView::MoveDown,
|
|
QtTestTableView::MoveDown}
|
|
<< 5 << 2;
|
|
|
|
QTest::newRow("Move through span up") << -1 << -1
|
|
<< IntList()
|
|
<< IntList()
|
|
<< QRect(1, 2, 2, 3)
|
|
<< 5 << 2
|
|
<< CursorActionList{QtTestTableView::MoveUp,
|
|
QtTestTableView::MoveUp}
|
|
<< 1 << 2;
|
|
|
|
IntList fullList;
|
|
for (int i = 0; i < 7; ++i)
|
|
fullList << i;
|
|
|
|
QTest::newRow("All disabled, wrap forward. => invalid index") << -1 << -1
|
|
<< fullList
|
|
<< fullList
|
|
<< QRect()
|
|
<< 1 << 0
|
|
<< CursorActionList{QtTestTableView::MoveNext}
|
|
<< -1 << -1;
|
|
|
|
QTest::newRow("All disabled, wrap backwards. => invalid index") << -1 << -1
|
|
<< fullList
|
|
<< fullList
|
|
<< QRect()
|
|
<< 1 << 0
|
|
<< CursorActionList{QtTestTableView::MovePrevious}
|
|
<< -1 << -1;
|
|
|
|
QTest::newRow("Last column disabled, MoveEnd. QTBUG-72400") << -1 << -1
|
|
<< IntList()
|
|
<< (IntList() << 6)
|
|
<< QRect()
|
|
<< 0 << 0
|
|
<< CursorActionList{QtTestTableView::MoveEnd}
|
|
<< 0 << 5;
|
|
|
|
QTest::newRow("First column disabled, MoveHome. QTBUG-72400") << -1 << -1
|
|
<< IntList()
|
|
<< (IntList() << 0)
|
|
<< QRect()
|
|
<< 0 << 6
|
|
<< CursorActionList{QtTestTableView::MoveHome}
|
|
<< 0 << 1;
|
|
|
|
QTest::newRow("First row disabled, MovePageUp. QTBUG-72400") << -1 << -1
|
|
<< (IntList() << 0)
|
|
<< IntList()
|
|
<< QRect()
|
|
<< 2 << 0
|
|
<< CursorActionList{QtTestTableView::MovePageUp}
|
|
<< 1 << 0;
|
|
|
|
QTest::newRow("Last row disabled, MovePageDown. QTBUG-72400") << -1 << -1
|
|
<< (IntList() << 6)
|
|
<< IntList()
|
|
<< QRect()
|
|
<< 4 << 0
|
|
<< CursorActionList{QtTestTableView::MovePageDown}
|
|
<< 5 << 0;
|
|
}
|
|
|
|
void tst_QTableView::moveCursorStrikesBack()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(const IntList, disableRows);
|
|
QFETCH(const IntList, disableColumns);
|
|
QFETCH(QRect, span);
|
|
|
|
QFETCH(int, startRow);
|
|
QFETCH(int, startColumn);
|
|
QFETCH(const CursorActionList, cursorMoveActions);
|
|
QFETCH(int, expectedRow);
|
|
QFETCH(int, expectedColumn);
|
|
|
|
QtTestTableModel model(7, 7);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
view.hideRow(hideRow);
|
|
view.hideColumn(hideColumn);
|
|
|
|
if (span.height() && span.width())
|
|
view.setSpan(span.top(), span.left(), span.height(), span.width());
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
// resize to make sure there are scrollbars
|
|
view.resize(view.columnWidth(0) * 7, view.rowHeight(0) * 7);
|
|
|
|
QModelIndex index = model.index(startRow, startColumn);
|
|
view.setCurrentIndex(index);
|
|
|
|
for (int row : disableRows)
|
|
model.disableRow(row);
|
|
for (int column : disableColumns)
|
|
model.disableColumn(column);
|
|
|
|
int newRow = -1;
|
|
int newColumn = -1;
|
|
for (auto cursorMoveAction : cursorMoveActions) {
|
|
QModelIndex newIndex = view.moveCursor(cursorMoveAction, {});
|
|
view.setCurrentIndex(newIndex);
|
|
newRow = newIndex.row();
|
|
newColumn = newIndex.column();
|
|
}
|
|
|
|
QCOMPARE(newRow, expectedRow);
|
|
QCOMPARE(newColumn, expectedColumn);
|
|
}
|
|
|
|
void tst_QTableView::moveCursorBiggerJump()
|
|
{
|
|
QtTestTableModel model(50, 7);
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
int height = view.horizontalHeader()->height();
|
|
for (int i=0;i<8;i++)
|
|
height += view.verticalHeader()->sectionSize(i);
|
|
view.resize(view.width(), height);
|
|
view.setCurrentIndex(model.index(0,0));
|
|
|
|
QTest::keyClick(&view, Qt::Key_PageDown);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(1,0));
|
|
QTest::keyClick(&view, Qt::Key_PageDown);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(8,0));
|
|
QTest::keyClick(&view, Qt::Key_PageDown);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(15,0));
|
|
QTest::keyClick(&view, Qt::Key_PageUp);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(14,0));
|
|
QTest::keyClick(&view, Qt::Key_PageUp);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(7,0));
|
|
QTest::keyClick(&view, Qt::Key_PageUp);
|
|
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(0,0));
|
|
|
|
QTest::keyClick(&view, Qt::Key_PageDown);
|
|
view.verticalHeader()->hideSection(0);
|
|
QTest::keyClick(&view, Qt::Key_PageUp);
|
|
QTRY_COMPARE(view.currentIndex().row(), view.rowAt(0));
|
|
}
|
|
|
|
void tst_QTableView::hideRows_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("showRow"); // hide, then show
|
|
QTest::addColumn<int>("hideRow"); // hide only
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
|
|
QTest::newRow("show row 0, hide row 3, no span")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< 3
|
|
<< -1 << -1
|
|
<< 1 << 1;
|
|
|
|
QTest::newRow("show row 0, hide row 3, span")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< 3
|
|
<< 0 << 0
|
|
<< 3 << 2;
|
|
}
|
|
|
|
void tst_QTableView::hideRows()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, showRow);
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QTableView view;
|
|
|
|
view.setModel(&model);
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
|
|
view.hideRow(showRow);
|
|
QVERIFY(view.isRowHidden(showRow));
|
|
|
|
view.hideRow(hideRow);
|
|
QVERIFY(view.isRowHidden(hideRow));
|
|
|
|
view.showRow(showRow);
|
|
QVERIFY(!view.isRowHidden(showRow));
|
|
QVERIFY(view.isRowHidden(hideRow));
|
|
}
|
|
|
|
void tst_QTableView::hideColumns_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("showColumn"); // hide, then show
|
|
QTest::addColumn<int>("hideColumn"); // hide only
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
|
|
QTest::newRow("show col 0, hide col 3, no span")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< 3
|
|
<< -1 << -1
|
|
<< 1 << 1;
|
|
|
|
QTest::newRow("show col 0, hide col 3, span")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< 3
|
|
<< 0 << 0
|
|
<< 3 << 2;
|
|
}
|
|
|
|
void tst_QTableView::hideColumns()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, showColumn);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
|
|
view.hideColumn(showColumn);
|
|
QVERIFY(view.isColumnHidden(showColumn));
|
|
|
|
view.hideColumn(hideColumn);
|
|
QVERIFY(view.isColumnHidden(hideColumn));
|
|
|
|
view.showColumn(showColumn);
|
|
QVERIFY(!view.isColumnHidden(showColumn));
|
|
QVERIFY(view.isColumnHidden(hideColumn));
|
|
}
|
|
|
|
void tst_QTableView::selection_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<int>("hideRow");
|
|
QTest::addColumn<int>("hideColumn");
|
|
QTest::addColumn<int>("moveRowFrom");
|
|
QTest::addColumn<int>("moveRowTo");
|
|
QTest::addColumn<int>("moveColumnFrom");
|
|
QTest::addColumn<int>("moveColumnTo");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<int>("x");
|
|
QTest::addColumn<int>("y");
|
|
QTest::addColumn<int>("width");
|
|
QTest::addColumn<int>("height");
|
|
QTest::addColumn<QItemSelectionModel::SelectionFlag>("command");
|
|
QTest::addColumn<int>("selectedCount"); // ### make this more detailed
|
|
|
|
QTest::newRow("no span, no hidden, no moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 9; // selected count
|
|
|
|
QTest::newRow("row span, no hidden, no moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< 1 << 1 // pos
|
|
<< 2 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 8; // selected count
|
|
|
|
QTest::newRow("col span, no hidden, no moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< 1 << 1 // pos
|
|
<< 1 << 2 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 8; // selected count
|
|
|
|
QTest::newRow("no span, row hidden, no moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 9; // selected count
|
|
|
|
QTest::newRow("no span, col hidden, no moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << 1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 9; // selected count
|
|
|
|
QTest::newRow("no span, no hidden, row moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< 1 << 3 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 9; // selected count
|
|
|
|
QTest::newRow("no span, no hidden, col moved, 3x3 select")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< 1 << 3 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 20 << 20 << 80 << 80 // rect
|
|
<< QItemSelectionModel::Select // command
|
|
<< 9; // selected count
|
|
}
|
|
|
|
void tst_QTableView::selection()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(int, moveRowFrom);
|
|
QFETCH(int, moveRowTo);
|
|
QFETCH(int, moveColumnFrom);
|
|
QFETCH(int, moveColumnTo);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(int, x);
|
|
QFETCH(int, y);
|
|
QFETCH(int, width);
|
|
QFETCH(int, height);
|
|
QFETCH(QItemSelectionModel::SelectionFlag, command);
|
|
QFETCH(int, selectedCount);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QtTestTableView view;
|
|
view.show();
|
|
view.setModel(&model);
|
|
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
|
|
view.hideRow(hideRow);
|
|
view.hideColumn(hideColumn);
|
|
|
|
view.verticalHeader()->moveSection(moveRowFrom, moveRowTo);
|
|
view.horizontalHeader()->moveSection(moveColumnFrom, moveColumnTo);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
view.setSelection(QRect(x, y, width, height), command);
|
|
|
|
QCOMPARE(view.selectedIndexes().size(), selectedCount);
|
|
}
|
|
|
|
void tst_QTableView::selectRow_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<QAbstractItemView::SelectionMode>("mode");
|
|
QTest::addColumn<QAbstractItemView::SelectionBehavior>("behavior");
|
|
QTest::addColumn<int>("selectedItems");
|
|
|
|
QTest::newRow("SingleSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 0;
|
|
|
|
QTest::newRow("SingleSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 10;
|
|
|
|
QTest::newRow("SingleSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 0;
|
|
|
|
QTest::newRow("MultiSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("MultiSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 10;
|
|
|
|
QTest::newRow("MultiSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 0;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 10;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 0;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 10;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 0;
|
|
}
|
|
|
|
void tst_QTableView::selectRow()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, row);
|
|
QFETCH(QAbstractItemView::SelectionMode, mode);
|
|
QFETCH(QAbstractItemView::SelectionBehavior, behavior);
|
|
QFETCH(int, selectedItems);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QTableView view;
|
|
|
|
view.setModel(&model);
|
|
view.setSelectionMode(mode);
|
|
view.setSelectionBehavior(behavior);
|
|
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0);
|
|
|
|
view.selectRow(row);
|
|
|
|
//test we have 10 items selected
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().size(), selectedItems);
|
|
//test that all 10 items are in the same row
|
|
for (int i = 0; selectedItems > 0 && i < rowCount; ++i)
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().at(i).row(), row);
|
|
}
|
|
|
|
void tst_QTableView::selectColumn_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<QAbstractItemView::SelectionMode>("mode");
|
|
QTest::addColumn<QAbstractItemView::SelectionBehavior>("behavior");
|
|
QTest::addColumn<int>("selectedItems");
|
|
|
|
QTest::newRow("SingleSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 0;
|
|
|
|
QTest::newRow("SingleSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 0;
|
|
|
|
QTest::newRow("SingleSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::SingleSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 10;
|
|
|
|
QTest::newRow("MultiSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("MultiSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 0;
|
|
|
|
QTest::newRow("MultiSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::MultiSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 10;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 0;
|
|
|
|
QTest::newRow("ExtendedSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ExtendedSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 10;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectItems")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectItems
|
|
<< 10;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectRows")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectRows
|
|
<< 0;
|
|
|
|
QTest::newRow("ContiguousSelection and SelectColumns")
|
|
<< 10 << 10
|
|
<< 0
|
|
<< QAbstractItemView::ContiguousSelection
|
|
<< QAbstractItemView::SelectColumns
|
|
<< 10;
|
|
}
|
|
|
|
void tst_QTableView::selectColumn()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, column);
|
|
QFETCH(QAbstractItemView::SelectionMode, mode);
|
|
QFETCH(QAbstractItemView::SelectionBehavior, behavior);
|
|
QFETCH(int, selectedItems);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.setSelectionMode(mode);
|
|
view.setSelectionBehavior(behavior);
|
|
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0);
|
|
|
|
view.selectColumn(column);
|
|
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().size(), selectedItems);
|
|
for (int i = 0; selectedItems > 0 && i < columnCount; ++i)
|
|
QCOMPARE(view.selectionModel()->selectedIndexes().at(i).column(), column);
|
|
}
|
|
|
|
#if QT_CONFIG(shortcut)
|
|
|
|
void tst_QTableView::selectall_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<int>("hideRow");
|
|
QTest::addColumn<int>("hideColumn");
|
|
QTest::addColumn<int>("moveRowFrom");
|
|
QTest::addColumn<int>("moveRowTo");
|
|
QTest::addColumn<int>("moveColumnFrom");
|
|
QTest::addColumn<int>("moveColumnTo");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<int>("selectedCount"); // ### make this more detailed
|
|
|
|
QTest::newRow("no span, no hidden, no moved")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 100; // selected count
|
|
|
|
QTest::newRow("row span, no hidden, no moved")
|
|
<< 10 << 10 // dim
|
|
<< 1 << 1 // pos
|
|
<< 2 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 99; // selected count
|
|
|
|
QTest::newRow("col span, no hidden, no moved")
|
|
<< 10 << 10 // dim
|
|
<< 1 << 1 // pos
|
|
<< 1 << 2 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 99; // selected count
|
|
|
|
QTest::newRow("no span, row hidden, no moved")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 90; // selected count
|
|
|
|
QTest::newRow("no span, col hidden, no moved")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << 1 // hide
|
|
<< -1 << -1 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 90; // selected count
|
|
|
|
QTest::newRow("no span, no hidden, row moved")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< 1 << 3 // move row
|
|
<< -1 << -1 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 100; // selected count
|
|
|
|
QTest::newRow("no span, no hidden, col moved")
|
|
<< 10 << 10 // dim
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // move row
|
|
<< 1 << 3 // move col
|
|
<< 40 << 40 // cell size
|
|
<< 100; // selected count
|
|
}
|
|
|
|
void QTest__keySequence(QWidget* widget, const QKeySequence &ks)
|
|
{
|
|
for (int i = 0; i < ks.count(); ++i)
|
|
{
|
|
Qt::Key key = ks[i].key();
|
|
Qt::KeyboardModifiers modifiers = ks[i].keyboardModifiers();
|
|
QTest::keyClick(widget, key, modifiers);
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::selectall()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(int, moveRowFrom);
|
|
QFETCH(int, moveRowTo);
|
|
QFETCH(int, moveColumnFrom);
|
|
QFETCH(int, moveColumnTo);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(int, selectedCount);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QtTestTableView view;
|
|
view.show();
|
|
view.setModel(&model);
|
|
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
|
|
view.hideRow(hideRow);
|
|
view.hideColumn(hideColumn);
|
|
|
|
view.verticalHeader()->moveSection(moveRowFrom, moveRowTo);
|
|
view.horizontalHeader()->moveSection(moveColumnFrom, moveColumnTo);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
// try slot first
|
|
view.clearSelection();
|
|
QCOMPARE(view.selectedIndexes().size(), 0);
|
|
view.selectAll();
|
|
QCOMPARE(view.selectedIndexes().size(), selectedCount);
|
|
|
|
// try by key sequence
|
|
view.clearSelection();
|
|
QCOMPARE(view.selectedIndexes().size(), 0);
|
|
QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll));
|
|
QCOMPARE(view.selectedIndexes().size(), selectedCount);
|
|
|
|
// check again with no selection mode
|
|
view.clearSelection();
|
|
view.setSelectionMode(QAbstractItemView::NoSelection);
|
|
QCOMPARE(view.selectedIndexes().size(), 0);
|
|
QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll));
|
|
QCOMPARE(view.selectedIndexes().size(), 0);
|
|
}
|
|
|
|
#endif // QT_CONFIG(shortcut)
|
|
|
|
void tst_QTableView::visualRect_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("hideRow");
|
|
QTest::addColumn<int>("hideColumn");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<QRect>("expectedRect");
|
|
|
|
QTest::newRow("(0,0)")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 20 << 30
|
|
<< QRect(0, 0, 29, 19);
|
|
|
|
QTest::newRow("(0,0) hidden row")
|
|
<< 10 << 10
|
|
<< 0 << -1
|
|
<< 0 << 0
|
|
<< 20 << 30
|
|
<< QRect();
|
|
|
|
QTest::newRow("(0,0) hidden column")
|
|
<< 10 << 10
|
|
<< -1 << 0
|
|
<< 0 << 0
|
|
<< 20 << 30
|
|
<< QRect();
|
|
|
|
QTest::newRow("(0,0) hidden row and column")
|
|
<< 10 << 10
|
|
<< 0 << 0
|
|
<< 0 << 0
|
|
<< 20 << 30
|
|
<< QRect();
|
|
|
|
QTest::newRow("(0,0) out of bounds")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 20 << 20
|
|
<< 20 << 30
|
|
<< QRect();
|
|
|
|
QTest::newRow("(5,5), hidden row")
|
|
<< 10 << 10
|
|
<< 5 << -1
|
|
<< 5 << 5
|
|
<< 20 << 30
|
|
<< QRect();
|
|
|
|
QTest::newRow("(9,9)")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 9 << 9
|
|
<< 20 << 30
|
|
<< QRect(30*9, 20*9, 29, 19);
|
|
}
|
|
|
|
void tst_QTableView::visualRect()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, hideRow);
|
|
QFETCH(int, hideColumn);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(QRect, expectedRect);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.horizontalHeader()->setMinimumSectionSize(0);
|
|
view.verticalHeader()->setMinimumSectionSize(0);
|
|
// Make sure that it has 1 pixel between each cell.
|
|
view.setGridStyle(Qt::SolidLine);
|
|
for (int i = 0; i < view.verticalHeader()->count(); ++i)
|
|
view.verticalHeader()->resizeSection(i, rowHeight);
|
|
for (int i = 0; i < view.horizontalHeader()->count(); ++i)
|
|
view.horizontalHeader()->resizeSection(i, columnWidth);
|
|
|
|
view.hideRow(hideRow);
|
|
view.hideColumn(hideColumn);
|
|
|
|
QRect rect = view.visualRect(model.index(row, column));
|
|
QCOMPARE(rect, expectedRect);
|
|
}
|
|
|
|
void tst_QTableView::fetchMore()
|
|
{
|
|
QtTestTableModel model(64, 64);
|
|
|
|
model.can_fetch_more = true;
|
|
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.show();
|
|
|
|
QCOMPARE(model.fetch_more_count, 0);
|
|
view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
|
|
QVERIFY(model.fetch_more_count > 0);
|
|
|
|
model.fetch_more_count = 0; //reset
|
|
view.scrollToTop();
|
|
QCOMPARE(model.fetch_more_count, 0);
|
|
|
|
view.scrollToBottom();
|
|
QVERIFY(model.fetch_more_count > 0);
|
|
|
|
model.fetch_more_count = 0; //reset
|
|
view.scrollToTop();
|
|
view.setCurrentIndex(model.index(0, 0));
|
|
QCOMPARE(model.fetch_more_count, 0);
|
|
|
|
for (int i = 0; i < 64; ++i)
|
|
QTest::keyClick(&view, Qt::Key_Down);
|
|
QCOMPARE(view.currentIndex(), model.index(63, 0));
|
|
QVERIFY(model.fetch_more_count > 0);
|
|
}
|
|
|
|
void tst_QTableView::setHeaders()
|
|
{
|
|
QTableView view;
|
|
|
|
// Make sure we don't delete ourselves
|
|
view.setVerticalHeader(view.verticalHeader());
|
|
view.verticalHeader()->count();
|
|
view.setHorizontalHeader(view.horizontalHeader());
|
|
view.horizontalHeader()->count();
|
|
|
|
// Try passing around a header without it being deleted
|
|
QTableView view2;
|
|
view2.setVerticalHeader(view.verticalHeader());
|
|
view2.setHorizontalHeader(view.horizontalHeader());
|
|
view.setHorizontalHeader(new QHeaderView(Qt::Horizontal));
|
|
view.setVerticalHeader(new QHeaderView(Qt::Vertical));
|
|
view2.verticalHeader()->count();
|
|
view2.horizontalHeader()->count();
|
|
|
|
}
|
|
|
|
void tst_QTableView::resizeRowsToContents_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<bool>("showGrid");
|
|
QTest::addColumn<int>("cellWidth");
|
|
QTest::addColumn<int>("cellHeight");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
|
|
QTest::newRow("10x10 grid shown 40x40")
|
|
<< 10 << 10 << false << 40 << 40 << 40 << 40;
|
|
|
|
QTest::newRow("10x10 grid not shown 40x40")
|
|
<< 10 << 10 << true << 40 << 40 << 41 << 41;
|
|
}
|
|
|
|
void tst_QTableView::resizeRowsToContents()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(bool, showGrid);
|
|
QFETCH(int, cellWidth);
|
|
QFETCH(int, cellHeight);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
Q_UNUSED(columnWidth);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QtTestTableView view;
|
|
QtTestItemDelegate delegate;
|
|
|
|
view.setModel(&model);
|
|
view.setItemDelegate(&delegate);
|
|
view.setShowGrid(showGrid); // the grid will add to the row height
|
|
|
|
delegate.hint = QSize(cellWidth, cellHeight);
|
|
|
|
QSignalSpy resizedSpy(view.verticalHeader(), &QHeaderView::sectionResized);
|
|
view.resizeRowsToContents();
|
|
|
|
QCOMPARE(resizedSpy.size(), model.rowCount());
|
|
for (int r = 0; r < model.rowCount(); ++r)
|
|
QCOMPARE(view.rowHeight(r), rowHeight);
|
|
}
|
|
|
|
void tst_QTableView::resizeColumnsToContents_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<bool>("showGrid");
|
|
QTest::addColumn<int>("cellWidth");
|
|
QTest::addColumn<int>("cellHeight");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
|
|
QTest::newRow("10x10 grid not shown 60x60")
|
|
<< 10 << 10 << false << 60 << 60 << 60 << 60;
|
|
|
|
QTest::newRow("10x10 grid shown 60x60")
|
|
<< 10 << 10 << true << 60 << 60 << 61 << 61;
|
|
}
|
|
|
|
void tst_QTableView::resizeColumnsToContents()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(bool, showGrid);
|
|
QFETCH(int, cellWidth);
|
|
QFETCH(int, cellHeight);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
Q_UNUSED(rowHeight);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QtTestTableView view;
|
|
QtTestItemDelegate delegate;
|
|
|
|
view.setModel(&model);
|
|
view.setItemDelegate(&delegate);
|
|
view.setShowGrid(showGrid); // the grid will add to the row height
|
|
|
|
delegate.hint = QSize(cellWidth, cellHeight);
|
|
|
|
QSignalSpy resizedSpy(view.horizontalHeader(), &QHeaderView::sectionResized);
|
|
view.resizeColumnsToContents();
|
|
|
|
QCOMPARE(resizedSpy.size(), model.columnCount());
|
|
for (int c = 0; c < model.columnCount(); ++c)
|
|
QCOMPARE(view.columnWidth(c), columnWidth);
|
|
}
|
|
|
|
void tst_QTableView::rowViewportPosition_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<QAbstractItemView::ScrollMode>("verticalScrollMode");
|
|
QTest::addColumn<int>("verticalScrollValue");
|
|
QTest::addColumn<int>("rowViewportPosition");
|
|
|
|
QTest::newRow("row 0, scroll per item 0")
|
|
<< 100 << 40 << 0 << QAbstractItemView::ScrollPerItem << 0 << 0;
|
|
|
|
QTest::newRow("row 1, scroll per item, 0")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerItem << 0 << 1 * 40;
|
|
|
|
QTest::newRow("row 1, scroll per item, 1")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerItem << 1 << 0;
|
|
|
|
QTest::newRow("row 5, scroll per item, 0")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerItem << 0 << 5 * 40;
|
|
|
|
QTest::newRow("row 5, scroll per item, 5")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerItem << 5 << 0;
|
|
|
|
QTest::newRow("row 9, scroll per item, 0")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerItem << 0 << 9 * 40;
|
|
|
|
QTest::newRow("row 9, scroll per item, 5")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerItem << 5 << 4 * 40;
|
|
|
|
QTest::newRow("row 0, scroll per pixel 0")
|
|
<< 100 << 40 << 0 << QAbstractItemView::ScrollPerPixel << 0 << 0;
|
|
|
|
QTest::newRow("row 1, scroll per pixel, 0")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerPixel << 0 << 1 * 40;
|
|
|
|
QTest::newRow("row 1, scroll per pixel, 1")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerPixel << 1 * 40 << 0;
|
|
|
|
QTest::newRow("row 5, scroll per pixel, 0")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerPixel << 0 << 5 * 40;
|
|
|
|
QTest::newRow("row 5, scroll per pixel, 5")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerPixel << 5 * 40 << 0;
|
|
|
|
QTest::newRow("row 9, scroll per pixel, 0")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerPixel << 0 << 9 * 40;
|
|
|
|
QTest::newRow("row 9, scroll per pixel, 5")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerPixel << 5 * 40 << 4 * 40;
|
|
}
|
|
|
|
void tst_QTableView::rowViewportPosition()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, row);
|
|
QFETCH(QAbstractItemView::ScrollMode, verticalScrollMode);
|
|
QFETCH(int, verticalScrollValue);
|
|
QFETCH(int, rowViewportPosition);
|
|
|
|
QtTestTableModel model(rowCount, 1);
|
|
QtTestTableView view;
|
|
setFrameless(&view);
|
|
view.resize(100, 2 * rowHeight);
|
|
view.show();
|
|
|
|
view.setModel(&model);
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
|
|
view.setVerticalScrollMode(verticalScrollMode);
|
|
view.verticalScrollBar()->setValue(verticalScrollValue);
|
|
|
|
QCOMPARE(view.rowViewportPosition(row), rowViewportPosition);
|
|
}
|
|
|
|
void tst_QTableView::rowAt_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<IntList>("hiddenRows");
|
|
QTest::addColumn<int>("coordinate");
|
|
QTest::addColumn<int>("row");
|
|
|
|
QTest::newRow("row at 100") << 5 << 40 << IntList() << 100 << 2;
|
|
QTest::newRow("row at 180") << 5 << 40 << IntList() << 180 << 4;
|
|
QTest::newRow("row at 20") << 5 << 40 << IntList() << 20 << 0;
|
|
|
|
// ### expand the dataset to include hidden rows
|
|
}
|
|
|
|
void tst_QTableView::rowAt()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(IntList, hiddenRows);
|
|
QFETCH(int, coordinate);
|
|
QFETCH(int, row);
|
|
|
|
QtTestTableModel model(rowCount, 1);
|
|
QtTestTableView view;
|
|
view.resize(100, 2 * rowHeight);
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
|
|
for (int i = 0; i < hiddenRows.size(); ++i)
|
|
view.hideRow(hiddenRows.at(i));
|
|
|
|
QCOMPARE(view.rowAt(coordinate), row);
|
|
}
|
|
|
|
void tst_QTableView::rowHeight_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<IntList>("rowHeights");
|
|
QTest::addColumn<BoolList>("hiddenRows");
|
|
|
|
QTest::newRow("increasing")
|
|
<< 5
|
|
<< (IntList() << 20 << 30 << 40 << 50 << 60)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("decreasing")
|
|
<< 5
|
|
<< (IntList() << 60 << 50 << 40 << 30 << 20)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("random")
|
|
<< 5
|
|
<< (IntList() << 87 << 34 << 68 << 91 << 27)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
// ### expand the dataset to include hidden rows
|
|
}
|
|
|
|
void tst_QTableView::rowHeight()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(IntList, rowHeights);
|
|
QFETCH(BoolList, hiddenRows);
|
|
|
|
QtTestTableModel model(rowCount, 1);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int r = 0; r < rowCount; ++r) {
|
|
view.setRowHeight(r, rowHeights.at(r));
|
|
view.setRowHidden(r, hiddenRows.at(r));
|
|
}
|
|
|
|
for (int r = 0; r < rowCount; ++r) {
|
|
if (hiddenRows.at(r))
|
|
QCOMPARE(view.rowHeight(r), 0);
|
|
else
|
|
QCOMPARE(view.rowHeight(r), rowHeights.at(r));
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::columnViewportPosition_data()
|
|
{
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<QAbstractItemView::ScrollMode>("horizontalScrollMode");
|
|
QTest::addColumn<int>("horizontalScrollValue");
|
|
QTest::addColumn<int>("columnViewportPosition");
|
|
|
|
QTest::newRow("column 0, scroll per item 0")
|
|
<< 100 << 40 << 0 << QAbstractItemView::ScrollPerItem << 0 << 0;
|
|
|
|
QTest::newRow("column 1, scroll per item, 0")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerItem << 0 << 1 * 40;
|
|
|
|
QTest::newRow("column 1, scroll per item, 1")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerItem << 1 << 0;
|
|
|
|
QTest::newRow("column 5, scroll per item, 0")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerItem << 0 << 5 * 40;
|
|
|
|
QTest::newRow("column 5, scroll per item, 5")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerItem << 5 << 0;
|
|
|
|
QTest::newRow("column 9, scroll per item, 0")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerItem << 0 << 9 * 40;
|
|
|
|
QTest::newRow("column 9, scroll per item, 5")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerItem << 5 << 4 * 40;
|
|
|
|
QTest::newRow("column 0, scroll per pixel 0")
|
|
<< 100 << 40 << 0 << QAbstractItemView::ScrollPerPixel << 0 << 0;
|
|
|
|
QTest::newRow("column 1, scroll per pixel 0")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerPixel << 0 << 1 * 40;
|
|
|
|
QTest::newRow("column 1, scroll per pixel 1")
|
|
<< 100 << 40 << 1 << QAbstractItemView::ScrollPerPixel << 1 * 40 << 0;
|
|
|
|
QTest::newRow("column 5, scroll per pixel 0")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerPixel << 0 << 5 * 40;
|
|
|
|
QTest::newRow("column 5, scroll per pixel 5")
|
|
<< 100 << 40 << 5 << QAbstractItemView::ScrollPerPixel << 5 * 40 << 0;
|
|
|
|
QTest::newRow("column 9, scroll per pixel 0")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerPixel << 0 << 9 * 40;
|
|
|
|
QTest::newRow("column 9, scroll per pixel 5")
|
|
<< 100 << 40 << 9 << QAbstractItemView::ScrollPerPixel << 5 * 40 << 4 * 40;
|
|
}
|
|
|
|
void tst_QTableView::columnViewportPosition()
|
|
{
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(int, column);
|
|
QFETCH(QAbstractItemView::ScrollMode, horizontalScrollMode);
|
|
QFETCH(int, horizontalScrollValue);
|
|
QFETCH(int, columnViewportPosition);
|
|
|
|
QtTestTableModel model(1, columnCount);
|
|
QtTestTableView view;
|
|
setFrameless(&view);
|
|
view.resize(2 * columnWidth, 100);
|
|
view.show();
|
|
|
|
view.setModel(&model);
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
view.setHorizontalScrollMode(horizontalScrollMode);
|
|
view.horizontalScrollBar()->setValue(horizontalScrollValue);
|
|
|
|
QCOMPARE(view.columnViewportPosition(column), columnViewportPosition);
|
|
}
|
|
|
|
void tst_QTableView::columnAt_data()
|
|
{
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<IntList>("hiddenColumns");
|
|
QTest::addColumn<int>("coordinate");
|
|
QTest::addColumn<int>("column");
|
|
|
|
QTest::newRow("column at 100") << 5 << 40 << IntList() << 100 << 2;
|
|
QTest::newRow("column at 180") << 5 << 40 << IntList() << 180 << 4;
|
|
QTest::newRow("column at 20") << 5 << 40 << IntList() << 20 << 0;
|
|
|
|
// ### expand the dataset to include hidden coumns
|
|
}
|
|
|
|
void tst_QTableView::columnAt()
|
|
{
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(IntList, hiddenColumns);
|
|
QFETCH(int, coordinate);
|
|
QFETCH(int, column);
|
|
|
|
QtTestTableModel model(1, columnCount);
|
|
QtTestTableView view;
|
|
view.resize(2 * columnWidth, 100);
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
for (int i = 0; i < hiddenColumns.size(); ++i)
|
|
view.hideColumn(hiddenColumns.at(i));
|
|
|
|
QCOMPARE(view.columnAt(coordinate), column);
|
|
}
|
|
|
|
void tst_QTableView::columnWidth_data()
|
|
{
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<IntList>("columnWidths");
|
|
QTest::addColumn<BoolList>("hiddenColumns");
|
|
|
|
QTest::newRow("increasing")
|
|
<< 5
|
|
<< (IntList() << 20 << 30 << 40 << 50 << 60)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("decreasing")
|
|
<< 5
|
|
<< (IntList() << 60 << 50 << 40 << 30 << 20)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("random")
|
|
<< 5
|
|
<< (IntList() << 87 << 34 << 68 << 91 << 27)
|
|
<< (BoolList() << false << false << false << false << false);
|
|
|
|
// ### expand the dataset to include hidden columns
|
|
}
|
|
|
|
void tst_QTableView::columnWidth()
|
|
{
|
|
QFETCH(int, columnCount);
|
|
QFETCH(IntList, columnWidths);
|
|
QFETCH(BoolList, hiddenColumns);
|
|
|
|
QtTestTableModel model(1, columnCount);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int c = 0; c < columnCount; ++c) {
|
|
view.setColumnWidth(c, columnWidths.at(c));
|
|
view.setColumnHidden(c, hiddenColumns.at(c));
|
|
}
|
|
|
|
for (int c = 0; c < columnCount; ++c) {
|
|
if (hiddenColumns.at(c))
|
|
QCOMPARE(view.columnWidth(c), 0);
|
|
else
|
|
QCOMPARE(view.columnWidth(c), columnWidths.at(c));
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::hiddenRow_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<BoolList>("hiddenRows");
|
|
|
|
QTest::newRow("first hidden")
|
|
<< 5 << (BoolList() << true << false << false << false << false);
|
|
|
|
QTest::newRow("last hidden")
|
|
<< 5 << (BoolList() << false << false << false << false << true);
|
|
|
|
QTest::newRow("none hidden")
|
|
<< 5 << (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("all hidden")
|
|
<< 5 << (BoolList() << true << true << true << true << true);
|
|
}
|
|
|
|
void tst_QTableView::hiddenRow()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(BoolList, hiddenRows);
|
|
|
|
|
|
QtTestTableModel model(rowCount, 1);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
QVERIFY(!view.isRowHidden(r));
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHidden(r, hiddenRows.at(r));
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
QCOMPARE(view.isRowHidden(r), hiddenRows.at(r));
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHidden(r, false);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
QVERIFY(!view.isRowHidden(r));
|
|
}
|
|
|
|
void tst_QTableView::hiddenColumn_data()
|
|
{
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<BoolList>("hiddenColumns");
|
|
|
|
QTest::newRow("first hidden")
|
|
<< 5 << (BoolList() << true << false << false << false << false);
|
|
|
|
QTest::newRow("last hidden")
|
|
<< 5 << (BoolList() << false << false << false << false << true);
|
|
|
|
QTest::newRow("none hidden")
|
|
<< 5 << (BoolList() << false << false << false << false << false);
|
|
|
|
QTest::newRow("all hidden")
|
|
<< 5 << (BoolList() << true << true << true << true << true);
|
|
}
|
|
|
|
void tst_QTableView::hiddenColumn()
|
|
{
|
|
QFETCH(int, columnCount);
|
|
QFETCH(BoolList, hiddenColumns);
|
|
|
|
QtTestTableModel model(1, columnCount);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
QVERIFY(!view.isColumnHidden(c));
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnHidden(c, hiddenColumns.at(c));
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
QCOMPARE(view.isColumnHidden(c), hiddenColumns.at(c));
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnHidden(c, false);
|
|
|
|
for (int c = 0; c < columnCount; ++c)
|
|
QVERIFY(!view.isColumnHidden(c));
|
|
}
|
|
|
|
void tst_QTableView::sortingEnabled_data()
|
|
{
|
|
// QTest::addColumn<int>("columnCount");
|
|
}
|
|
|
|
void tst_QTableView::sortingEnabled()
|
|
{
|
|
// QFETCH(int, columnCount);
|
|
}
|
|
|
|
void tst_QTableView::sortByColumn_data()
|
|
{
|
|
QTest::addColumn<bool>("sortingEnabled");
|
|
QTest::newRow("sorting enabled") << true;
|
|
QTest::newRow("sorting disabled") << false;
|
|
}
|
|
|
|
// Checks sorting and that sortByColumn also sets the sortIndicator
|
|
void tst_QTableView::sortByColumn()
|
|
{
|
|
QFETCH(bool, sortingEnabled);
|
|
QTableView view;
|
|
QStandardItemModel model(4, 2);
|
|
QSortFilterProxyModel sfpm; // default QStandardItemModel does not support 'unsorted' state
|
|
sfpm.setSourceModel(&model);
|
|
model.setItem(0, 0, new QStandardItem("b"));
|
|
model.setItem(1, 0, new QStandardItem("d"));
|
|
model.setItem(2, 0, new QStandardItem("c"));
|
|
model.setItem(3, 0, new QStandardItem("a"));
|
|
model.setItem(0, 1, new QStandardItem("e"));
|
|
model.setItem(1, 1, new QStandardItem("g"));
|
|
model.setItem(2, 1, new QStandardItem("h"));
|
|
model.setItem(3, 1, new QStandardItem("f"));
|
|
|
|
view.setSortingEnabled(sortingEnabled);
|
|
view.setModel(&sfpm);
|
|
view.show();
|
|
|
|
view.sortByColumn(1, Qt::DescendingOrder);
|
|
QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 1);
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 0)).toString(), QString::fromLatin1("c"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 0)).toString(), QString::fromLatin1("d"));
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 1)).toString(), QString::fromLatin1("h"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 1)).toString(), QString::fromLatin1("g"));
|
|
|
|
view.sortByColumn(0, Qt::AscendingOrder);
|
|
QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 0);
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 0)).toString(), QString::fromLatin1("a"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 0)).toString(), QString::fromLatin1("b"));
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 1)).toString(), QString::fromLatin1("f"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 1)).toString(), QString::fromLatin1("e"));
|
|
|
|
view.sortByColumn(-1, Qt::AscendingOrder);
|
|
QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), -1);
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 0)).toString(), QString::fromLatin1("b"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 0)).toString(), QString::fromLatin1("d"));
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 1)).toString(), QString::fromLatin1("e"));
|
|
QCOMPARE(view.model()->data(view.model()->index(1, 1)).toString(), QString::fromLatin1("g"));
|
|
|
|
// a new 'sortByColumn()' should do a re-sort (e.g. due to the data changed), QTBUG-86268
|
|
view.setModel(&model);
|
|
view.sortByColumn(0, Qt::AscendingOrder);
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 0)).toString(), QString::fromLatin1("a"));
|
|
model.setItem(0, 0, new QStandardItem("x"));
|
|
view.sortByColumn(0, Qt::AscendingOrder);
|
|
QCOMPARE(view.model()->data(view.model()->index(0, 0)).toString(), QString::fromLatin1("b"));
|
|
}
|
|
|
|
void tst_QTableView::scrollTo_data()
|
|
{
|
|
QTest::addColumn<QAbstractItemView::ScrollMode>("verticalScrollMode");
|
|
QTest::addColumn<QAbstractItemView::ScrollMode>("horizontalScrollMode");
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
QTest::addColumn<int>("hiddenRow");
|
|
QTest::addColumn<int>("hiddenColumn");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<int>("horizontalScroll");
|
|
QTest::addColumn<int>("verticalScroll");
|
|
QTest::addColumn<QAbstractItemView::ScrollHint>("scrollHint");
|
|
QTest::addColumn<int>("expectedHorizontalScroll");
|
|
QTest::addColumn<int>("expectedVerticalScroll");
|
|
|
|
QTest::newRow("no hidden, no span, no scroll, per item")
|
|
<< QAbstractItemView::ScrollPerItem
|
|
<< QAbstractItemView::ScrollPerItem
|
|
<< 10 << 10 // table
|
|
<< 80 << 80 // size
|
|
<< -1 << -1 // hide
|
|
<< 0 << 0 // cell
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< QAbstractItemView::PositionAtTop
|
|
<< 0 << 0; // expected
|
|
|
|
QTest::newRow("no hidden, no span, no scroll, per pixel")
|
|
<< QAbstractItemView::ScrollPerPixel
|
|
<< QAbstractItemView::ScrollPerPixel
|
|
<< 10 << 10 // table
|
|
<< 80 << 80 // size
|
|
<< -1 << -1 // hide
|
|
<< 0 << 0 // cell
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< QAbstractItemView::PositionAtTop
|
|
<< 0 << 0; // expected
|
|
|
|
QTest::newRow("hidden, no span, no scroll, per item")
|
|
<< QAbstractItemView::ScrollPerItem
|
|
<< QAbstractItemView::ScrollPerItem
|
|
<< 10 << 10 // table
|
|
<< 80 << 80 // size
|
|
<< 3 << 3 // hide
|
|
<< 5 << 5 // cell
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< QAbstractItemView::PositionAtTop
|
|
<< 4 << 4; // expected
|
|
}
|
|
|
|
void tst_QTableView::scrollTo()
|
|
{
|
|
QFETCH(QAbstractItemView::ScrollMode, horizontalScrollMode);
|
|
QFETCH(QAbstractItemView::ScrollMode, verticalScrollMode);
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(int, hiddenRow);
|
|
QFETCH(int, hiddenColumn);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(int, horizontalScroll);
|
|
QFETCH(int, verticalScroll);
|
|
QFETCH(QAbstractItemView::ScrollHint, scrollHint);
|
|
QFETCH(int, expectedHorizontalScroll);
|
|
QFETCH(int, expectedVerticalScroll);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QWidget toplevel;
|
|
setFrameless(&toplevel);
|
|
QtTestTableView view(&toplevel);
|
|
|
|
toplevel.show();
|
|
// resizing to this size will ensure that there can ONLY_BE_ONE_CELL inside the view.
|
|
QSize forcedSize(columnWidth * 2, rowHeight * 2);
|
|
view.resize(forcedSize);
|
|
QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
|
|
QTRY_COMPARE(view.size(), forcedSize);
|
|
|
|
view.setModel(&model);
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
view.hideRow(hiddenRow);
|
|
view.hideColumn(hiddenColumn);
|
|
view.setHorizontalScrollMode(horizontalScrollMode);
|
|
view.setVerticalScrollMode(verticalScrollMode);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
view.horizontalScrollBar()->setValue(horizontalScroll);
|
|
view.verticalScrollBar()->setValue(verticalScroll);
|
|
|
|
QModelIndex index = model.index(row, column);
|
|
QVERIFY(index.isValid());
|
|
view.scrollTo(index, scrollHint);
|
|
QTRY_COMPARE(view.verticalScrollBar()->value(), expectedVerticalScroll);
|
|
QTRY_COMPARE(view.horizontalScrollBar()->value(), expectedHorizontalScroll);
|
|
}
|
|
|
|
void tst_QTableView::indexAt_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
|
|
QTest::addColumn<int>("rowHeight");
|
|
QTest::addColumn<int>("columnWidth");
|
|
|
|
QTest::addColumn<int>("hiddenRow");
|
|
QTest::addColumn<int>("hiddenColumn");
|
|
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<int>("horizontalScroll");
|
|
QTest::addColumn<int>("verticalScroll");
|
|
QTest::addColumn<int>("x");
|
|
QTest::addColumn<int>("y");
|
|
QTest::addColumn<int>("expectedRow");
|
|
QTest::addColumn<int>("expectedColumn");
|
|
|
|
QTest::newRow("no hidden, no span, no scroll, (20,20)")
|
|
<< 10 << 10 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< 20 << 20 // point
|
|
<< 0 << 0; // expected
|
|
|
|
QTest::newRow("row hidden, no span, no scroll, at (20,20)")
|
|
<< 10 << 10 // dim
|
|
<< 40 << 40 // size
|
|
<< 0 << -1 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< 20 << 20 // point
|
|
<< 1 << 0; // expected
|
|
|
|
QTest::newRow("col hidden, no span, no scroll, at (20,20)")
|
|
<< 10 << 10 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << 0 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< 20 << 20 // point
|
|
<< 0 << 1; // expected
|
|
|
|
QTest::newRow("no hidden, row span, no scroll, at (60,20)")
|
|
<< 10 << 10 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< 0 << 0 // pos
|
|
<< 2 << 1 // span
|
|
<< 0 << 0 // scroll
|
|
<< 20 << 60 // point
|
|
<< 0 << 0; // expected
|
|
|
|
|
|
QTest::newRow("no hidden, col span, no scroll, at (60,20)")
|
|
<< 10 << 10 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< 0 << 0 // pos
|
|
<< 1 << 2 // span
|
|
<< 0 << 0 // scroll
|
|
<< 60 << 20 // point
|
|
<< 0 << 0; // expected
|
|
|
|
QTest::newRow("no hidden, no span, scroll (5,0), at (20,20)")
|
|
<< 20 << 20 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 5 << 0 // scroll
|
|
<< 20 << 20 // point
|
|
<< 0 << 5; // expected
|
|
|
|
QTest::newRow("no hidden, no span, scroll (0,5), at (20,20)")
|
|
<< 20 << 20 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 0 << 5 // scroll
|
|
<< 20 << 20 // point
|
|
<< 5 << 0; // expected
|
|
|
|
QTest::newRow("no hidden, no span, scroll (5,5), at (20,20)")
|
|
<< 20 << 20 // dim
|
|
<< 40 << 40 // size
|
|
<< -1 << -1 // hide
|
|
<< -1 << -1 // pos
|
|
<< 1 << 1 // span
|
|
<< 5 << 5 // scroll
|
|
<< 20 << 20 // point
|
|
<< 5 << 5; // expected
|
|
}
|
|
|
|
void tst_QTableView::indexAt()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, rowHeight);
|
|
QFETCH(int, columnWidth);
|
|
QFETCH(int, hiddenRow);
|
|
QFETCH(int, hiddenColumn);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(int, horizontalScroll);
|
|
QFETCH(int, verticalScroll);
|
|
QFETCH(int, x);
|
|
QFETCH(int, y);
|
|
QFETCH(int, expectedRow);
|
|
QFETCH(int, expectedColumn);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QWidget toplevel;
|
|
QtTestTableView view(&toplevel);
|
|
|
|
toplevel.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
|
|
|
|
//some styles change the scroll mode in their polish
|
|
view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
view.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
|
|
view.setModel(&model);
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
view.hideRow(hiddenRow);
|
|
view.hideColumn(hiddenColumn);
|
|
|
|
for (int r = 0; r < rowCount; ++r)
|
|
view.setRowHeight(r, rowHeight);
|
|
for (int c = 0; c < columnCount; ++c)
|
|
view.setColumnWidth(c, columnWidth);
|
|
|
|
view.horizontalScrollBar()->setValue(horizontalScroll);
|
|
view.verticalScrollBar()->setValue(verticalScroll);
|
|
|
|
QModelIndex index = view.indexAt(QPoint(x, y));
|
|
QTRY_COMPARE(index.row(), expectedRow);
|
|
QTRY_COMPARE(index.column(), expectedColumn);
|
|
}
|
|
|
|
void tst_QTableView::span_data()
|
|
{
|
|
QTest::addColumn<int>("rowCount");
|
|
QTest::addColumn<int>("columnCount");
|
|
QTest::addColumn<int>("hiddenRow");
|
|
QTest::addColumn<int>("hiddenColumn");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<int>("expectedRowSpan");
|
|
QTest::addColumn<int>("expectedColumnSpan");
|
|
QTest::addColumn<bool>("clear");
|
|
|
|
QTest::newRow("top left 2x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 2 << 2
|
|
<< 2 << 2
|
|
<< false;
|
|
|
|
QTest::newRow("top left 1x2")
|
|
<< 10 << 10
|
|
<< 3 << 3
|
|
<< 0 << 0
|
|
<< 1 << 2
|
|
<< 1 << 2
|
|
<< false;
|
|
|
|
QTest::newRow("top left 2x1")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 2 << 1
|
|
<< 2 << 1
|
|
<< false;
|
|
|
|
/* This makes no sens.
|
|
QTest::newRow("top left 2x0")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 2 << 0
|
|
<< 2 << 0
|
|
<< false;
|
|
|
|
QTest::newRow("top left 0x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 0 << 2
|
|
<< 0 << 2
|
|
<< false;*/
|
|
|
|
QTest::newRow("invalid 2x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< -1 << -1
|
|
<< 2 << 2
|
|
<< 1 << 1
|
|
<< false;
|
|
|
|
QTest::newRow("top left 2x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 0 << 0
|
|
<< 2 << 2
|
|
<< 2 << 2
|
|
<< false;
|
|
|
|
QTest::newRow("bottom right 2x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 8 << 8
|
|
<< 2 << 2
|
|
<< 2 << 2
|
|
<< false;
|
|
|
|
QTest::newRow("invalid span 2x2")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 8 << 8
|
|
<< 2 << 2
|
|
<< 2 << 2
|
|
<< false;
|
|
|
|
QTest::newRow("invalid span 3x3")
|
|
<< 10 << 10
|
|
<< -1 << -1
|
|
<< 6 << 6
|
|
<< 3 << 3
|
|
<< 2 << 3
|
|
<< true;
|
|
|
|
}
|
|
|
|
void tst_QTableView::span()
|
|
{
|
|
QFETCH(int, rowCount);
|
|
QFETCH(int, columnCount);
|
|
QFETCH(int, hiddenRow);
|
|
QFETCH(int, hiddenColumn);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(int, expectedRowSpan);
|
|
QFETCH(int, expectedColumnSpan);
|
|
QFETCH(bool, clear);
|
|
|
|
QtTestTableModel model(rowCount, columnCount);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
view.show();
|
|
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
if (clear) {
|
|
model.removeLastRow();
|
|
model.removeLastRow();
|
|
view.update();
|
|
}
|
|
|
|
view.hideRow(hiddenRow);
|
|
view.hideColumn(hiddenColumn);
|
|
view.show();
|
|
|
|
QCOMPARE(view.rowSpan(row, column), expectedRowSpan);
|
|
QCOMPARE(view.columnSpan(row, column), expectedColumnSpan);
|
|
|
|
if (hiddenRow > -1) {
|
|
QModelIndex hidden = model.index(hiddenRow, columnCount - 1);
|
|
QVERIFY(view.isIndexHidden(hidden));
|
|
}
|
|
|
|
if (hiddenColumn > -1) {
|
|
QModelIndex hidden = model.index(rowCount - 1, hiddenColumn);
|
|
QVERIFY(view.isIndexHidden(hidden));
|
|
}
|
|
|
|
view.clearSpans();
|
|
QCOMPARE(view.rowSpan(row, column), 1);
|
|
QCOMPARE(view.columnSpan(row, column), 1);
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::spans_data()
|
|
{
|
|
QTest::addColumn<int>("rows");
|
|
QTest::addColumn<int>("columns");
|
|
QTest::addColumn<SpanList>("spans");
|
|
QTest::addColumn<bool>("hideRowLastRowOfFirstSpan");
|
|
QTest::addColumn<QPoint>("pos");
|
|
QTest::addColumn<int>("expectedRowSpan");
|
|
QTest::addColumn<int>("expectedColumnSpan");
|
|
|
|
QTest::newRow("1x3 span, query 3,0")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(3, 0, 1, 3))
|
|
<< false //no hidden row
|
|
<< QPoint(3, 0)
|
|
<< 1
|
|
<< 3;
|
|
|
|
QTest::newRow("1x3 span, query 3,1")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(3, 0, 1, 3))
|
|
<< false //no hidden row
|
|
<< QPoint(3, 1)
|
|
<< 1
|
|
<< 3;
|
|
|
|
QTest::newRow("1x3 span, query 3,2")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(3, 0, 1, 3))
|
|
<< false //no hidden row
|
|
<< QPoint(3, 2)
|
|
<< 1
|
|
<< 3;
|
|
|
|
QTest::newRow("two 1x2 spans at the same column, query at 3,0")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
|
|
<< false //no hidden row
|
|
<< QPoint(3, 0)
|
|
<< 1
|
|
<< 2;
|
|
|
|
QTest::newRow("two 1x2 spans at the same column, query at 4,0")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(3, 0, 1, 2) << QRect(4, 0, 1, 2))
|
|
<< false //no hidden row
|
|
<< QPoint(4, 0)
|
|
<< 1
|
|
<< 2;
|
|
|
|
QTest::newRow("how to order spans (1,1)")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
|
|
<< false //no hidden row
|
|
<< QPoint(1, 1)
|
|
<< 3
|
|
<< 1;
|
|
|
|
QTest::newRow("how to order spans (2,1)")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
|
|
<< false //no hidden row
|
|
<< QPoint(2, 1)
|
|
<< 3
|
|
<< 1;
|
|
|
|
QTest::newRow("how to order spans (3,1)")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
|
|
<< false //no hidden row
|
|
<< QPoint(3, 1)
|
|
<< 3
|
|
<< 1;
|
|
|
|
QTest::newRow("how to order spans (1,2)")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
|
|
<< false //no hidden row
|
|
<< QPoint(1, 2)
|
|
<< 2
|
|
<< 1;
|
|
|
|
QTest::newRow("how to order spans (2,2)")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(1, 1, 3, 1) << QRect(1, 2, 2, 1))
|
|
<< false //no hidden row
|
|
<< QPoint(2, 2)
|
|
<< 2
|
|
<< 1;
|
|
|
|
QTest::newRow("spans with hidden rows")
|
|
<< 3 << 2
|
|
<< (SpanList() << QRect(0, 0, 2, 2) << QRect(2, 0, 1, 2))
|
|
<< true //we hide the last row of the first span
|
|
<< QPoint(2, 0)
|
|
<< 1
|
|
<< 2;
|
|
|
|
QTest::newRow("QTBUG-6004: No failing assertion, then it passes.")
|
|
<< 5 << 5
|
|
<< (SpanList() << QRect(0, 0, 2, 2) << QRect(0, 0, 1, 1))
|
|
<< false
|
|
<< QPoint(0, 0)
|
|
<< 1
|
|
<< 1;
|
|
|
|
QTest::newRow("QTBUG-6004 (follow-up): No failing assertion, then it passes.")
|
|
<< 10 << 10
|
|
<< (SpanList() << QRect(2, 2, 1, 3) << QRect(2, 2, 1, 1))
|
|
<< false
|
|
<< QPoint(0, 0)
|
|
<< 1
|
|
<< 1;
|
|
|
|
QTest::newRow("QTBUG-9631: remove one span")
|
|
<< 10 << 10
|
|
<< (SpanList() << QRect(1, 1, 2, 1) << QRect(2, 2, 2, 2) << QRect(1, 1, 1, 1))
|
|
<< false
|
|
<< QPoint(1, 1)
|
|
<< 1
|
|
<< 1;
|
|
}
|
|
|
|
void tst_QTableView::spans()
|
|
{
|
|
QFETCH(int, rows);
|
|
QFETCH(int, columns);
|
|
QFETCH(const SpanList, spans);
|
|
QFETCH(bool, hideRowLastRowOfFirstSpan);
|
|
QFETCH(QPoint, pos);
|
|
QFETCH(int, expectedRowSpan);
|
|
QFETCH(int, expectedColumnSpan);
|
|
|
|
QtTestTableModel model(rows, columns);
|
|
QtTestTableView view;
|
|
|
|
view.setModel(&model);
|
|
view.show();
|
|
|
|
for (const auto &sp : spans)
|
|
view.setSpan(sp.x(), sp.y(), sp.width(), sp.height());
|
|
|
|
if (hideRowLastRowOfFirstSpan) {
|
|
view.setRowHidden(spans.at(0).bottom(), true);
|
|
//we check that the span didn't break the visual rects of the model indexes
|
|
QRect first = view.visualRect( model.index(spans.at(0).top(), 0));
|
|
QRect next = view.visualRect( model.index(spans.at(0).bottom() + 1, 0));
|
|
QVERIFY(first.intersected(next).isEmpty());
|
|
}
|
|
|
|
QCOMPARE(view.columnSpan(pos.x(), pos.y()), expectedColumnSpan);
|
|
QCOMPARE(view.rowSpan(pos.x(), pos.y()), expectedRowSpan);
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::spansAfterRowInsertion()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QtTestTableModel model(10, 10);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
view.setSpan(3, 3, 3, 3);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
|
|
// Insertion before the span only shifts the span.
|
|
view.model()->insertRows(0, 2);
|
|
QCOMPARE(view.rowSpan(3, 3), 1);
|
|
QCOMPARE(view.columnSpan(3, 3), 1);
|
|
QCOMPARE(view.rowSpan(5, 3), 3);
|
|
QCOMPARE(view.columnSpan(5, 3), 3);
|
|
|
|
// Insertion happens before the given row, so it only shifts the span also.
|
|
view.model()->insertRows(5, 2);
|
|
QCOMPARE(view.rowSpan(5, 3), 1);
|
|
QCOMPARE(view.columnSpan(5, 3), 1);
|
|
QCOMPARE(view.rowSpan(7, 3), 3);
|
|
QCOMPARE(view.columnSpan(7, 3), 3);
|
|
|
|
// Insertion inside the span expands it.
|
|
view.model()->insertRows(8, 2);
|
|
QCOMPARE(view.rowSpan(7, 3), 5);
|
|
QCOMPARE(view.columnSpan(7, 3), 3);
|
|
|
|
// Insertion after the span does nothing to it.
|
|
view.model()->insertRows(12, 2);
|
|
QCOMPARE(view.rowSpan(7, 3), 5);
|
|
QCOMPARE(view.columnSpan(7, 3), 3);
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::spansAfterColumnInsertion()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QtTestTableModel model(10, 10);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
view.setSpan(3, 3, 3, 3);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
|
|
// Insertion before the span only shifts the span.
|
|
view.model()->insertColumns(0, 2);
|
|
QCOMPARE(view.rowSpan(3, 3), 1);
|
|
QCOMPARE(view.columnSpan(3, 3), 1);
|
|
QCOMPARE(view.rowSpan(3, 5), 3);
|
|
QCOMPARE(view.columnSpan(3, 5), 3);
|
|
|
|
// Insertion happens before the given column, so it only shifts the span also.
|
|
view.model()->insertColumns(5, 2);
|
|
QCOMPARE(view.rowSpan(3, 5), 1);
|
|
QCOMPARE(view.columnSpan(3, 5), 1);
|
|
QCOMPARE(view.rowSpan(3, 7), 3);
|
|
QCOMPARE(view.columnSpan(3, 7), 3);
|
|
|
|
// Insertion inside the span expands it.
|
|
view.model()->insertColumns(8, 2);
|
|
QCOMPARE(view.rowSpan(3, 7), 3);
|
|
QCOMPARE(view.columnSpan(3, 7), 5);
|
|
|
|
// Insertion after the span does nothing to it.
|
|
view.model()->insertColumns(12, 2);
|
|
QCOMPARE(view.rowSpan(3, 7), 3);
|
|
QCOMPARE(view.columnSpan(3, 7), 5);
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::spansAfterRowRemoval()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QtTestTableModel model(10, 10);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
|
|
static const QRect spans[] = {
|
|
{0, 1, 1, 2},
|
|
{1, 2, 1, 2},
|
|
{2, 2, 1, 5},
|
|
{2, 8, 1, 2},
|
|
{3, 4, 1, 2},
|
|
{4, 4, 1, 4},
|
|
{5, 6, 1, 3},
|
|
{6, 7, 1, 3}
|
|
};
|
|
for (const QRect &span : spans)
|
|
view.setSpan(span.top(), span.left(), span.height(), span.width());
|
|
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
view.model()->removeRows(3, 3);
|
|
|
|
static const QRect expectedSpans[] = {
|
|
{0, 1, 1, 2},
|
|
{1, 2, 1, 1},
|
|
{2, 2, 1, 2},
|
|
{2, 5, 1, 2},
|
|
{3, 4, 1, 1},
|
|
{4, 3, 1, 2},
|
|
{5, 3, 1, 3},
|
|
{6, 4, 1, 3}
|
|
};
|
|
for (const QRect &span : expectedSpans) {
|
|
QCOMPARE(view.columnSpan(span.top(), span.left()), span.width());
|
|
QCOMPARE(view.rowSpan(span.top(), span.left()), span.height());
|
|
}
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::spansAfterColumnRemoval()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QtTestTableModel model(10, 10);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
|
|
// Same set as above just swapping columns and rows.
|
|
static const QRect spans[] = {
|
|
{0, 1, 1, 2},
|
|
{1, 2, 1, 2},
|
|
{2, 2, 1, 5},
|
|
{2, 8, 1, 2},
|
|
{3, 4, 1, 2},
|
|
{4, 4, 1, 4},
|
|
{5, 6, 1, 3},
|
|
{6, 7, 1, 3}
|
|
};
|
|
for (const QRect &span : spans)
|
|
view.setSpan(span.left(), span.top(), span.width(), span.height());
|
|
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
view.model()->removeColumns(3, 3);
|
|
|
|
static const QRect expectedSpans[] = {
|
|
{0, 1, 1, 2},
|
|
{1, 2, 1, 1},
|
|
{2, 2, 1, 2},
|
|
{2, 5, 1, 2},
|
|
{3, 4, 1, 1},
|
|
{4, 3, 1, 2},
|
|
{5, 3, 1, 3},
|
|
{6, 4, 1, 3}
|
|
};
|
|
for (const QRect &span : expectedSpans) {
|
|
QCOMPARE(view.columnSpan(span.left(), span.top()), span.height());
|
|
QCOMPARE(view.rowSpan(span.left(), span.top()), span.width());
|
|
}
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::editSpanFromDirections_data()
|
|
{
|
|
QTest::addColumn<KeyList>("keyPresses");
|
|
QTest::addColumn<QSharedPointer<QStandardItemModel>>("model");
|
|
QTest::addColumn<int>("row");
|
|
QTest::addColumn<int>("column");
|
|
QTest::addColumn<int>("rowSpan");
|
|
QTest::addColumn<int>("columnSpan");
|
|
QTest::addColumn<QModelIndex>("expectedVisualCursorIndex");
|
|
QTest::addColumn<QModelIndex>("expectedEditedIndex");
|
|
|
|
/* x = the cell that should be edited
|
|
c = the cell that should actually be the current index
|
|
+---+---+
|
|
| | |
|
|
+---+---+
|
|
| | x |
|
|
+---+ +
|
|
| | c |
|
|
+---+---+
|
|
| | ^ |
|
|
+---+---+ */
|
|
KeyList keyPresses {Qt::Key_Right, Qt::Key_PageDown, Qt::Key_Up};
|
|
QSharedPointer<QStandardItemModel> model(new QStandardItemModel(4, 2));
|
|
QTest::newRow("row span, bottom up")
|
|
<< keyPresses << model << 1 << 1 << 2 << 1 << model->index(2, 1) << model->index(1, 1);
|
|
|
|
/* +---+---+
|
|
| | v |
|
|
+---+---+
|
|
| |x,c|
|
|
+---+ +
|
|
| | |
|
|
+---+---+
|
|
| | |
|
|
+---+---+ */
|
|
keyPresses = {Qt::Key_Right, Qt::Key_Down};
|
|
model = QSharedPointer<QStandardItemModel>::create(4, 2);
|
|
QTest::newRow("row span, top down")
|
|
<< keyPresses << model << 1 << 1 << 2 << 1 << model->index(1, 1) << model->index(1, 1);
|
|
|
|
/* +---+---+---+
|
|
| | | |
|
|
+---+---+---+
|
|
| |x,c| < |
|
|
+---+ +---+
|
|
| | | |
|
|
+---+---+---+ */
|
|
keyPresses = {Qt::Key_End, Qt::Key_Down, Qt::Key_Left};
|
|
model = QSharedPointer<QStandardItemModel>::create(3, 3);
|
|
QTest::newRow("row span, right to left")
|
|
<< keyPresses << model << 1 << 1 << 2 << 1 << model->index(1, 1) << model->index(1, 1);
|
|
|
|
/* +---+---+---+
|
|
| | | |
|
|
+---+---+---+
|
|
| | x | |
|
|
+---+ +---+
|
|
| > | c | |
|
|
+---+---+---+ */
|
|
keyPresses = {Qt::Key_PageDown, Qt::Key_Right};
|
|
model = QSharedPointer<QStandardItemModel>::create(3, 3);
|
|
QTest::newRow("row span, left to right")
|
|
<< keyPresses << model << 1 << 1 << 2 << 1 << model->index(2, 1) << model->index(1, 1);
|
|
|
|
/* +---+---+---+
|
|
| | | |
|
|
+---+---+---+
|
|
|x,c |
|
|
+---+---+---+
|
|
| ^ | | |
|
|
+---+---+---+ */
|
|
keyPresses = {Qt::Key_PageDown, Qt::Key_Up};
|
|
model = QSharedPointer<QStandardItemModel>::create(3, 3);
|
|
QTest::newRow("col span, bottom up")
|
|
<< keyPresses << model << 1 << 0 << 1 << 3 << model->index(1, 0) << model->index(1, 0);
|
|
|
|
/* +---+---+---+
|
|
| | | |
|
|
+---+---+---+
|
|
| x c |
|
|
+---+---+---+
|
|
| | ^ | |
|
|
+---+---+---+ */
|
|
keyPresses = {Qt::Key_PageDown, Qt::Key_Right, Qt::Key_Up};
|
|
model = QSharedPointer<QStandardItemModel>::create(3, 3);
|
|
QTest::newRow("col span, bottom up #2")
|
|
<< keyPresses << model << 1 << 0 << 1 << 3 << model->index(1, 1) << model->index(1, 0);
|
|
|
|
/* +---+---+---+
|
|
| | | v |
|
|
+---+---+---+
|
|
| x c |
|
|
+---+---+---+
|
|
| | | |
|
|
+---+---+---+ */
|
|
keyPresses = {Qt::Key_End, Qt::Key_Down};
|
|
model = QSharedPointer<QStandardItemModel>::create(3, 3);
|
|
QTest::newRow("col span, top down")
|
|
<< keyPresses << model << 1 << 0 << 1 << 3 << model->index(1, 2) << model->index(1, 0);
|
|
}
|
|
|
|
class TableViewWithCursorExposed : public QTableView
|
|
{
|
|
public:
|
|
using QTableView::QTableView;
|
|
|
|
QModelIndex visualCursorIndex()
|
|
{
|
|
QTableViewPrivate *d = static_cast<QTableViewPrivate*>(qt_widget_private(this));
|
|
return d->model->index(d->visualCursor.y(), d->visualCursor.x());
|
|
}
|
|
};
|
|
|
|
void tst_QTableView::editSpanFromDirections()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QFETCH(const KeyList, keyPresses);
|
|
QFETCH(QSharedPointer<QStandardItemModel>, model);
|
|
QFETCH(int, row);
|
|
QFETCH(int, column);
|
|
QFETCH(int, rowSpan);
|
|
QFETCH(int, columnSpan);
|
|
QFETCH(QModelIndex, expectedVisualCursorIndex);
|
|
QFETCH(QModelIndex, expectedEditedIndex);
|
|
|
|
TableViewWithCursorExposed view;
|
|
view.setModel(model.data());
|
|
// we have to make sure that PgUp/PgDown can scroll to the bottom/top
|
|
view.resize(view.horizontalHeader()->length() + 50,
|
|
view.verticalHeader()->length() + 50);
|
|
view.setSpan(row, column, rowSpan, columnSpan);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&view));
|
|
|
|
for (Qt::Key key : keyPresses)
|
|
QTest::keyClick(&view, key);
|
|
QCOMPARE(view.visualCursorIndex(), expectedVisualCursorIndex);
|
|
QCOMPARE(view.selectionModel()->currentIndex(), expectedEditedIndex);
|
|
|
|
QTest::keyClick(&view, Qt::Key_X);
|
|
QTest::keyClick(QApplication::focusWidget(), Qt::Key_Enter);
|
|
QTRY_COMPARE(view.model()->data(expectedEditedIndex).toString(), QLatin1String("x"));
|
|
}
|
|
|
|
class Model : public QAbstractTableModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
using QAbstractTableModel::QAbstractTableModel;
|
|
|
|
int rowCount(const QModelIndex &) const override
|
|
{
|
|
return rows;
|
|
}
|
|
int columnCount(const QModelIndex &) const override
|
|
{
|
|
return columns;
|
|
}
|
|
QVariant data(const QModelIndex &, int) const override
|
|
{
|
|
return QVariant();
|
|
}
|
|
void res()
|
|
{
|
|
beginResetModel();
|
|
endResetModel();
|
|
}
|
|
|
|
int rows = 0;
|
|
int columns = 0;
|
|
};
|
|
|
|
void tst_QTableView::checkHeaderReset()
|
|
{
|
|
QTableView view;
|
|
Model m;
|
|
m.rows = 3;
|
|
m.columns = 3;
|
|
view.setModel(&m);
|
|
|
|
m.rows = 4;
|
|
m.columns = 4;
|
|
m.res();
|
|
QCOMPARE(view.horizontalHeader()->count(), 4);
|
|
}
|
|
|
|
void tst_QTableView::checkHeaderMinSize()
|
|
{
|
|
//tests if the minimumsize is of a header is taken into account
|
|
//while computing QTableView geometry. For that we test the position of the
|
|
//viewport.
|
|
QTableView view;
|
|
QStringListModel m;
|
|
m.setStringList({QLatin1String("one cell is enough")});
|
|
view.setModel(&m);
|
|
|
|
//setting the minimum height on the horizontal header
|
|
//and the minimum width on the vertical header
|
|
view.horizontalHeader()->setMinimumHeight(50);
|
|
view.verticalHeader()->setMinimumWidth(100);
|
|
|
|
view.show();
|
|
|
|
QVERIFY( view.verticalHeader()->y() >= view.horizontalHeader()->minimumHeight());
|
|
QVERIFY( view.horizontalHeader()->x() >= view.verticalHeader()->minimumWidth());
|
|
}
|
|
|
|
void tst_QTableView::resizeToContents()
|
|
{
|
|
//checks that the resize to contents is consistent
|
|
QTableWidget table(2,3);
|
|
QTableWidget table2(2,3);
|
|
QTableWidget table3(2,3);
|
|
|
|
|
|
table.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
|
|
table2.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
|
|
table3.setHorizontalHeaderItem(0, new QTableWidgetItem("A Lot of text here: BLA BLA BLA"));
|
|
table.horizontalHeader()->setVisible(false);
|
|
table2.horizontalHeader()->setVisible(false);
|
|
table.verticalHeader()->setVisible(false);
|
|
table2.verticalHeader()->setVisible(false);
|
|
|
|
|
|
for (int i = 0; i < table.columnCount(); i++)
|
|
table.resizeColumnToContents(i);
|
|
for (int i = 0; i < table.rowCount(); i++)
|
|
table.resizeRowToContents(i);
|
|
table2.resizeColumnsToContents();
|
|
table2.resizeRowsToContents();
|
|
table3.resizeColumnsToContents();
|
|
table3.resizeRowsToContents();
|
|
|
|
//now let's check the row/col sizes
|
|
for (int i = 0; i < table.columnCount(); i++) {
|
|
QCOMPARE(table.columnWidth(i), table2.columnWidth(i));
|
|
QCOMPARE(table2.columnWidth(i), table3.columnWidth(i));
|
|
}
|
|
for (int i = 0; i < table.rowCount(); i++) {
|
|
QCOMPARE(table.rowHeight(i), table2.rowHeight(i));
|
|
QCOMPARE(table2.rowHeight(i), table3.rowHeight(i));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
class SpanModel : public QAbstractTableModel
|
|
{
|
|
public:
|
|
SpanModel(bool sectionsMoved)
|
|
: _sectionsMoved(sectionsMoved)
|
|
{}
|
|
int columnCount(const QModelIndex & = {}) const override { return 2; }
|
|
int rowCount(const QModelIndex & = {}) const override { return 1; }
|
|
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
|
|
{
|
|
if (role != Qt::DisplayRole)
|
|
return QVariant();
|
|
const int col = _sectionsMoved ? 1 - idx.column() : idx.column();
|
|
if (col == 0)
|
|
return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
|
return QVariant();
|
|
}
|
|
private:
|
|
bool _sectionsMoved;
|
|
};
|
|
|
|
|
|
void tst_QTableView::resizeToContentsSpans()
|
|
{
|
|
SpanModel model1(false);
|
|
SpanModel model2(true);
|
|
QTableView view1, view2, view3;
|
|
view1.setModel(&model1);
|
|
view2.setModel(&model2);
|
|
view2.horizontalHeader()->moveSection(0, 1);
|
|
view3.setModel(&model1);
|
|
|
|
view1.setSpan(0, 0, 1, 2);
|
|
view2.setSpan(0, 1, 1, 2);
|
|
view1.show();
|
|
view2.show();
|
|
view3.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view1));
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view2));
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view3));
|
|
view1.setColumnWidth(0, 100);
|
|
view1.setColumnWidth(1, 100);
|
|
view2.setColumnWidth(0, 100);
|
|
view2.setColumnWidth(1, 100);
|
|
view3.setColumnWidth(0, 200);
|
|
|
|
view1.resizeRowToContents(0);
|
|
view2.resizeRowToContents(0);
|
|
view3.resizeRowToContents(0);
|
|
QCOMPARE(view1.rowHeight(0), view3.rowHeight(0));
|
|
QCOMPARE(view2.rowHeight(0), view3.rowHeight(0));
|
|
|
|
view3.resizeColumnToContents(0);
|
|
view3.resizeRowToContents(0);
|
|
// height should be only 1 text line for easy testing
|
|
view1.setRowHeight(0, view3.verticalHeader()->sectionSize(0));
|
|
view2.setRowHeight(0, view3.verticalHeader()->sectionSize(0));
|
|
view1.resizeColumnToContents(0);
|
|
view2.resizeColumnToContents(1);
|
|
QCOMPARE(view1.columnWidth(0), view3.columnWidth(0) - view1.columnWidth(1));
|
|
QCOMPARE(view2.columnWidth(0), view3.columnWidth(0) - view2.columnWidth(1));
|
|
}
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
extern bool Q_WIDGETS_EXPORT qt_tab_all_widgets(); // qapplication.cpp
|
|
QT_END_NAMESPACE
|
|
|
|
void tst_QTableView::tabFocus()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
if (!qt_tab_all_widgets())
|
|
QSKIP("This test requires full keyboard control to be enabled.");
|
|
|
|
// QTableView enables tabKeyNavigation by default, but you should be able
|
|
// to change focus on an empty table view, or on a table view that doesn't
|
|
// have this property set.
|
|
QWidget window;
|
|
window.resize(200, 200);
|
|
|
|
QTableView *view = new QTableView(&window);
|
|
QLineEdit *edit = new QLineEdit(&window);
|
|
|
|
window.show();
|
|
QApplicationPrivate::setActiveWindow(&window);
|
|
window.setFocus();
|
|
window.activateWindow();
|
|
QVERIFY(QTest::qWaitForWindowActive(&window));
|
|
|
|
// window
|
|
QVERIFY(window.hasFocus());
|
|
QVERIFY(!view->hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
// tab to view
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
|
|
QTRY_VERIFY(!window.hasFocus());
|
|
QVERIFY(view->hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
// tab to edit
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
|
|
QTRY_VERIFY(edit->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!view->hasFocus());
|
|
}
|
|
|
|
// backtab to view
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(view->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
// backtab to edit
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(edit->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!view->hasFocus());
|
|
|
|
QStandardItemModel model;
|
|
view->setModel(&model);
|
|
|
|
// backtab to view
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(view->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
// backtab to edit
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(edit->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!view->hasFocus());
|
|
|
|
model.insertRow(0, new QStandardItem("Hei"));
|
|
model.insertRow(0, new QStandardItem("Hei"));
|
|
model.insertRow(0, new QStandardItem("Hei"));
|
|
|
|
// backtab to view
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(view->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
// backtab to edit doesn't work
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(view->hasFocus());
|
|
QVERIFY(!edit->hasFocus());
|
|
|
|
view->setTabKeyNavigation(false);
|
|
|
|
// backtab to edit
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
|
|
QTRY_VERIFY(edit->hasFocus());
|
|
QVERIFY(!window.hasFocus());
|
|
QVERIFY(!view->hasFocus());
|
|
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
|
|
QTRY_VERIFY(view->hasFocus());
|
|
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
|
|
QTRY_VERIFY(edit->hasFocus());
|
|
}
|
|
|
|
class BigModel : public QAbstractTableModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
QVariant data(const QModelIndex &index,
|
|
int role = Qt::DisplayRole) const override
|
|
{
|
|
if (role == Qt::DisplayRole)
|
|
return QString::number(index.column()) + QLatin1String(" - ") + QString::number(index.row());
|
|
return QVariant();
|
|
}
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
|
{
|
|
Q_UNUSED(parent);
|
|
return 10000000;
|
|
}
|
|
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
|
{
|
|
Q_UNUSED(parent);
|
|
return 20000000;
|
|
}
|
|
};
|
|
|
|
void tst_QTableView::bigModel()
|
|
{
|
|
//should not crash
|
|
QTableView view;
|
|
BigModel model;
|
|
view.setModel(&model);
|
|
view.show();
|
|
view.setSpan(10002,10002,6,6);
|
|
QTest::qWait(100);
|
|
view.resize(1000,1000);
|
|
QTest::qWait(100);
|
|
view.scrollTo(model.index(10010,10010));
|
|
QTest::qWait(100);
|
|
}
|
|
|
|
void tst_QTableView::selectionSignal()
|
|
{
|
|
QtTestTableModel model(10, 10);
|
|
QtTestTableView view;
|
|
view.checkSignalOrder = true;
|
|
view.setModel(&model);
|
|
view.resize(200, 200);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.visualRect(model.index(2, 0)).center());
|
|
}
|
|
|
|
void tst_QTableView::setCurrentIndex()
|
|
{
|
|
QtTestTableModel model(4, 4);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
|
|
// submit() slot should be called in model when current row changes
|
|
view.setCurrentIndex(model.index(0,0));
|
|
QCOMPARE(model.submit_count, 1);
|
|
view.setCurrentIndex(model.index(0,2));
|
|
QCOMPARE(model.submit_count, 1);
|
|
view.setCurrentIndex(model.index(1,0));
|
|
QCOMPARE(model.submit_count, 2);
|
|
view.setCurrentIndex(model.index(3,3));
|
|
QCOMPARE(model.submit_count, 3);
|
|
view.setCurrentIndex(model.index(0,1));
|
|
QCOMPARE(model.submit_count, 4);
|
|
view.setCurrentIndex(model.index(0,0));
|
|
QCOMPARE(model.submit_count, 4);
|
|
}
|
|
|
|
void tst_QTableView::checkIntersectedRect_data()
|
|
{
|
|
QTest::addColumn<QtTestTableModel *>("model");
|
|
QTest::addColumn<QList<QModelIndex>>("changedIndexes");
|
|
QTest::addColumn<bool>("isEmpty");
|
|
QTest::addColumn<bool>("swapFirstAndLastIndexRow"); // for QHeaderView::sectionsMoved()
|
|
QTest::addColumn<bool>("swapFirstAndLastIndexColumn"); // for QHeaderView::sectionsMoved()
|
|
QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
|
|
QTest::addColumn<int>("hiddenRow");
|
|
QTest::addColumn<int>("hiddenCol");
|
|
const auto testName = [](const QByteArray &prefix, Qt::LayoutDirection dir, bool r, bool c)
|
|
{
|
|
const char *strDir = dir == Qt::LeftToRight ? ", LeftToRight" : ", RightToLeft";
|
|
const char *strRow = r ? ", rowsSwapped" : "";
|
|
const char *strCol = c ? ", colsSwapped" : "";
|
|
return prefix + strDir + strRow + strCol;
|
|
};
|
|
for (int i = 0; i < 2; ++i) {
|
|
const Qt::LayoutDirection dir(i == 0 ? Qt::LeftToRight : Qt::RightToLeft);
|
|
for (int j = 0; j < 4; ++j) {
|
|
const bool swapRow = ((j & 1) == 1);
|
|
const bool swapColumn = ((j & 2) == 2);
|
|
{
|
|
QtTestTableModel *model = new QtTestTableModel(10, 3);
|
|
QTest::newRow(testName("multiple columns", dir, swapRow, swapColumn).data())
|
|
<< model << QList<QModelIndex>({ model->index(0, 0), model->index(0, 1) })
|
|
<< false << swapRow << swapColumn << dir << -1 << -1;
|
|
}
|
|
{
|
|
QtTestTableModel *model = new QtTestTableModel(10, 3);
|
|
QTest::newRow(testName("multiple rows", dir, swapRow, swapColumn).data())
|
|
<< model
|
|
<< QList<QModelIndex>(
|
|
{ model->index(0, 0), model->index(1, 0), model->index(2, 0) })
|
|
<< false << swapRow << swapColumn << dir << -1 << -1;
|
|
}
|
|
{
|
|
QtTestTableModel *model = new QtTestTableModel(10, 3);
|
|
QTest::newRow(testName("hidden row", dir, swapRow, swapColumn).data())
|
|
<< model << QList<QModelIndex>({ model->index(3, 0), model->index(3, 1) })
|
|
<< true << swapRow << swapColumn << dir << 3 << -1;
|
|
}
|
|
{
|
|
QtTestTableModel *model = new QtTestTableModel(50, 2);
|
|
QTest::newRow(testName("row outside viewport", dir, swapRow, swapColumn).data())
|
|
<< model << QList<QModelIndex>({ model->index(49, 0), model->index(49, 1) })
|
|
<< true << swapRow << swapColumn << dir << -1 << -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::checkIntersectedRect()
|
|
{
|
|
QFETCH(QtTestTableModel *, model);
|
|
QFETCH(const QList<QModelIndex>, changedIndexes);
|
|
QFETCH(bool, isEmpty);
|
|
QFETCH(bool, swapFirstAndLastIndexRow);
|
|
QFETCH(bool, swapFirstAndLastIndexColumn);
|
|
QFETCH(Qt::LayoutDirection, layoutDirection);
|
|
QFETCH(int, hiddenRow);
|
|
QFETCH(int, hiddenCol);
|
|
|
|
QtTestTableView view;
|
|
model->setParent(&view);
|
|
view.setLayoutDirection(layoutDirection);
|
|
view.setModel(model);
|
|
view.resize(400, 400);
|
|
view.show();
|
|
if (hiddenRow >= 0)
|
|
view.hideRow(hiddenRow);
|
|
if (hiddenCol >= 0)
|
|
view.hideRow(hiddenCol);
|
|
if (swapFirstAndLastIndexRow)
|
|
view.verticalHeader()->swapSections(changedIndexes.first().row(), changedIndexes.last().row());
|
|
if (swapFirstAndLastIndexColumn)
|
|
view.horizontalHeader()->swapSections(changedIndexes.first().column(), changedIndexes.last().column());
|
|
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
const auto toString = [](const QModelIndex &idx)
|
|
{
|
|
return QStringLiteral("idx: %1/%2").arg(idx.row()).arg(idx.column());
|
|
};
|
|
|
|
view.m_intersectecRect = QRect();
|
|
emit view.model()->dataChanged(changedIndexes.first(), changedIndexes.last());
|
|
if (isEmpty) {
|
|
QVERIFY(view.m_intersectecRect.isEmpty());
|
|
} else if (!changedIndexes.first().isValid()) {
|
|
QCOMPARE(view.m_intersectecRect, view.viewport()->rect());
|
|
} else {
|
|
const auto parent = changedIndexes.first().parent();
|
|
const int rCount = view.model()->rowCount(parent);
|
|
const int cCount = view.model()->columnCount(parent);
|
|
for (int r = 0; r < rCount; ++r) {
|
|
for (int c = 0; c < cCount; ++c) {
|
|
const QModelIndex &idx = view.model()->index(r, c, parent);
|
|
const auto rect = view.visualRect(idx);
|
|
if (changedIndexes.contains(idx))
|
|
QVERIFY2(view.m_intersectecRect.contains(rect), qPrintable(toString(idx)));
|
|
else
|
|
QVERIFY2(!view.m_intersectecRect.contains(rect), qPrintable(toString(idx)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class task173773_EventFilter : public QObject
|
|
{
|
|
int paintEventCount_ = 0;
|
|
public:
|
|
using QObject::QObject;
|
|
int paintEventCount() const { return paintEventCount_; }
|
|
private:
|
|
bool eventFilter(QObject *obj, QEvent *e) override
|
|
{
|
|
Q_UNUSED(obj);
|
|
if (e->type() == QEvent::Paint)
|
|
++paintEventCount_;
|
|
return false;
|
|
}
|
|
};
|
|
|
|
void tst_QTableView::task173773_updateVerticalHeader()
|
|
{
|
|
QStandardItemModel model(2, 1);
|
|
model.setData(model.index(0, 0), 0);
|
|
model.setData(model.index(1, 0), 1);
|
|
|
|
QSortFilterProxyModel proxyModel;
|
|
proxyModel.setSourceModel(&model);
|
|
|
|
QTableView view;
|
|
view.setModel(&proxyModel);
|
|
view.setSortingEnabled(true);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
view.sortByColumn(0, Qt::AscendingOrder);
|
|
QTest::qWait(100);
|
|
|
|
task173773_EventFilter eventFilter;
|
|
view.verticalHeader()->viewport()->installEventFilter(&eventFilter);
|
|
|
|
view.sortByColumn(0, Qt::DescendingOrder);
|
|
QTest::qWait(100);
|
|
|
|
// ### note: this test may occasionally pass even if the bug is present!
|
|
QVERIFY(eventFilter.paintEventCount() > 0);
|
|
}
|
|
|
|
void tst_QTableView::task227953_setRootIndex()
|
|
{
|
|
QTableView tableView;
|
|
|
|
//model = tree with two items with tables as children
|
|
QStandardItemModel model;
|
|
QStandardItem item1, item2;
|
|
model.appendColumn(QList<QStandardItem*>() << &item1 << &item2);
|
|
|
|
|
|
//setup the first table as a child of the first item
|
|
for ( int row = 0; row < 40; ++row ) {
|
|
item1.appendRow(QList<QStandardItem*>() << new QStandardItem(QLatin1String("row ") + QString::number(row)));
|
|
}
|
|
|
|
//setup the second table as a child of the second item
|
|
for ( int row = 0; row < 10; ++row ) {
|
|
item2.appendRow(QList<QStandardItem*>() << new QStandardItem(QLatin1String("row ") + QString::number(row)));
|
|
}
|
|
|
|
tableView.setModel(&model);
|
|
|
|
//show the first 10 rows of the first table
|
|
QModelIndex root = model.indexFromItem(&item1);
|
|
tableView.setRootIndex(root);
|
|
for (int i = 10; i != 40; ++i) {
|
|
tableView.setRowHidden(i, true);
|
|
}
|
|
|
|
QCOMPARE(tableView.verticalHeader()->count(), 40);
|
|
QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 30);
|
|
|
|
//show the first 10 rows of the second table
|
|
tableView.setRootIndex(model.indexFromItem(&item2));
|
|
|
|
QCOMPARE(tableView.verticalHeader()->count(), 10);
|
|
QCOMPARE(tableView.verticalHeader()->hiddenSectionCount(), 0);
|
|
QVERIFY(!tableView.verticalHeader()->isHidden());
|
|
}
|
|
|
|
void tst_QTableView::task240266_veryBigColumn()
|
|
{
|
|
QTableView table;
|
|
table.setFixedSize(500, 300); //just to make sure we have the 2 first columns visible
|
|
QStandardItemModel model(1, 3);
|
|
table.setModel(&model);
|
|
table.setColumnWidth(0, 100); //normal column
|
|
table.setColumnWidth(1, 100); //normal column
|
|
table.setColumnWidth(2, 9000); //very big column
|
|
table.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&table));
|
|
|
|
//some styles change the scroll mode in their polish
|
|
table.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
table.setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
|
|
QScrollBar *scroll = table.horizontalScrollBar();
|
|
QCOMPARE(scroll->minimum(), 0);
|
|
QCOMPARE(scroll->maximum(), model.columnCount() - 1);
|
|
QCOMPARE(scroll->singleStep(), 1);
|
|
|
|
//1 is not always a very correct value for pageStep. Ideally this should be dynamic.
|
|
//Maybe something for Qt 5 ;-)
|
|
QCOMPARE(scroll->pageStep(), 1);
|
|
|
|
}
|
|
|
|
void tst_QTableView::task248688_autoScrollNavigation()
|
|
{
|
|
//we make sure that when navigating with the keyboard the view is correctly scrolled
|
|
//to the current item
|
|
QStandardItemModel model(16, 16);
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
|
|
view.hideColumn(8);
|
|
view.hideRow(8);
|
|
view.show();
|
|
for (int r = 0; r < model.rowCount(); ++r) {
|
|
if (view.isRowHidden(r))
|
|
continue;
|
|
for (int c = 0; c < model.columnCount(); ++c) {
|
|
if (view.isColumnHidden(c))
|
|
continue;
|
|
QModelIndex index = model.index(r, c);
|
|
view.setCurrentIndex(index);
|
|
QVERIFY(view.viewport()->rect().contains(view.visualRect(index)));
|
|
}
|
|
}
|
|
}
|
|
|
|
#if QT_CONFIG(wheelevent)
|
|
void tst_QTableView::mouseWheel_data()
|
|
{
|
|
QTest::addColumn<QAbstractItemView::ScrollMode>("scrollMode");
|
|
QTest::addColumn<int>("delta");
|
|
QTest::addColumn<int>("horizontalPositon");
|
|
QTest::addColumn<int>("verticalPosition");
|
|
|
|
QTest::newRow("scroll up per item")
|
|
<< QAbstractItemView::ScrollPerItem << 120
|
|
<< 10 - QApplication::wheelScrollLines() << 10 - QApplication::wheelScrollLines();
|
|
QTest::newRow("scroll down per item")
|
|
<< QAbstractItemView::ScrollPerItem << -120
|
|
<< 10 + QApplication::wheelScrollLines() << 10 + QApplication::wheelScrollLines();
|
|
QTest::newRow("scroll down per pixel")
|
|
<< QAbstractItemView::ScrollPerPixel << -120
|
|
<< 10 + QApplication::wheelScrollLines() * 91 << 10 + QApplication::wheelScrollLines() * 46;
|
|
}
|
|
|
|
void tst_QTableView::mouseWheel()
|
|
{
|
|
QFETCH(QAbstractItemView::ScrollMode, scrollMode);
|
|
QFETCH(int, delta);
|
|
QFETCH(int, horizontalPositon);
|
|
QFETCH(int, verticalPosition);
|
|
|
|
QtTestTableModel model(100, 100);
|
|
QWidget topLevel;
|
|
QtTestTableView view(&topLevel);
|
|
view.resize(500, 500);
|
|
topLevel.show();
|
|
|
|
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
|
|
|
|
view.setModel(&model);
|
|
|
|
for (int r = 0; r < 100; ++r)
|
|
view.setRowHeight(r, 50);
|
|
for (int c = 0; c < 100; ++c)
|
|
view.setColumnWidth(c, 100);
|
|
|
|
view.setHorizontalScrollMode(scrollMode);
|
|
view.setVerticalScrollMode(scrollMode);
|
|
view.horizontalScrollBar()->setValue(10);
|
|
view.verticalScrollBar()->setValue(10);
|
|
|
|
QPoint pos = view.viewport()->geometry().center();
|
|
QWheelEvent verticalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(0, delta),
|
|
Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
|
|
QWheelEvent horizontalEvent(pos, view.mapToGlobal(pos), QPoint(), QPoint(delta, 0),
|
|
Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
|
|
QApplication::sendEvent(view.viewport(), &horizontalEvent);
|
|
QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 15);
|
|
QApplication::sendEvent(view.viewport(), &verticalEvent);
|
|
QVERIFY(qAbs(view.verticalScrollBar()->value() - verticalPosition) < 15);
|
|
}
|
|
#endif // QT_CONFIG(wheelevent)
|
|
|
|
void tst_QTableView::addColumnWhileEditing()
|
|
{
|
|
QTableView view;
|
|
QStandardItemModel model(1, 10);
|
|
view.setModel(&model);
|
|
QModelIndex last = model.index(0,9);
|
|
view.show();
|
|
|
|
view.openPersistentEditor(last);
|
|
view.scrollTo(last);
|
|
|
|
//let's see if the editor is moved to the right location
|
|
//after adding a column
|
|
model.setColumnCount(model.columnCount() + 1);
|
|
QPointer<QLineEdit> editor = view.findChild<QLineEdit*>();
|
|
QVERIFY(editor);
|
|
QCOMPARE(editor->geometry(), view.visualRect(last));
|
|
|
|
//let's see if the editor is moved to the right location
|
|
//after removing a column
|
|
view.scrollTo(model.index(0, model.columnCount()-1));
|
|
model.setColumnCount(model.columnCount() - 1);
|
|
QVERIFY(editor);
|
|
QCOMPARE(editor->geometry(), view.visualRect(last));
|
|
}
|
|
|
|
void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections()
|
|
{
|
|
QStandardItemModel model;
|
|
model.setRowCount(50);
|
|
model.setColumnCount(2);
|
|
for (int row = 0; row < model.rowCount(); ++row)
|
|
for (int col = 0; col < model.columnCount(); ++col) {
|
|
const QModelIndex &idx = model.index(row, col);
|
|
model.setData(idx, QVariant(row), Qt::EditRole);
|
|
}
|
|
|
|
QTableView tv;
|
|
tv.setModel(&model);
|
|
tv.show();
|
|
tv.verticalHeader()->swapSections(0, model.rowCount() - 1);
|
|
tv.setCurrentIndex(model.index(model.rowCount() - 1, 0));
|
|
|
|
QVERIFY(QTest::qWaitForWindowExposed(&tv));
|
|
QTest::keyClick(&tv, Qt::Key_PageUp); // PageUp won't scroll when at top
|
|
QTRY_COMPARE(tv.rowAt(0), tv.verticalHeader()->logicalIndex(0));
|
|
|
|
int newRow = tv.rowAt(tv.viewport()->height());
|
|
QTest::keyClick(&tv, Qt::Key_PageDown); // Scroll down and check current
|
|
QTRY_COMPARE(tv.currentIndex().row(), newRow);
|
|
|
|
tv.setCurrentIndex(model.index(0, 0));
|
|
QTest::keyClick(&tv, Qt::Key_PageDown); // PageDown won't scroll when at the bottom
|
|
QTRY_COMPARE(tv.rowAt(tv.viewport()->height() - 1), tv.verticalHeader()->logicalIndex(model.rowCount() - 1));
|
|
}
|
|
|
|
template <typename T>
|
|
struct ValueSaver {
|
|
T &var, value;
|
|
ValueSaver(T &v) : var(v), value(v) { }
|
|
~ValueSaver() { var = value; }
|
|
};
|
|
|
|
void tst_QTableView::task191545_dragSelectRows()
|
|
{
|
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
|
QSKIP("Wayland: This fails. Figure out why.");
|
|
|
|
QStandardItemModel model(10, 10);
|
|
QTableView table;
|
|
table.setModel(&model);
|
|
table.setSelectionBehavior(QAbstractItemView::SelectItems);
|
|
table.setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
table.setMinimumSize(1000, 400);
|
|
table.show();
|
|
QVERIFY(QTest::qWaitForWindowActive(&table));
|
|
|
|
ValueSaver<Qt::KeyboardModifiers> saver(QApplicationPrivate::modifier_buttons);
|
|
QApplicationPrivate::modifier_buttons = Qt::ControlModifier;
|
|
|
|
{
|
|
QRect cellRect = table.visualRect(model.index(3, 0));
|
|
QHeaderView *vHeader = table.verticalHeader();
|
|
QWidget *vHeaderVp = vHeader->viewport();
|
|
QPoint rowPos(cellRect.center());
|
|
QMouseEvent rowPressEvent(QEvent::MouseButtonPress, rowPos, rowPos, vHeaderVp->mapToGlobal(rowPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(vHeaderVp, &rowPressEvent);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
rowPos.setY(rowPos.y() + cellRect.height());
|
|
QMouseEvent moveEvent(QEvent::MouseMove, rowPos, rowPos, vHeaderVp->mapToGlobal(rowPos),
|
|
Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(vHeaderVp, &moveEvent);
|
|
}
|
|
QMouseEvent rowReleaseEvent(QEvent::MouseButtonRelease, rowPos, vHeaderVp->mapToGlobal(rowPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(vHeaderVp, &rowReleaseEvent);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
QModelIndex index = model.index(3 + i, 0, table.rootIndex());
|
|
QVERIFY(vHeader->selectionModel()->selectedRows().contains(index));
|
|
}
|
|
}
|
|
|
|
{
|
|
QRect cellRect = table.visualRect(model.index(0, 3));
|
|
QHeaderView *hHeader = table.horizontalHeader();
|
|
QWidget *hHeaderVp = hHeader->viewport();
|
|
QPoint colPos((cellRect.left() + cellRect.right()) / 2, 5);
|
|
QMouseEvent colPressEvent(QEvent::MouseButtonPress, colPos, hHeaderVp->mapToGlobal(colPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(hHeaderVp, &colPressEvent);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
colPos.setX(colPos.x() + cellRect.width());
|
|
QMouseEvent moveEvent(QEvent::MouseMove, colPos, hHeaderVp->mapToGlobal(colPos),
|
|
Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(hHeaderVp, &moveEvent);
|
|
}
|
|
QMouseEvent colReleaseEvent(QEvent::MouseButtonRelease, colPos, hHeaderVp->mapToGlobal(colPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(hHeaderVp, &colReleaseEvent);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
QModelIndex index = model.index(0, 3 + i, table.rootIndex());
|
|
QVERIFY(hHeader->selectionModel()->selectedColumns().contains(index));
|
|
}
|
|
}
|
|
|
|
{
|
|
QRect cellRect = table.visualRect(model.index(2, 2));
|
|
QWidget *tableVp = table.viewport();
|
|
QPoint cellPos = cellRect.center();
|
|
QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &cellPressEvent);
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
cellPos.setX(cellPos.x() + cellRect.width());
|
|
cellPos.setY(cellPos.y() + cellRect.height());
|
|
QMouseEvent moveEvent(QEvent::MouseMove, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &moveEvent);
|
|
}
|
|
QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &cellReleaseEvent);
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
for (int j = 0; j < 6; ++j) {
|
|
QModelIndex index = model.index(2 + i, 2 + j, table.rootIndex());
|
|
QVERIFY(table.selectionModel()->isSelected(index));
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
QRect cellRect = table.visualRect(model.index(3, 3));
|
|
QWidget *tableVp = table.viewport();
|
|
QPoint cellPos = cellRect.center();
|
|
QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &cellPressEvent);
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
// cellPos might have been updated by scrolling, so refresh
|
|
cellPos = table.visualRect(model.index(3+i, 3+i)).center();
|
|
cellPos.setX(cellPos.x() + cellRect.width());
|
|
cellPos.setY(cellPos.y() + cellRect.height());
|
|
QMouseEvent moveEvent(QEvent::MouseMove, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::NoButton, Qt::LeftButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &moveEvent);
|
|
}
|
|
QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, tableVp->mapToGlobal(cellPos),
|
|
Qt::LeftButton, Qt::NoButton, Qt::ControlModifier);
|
|
QCoreApplication::sendEvent(tableVp, &cellReleaseEvent);
|
|
|
|
QTest::qWait(200);
|
|
for (int i = 0; i < 6; ++i) {
|
|
for (int j = 0; j < 6; ++j) {
|
|
QModelIndex index = model.index(3 + i, 3 + j, table.rootIndex());
|
|
QVERIFY(!table.selectionModel()->isSelected(index));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void tst_QTableView::task234926_setHeaderSorting()
|
|
{
|
|
QStringListModel model;
|
|
QSortFilterProxyModel sfpm; // default QStandardItemModel does not support 'unsorted' state
|
|
sfpm.setSourceModel(&model);
|
|
const QStringList data({"orange", "apple", "banana", "lemon", "pumpkin"});
|
|
QStringList sortedDataA = data;
|
|
QStringList sortedDataD = data;
|
|
std::sort(sortedDataA.begin(), sortedDataA.end());
|
|
std::sort(sortedDataD.begin(), sortedDataD.end(), std::greater<QString>());
|
|
model.setStringList(data);
|
|
QTableView view;
|
|
view.setModel(&sfpm);
|
|
|
|
QTRY_COMPARE(model.stringList(), data);
|
|
view.setSortingEnabled(true);
|
|
view.sortByColumn(0, Qt::AscendingOrder);
|
|
for (int i = 0; i < sortedDataA.size(); ++i)
|
|
QCOMPARE(view.model()->data(view.model()->index(i, 0)).toString(), sortedDataA.at(i));
|
|
|
|
view.horizontalHeader()->setSortIndicator(0, Qt::DescendingOrder);
|
|
for (int i = 0; i < sortedDataD.size(); ++i)
|
|
QCOMPARE(view.model()->data(view.model()->index(i, 0)).toString(), sortedDataD.at(i));
|
|
|
|
QHeaderView *h = new QHeaderView(Qt::Horizontal);
|
|
h->setModel(&model);
|
|
view.setHorizontalHeader(h);
|
|
h->setSortIndicator(0, Qt::AscendingOrder);
|
|
for (int i = 0; i < sortedDataA.size(); ++i)
|
|
QCOMPARE(view.model()->data(view.model()->index(i, 0)).toString(), sortedDataA.at(i));
|
|
|
|
h->setSortIndicator(0, Qt::DescendingOrder);
|
|
for (int i = 0; i < sortedDataD.size(); ++i)
|
|
QCOMPARE(view.model()->data(view.model()->index(i, 0)).toString(), sortedDataD.at(i));
|
|
|
|
view.sortByColumn(-1, Qt::AscendingOrder);
|
|
QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), -1);
|
|
for (int i = 0; i < data.size(); ++i)
|
|
QCOMPARE(view.model()->data(view.model()->index(i, 0)).toString(), data.at(i));
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_5062_spansInconsistency()
|
|
{
|
|
const int nRows = 5;
|
|
const int nColumns = 5;
|
|
|
|
QtTestTableModel model(nRows, nColumns);
|
|
QtTestTableView view;
|
|
view.setModel(&model);
|
|
|
|
for (int i = 0; i < nRows; ++i)
|
|
view.setSpan(i, 0, 1, nColumns);
|
|
view.setSpan(2, 0, 1, 1);
|
|
view.setSpan(3, 0, 1, 1);
|
|
|
|
VERIFY_SPANS_CONSISTENCY(&view);
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_4516_clickOnRichTextLabel()
|
|
{
|
|
QTableView view;
|
|
QStandardItemModel model(5,5);
|
|
view.setModel(&model);
|
|
QLabel label("rich text");
|
|
label.setTextFormat(Qt::RichText);
|
|
view.setIndexWidget(model.index(1,1), &label);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
view.setCurrentIndex(model.index(0,0));
|
|
QCOMPARE(view.currentIndex(), model.index(0,0));
|
|
|
|
QTest::mouseClick(&label, Qt::LeftButton);
|
|
QCOMPARE(view.currentIndex(), model.index(1,1));
|
|
}
|
|
|
|
|
|
void tst_QTableView::changeHeaderData()
|
|
{
|
|
QTableView view;
|
|
QStandardItemModel model(5,5);
|
|
view.setModel(&model);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
QString text = "long long long text";
|
|
const int textWidth = view.verticalHeader()->fontMetrics().horizontalAdvance(text);
|
|
QVERIFY(view.verticalHeader()->width() < textWidth);
|
|
|
|
model.setHeaderData(2, Qt::Vertical, text);
|
|
|
|
QTRY_VERIFY(view.verticalHeader()->width() > textWidth);
|
|
}
|
|
|
|
#if QT_CONFIG(wheelevent)
|
|
void tst_QTableView::taskQTBUG_5237_wheelEventOnHeader()
|
|
{
|
|
QTableView view;
|
|
QStandardItemModel model(500,5);
|
|
view.setModel(&model);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
int sbValueBefore = view.verticalScrollBar()->value();
|
|
QHeaderView *header = view.verticalHeader();
|
|
QTest::mouseMove(header);
|
|
QPoint pos = header->geometry().center();
|
|
QWheelEvent wheelEvent(pos, header->viewport()->mapToGlobal(pos), QPoint(), QPoint(0, -720),
|
|
Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
|
|
QApplication::sendEvent(header->viewport(), &wheelEvent);
|
|
int sbValueAfter = view.verticalScrollBar()->value();
|
|
QVERIFY(sbValueBefore != sbValueAfter);
|
|
}
|
|
#endif
|
|
|
|
class TestTableView : public QTableView
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
TestTableView(QWidget *parent = nullptr) : QTableView(parent)
|
|
{
|
|
connect(this, &QTableView::entered, this, &TestTableView::openPersistentEditor);
|
|
}
|
|
public slots:
|
|
void onDataChanged()
|
|
{
|
|
for (int i = 0; i < model()->rowCount(); i++) {
|
|
setRowHidden(i, model()->data(model()->index(i, 0)).toBool());
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
void tst_QTableView::taskQTBUG_8585_crashForNoGoodReason()
|
|
{
|
|
QStandardItemModel model;
|
|
model.insertColumn(0, QModelIndex());
|
|
for (int i = 0; i < 20; i++)
|
|
model.insertRow(i);
|
|
|
|
TestTableView w;
|
|
w.setMouseTracking(true);
|
|
w.setModel(&model);
|
|
connect(&model, &QStandardItemModel::dataChanged, &w, &TestTableView::onDataChanged);
|
|
w.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
QTest::mouseMove(w.viewport(), QPoint(50, 20));
|
|
w.model()->setData(w.indexAt(QPoint(50, 20)), true);
|
|
QTest::mouseMove(w.viewport(), QPoint(50, 25));
|
|
}
|
|
}
|
|
|
|
class TableView7774 : public QTableView
|
|
{
|
|
public:
|
|
using QTableView::visualRegionForSelection;
|
|
};
|
|
|
|
void tst_QTableView::taskQTBUG_7774_RtoLVisualRegionForSelection()
|
|
{
|
|
TableView7774 view;
|
|
QStandardItemModel model(5,5);
|
|
view.setModel(&model);
|
|
view.setLayoutDirection(Qt::RightToLeft);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
QItemSelectionRange range(model.index(2, 0), model.index(2, model.columnCount() - 1));
|
|
QItemSelection selection;
|
|
selection << range;
|
|
QRegion region = view.visualRegionForSelection(selection);
|
|
QVERIFY(!region.isEmpty());
|
|
QCOMPARE(region.begin()[0], view.visualRect(range.topLeft()) | view.visualRect(range.bottomRight()));
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_8777_scrollToSpans()
|
|
{
|
|
QTableWidget table(75,5);
|
|
for (int i=0; i<50; i++)
|
|
table.setSpan(2+i, 0, 1, 5);
|
|
table.setCurrentCell(0,2);
|
|
table.show();
|
|
|
|
for (int i = 0; i < 45; ++i)
|
|
QTest::keyClick(&table, Qt::Key_Down);
|
|
|
|
QVERIFY(table.verticalScrollBar()->value() > 10);
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_10169_sizeHintForRow()
|
|
{
|
|
QtTestTableView tableView;
|
|
QStandardItemModel model(1, 3);
|
|
model.setData(model.index(0, 0), "Word wrapping text goes here.");
|
|
tableView.setModel(&model);
|
|
tableView.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
const int orderedHeight = tableView.sizeHintForRow(0);
|
|
tableView.horizontalHeader()->moveSection(2, 0);
|
|
const int reorderedHeight = tableView.sizeHintForRow(0);
|
|
|
|
//the order of the columns shouldn't matter.
|
|
QCOMPARE(orderedHeight, reorderedHeight);
|
|
}
|
|
|
|
void tst_QTableView::viewOptions()
|
|
{
|
|
QtTestTableView view;
|
|
QStyleOptionViewItem options;
|
|
view.initViewItemOption(&options);
|
|
QVERIFY(options.showDecorationSelected);
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_30653_doItemsLayout()
|
|
{
|
|
QWidget topLevel;
|
|
QtTestTableView view(&topLevel);
|
|
|
|
QtTestTableModel model(5, 5);
|
|
view.setModel(&model);
|
|
|
|
QtTestItemDelegate delegate;
|
|
delegate.hint = QSize(50, 50);
|
|
view.setItemDelegate(&delegate);
|
|
|
|
view.resizeRowsToContents();
|
|
view.resizeColumnsToContents();
|
|
|
|
// show two and half rows/cols
|
|
int extraWidth = view.verticalHeader()->sizeHint().width() + view.verticalScrollBar()->sizeHint().width();
|
|
int extraHeight = view.horizontalHeader()->sizeHint().height() + view.horizontalScrollBar()->sizeHint().height();
|
|
view.resize(125 + extraWidth, 125 + extraHeight);
|
|
|
|
topLevel.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
|
|
|
|
// the offset after scrollToBottom() and doItemsLayout() should not differ
|
|
// as the view content should stay aligned to the last section
|
|
view.scrollToBottom();
|
|
int scrollToBottomOffset = view.verticalHeader()->offset();
|
|
view.doItemsLayout();
|
|
int doItemsLayoutOffset = view.verticalHeader()->offset();
|
|
|
|
QCOMPARE(scrollToBottomOffset, doItemsLayoutOffset);
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_7232_AllowUserToControlSingleStep()
|
|
{
|
|
// When we set the scrollMode to ScrollPerPixel it will adjust the scrollbars singleStep automatically
|
|
// Setting a singlestep on a scrollbar should however imply that the user takes control (and it is not changed by geometry updates).
|
|
// Setting a singlestep to -1 return to an automatic control of the singleStep.
|
|
QTableView t;
|
|
t.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
t.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
QStandardItemModel model(200, 200);
|
|
t.setModel(&model);
|
|
t.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&t));
|
|
t.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
t.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
|
|
t.setGeometry(200, 200, 200, 200);
|
|
int vStep1 = t.verticalScrollBar()->singleStep();
|
|
int hStep1 = t.horizontalScrollBar()->singleStep();
|
|
QVERIFY(vStep1 > 1);
|
|
QVERIFY(hStep1 > 1);
|
|
|
|
t.verticalScrollBar()->setSingleStep(1);
|
|
t.setGeometry(300, 300, 300, 300);
|
|
QCOMPARE(t.verticalScrollBar()->singleStep(), 1);
|
|
|
|
t.horizontalScrollBar()->setSingleStep(1);
|
|
t.setGeometry(400, 400, 400, 400);
|
|
QCOMPARE(t.horizontalScrollBar()->singleStep(), 1);
|
|
|
|
t.setGeometry(200, 200, 200, 200);
|
|
t.verticalScrollBar()->setSingleStep(-1);
|
|
t.horizontalScrollBar()->setSingleStep(-1);
|
|
QCOMPARE(vStep1, t.verticalScrollBar()->singleStep());
|
|
QCOMPARE(hStep1, t.horizontalScrollBar()->singleStep());
|
|
}
|
|
|
|
void tst_QTableView::taskQTBUG_50171_selectRowAfterSwapColumns()
|
|
{
|
|
{
|
|
QtTestTableView tableView;
|
|
QtTestTableModel model(2, 3);
|
|
tableView.setModel(&model);
|
|
|
|
tableView.horizontalHeader()->swapSections(1, 2);
|
|
tableView.horizontalHeader()->hideSection(0);
|
|
tableView.selectRow(1);
|
|
|
|
QItemSelectionModel* tableSelectionModel = tableView.selectionModel();
|
|
QCOMPARE(tableSelectionModel->isRowSelected(1, QModelIndex()), true);
|
|
QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 0)), false);
|
|
QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 1)), false);
|
|
QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 2)), false);
|
|
}
|
|
|
|
{
|
|
QtTestTableView tableView;
|
|
QtTestTableModel model(3, 2);
|
|
tableView.setModel(&model);
|
|
|
|
tableView.verticalHeader()->swapSections(1, 2);
|
|
tableView.verticalHeader()->hideSection(0);
|
|
tableView.selectColumn(1);
|
|
|
|
QItemSelectionModel* sModel = tableView.selectionModel();
|
|
QCOMPARE(sModel->isColumnSelected(1, QModelIndex()), true);
|
|
QCOMPARE(sModel->isSelected(tableView.model()->index(0, 0)), false);
|
|
QCOMPARE(sModel->isSelected(tableView.model()->index(1, 0)), false);
|
|
QCOMPARE(sModel->isSelected(tableView.model()->index(2, 0)), false);
|
|
}
|
|
}
|
|
|
|
class DeselectTableWidget : public QTableWidget
|
|
{
|
|
public:
|
|
using QTableWidget::QTableWidget;
|
|
QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &,
|
|
const QEvent * = nullptr) const override
|
|
{
|
|
return QItemSelectionModel::Toggle;
|
|
}
|
|
};
|
|
|
|
void tst_QTableView::deselectRow()
|
|
{
|
|
DeselectTableWidget tw(20, 20);
|
|
tw.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&tw));
|
|
tw.hideColumn(0);
|
|
QVERIFY(tw.isColumnHidden(0));
|
|
tw.selectRow(1);
|
|
QVERIFY(tw.selectionModel()->isRowSelected(1, QModelIndex()));
|
|
tw.selectRow(1);
|
|
// QTBUG-79092 - deselection was not possible when column 0 was hidden
|
|
QVERIFY(!tw.selectionModel()->isRowSelected(1, QModelIndex()));
|
|
}
|
|
|
|
class QTableViewSelectCells : public QTableView
|
|
{
|
|
public:
|
|
QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &index,
|
|
const QEvent *) const override
|
|
{
|
|
return QTableView::selectionCommand(index, shiftPressed ? &mouseEvent : nullptr);
|
|
}
|
|
QMouseEvent mouseEvent = QMouseEvent(QEvent::MouseButtonPress, QPointF(), QPointF(),
|
|
Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier);
|
|
bool shiftPressed = false;
|
|
};
|
|
|
|
void tst_QTableView::selectRowsAndCells()
|
|
{
|
|
const auto checkRows = [](const QModelIndexList &mil)
|
|
{
|
|
QCOMPARE(mil.size(), 3);
|
|
for (const auto &mi : mil)
|
|
QVERIFY(mi.row() >= 1 && mi.row() <= 3);
|
|
};
|
|
QTableViewSelectCells tw;
|
|
QtTestTableModel model(5, 1);
|
|
tw.setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
tw.setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
tw.setModel(&model);
|
|
tw.show();
|
|
|
|
tw.selectRow(1);
|
|
tw.shiftPressed = true;
|
|
tw.selectRow(2);
|
|
tw.shiftPressed = false;
|
|
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ShiftModifier, tw.visualRect(model.index(3, 0)).center());
|
|
checkRows(tw.selectionModel()->selectedRows());
|
|
|
|
tw.clearSelection();
|
|
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, tw.visualRect(model.index(3, 0)).center());
|
|
tw.shiftPressed = true;
|
|
tw.selectRow(1);
|
|
checkRows(tw.selectionModel()->selectedRows());
|
|
}
|
|
|
|
void tst_QTableView::selectColumnsAndCells()
|
|
{
|
|
const auto checkColumns = [](const QModelIndexList &mil)
|
|
{
|
|
QCOMPARE(mil.size(), 3);
|
|
for (const auto &mi : mil)
|
|
QVERIFY(mi.column() >= 1 && mi.column() <= 3);
|
|
};
|
|
QTableViewSelectCells tw;
|
|
QtTestTableModel model(1, 5);
|
|
tw.setSelectionBehavior(QAbstractItemView::SelectColumns);
|
|
tw.setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
tw.setModel(&model);
|
|
tw.show();
|
|
|
|
tw.selectColumn(1);
|
|
tw.shiftPressed = true;
|
|
tw.selectColumn(2);
|
|
tw.shiftPressed = false;
|
|
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ShiftModifier, tw.visualRect(model.index(0, 3)).center());
|
|
checkColumns(tw.selectionModel()->selectedColumns());
|
|
|
|
tw.clearSelection();
|
|
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, tw.visualRect(model.index(0, 3)).center());
|
|
tw.shiftPressed = true;
|
|
tw.selectColumn(1);
|
|
checkColumns(tw.selectionModel()->selectedColumns());
|
|
}
|
|
|
|
void tst_QTableView::selectWithHeader_data()
|
|
{
|
|
QTest::addColumn<Qt::Orientation>("orientation");
|
|
|
|
QTest::addRow("horizontal") << Qt::Horizontal;
|
|
QTest::addRow("vertical") << Qt::Vertical;
|
|
}
|
|
|
|
void tst_QTableView::selectWithHeader()
|
|
{
|
|
QFETCH(Qt::Orientation, orientation);
|
|
|
|
QTableWidget view(10, 10);
|
|
view.resize(200, 100);
|
|
view.show();
|
|
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
|
|
QHeaderView *header;
|
|
QPoint clickPos;
|
|
QModelIndex lastIndex;
|
|
|
|
switch (orientation) {
|
|
case Qt::Horizontal:
|
|
header = view.horizontalHeader();
|
|
clickPos.rx() = header->sectionPosition(0) + header->sectionSize(0) / 2;
|
|
clickPos.ry() = header->height() / 2;
|
|
lastIndex = view.model()->index(9, 0);
|
|
break;
|
|
case Qt::Vertical:
|
|
header = view.verticalHeader();
|
|
clickPos.rx() = header->width() / 2;
|
|
clickPos.ry() = header->sectionPosition(0) + header->sectionSize(0) / 2;
|
|
lastIndex = view.model()->index(0, 9);
|
|
break;
|
|
}
|
|
|
|
const auto isSelected = [&]{
|
|
return orientation == Qt::Horizontal
|
|
? view.selectionModel()->isColumnSelected(0)
|
|
: view.selectionModel()->isRowSelected(0);
|
|
};
|
|
|
|
QTest::mouseClick(header->viewport(), Qt::LeftButton, {}, clickPos);
|
|
QVERIFY(isSelected());
|
|
QTest::mouseClick(header->viewport(), Qt::LeftButton, Qt::ControlModifier, clickPos);
|
|
QVERIFY(!isSelected());
|
|
QTest::mouseClick(header->viewport(), Qt::LeftButton, {}, clickPos);
|
|
QVERIFY(isSelected());
|
|
view.scrollTo(lastIndex);
|
|
QTest::mouseClick(header->viewport(), Qt::LeftButton, Qt::ControlModifier, clickPos);
|
|
QVERIFY(!isSelected());
|
|
}
|
|
|
|
// This has nothing to do with QTableView, but it's convenient to reuse the QtTestTableModel
|
|
#if QT_CONFIG(textmarkdownwriter)
|
|
|
|
// #define DEBUG_WRITE_OUTPUT
|
|
|
|
void tst_QTableView::markdownWriter()
|
|
{
|
|
QtTestTableModel model(2, 3);
|
|
QString md;
|
|
{
|
|
QTextStream stream(&md);
|
|
QTextMarkdownWriter writer(stream, QTextDocument::MarkdownDialectGitHub);
|
|
writer.writeTable(&model);
|
|
}
|
|
|
|
#ifdef DEBUG_WRITE_OUTPUT
|
|
{
|
|
QFile out("/tmp/table.md");
|
|
out.open(QFile::WriteOnly);
|
|
out.write(md.toUtf8());
|
|
out.close();
|
|
}
|
|
#endif
|
|
|
|
QCOMPARE(md, QString::fromLatin1("|1 |2 |3 |\n|-------|-------|-------|\n|[0,0,0]|[0,1,0]|[0,2,0]|\n|[1,0,0]|[1,1,0]|[1,2,0]|\n"));
|
|
}
|
|
#endif
|
|
|
|
void tst_QTableView::rowsInVerticalHeader()
|
|
{
|
|
QtTestTableModel model(0, 2);
|
|
QTableView view;
|
|
view.setModel(&model);
|
|
view.show();
|
|
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
|
auto *verticalHeader = view.verticalHeader();
|
|
QCOMPARE(verticalHeader->count(), 0);
|
|
model.insertRows(2);
|
|
QCOMPARE(verticalHeader->count(), 2);
|
|
}
|
|
|
|
QTEST_MAIN(tst_QTableView)
|
|
#include "tst_qtableview.moc"
|