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#include <QtCore/QThread>
43#include <Qt3DCore/QAspectEngine>
44#include <Qt3DCore/private/qabstractserviceprovider_p.h>
45#include <Qt3DCore/private/qaspectengine_p.h>
46#include <Qt3DCore/private/qaspectmanager_p.h>
47#include <Qt3DCore/private/qservicelocator_p.h>
48
49#include <QFile>
50
51QT_BEGIN_NAMESPACE
52
53namespace Qt3DCore {
54
55QDownloadRequest::QDownloadRequest(const QUrl &url)
56 : m_url(url)
57 , m_succeeded(false)
58 , m_cancelled(false)
59{
60
61}
62
63QDownloadRequest::~QDownloadRequest()
64{
65
66}
67
68void QDownloadRequest::onDownloaded()
69{
70 // this is called in dl thread. It's an opportunity to do long running tasks
71 // like loading the data into a QImage
72}
73
74
75class Q_AUTOTEST_EXPORT QDownloadHelperServicePrivate : public QAbstractServiceProviderPrivate
76{
77public:
78 explicit QDownloadHelperServicePrivate(const QString &description);
79 ~QDownloadHelperServicePrivate();
80
81 void init();
82 void shutdown();
83 void _q_onRequestCompleted(const QDownloadRequestPtr &request);
84
85 Q_DECLARE_PUBLIC(QDownloadHelperService)
86
87 QThread *m_downloadThread;
88 QDownloadNetworkWorker *m_downloadWorker;
89};
90
91
92QDownloadHelperServicePrivate::QDownloadHelperServicePrivate(const QString &description)
93 : QAbstractServiceProviderPrivate(QServiceLocator::DownloadHelperService, description)
94 , m_downloadThread(nullptr)
95 , m_downloadWorker(nullptr)
96{
97}
98
99QDownloadHelperServicePrivate::~QDownloadHelperServicePrivate()
100{
101}
102
103void QDownloadHelperServicePrivate::init()
104{
105 Q_Q(QDownloadHelperService);
106 m_downloadThread = new QThread(q);
107 m_downloadWorker = new QDownloadNetworkWorker;
108 m_downloadWorker->moveToThread(thread: m_downloadThread);
109 // QueuedConnection
110 QObject::connect(sender: m_downloadWorker, SIGNAL(requestDownloaded(const Qt3DCore::QDownloadRequestPtr &)),
111 receiver: q, SLOT(_q_onRequestCompleted(const Qt3DCore::QDownloadRequestPtr &)));
112 m_downloadThread->start();
113}
114
115void QDownloadHelperServicePrivate::shutdown()
116{
117 emit m_downloadWorker->cancelAllRequests();
118 m_downloadThread->exit();
119 m_downloadThread->wait();
120 m_downloadWorker->deleteLater();
121}
122
123// Executed in AspectThread (queued signal connected to download thread)
124void QDownloadHelperServicePrivate::_q_onRequestCompleted(const Qt3DCore::QDownloadRequestPtr &request)
125{
126 request->onCompleted();
127}
128
129
130QDownloadHelperService::QDownloadHelperService(const QString &description)
131 : QAbstractServiceProvider(*new QDownloadHelperServicePrivate(description))
132{
133 Q_D(QDownloadHelperService);
134 d->init();
135 qRegisterMetaType<Qt3DCore::QDownloadRequestPtr>();
136}
137
138QDownloadHelperService::~QDownloadHelperService()
139{
140 Q_D(QDownloadHelperService);
141 d->shutdown();
142}
143
144void QDownloadHelperService::submitRequest(const Qt3DCore::QDownloadRequestPtr &request)
145{
146 Q_D(QDownloadHelperService);
147
148 if (isLocal(url: request->url())) {
149 QFile file(urlToLocalFileOrQrc(url: request->url()));
150 if (file.open(flags: QIODevice::ReadOnly)) {
151 request->m_data = file.readAll();
152 file.close();
153 request->m_succeeded = true;
154 } else {
155 request->m_succeeded = false;
156 }
157 request->onCompleted();
158 } else {
159 emit d->m_downloadWorker->submitRequest(request);
160 }
161}
162
163void QDownloadHelperService::cancelRequest(const Qt3DCore::QDownloadRequestPtr &request)
164{
165 Q_D(QDownloadHelperService);
166 request->m_cancelled = true;
167 emit d->m_downloadWorker->cancelRequest(request);
168}
169
170void QDownloadHelperService::cancelAllRequests()
171{
172 Q_D(QDownloadHelperService);
173 emit d->m_downloadWorker->cancelAllRequests();
174}
175
176QString QDownloadHelperService::urlToLocalFileOrQrc(const QUrl &url)
177{
178 const QString scheme(url.scheme().toLower());
179 if (scheme == QLatin1String("qrc")) {
180 if (url.authority().isEmpty())
181 return QLatin1Char(':') + url.path();
182 return QString();
183 }
184
185#if defined(Q_OS_ANDROID)
186 if (scheme == QLatin1String("assets")) {
187 if (url.authority().isEmpty())
188 return url.toString();
189 return QString();
190 }
191#endif
192
193 return url.toLocalFile();
194}
195
196QDownloadHelperService *QDownloadHelperService::getService(QAspectEngine *engine)
197{
198 auto enginePrivate = Qt3DCore::QAspectEnginePrivate::get(engine);
199 return enginePrivate->m_aspectManager->serviceLocator()->downloadHelperService();
200}
201
202bool QDownloadHelperService::isLocal(const QUrl &url)
203{
204 const QString scheme(url.scheme().toLower());
205 if (scheme == QLatin1String("file") || scheme == QLatin1String("qrc"))
206 return true;
207#if defined(Q_OS_ANDROID)
208 if (scheme == QLatin1String("assets"))
209 return true;
210#endif
211 return false;
212}
213
214} // namespace Qt3DCore
215
216QT_END_NAMESPACE
217
218#include "moc_qdownloadhelperservice_p.cpp"
219

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