1/****************************************************************************
2**
3** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qdownloadhelperservice_p.h"
41#include "qdownloadnetworkworker_p.h"
42
43#include <QNetworkAccessManager>
44#include <QNetworkRequest>
45#include <QNetworkReply>
46#include <QDataStream>
47
48QT_BEGIN_NAMESPACE
49
50namespace Qt3DCore {
51
52QDownloadNetworkWorker::QDownloadNetworkWorker(QObject *parent)
53 : QObject(parent)
54 , m_networkManager(nullptr)
55{
56 connect(sender: this, signal: &QDownloadNetworkWorker::submitRequest,
57 receiver: this, slot: &QDownloadNetworkWorker::onRequestSubmited);
58 connect(sender: this, signal: &QDownloadNetworkWorker::cancelRequest,
59 receiver: this, slot: &QDownloadNetworkWorker::onRequestCancelled);
60 connect(sender: this, signal: &QDownloadNetworkWorker::cancelAllRequests,
61 receiver: this, slot: &QDownloadNetworkWorker::onAllRequestsCancelled);
62}
63
64void QDownloadNetworkWorker::onRequestSubmited(const QDownloadRequestPtr &request)
65{
66 QMutexLocker l(&m_mutex);
67 if (!m_networkManager) {
68 m_networkManager = new QNetworkAccessManager(this);
69 connect(sender: m_networkManager, signal: &QNetworkAccessManager::finished,
70 receiver: this, slot: &QDownloadNetworkWorker::onRequestFinished);
71 }
72 auto reply = m_networkManager->get(request: QNetworkRequest(request->url()));
73 m_requests << QPair<QDownloadRequestPtr, QNetworkReply *>(request, reply);
74 connect(sender: reply, signal: &QNetworkReply::downloadProgress, receiver: this, slot: &QDownloadNetworkWorker::onDownloadProgressed);
75}
76
77void QDownloadNetworkWorker::onRequestCancelled(const QDownloadRequestPtr &request)
78{
79 QMutexLocker l(&m_mutex);
80 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
81 pred: [request](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
82 return e.first == request;
83 });
84 if (it == m_requests.end())
85 return;
86
87 (*it).first->m_cancelled = true;
88 (*it).second->abort();
89}
90
91void QDownloadNetworkWorker::onAllRequestsCancelled()
92{
93 QMutexLocker l(&m_mutex);
94 for (auto &e: qAsConst(t&: m_requests)) {
95 e.first->m_cancelled = true;
96 e.second->abort();
97 }
98 m_requests.clear();
99}
100
101void QDownloadNetworkWorker::onRequestFinished(QNetworkReply *reply)
102{
103 QMutexLocker l(&m_mutex);
104 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
105 pred: [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
106 return e.second == reply;
107 });
108 if (it == m_requests.end())
109 return;
110
111 auto request = (*it).first;
112 if (reply->error() == QNetworkReply::NoError) {
113 request->m_succeeded = true;
114 }
115 request->onDownloaded();
116 emit requestDownloaded(request);
117
118 m_requests.erase(pos: it);
119}
120
121void QDownloadNetworkWorker::onDownloadProgressed(qint64 bytesReceived, qint64 bytesTotal)
122{
123 Q_UNUSED(bytesReceived);
124 Q_UNUSED(bytesTotal);
125 // TODO forward progress details somewhere
126
127 QNetworkReply *reply = qobject_cast<QNetworkReply *>(object: sender());
128 if (!reply)
129 return;
130
131 QMutexLocker l(&m_mutex);
132 auto it = std::find_if(first: m_requests.begin(), last: m_requests.end(),
133 pred: [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
134 return e.second == reply;
135 });
136 if (it == m_requests.end())
137 return;
138
139 auto request = (*it).first;
140 QDataStream stream(&request->m_data, QIODevice::Append);
141 QByteArray data = reply->readAll();
142 stream.writeRawData(data.data(), len: data.size());
143}
144
145} // namespace Qt3DCore
146
147QT_END_NAMESPACE
148
149

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