diff options
Diffstat (limited to 'tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp')
-rw-r--r-- | tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp | 524 |
1 files changed, 480 insertions, 44 deletions
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 3768acade7..236cd6212f 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QListWidget> @@ -37,14 +12,18 @@ #include <QTest> #include <QTimer> #include <QtMath> +#include <QProxyStyle> +#include <QVBoxLayout> +#include <QDialog> #include <QtTest/private/qtesthelpers_p.h> #include <QtWidgets/private/qlistview_p.h> +#include <QtWidgets/private/qapplication_p.h> using namespace QTestPrivate; #if defined(Q_OS_WIN) -# include <windows.h> +# include <qt_windows.h> # include <QDialog> # include <QGuiApplication> # include <QVBoxLayout> @@ -89,8 +68,14 @@ public: { return QListView::visualRegionForSelection(selectionModel()->selection()); } + void moveEvent(QMoveEvent *e) override + { + QListView::moveEvent(e); + m_gotValidResizeEvent = !e->pos().isNull(); + } friend class tst_QListView; + bool m_gotValidResizeEvent = false; }; class tst_QListView : public QObject @@ -109,6 +94,8 @@ private slots: void moveCursor(); void moveCursor2(); void moveCursor3(); + void moveCursor4(); + void moveCursor5(); void indexAt(); void clicked(); void singleSelectionRemoveRow(); @@ -164,12 +151,18 @@ private slots: void taskQTBUG_39902_mutualScrollBars(); void horizontalScrollingByVerticalWheelEvents(); void taskQTBUG_7232_AllowUserToControlSingleStep(); + void taskQTBUG_58749_adjustToContent(); void taskQTBUG_51086_skippingIndexesInSelectedIndexes(); void taskQTBUG_47694_indexOutOfBoundBatchLayout(); + void moveLastRow(); void itemAlignment(); void internalDragDropMove_data(); void internalDragDropMove(); + void spacingWithWordWrap_data(); void spacingWithWordWrap(); + void scrollOnRemove_data(); + void scrollOnRemove(); + void wordWrapNullIcon(); }; // Testing get/set functions @@ -435,7 +428,7 @@ void tst_QListView::cursorMove() } break; default: - QVERIFY(false); + QFAIL(qPrintable(QStringLiteral("Unexpected key: %1").arg(key))); } QCoreApplication::processEvents(); @@ -573,6 +566,76 @@ void tst_QListView::moveCursor3() QCOMPARE(view.selectionModel()->currentIndex(), model.index(0, 0)); } +void tst_QListView::moveCursor4() +{ + int indexCount = 100; + PublicListView listView; + QStandardItemModel model; + for (int i = 0; i < 100; i++) + { + QStandardItem* item = new QStandardItem(QString("item 0%0").arg(i)); + QFont font = item->font(); + font.setPixelSize(14); + item->setFont(font); + model.appendRow(item); + } + QFont font = model.item(0)->font(); + font.setPixelSize(50); + font.setBold(true); + model.item(0)->setFont(font); + listView.setModel(&model); + listView.setFixedSize(200, 200); + listView.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView.show(); + listView.selectionModel()->setCurrentIndex(model.index(0, 0), QItemSelectionModel::SelectCurrent); + + QModelIndex idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + + int actualIndex = 0; + int indexHeight = 0; + while (indexHeight <= listView.viewport()->height()) { + indexHeight += listView.visualRect(model.item(actualIndex)->index()).height(); + actualIndex++; + } + QTRY_COMPARE(idx, model.index(actualIndex - 2, 0)); + idx = listView.moveCursor(PublicListView::MoveUp, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(0, 0)); + + listView.setCurrentIndex(model.index(indexCount - 2, 0)); + idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(99, 0)); + + listView.setCurrentIndex(model.index(3, 0)); + actualIndex = 3; + indexHeight = 0; + while (indexHeight <= listView.viewport()->height()) { + indexHeight += listView.visualRect(model.item(actualIndex)->index()).height(); + actualIndex++; + } + idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(actualIndex - 2, 0)); +} + +void tst_QListView::moveCursor5() +{ + PublicListView listView; + QStandardItemModel model; + QIcon icon(QPixmap(300,300)); + model.appendRow(new QStandardItem(icon,"11")); + model.appendRow(new QStandardItem(icon,"22")); + model.appendRow(new QStandardItem(icon,"33")); + listView.setModel(&model); + listView.setGeometry(10,10,200,200); + listView.setIconSize(QSize(300,300)); + listView.setViewMode(QListView::IconMode); + listView.setCurrentIndex(model.index(0, 0)); + + QModelIndex idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(1, 0)); + idx = listView.moveCursor(PublicListView::MovePageUp, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(0, 0)); +} class QListViewShowEventListener : public QListView { @@ -663,7 +726,7 @@ void tst_QListView::clicked() continue; QSignalSpy spy(&view, &QListView::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } } @@ -1092,7 +1155,7 @@ void tst_QListView::selection() v.setSelection(selectionRect, QItemSelectionModel::ClearAndSelect); const QModelIndexList selected = v.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), expectedItems.count()); + QCOMPARE(selected.size(), expectedItems.size()); for (const auto &idx : selected) QVERIFY(expectedItems.contains(idx.row())); } @@ -1502,7 +1565,7 @@ void tst_QListView::task203585_selectAll() QVERIFY(view.selectionModel()->selectedIndexes().isEmpty()); view.setRowHidden(0, false); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); } void tst_QListView::task228566_infiniteRelayout() @@ -1587,7 +1650,7 @@ void tst_QListView::task196118_visualRegionForSelection() view.selectionModel()->select(top1.index(), QItemSelectionModel::Select); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.getVisualRegionForSelection().isEmpty()); } @@ -1644,7 +1707,6 @@ void tst_QListView::keyboardSearch() QListView view; view.setModel(&model); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::keyClick(&view, Qt::Key_K); @@ -1685,7 +1747,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() QTRY_COMPARE(view.currentIndex(), model.index(1, 0)); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(!selected.contains(model.index(0, 0))); } { // Second test: QListView::TopToBottom flow @@ -1712,7 +1774,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() QTRY_COMPARE(view.currentIndex(), model.index(1, 0)); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(!selected.contains(model.index(0, 0))); } } @@ -1746,7 +1808,6 @@ void tst_QListView::shiftSelectionWithItemAlignment() view.resize(300, view.sizeHintForRow(0) * items.size() / 2 + view.horizontalScrollBar()->height()); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow()); @@ -1774,7 +1835,7 @@ void tst_QListView::clickOnViewportClearsSelection() view.selectAll(); QModelIndex index = model.index(0); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.selectionModel()->isSelected(index)); //we try to click outside of the index @@ -1782,7 +1843,7 @@ void tst_QListView::clickOnViewportClearsSelection() QTest::mousePress(view.viewport(), Qt::LeftButton, {}, point); //at this point, the selection shouldn't have changed - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.selectionModel()->isSelected(index)); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, point); @@ -1805,7 +1866,6 @@ void tst_QListView::task262152_setModelColumnNavigate() view.setModelColumn(1); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); QTest::keyClick(&view, Qt::Key_Down); @@ -1891,7 +1951,7 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() view.setModel(&model); view.setSelectionMode(QAbstractItemView::ExtendedSelection); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), model.rowCount()); const QRect itemRect = view.visualRect(model.index(model.rowCount() - 1)); @@ -1901,7 +1961,7 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() QVERIFY(!view.selectionModel()->hasSelection()); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), model.rowCount()); //and now the right button QTest::mouseClick(view.viewport(), Qt::RightButton, {}, p); @@ -2472,6 +2532,46 @@ void tst_QListView::taskQTBUG_7232_AllowUserToControlSingleStep() QCOMPARE(hStep1, lv.horizontalScrollBar()->singleStep()); } +void tst_QListView::taskQTBUG_58749_adjustToContent() +{ + QStandardItemModel model; + model.setRowCount(20); + model.setColumnCount(1); + const QString rowStr = QStringLiteral("Row number txt:"); + for (int u = 0; u < model.rowCount(); ++u) + model.setData(model.index(u, 0), rowStr + QString::number(u)); + + QDialog w; // It really should work for QWidget, too, but sometimes an event (like move) + // is needed to get the resize triggered. + QVBoxLayout *l = new QVBoxLayout(&w); + l->setSizeConstraint(QLayout::SetFixedSize); + auto *view = new QListView; + view->setModel(&model); + view->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + l->addWidget(view); + l->setSizeConstraint(QLayout::SetFixedSize); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + const QString longText = "Here we have a row text that is somewhat longer ..."; + + QFontMetrics fm(w.font(), &w); + QRect r = fm.boundingRect(model.data(model.index(0, 0)).toString()); + const int longTextWidth = fm.horizontalAdvance(longText); + QVERIFY(w.height() > r.height() * model.rowCount()); + // We have a width longer than the width for the given index data. + QVERIFY(w.width() > r.width()); + // but ... the width should not have a width matching the much longer text. + QVERIFY(w.width() < longTextWidth); + + // use the long text and make sure the width is adjusted. + model.setData(model.index(0, 0), longText); + QApplication::processEvents(); + const QRect itemRect = view->visualRect(model.index(0, 0)); + QVERIFY(w.width() > itemRect.width()); + QCOMPARE_GE(view->width(), itemRect.width()); +} + void tst_QListView::taskQTBUG_51086_skippingIndexesInSelectedIndexes() { QStandardItemModel data(10, 1); @@ -2505,6 +2605,221 @@ void tst_QListView::taskQTBUG_47694_indexOutOfBoundBatchLayout() view.scrollTo(model.index(batchSize - 1, 0)); } +class TstMoveItem +{ + friend class TstMoveModel; +public: + TstMoveItem(TstMoveItem *parent = nullptr) + : parentItem(parent) + { + if (parentItem) + parentItem->childItems.append(this); + } + + ~TstMoveItem() + { + QList<TstMoveItem *> delItms; + delItms.swap(childItems); + qDeleteAll(delItms); + + if (parentItem) + parentItem->childItems.removeAll(this); + } + + int row() + { + if (parentItem) + return parentItem->childItems.indexOf(this); + return -1; + } + +public: + TstMoveItem *parentItem = nullptr; + QList<TstMoveItem *> childItems; + QHash<int, QVariant> data; +}; + +/*! + Test that removing the last row in an IconView mode QListView + doesn't crash. The model is specifically crafted to provoke a + stale QBspTree by returning a 0 column count for indexes without + children, which changes the column count after moving the last row. + + See QTBUG_95463. +*/ +class TstMoveModel : public QAbstractItemModel +{ + Q_OBJECT +public: + TstMoveModel(QObject *parent = nullptr) + : QAbstractItemModel(parent) + { + rootItem = new TstMoveItem; + rootItem->data.insert(Qt::DisplayRole, "root"); + + TstMoveItem *itm = new TstMoveItem(rootItem); + itm->data.insert(Qt::DisplayRole, "parentItem1"); + + TstMoveItem *itmCh = new TstMoveItem(itm); + itmCh->data.insert(Qt::DisplayRole, "childItem"); + + itm = new TstMoveItem(rootItem); + itm->data.insert(Qt::DisplayRole, "parentItem2"); + } + + ~TstMoveModel() + { + delete rootItem; + } + + QModelIndex index(int row, int column, const QModelIndex &idxPar = QModelIndex()) const override + { + QModelIndex idx; + if (hasIndex(row, column, idxPar)) { + TstMoveItem *parentItem = nullptr; + if (idxPar.isValid()) + parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer()); + else + parentItem = rootItem; + + Q_ASSERT(parentItem); + TstMoveItem *childItem = parentItem->childItems.at(row); + if (childItem) + idx = createIndex(row, column, childItem); + } + return idx; + } + + QModelIndex parent(const QModelIndex &index) const override + { + QModelIndex idxPar; + if (index.isValid()) { + TstMoveItem *childItem = static_cast<TstMoveItem *>(index.internalPointer()); + TstMoveItem *parentItem = childItem->parentItem; + if (parentItem != rootItem) + idxPar = createIndex(parentItem->row(), 0, parentItem); + } + return idxPar; + } + + int columnCount(const QModelIndex &idxPar = QModelIndex()) const override + { + int cnt = 0; + if (idxPar.isValid()) { + TstMoveItem *parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer()); + Q_ASSERT(parentItem); + cnt = parentItem->childItems.isEmpty() ? 0 : 1; + } else { + cnt = rootItem->childItems.isEmpty() ? 0 : 1; + } + return cnt; + } + + int rowCount(const QModelIndex &idxPar = QModelIndex()) const override + { + int cnt = 0; + if (idxPar.isValid()) { + TstMoveItem *parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer()); + Q_ASSERT(parentItem); + cnt = parentItem->childItems.size(); + } else { + cnt = rootItem->childItems.size(); + } + return cnt; + } + + Qt::ItemFlags flags(const QModelIndex &index) const override + { + Q_UNUSED(index) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + + bool hasChildren(const QModelIndex &parent = QModelIndex()) const override + { + bool ret = false; + if (parent.isValid()) { + TstMoveItem *parentItem = static_cast<TstMoveItem *>(parent.internalPointer()); + Q_ASSERT(parentItem); + ret = parentItem->childItems.size() > 0; + } else { + ret = rootItem->childItems.size() > 0; + } + return ret; + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + { + QVariant dt; + if (index.isValid()) { + TstMoveItem *item = static_cast<TstMoveItem *>(index.internalPointer()); + if (item) + dt = item->data.value(role); + } + return dt; + } + + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override + { + TstMoveItem *itmSrcParent = itemAt(sourceParent); + TstMoveItem *itmDestParent = itemAt(destinationParent); + + if (itmSrcParent && sourceRow >= 0 + && sourceRow + count <= itmSrcParent->childItems.size() + && itmDestParent && destinationChild <= itmDestParent->childItems.size()) { + beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, + destinationParent, destinationChild); + QList<TstMoveItem *> itemsToMove; + for (int i = 0; i < count; ++i) { + TstMoveItem *itm = itmSrcParent->childItems.at(sourceRow+i); + itemsToMove.append(itm); + } + for (int i = itemsToMove.size() -1; i >= 0; --i) { + TstMoveItem *itm = itemsToMove.at(i); + itm->parentItem->childItems.removeAll(itm); + itm->parentItem = itmDestParent; + itmDestParent->childItems.insert(destinationChild, itm); + } + endMoveRows(); + return true; + } + return false; + } + +private: + TstMoveItem *itemAt(const QModelIndex &index) const + { + TstMoveItem *item = nullptr; + if (index.isValid()) { + Q_ASSERT(index.model() == this); + item = static_cast<TstMoveItem *>(index.internalPointer()); + } else { + item = rootItem; + } + return item; + } + +private: + TstMoveItem *rootItem = nullptr; +}; + +void tst_QListView::moveLastRow() +{ + TstMoveModel model; + QListView view; + view.setModel(&model); + view.setRootIndex(model.index(0, 0, QModelIndex())); + view.setViewMode(QListView::IconMode); + view.show(); + + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QModelIndex sourceParent = model.index(0, 0); + QModelIndex destinationParent = model.index(1, 0); + // must not crash when paint event is processed + model.moveRow(sourceParent, 0, destinationParent, 0); + QTest::qWait(100); +} + void tst_QListView::itemAlignment() { auto item1 = new QStandardItem("111"); @@ -2543,6 +2858,7 @@ void tst_QListView::internalDragDropMove_data() | Qt::ItemIsEditable | Qt::ItemIsDragEnabled; + const QStringList unchanged = QStringList{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; const QStringList reordered = QStringList{"0", "2", "3", "4", "5", "6", "7", "8", "9", "1"}; const QStringList replaced = QStringList{"0", "2", "3", "4", "1", "6", "7", "8", "9"}; @@ -2557,7 +2873,8 @@ void tst_QListView::internalDragDropMove_data() << Qt::MoveAction << defaultFlags << modelMoves - << reordered; + // listview in IconMode doesn't change the model + << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered); QTest::newRow((rowName + ", only move").constData()) << viewMode @@ -2566,7 +2883,8 @@ void tst_QListView::internalDragDropMove_data() << Qt::MoveAction << defaultFlags << modelMoves - << reordered; + // listview in IconMode doesn't change the model + << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered); QTest::newRow((rowName + ", replace item").constData()) << viewMode @@ -2679,6 +2997,7 @@ void tst_QListView::internalDragDropMove() // The test relies on the global position of mouse events; make sure // the window is properly mapped on X11. QVERIFY(QTest::qWaitForWindowActive(&list)); + QVERIFY(QTest::qWaitFor([&]() { return list.m_gotValidResizeEvent; })); // execute as soon as the eventloop is running again // which is the case inside list.startDrag() QTimer::singleShot(0, [&]() @@ -2714,8 +3033,42 @@ void tst_QListView::internalDragDropMove() /*! Verify fix for QTBUG-92366 */ +void tst_QListView::spacingWithWordWrap_data() +{ + QTest::addColumn<bool>("scrollBarOverlap"); + + QTest::addRow("Without overlap") << false; + QTest::addRow("With overlap") << true; +} + void tst_QListView::spacingWithWordWrap() { + QFETCH(bool, scrollBarOverlap); + + class MyStyle : public QProxyStyle + { + bool scrollBarOverlap; + public: + MyStyle(bool scrollBarOverlap) : scrollBarOverlap(scrollBarOverlap) {} + + int pixelMetric(PixelMetric metric, const QStyleOption *option = nullptr, + const QWidget *widget = nullptr) const override{ + switch (metric) { + case QStyle::PM_ScrollView_ScrollBarOverlap: return scrollBarOverlap; + default: + break; + } + return QProxyStyle::pixelMetric(metric, option, widget); + } + }; + + QStyle *oldStyle = QApplication::style(); + oldStyle->setParent(nullptr); + const auto resetStyle = qScopeGuard([oldStyle]{ + QApplication::setStyle(oldStyle); + }); + QApplication::setStyle(new MyStyle(scrollBarOverlap)); + const int listViewResizeCount = 200; QWidget window; window.resize(300, 200); @@ -2765,5 +3118,88 @@ void tst_QListView::spacingWithWordWrap() } } +void tst_QListView::scrollOnRemove_data() +{ + QTest::addColumn<QListView::ViewMode>("viewMode"); + QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode"); + + const QMetaObject &mo = QListView::staticMetaObject; + const auto viewModeEnum = mo.enumerator(mo.indexOfEnumerator("ViewMode")); + const auto selectionModeEnum = mo.enumerator(mo.indexOfEnumerator("SelectionMode")); + for (auto viewMode : { QListView::ListMode, QListView::IconMode }) { + const char *viewModeName = viewModeEnum.valueToKey(viewMode); + for (int index = 0; index < selectionModeEnum.keyCount(); ++index) { + const auto selectionMode = QAbstractItemView::SelectionMode(selectionModeEnum.value(index)); + const char *selectionModeName = selectionModeEnum.valueToKey(selectionMode); + QTest::addRow("%s, %s", viewModeName, selectionModeName) << viewMode << selectionMode; + } + } +} + +void tst_QListView::scrollOnRemove() +{ + QFETCH(QListView::ViewMode, viewMode); + QFETCH(QAbstractItemView::SelectionMode, selectionMode); + + QPixmap pixmap; + if (viewMode == QListView::IconMode) { + pixmap = QPixmap(25, 25); + pixmap.fill(Qt::red); + } + + QStandardItemModel model; + for (int i = 0; i < 50; ++i) { + QStandardItem *item = new QStandardItem(QString::number(i)); + item->setIcon(pixmap); + model.appendRow(item); + } + + QWidget widget; + QListView view(&widget); + view.setFixedSize(100, 100); + view.setAutoScroll(true); + if (viewMode == QListView::IconMode) + view.setWrapping(true); + view.setModel(&model); + view.setSelectionMode(selectionMode); + view.setViewMode(viewMode); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QCOMPARE(view.verticalScrollBar()->value(), 0); + const QModelIndex item25 = model.index(25, 0); + view.scrollTo(item25); + QTRY_VERIFY(view.verticalScrollBar()->value() > 0); // layout and scrolling are delayed + const int item25Position = view.verticalScrollBar()->value(); + // selecting a fully visible item shouldn't scroll + view.selectionModel()->setCurrentIndex(item25, QItemSelectionModel::SelectCurrent); + QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position); + + // removing the selected item might scroll if another item is selected + model.removeRow(25); + + // if nothing is selected now, then the view should not have scrolled + if (!view.selectionModel()->selectedIndexes().size()) + QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position); +} + +void tst_QListView::wordWrapNullIcon() +{ + QListView listView; + listView.setViewMode(QListView::IconMode); + listView.setWrapping(true); + listView.setWordWrap(true); + listView.setFixedSize(QSize(100, 500)); + + QStandardItemModel model; + QStandardItem *item = new QStandardItem(QIcon(), "This is a long text for word wrapping Item_"); + model.appendRow(item); + listView.setModel(&model); + + listView.indexAt(QPoint(0, 0)); +} + + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" |