diff options
-rw-r--r-- | src/widgets/itemviews/qtreeview.cpp | 12 | ||||
-rw-r--r-- | tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp | 151 |
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" |