Crash fix in QTreeView::sizeHintForColumn().

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 <tmartsum@gmail.com>
This commit is contained in:
Martin Pley 2013-11-15 22:01:54 +01:00 committed by The Qt Project
parent 8cbea7a886
commit 6c04c21c10
2 changed files with 49 additions and 1 deletions

View File

@ -2858,6 +2858,21 @@ int QTreeView::sizeHintForColumn(int column) const
int offset = 0; int offset = 0;
int start = d->firstVisibleItem(&offset); int start = d->firstVisibleItem(&offset);
int end = d->lastVisibleItem(start, 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; int rowsProcessed = 0;
@ -3606,8 +3621,11 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const
int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const
{ {
if (firstVisual < 0 || offset < 0) if (firstVisual < 0 || offset < 0) {
firstVisual = firstVisibleItem(&offset); firstVisual = firstVisibleItem(&offset);
if (firstVisual < 0)
return -1;
}
int y = - offset; int y = - offset;
int value = viewport->height(); int value = viewport->height();

View File

@ -259,6 +259,7 @@ private slots:
void taskQTBUG_25333_adjustViewOptionsForIndex(); void taskQTBUG_25333_adjustViewOptionsForIndex();
void taskQTBUG_18539_emitLayoutChanged(); void taskQTBUG_18539_emitLayoutChanged();
void taskQTBUG_8176_emitOnExpandAll(); void taskQTBUG_8176_emitOnExpandAll();
void taskQTBUG_34717_collapseAtBottom();
void testInitialFocus(); void testInitialFocus();
}; };
@ -4240,6 +4241,35 @@ void tst_QTreeView::taskQTBUG_8176_emitOnExpandAll()
QCOMPARE(spy2.size(), 1); // item2 is collapsed 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() void tst_QTreeView::testInitialFocus()
{ {
QTreeWidget treeWidget; QTreeWidget treeWidget;