diff options
| author | Otto Ryynänen <otto.ryynanen@qt.io> | 2025-03-31 10:18:10 +0300 |
|---|---|---|
| committer | Otto Ryynänen <otto.ryynanen@qt.io> | 2025-04-04 19:31:49 +0300 |
| commit | 0e92a8e0683e2d388a61aac85509a8efbc16cd01 (patch) | |
| tree | 3b5588fb8f6e7ebdeff23b1cb6867941e00cdf51 /examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp | |
| parent | a951832b74749cde7832ee906df087ac857f5cbd (diff) | |
Introduce threaded fetchmore example
Added an example of combining QThread and QAbstractItemModel - a feat
that our customers ask every now and then
Task-number: QTBUG-135351
Pick-to: 6.8 6.9
Change-Id: I476e7121361e4d85c2d87eb663f0389a337a3085
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp')
| -rw-r--r-- | examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp b/examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp new file mode 100644 index 0000000000..a7b8d44570 --- /dev/null +++ b/examples/quick/models/threadedfetchmore/threadedfetchmoremodel.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "threadedfetchmoremodel.h" + +ThreadedFetchMoreModel::ThreadedFetchMoreModel() +{ + auto worker = new FetchWorker(); + connect(&m_workerThread, &QThread::finished, worker, &QObject::deleteLater); + worker->moveToThread(&m_workerThread); + connect(this, &ThreadedFetchMoreModel::fetchDataBlock, worker, &FetchWorker::fetchDataBlock); + connect(worker, &FetchWorker::dataFetched, this, &ThreadedFetchMoreModel::dataReceived); + connect(worker, &FetchWorker::noMoreToFetch, this, &ThreadedFetchMoreModel::noMoreToFetch); + m_workerThread.start(); +} + +ThreadedFetchMoreModel::~ThreadedFetchMoreModel() +{ + m_workerThread.requestInterruption(); + m_workerThread.quit(); + m_workerThread.wait(); +} + +int ThreadedFetchMoreModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + return m_dataList.size(); +} + +QVariant ThreadedFetchMoreModel::data(const QModelIndex &index, int role) const +{ + const auto item = m_dataList.at(index.row()); + switch (static_cast<Role>(role)) { + case Role::Title: + return item.title; + case Role::Subtitle: + return item.subtitle; + case Role::Number: + return item.number; + case Role::LoadingElement: + return m_fetchOngoing && index.row() == (rowCount() - 1); + default: + break; + } + return QVariant{}; +} + +void ThreadedFetchMoreModel::fetchMore(const QModelIndex &parent) +{ + Q_UNUSED(parent) + if (!m_fetchOngoing) { + addLoadingItem(); + emit fetchDataBlock(); + } +} + +bool ThreadedFetchMoreModel::canFetchMore(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + if (m_fetchOngoing) + return false; + return m_hasUnfetchedItems; +} + +void ThreadedFetchMoreModel::dataReceived(const QList<FetchWorker::DataBlock> &items) +{ + removeLoadingItem(); + beginInsertRows(QModelIndex{}, rowCount(), rowCount() + items.size() - 1); + m_dataList.append(items); + endInsertRows(); +} + +void ThreadedFetchMoreModel::noMoreToFetch() +{ + m_hasUnfetchedItems = false; +} + +void ThreadedFetchMoreModel::addLoadingItem() +{ + beginInsertRows(QModelIndex{}, rowCount(), rowCount()); + m_fetchOngoing = true; + m_dataList.append({{}, {}, 0}); + endInsertRows(); +} + +void ThreadedFetchMoreModel::removeLoadingItem() +{ + beginRemoveRows(QModelIndex{}, rowCount() - 1, rowCount() - 1); + m_fetchOngoing = false; + m_dataList.removeAt(rowCount() - 1); + endRemoveRows(); +} + +QHash<int, QByteArray> ThreadedFetchMoreModel::roleNames() const +{ + static const QHash<int, QByteArray> names = {{static_cast<int>(Role::Title), "title"}, + {static_cast<int>(Role::Subtitle), "subtitle"}, + {static_cast<int>(Role::Number), "number"}, + {static_cast<int>(Role::LoadingElement), + "isLoadingElement"}}; + return names; +} |
