// 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)) { 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 &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 ThreadedFetchMoreModel::roleNames() const { static const QHash names = {{static_cast(Role::Title), "title"}, {static_cast(Role::Subtitle), "subtitle"}, {static_cast(Role::Number), "number"}, {static_cast(Role::LoadingElement), "isLoadingElement"}}; return names; }