1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "datastorage.h"
#include "queueworker.h"
DataStorage::DataStorage() : QObject{ nullptr }
{
/* Generate a list of IDs to use locally.
* DataStorage will use indexes for accessing the remote data.
*/
m_idList.reserve(RemoteMedia::count());
for (int id = 1; id <= RemoteMedia::count(); ++id) {
m_idList.append(id);
}
m_worker = new QueueWorker;
connect(&m_workerThread, &QThread::finished, m_worker, &QObject::deleteLater);
m_worker->moveToThread(&m_workerThread);
connect(m_worker, &QueueWorker::dataFetched, this, &DataStorage::dataReceived);
connect(m_worker, &QueueWorker::processing, this, &DataStorage::fetchStarted);
connect(m_worker, &QueueWorker::dropped, this, &DataStorage::fetchAborted);
connect(this, &DataStorage::dataFetchNeeded, m_worker, &QueueWorker::fetchData);
m_workerThread.start();
}
DataStorage::~DataStorage()
{
/* Clean the worker object by stopping it and then ending the thread */
m_worker->abort();
m_worker = nullptr;
m_workerThread.quit();
m_workerThread.wait();
}
QList<int> DataStorage::idList()
{
return m_idList;
}
MediaElement DataStorage::item(int id) const
{
if (id < 1)
return MediaElement{};
//! [Send signal if no data]
if (!m_items.contains(id)) {
m_items.insert(id, MediaElement{});
emit dataFetchNeeded(m_idList.indexOf(id));
}
return m_items.value(id);
//! [Send signal if no data]
}
std::optional<int> DataStorage::currentlyFetchedId() const
{
return m_currentlyFetchedId;
}
void DataStorage::fetchStarted(int index)
{
const auto idBeingFetched = m_idList.at(index);
m_currentlyFetchedId = idBeingFetched;
emit dataUpdated(idBeingFetched);
}
void DataStorage::fetchAborted(int index)
{
/* The data will never be fetched. Remove the empty item (so storge will send a signal to thread
* if needed). Then send dataUpdated signal. If the item is still visible, view will re-request
* its data and item will be requeued to thread. If item is no longer in visible area, view will
* ignore the dataChanged signal and storage will not receive any calls.
*/
const auto idAborted = m_idList.at(index);
m_items.remove(idAborted);
if (m_currentlyFetchedId == idAborted)
m_currentlyFetchedId = std::nullopt;
emit dataUpdated(idAborted);
}
void DataStorage::dataReceived(int index, MediaElement element)
{
const auto idUpdated = m_idList.at(index);
m_items.insert(idUpdated, element);
emit dataUpdated(idUpdated);
}
|