summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/itemviews/qtreeview.cpp12
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp151
2 files changed, 161 insertions, 2 deletions
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index dedc27501f..3fd0da37cf 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3342,9 +3342,17 @@ void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninit
int count = 0;
if (model->hasChildren(parent)) {
- if (model->canFetchMore(parent))
+ if (model->canFetchMore(parent)) {
+ // fetchMore first, otherwise we might not yet have any data for sizeHintForRow
model->fetchMore(parent);
- count = model->rowCount(parent);
+ // guestimate the number of items in the viewport, and fetch as many as might fit
+ const int itemHeight = defaultItemHeight <= 0 ? q->sizeHintForRow(0) : defaultItemHeight;
+ const int viewCount = viewport->height() / itemHeight;
+ while ((count = model->rowCount(parent)) < viewCount && model->canFetchMore(parent))
+ model->fetchMore(parent);
+ } else {
+ count = model->rowCount(parent);
+ }
}
bool expanding = true;
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 7a22128af3..844c9260bf 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -251,6 +251,7 @@ private slots:
void taskQTBUG_8376();
void taskQTBUG_61476();
void testInitialFocus();
+ void fetchUntilScreenFull();
};
class QtTestModel: public QAbstractItemModel
@@ -5068,5 +5069,155 @@ void tst_QTreeView::taskQTBUG_61476()
QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
}
+void tst_QTreeView::fetchUntilScreenFull()
+{
+ class TreeModel : public QAbstractItemModel
+ {
+ public:
+ const int maxChildren = 49;
+ explicit TreeModel(QObject* parent = nullptr) : QAbstractItemModel(parent)
+ {
+ QVariant rootData1("Parent Col 1");
+ QVariant rootData2("Parent Col 2");
+ QVector<QVariant> rootData;
+ rootData.append(rootData1);
+ rootData.append(rootData2);
+
+ m_root = new TreeItem(rootData, nullptr);
+
+ QVariant childData1("Col 1");
+ QVariant childData2("Col 2");
+ QVector<QVariant> childData;
+ childData.append(childData1);
+ childData.append(childData2);
+
+ TreeItem* item_1 = new TreeItem(childData, m_root);
+ m_root->children.append(item_1);
+
+ TreeItem* item_2 = new TreeItem(childData, item_1);
+ item_1->children.append(item_2);
+ }
+
+ QModelIndex index(const int row, const int column,
+ const QModelIndex& parent = QModelIndex()) const override
+ {
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ TreeItem* parentItem =
+ parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer()) : m_root;
+ TreeItem* childItem = parentItem->children.at(row);
+ return createIndex(row, column, childItem);
+ }
+
+ int rowCount(const QModelIndex& parent) const override
+ {
+ if (parent.column() > 0)
+ return 0;
+
+ TreeItem* parentItem = parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer())
+ : m_root;
+ return parentItem->children.count();
+ }
+
+ int columnCount(const QModelIndex&) const override { return 2; }
+
+ QModelIndex parent(const QModelIndex& childIndex) const override
+ {
+ if (!childIndex.isValid())
+ return QModelIndex();
+
+ TreeItem* parentItem =
+ static_cast<TreeItem*>(childIndex.internalPointer())->parent;
+ return parentItem == m_root ? QModelIndex()
+ : createIndex(parentItem->rowInParent(), 0, parentItem);
+ }
+
+ QVariant data(const QModelIndex& index, const int role) const override
+ {
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
+ return item->data.at(index.column());
+ }
+
+ bool canFetchMore(const QModelIndex& parent) const override
+ {
+ if (!parent.isValid()) {
+ return false;
+ } else {
+ TreeItem* item = static_cast<TreeItem*>(parent.internalPointer());
+ return item->children.size() < maxChildren;
+ }
+ }
+
+ void fetchMore(const QModelIndex& parent) override
+ {
+ if (!parent.isValid())
+ return;
+
+ fetchMoreCount++;
+ TreeItem* parentItem = static_cast<TreeItem*>(parent.internalPointer());
+ int childCount = parentItem->children.size();
+
+ beginInsertRows(parent, childCount, childCount);
+
+ QVariant childData1("Col 1");
+ QVariant childData2("Col 2");
+ QVector<QVariant> childData;
+ childData.append(childData1);
+ childData.append(childData2);
+ TreeItem* newChild = new TreeItem(childData, parentItem);
+ parentItem->children.append(newChild);
+
+ endInsertRows();
+ }
+
+ int fetchMoreCount = 0;
+ private:
+ struct TreeItem
+ {
+ TreeItem(const QVector<QVariant>& values, TreeItem* parent)
+ : data(values), parent(parent)
+ {
+ }
+ ~TreeItem() { qDeleteAll(children); }
+ int rowInParent() const
+ {
+ if (parent)
+ return parent->children.indexOf(const_cast<TreeItem*>(this));
+ return 0;
+ }
+ QVector<QVariant> data;
+ QVector<TreeItem*> children;
+ TreeItem* parent = nullptr;
+ };
+ TreeItem* m_root;
+ };
+
+ QTreeView tv;
+ TreeModel model;
+ tv.setModel(&model);
+
+ const int itemHeight = tv.sizeHintForRow(0);
+ tv.resize(250, itemHeight * 10);
+ tv.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&tv));
+
+ tv.expand(model.index(0, 0));
+ const int viewportHeight = tv.viewport()->height();
+ const int itemCount = viewportHeight / itemHeight;
+ const int minFetchCount = itemCount - 1;
+ const int maxFetchCount = itemCount + 1;
+
+ const bool expectedItemNumberFetched = model.fetchMoreCount >= minFetchCount
+ && model.fetchMoreCount <= maxFetchCount;
+ if (!expectedItemNumberFetched)
+ qDebug() << model.fetchMoreCount << minFetchCount << maxFetchCount;
+ QVERIFY(expectedItemNumberFetched);
+}
+
+
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"