From daccbc9300abbfdc0baa6d4ef44d26cb81f0d01a Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Thu, 2 Sep 2010 14:13:14 +1000 Subject: Fix crash when all the items in a QListView are hidden Calling QIconModeViewBase::initDynamicLayout() on the second and successive segments would return QPoint(-1,-1), resulting in a totally empty area rectangle for all the items while in QIconModeViewBase::doDynamicLayout(). This rectangle is used to initialize the BSP tree, and produces an arithmetic exception when empty. Furthermore, a rendering bug was also apparent when displaying the first item of a segment while the last item of the previous segment was hidden. Auto-tests included. Reviewed-by: Olivier Task-number: QTBUG-12308 (cherry picked from commit 3c7e7992461b1fef37ada68244f1b5b891015bda) Conflicts: src/gui/itemviews/qlistview.cpp tests/auto/qlistview/tst_qlistview.cpp --- src/gui/itemviews/qlistview.cpp | 7 ++++- tests/auto/qlistview/tst_qlistview.cpp | 53 +++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 1869093..76d7642 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -2782,7 +2782,10 @@ QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info) y = info.bounds.y() + info.spacing; items.reserve(rowCount() - hiddenCount()); } else { - const QListViewItem item = items.at(info.first - 1); + int idx = info.first - 1; + while (idx > 0 && !items.at(idx).isValid()) + --idx; + const QListViewItem &item = items.at(idx); x = item.x; y = item.y; if (info.flow == QListView::LeftToRight) @@ -2913,6 +2916,8 @@ void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info) else contentsSize.rwidth() += info.spacing; } + if (rect.size().isEmpty()) + return; // resize tree int insertFrom = info.first; if (done || info.first == 0) { diff --git a/tests/auto/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp index 330f803..425ac89 100644 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ b/tests/auto/qlistview/tst_qlistview.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -125,6 +126,8 @@ private slots: void taskQTBUG_5877_skippingItemInPageDownUp(); void taskQTBUG_9455_wrongScrollbarRanges(); void styleOptionViewItem(); + void taskQTBUG_12308_artihmeticException(); + void taskQTBUG_12308_wrongFlowLayout(); }; // Testing get/set functions @@ -1653,8 +1656,8 @@ void tst_QListView::task254449_draggingItemToNegativeCoordinates() //we'll make sure the item is repainted delegate.numPaints = 0; QApplication::processEvents(); + QTRY_COMPARE(delegate.numPaints, 1); QCOMPARE(list.visualRect(index).topLeft(), topLeft); - QCOMPARE(delegate.numPaints, 1); } @@ -2002,5 +2005,53 @@ void tst_QListView::styleOptionViewItem() QApplication::processEvents(); } +void tst_QListView::taskQTBUG_12308_artihmeticException() +{ + QListWidget lw; + lw.setLayoutMode(QListView::Batched); + lw.setViewMode(QListView::IconMode); + for (int i = 0; i < lw.batchSize() + 1; i++) { + QListWidgetItem *item = new QListWidgetItem(); + item->setText(QString("Item %L1").arg(i)); + lw.addItem(item); + item->setHidden(true); + } + lw.show(); + QTest::qWaitForWindowShown(&lw); + // No crash, it's all right. +} + +class Delegate12308 : public QStyledItemDelegate +{ + Q_OBJECT +public: + Delegate12308(QObject *parent = 0) : QStyledItemDelegate(parent) + { } + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + { + QVERIFY(option.rect.topLeft() != QPoint(-1, -1)); + QStyledItemDelegate::paint(painter, option, index); + } +}; + +void tst_QListView::taskQTBUG_12308_wrongFlowLayout() +{ + QListWidget lw; + Delegate12308 delegate; + lw.setLayoutMode(QListView::Batched); + lw.setViewMode(QListView::IconMode); + lw.setItemDelegate(&delegate); + for (int i = 0; i < lw.batchSize() + 1; i++) { + QListWidgetItem *item = new QListWidgetItem(); + item->setText(QString("Item %L1").arg(i)); + lw.addItem(item); + if (!item->text().contains(QString::fromAscii("1"))) + item->setHidden(true); + } + lw.show(); + QTest::qWaitForWindowShown(&lw); +} + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" -- cgit v0.12