From 6c04c21c101b70401ad9cb08de1562dc90166e9c Mon Sep 17 00:00:00 2001 From: Martin Pley Date: Fri, 15 Nov 2013 22:01:54 +0100 Subject: Crash fix in QTreeView::sizeHintForColumn(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vertical scrollbar may get out of sync. When this happens, the calculation of firstVisibleItem will retrun "-1". This must be handled in ::sizeHintForColumn(). Added an auto-test for the crashes. Task-number: QTBUG-34717 Change-Id: I867fd144ef3ce45e382337c5eafe345f573cd944 Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qtreeview.cpp | 20 ++++++++++++++- .../widgets/itemviews/qtreeview/tst_qtreeview.cpp | 30 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index fc0d639483..4d0eb5c3ad 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -2858,6 +2858,21 @@ int QTreeView::sizeHintForColumn(int column) const int offset = 0; int start = d->firstVisibleItem(&offset); int end = d->lastVisibleItem(start, offset); + if (start < 0 || end < 0 || end == viewItems.size() - 1) { + end = viewItems.size() - 1; + if (maximumProcessRows < 0) { + start = 0; + } else if (maximumProcessRows == 0) { + start = qMax(0, end - 1); + int remainingHeight = viewport()->height(); + while (start > 0 && remainingHeight > 0) { + remainingHeight -= d->itemHeight(start); + --start; + } + } else { + start = qMax(0, end - maximumProcessRows); + } + } int rowsProcessed = 0; @@ -3606,8 +3621,11 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const { - if (firstVisual < 0 || offset < 0) + if (firstVisual < 0 || offset < 0) { firstVisual = firstVisibleItem(&offset); + if (firstVisual < 0) + return -1; + } int y = - offset; int value = viewport->height(); diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 8d31fcdf13..ccdce1fe0c 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -259,6 +259,7 @@ private slots: void taskQTBUG_25333_adjustViewOptionsForIndex(); void taskQTBUG_18539_emitLayoutChanged(); void taskQTBUG_8176_emitOnExpandAll(); + void taskQTBUG_34717_collapseAtBottom(); void testInitialFocus(); }; @@ -4240,6 +4241,35 @@ void tst_QTreeView::taskQTBUG_8176_emitOnExpandAll() QCOMPARE(spy2.size(), 1); // item2 is collapsed } +// From QTBUG_34717 (QTreeWidget crashes when scrolling to the end +// of an expanded tree, then collapse all) +// The test passes simply if it doesn't crash. +void tst_QTreeView::taskQTBUG_34717_collapseAtBottom() +{ + QTreeWidget treeWidget; + treeWidget.header()->setSectionResizeMode(QHeaderView::ResizeToContents); + treeWidget.setColumnCount(2); + QTreeWidgetItem *mainItem = new QTreeWidgetItem(&treeWidget, QStringList() << "Root"); + for (int i = 0; i < 200; ++i) { + QTreeWidgetItem *item = new QTreeWidgetItem(mainItem, QStringList(QString("Item"))); + new QTreeWidgetItem(item, QStringList() << "Child" << "1"); + new QTreeWidgetItem(item, QStringList() << "Child" << "2"); + new QTreeWidgetItem(item, QStringList() << "Child" << "3"); + } + treeWidget.show(); + treeWidget.expandAll(); + treeWidget.scrollToBottom(); + treeWidget.collapseAll(); + + treeWidget.setAnimated(true); + treeWidget.expandAll(); + treeWidget.scrollToBottom(); + mainItem->setExpanded(false); + + PublicView *pview = (PublicView*) &treeWidget; + QVERIFY(pview->sizeHintForColumn(1) >= 0); +} + void tst_QTreeView::testInitialFocus() { QTreeWidget treeWidget; -- cgit v1.2.3