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

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