1// Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qdownloadhelperservice_p.h"
5#include "qdownloadnetworkworker_p.h"
6
7#include <QNetworkAccessManager>
8#include <QNetworkRequest>
9#include <QNetworkReply>
10#include <QDataStream>
11
12QT_BEGIN_NAMESPACE
13
14namespace Qt3DCore {
15
16QDownloadNetworkWorker::QDownloadNetworkWorker(QObject *parent)
17 : QObject(parent)
18 , m_networkManager(nullptr)
19{
20 connect(sender: this, signal: &QDownloadNetworkWorker::submitRequest,
21 context: this, slot: &QDownloadNetworkWorker::onRequestSubmited);
22 connect(sender: this, signal: &QDownloadNetworkWorker::cancelRequest,
23 context: this, slot: &QDownloadNetworkWorker::onRequestCancelled);
24 connect(sender: this, signal: &QDownloadNetworkWorker::cancelAllRequests,
25 context: this, slot: &QDownloadNetworkWorker::onAllRequestsCancelled);
26}
27
28void QDownloadNetworkWorker::onRequestSubmited(const QDownloadRequestPtr &request)
29{
30 QMutexLocker l(&m_mutex);
31 if (!m_networkManager) {
32 m_networkManager = new QNetworkAccessManager(this);
33 connect(sender: m_networkManager, signal: &QNetworkAccessManager::finished,
34 context: this, slot: &QDownloadNetworkWorker::onRequestFinished);
35 }
36 auto reply = m_networkManager->get(request: QNetworkRequest(request->url()));
37 m_requests << QPair<QDownloadRequestPtr, QNetworkReply *>(request, reply);
38 connect(sender: reply, signal: &QNetworkReply::downloadProgress, context: this, slot: &QDownloadNetworkWorker::onDownloadProgressed);
39}
40
41void QDownloadNetworkWorker::onRequestCancelled(const QDownloadRequestPtr &request)
42{
43 QMutexLocker l(&m_mutex);
44 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
45 pred: [request](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
46 return e.first == request;
47 });
48 if (it == m_requests.end())
49 return;
50
51 (*it).first->m_cancelled = true;
52 (*it).second->abort();
53}
54
55void QDownloadNetworkWorker::onAllRequestsCancelled()
56{
57 QMutexLocker l(&m_mutex);
58 for (auto &e: std::as_const(t&: m_requests)) {
59 e.first->m_cancelled = true;
60 e.second->abort();
61 }
62 m_requests.clear();
63}
64
65void QDownloadNetworkWorker::onRequestFinished(QNetworkReply *reply)
66{
67 QMutexLocker l(&m_mutex);
68 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
69 pred: [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
70 return e.second == reply;
71 });
72 if (it == m_requests.end())
73 return;
74
75 auto request = (*it).first;
76 if (reply->error() == QNetworkReply::NoError) {
77 request->m_succeeded = true;
78 }
79 request->onDownloaded();
80 emit requestDownloaded(request);
81
82 m_requests.erase(pos: it);
83}
84
85void QDownloadNetworkWorker::onDownloadProgressed(qint64 bytesReceived, qint64 bytesTotal)
86{
87 Q_UNUSED(bytesReceived);
88 Q_UNUSED(bytesTotal);
89 // TODO forward progress details somewhere
90
91 QNetworkReply *reply = qobject_cast<QNetworkReply *>(object: sender());
92 if (!reply)
93 return;
94
95 QMutexLocker l(&m_mutex);
96 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
97 pred: [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
98 return e.second == reply;
99 });
100 if (it == m_requests.end())
101 return;
102
103 auto request = (*it).first;
104 QDataStream stream(&request->m_data, QIODevice::Append);
105 QByteArray data = reply->readAll();
106 stream.writeRawData(data.data(), len: data.size());
107}
108
109} // namespace Qt3DCore
110
111QT_END_NAMESPACE
112
113#include "moc_qdownloadnetworkworker_p.cpp"
114
115

source code of qt3d/src/core/services/qdownloadnetworkworker.cpp