Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmldatablob.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
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 <private/qqmldatablob_p.h>
5#include <private/qqmlglobal_p.h>
6#include <private/qqmlprofiler_p.h>
7#include <private/qqmltypeloader_p.h>
8#include <private/qqmltypeloaderthread_p.h>
9#include <private/qqmlsourcecoordinate_p.h>
10
11#include <QtQml/qqmlengine.h>
12
13#include <qtqml_tracepoints_p.h>
14
15#ifdef DATABLOB_DEBUG
16#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
17#else
18#define ASSERT_CALLBACK()
19#endif
20
21DEFINE_BOOL_CONFIG_OPTION(dumpErrors, QML_DUMP_ERRORS);
22
24
26
66: m_typeLoader(manager), m_type(type), m_url(url), m_finalUrl(url), m_redirectCount(0),
67 m_inCallback(false), m_isDone(false)
68{
69 //Set here because we need to get the engine from the manager
72}
73
76{
78
79 cancelAllWaitingFor();
80}
81
90
95{
96 return m_type;
97}
98
103{
104 return m_data.status();
105}
106
111{
112 return status() == Null;
113}
114
119{
120 return status() == Loading;
121}
122
127{
128 return status() == WaitingForDependencies ||
130}
131
136{
137 return status() == Complete;
138}
139
144{
145 return status() == Error;
146}
147
152{
153 Status s = status();
154 return s == Error || s == Complete;
155}
156
161{
162 quint8 p = m_data.progress();
163 if (p == 0xFF) return 1.;
164 else return qreal(p) / qreal(0xFF);
165}
166
175{
176 return m_url;
177}
178
180{
181 if (m_urlString.isEmpty())
182 m_urlString = m_url.toString();
183
184 return m_urlString;
185}
186
201{
202 return m_finalUrl;
203}
204
209{
210 if (m_finalUrlString.isEmpty())
211 m_finalUrlString = m_finalUrl.toString();
212
213 return m_finalUrlString;
214}
215
221QList<QQmlError> QQmlDataBlob::errors() const
222{
224 return m_errors;
225}
226
236{
238
239 QList<QQmlError> l;
240 l << errors;
241 setError(l);
242}
243
247void QQmlDataBlob::setError(const QList<QQmlError> &errors)
248{
250
251 Q_ASSERT(status() != Error);
252 Q_ASSERT(m_errors.isEmpty());
253
254 // m_errors must be set before the m_data fence
255 m_errors.reserve(errors.size());
256 for (const QQmlError &error : errors) {
257 if (error.url().isEmpty()) {
258 QQmlError mutableError = error;
259 mutableError.setUrl(url());
260 m_errors.append(mutableError);
261 } else {
262 m_errors.append(error);
263 }
264 }
265
266 m_data.setStatus(Error);
267
268 if (dumpErrors()) {
269 qWarning().nospace() << "Errors for " << urlString();
270 for (int ii = 0; ii < errors.size(); ++ii)
271 qWarning().nospace() << " " << qPrintable(errors.at(ii).toString());
272 }
273 cancelAllWaitingFor();
274
275 if (!m_inCallback)
276 tryDone();
277}
278
280{
281 QQmlError e;
282 e.setColumn(qmlConvertSourceCoordinate<quint32, int>(error.loc.startColumn));
283 e.setLine(qmlConvertSourceCoordinate<quint32, int>(error.loc.startLine));
284 e.setDescription(error.message);
285 e.setUrl(url());
286 setError(e);
287}
288
289void QQmlDataBlob::setError(const QString &description)
290{
291 QQmlError e;
292 e.setDescription(description);
293 e.setUrl(url());
294 setError(e);
295}
296
304{
306
307 Q_ASSERT(status() != Null);
308
309 if (!blob ||
310 blob->status() == Error || blob->status() == Complete ||
311 status() == Error || status() == Complete || m_isDone)
312 return;
313
314 for (const auto &existingDep: std::as_const(m_waitingFor))
315 if (existingDep.data() == blob)
316 return;
317
318 m_data.setStatus(WaitingForDependencies);
319
320 m_waitingFor.append(blob);
321 blob->m_waitingOnMe.append(this);
322
323 // Check circular dependency
324 if (m_waitingOnMe.indexOf(blob) >= 0) {
325 qCWarning(lcCycle) << "Cyclic dependency detected between" << this->url().toString()
326 << "and" << blob->url().toString();
327 m_data.setStatus(Error);
328 }
329}
330
352{
353}
354
355#if QT_CONFIG(qml_network)
361void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
362{
363 Q_UNUSED(networkError);
364
366 error.setUrl(m_url);
367
368 const char *errorString = nullptr;
369 switch (networkError) {
370 default:
371 errorString = "Network error";
372 break;
374 errorString = "Connection refused";
375 break;
377 errorString = "Remote host closed the connection";
378 break;
380 errorString = "Host not found";
381 break;
383 errorString = "Timeout";
384 break;
391 errorString = "Proxy error";
392 break;
394 errorString = "Access denied";
395 break;
397 errorString = "File not found";
398 break;
400 errorString = "Authentication required";
401 break;
402 };
403
404 error.setDescription(QLatin1String(errorString));
405
407}
408#endif // qml_network
409
416{
417 Q_UNUSED(blob);
418}
419
429
440
456
472{
473}
474
475
476void QQmlDataBlob::tryDone()
477{
478 if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
479 m_isDone = true;
480 addref();
481
482#ifdef DATABLOB_DEBUG
483 qWarning("QQmlDataBlob::done() %s", qPrintable(urlString()));
484#endif
485 done();
486
487 if (status() != Error)
488 m_data.setStatus(Complete);
489
490 notifyAllWaitingOnMe();
491
492 // Locking is not required here, as anyone expecting callbacks must
493 // already be protected against the blob being completed (as set above);
494#ifdef DATABLOB_DEBUG
495 qWarning("QQmlDataBlob: Dispatching completed");
496#endif
497 m_typeLoader->m_thread->callCompleted(this);
498
499 release();
500 }
501}
502
503void QQmlDataBlob::cancelAllWaitingFor()
504{
505 while (m_waitingFor.size()) {
506 QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
507
508 Q_ASSERT(blob->m_waitingOnMe.contains(this));
509
510 blob->m_waitingOnMe.removeOne(this);
511 }
512}
513
514void QQmlDataBlob::notifyAllWaitingOnMe()
515{
516 while (m_waitingOnMe.size()) {
518
519 Q_ASSERT(std::any_of(blob->m_waitingFor.constBegin(), blob->m_waitingFor.constEnd(),
520 [this](const QQmlRefPointer<QQmlDataBlob> &waiting) { return waiting.data() == this; }));
521
522 blob->notifyComplete(this);
523 }
524}
525
526void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
527{
528 Q_ASSERT(blob->status() == Error || blob->status() == Complete);
529 Q_TRACE_SCOPE(QQmlCompiling, blob->url());
530 QQmlCompilingProfiler prof(typeLoader()->profiler(), blob);
531
532 m_inCallback = true;
533
534 QQmlRefPointer<QQmlDataBlob> blobRef;
535 for (int i = 0; i < m_waitingFor.size(); ++i) {
536 if (m_waitingFor.at(i).data() == blob) {
537 blobRef = m_waitingFor.takeAt(i);
538 break;
539 }
540 }
541 Q_ASSERT(blobRef);
542
543 if (blob->status() == Error) {
544 dependencyError(blob);
545 } else if (blob->status() == Complete) {
546 dependencyComplete(blob);
547 }
548
549 if (!isError() && m_waitingFor.isEmpty())
551
552 m_inCallback = false;
553
554 tryDone();
555}
556
558{
559 error->clear();
560 if (hasInlineSourceCode)
561 return inlineSourceCode;
562
563 QFile f(fileInfo.absoluteFilePath());
564 if (!f.open(QIODevice::ReadOnly)) {
565 *error = f.errorString();
566 return QString();
567 }
568
569 const qint64 fileSize = fileInfo.size();
570
571 if (uchar *mappedData = f.map(0, fileSize)) {
572 QString source = QString::fromUtf8(reinterpret_cast<const char *>(mappedData), fileSize);
573 f.unmap(mappedData);
574 return source;
575 }
576
578 if (f.read(data.data(), data.size()) != data.size()) {
579 *error = f.errorString();
580 return QString();
581 }
582 return QString::fromUtf8(data);
583}
584
586{
587 if (hasInlineSourceCode)
588 return QDateTime();
589
590 return fileInfo.lastModified();
591}
592
594{
595 if (hasInlineSourceCode)
596 return true;
597 return fileInfo.exists();
598}
599
601{
602 if (hasInlineSourceCode)
603 return inlineSourceCode.isEmpty();
604 return fileInfo.size() == 0;
605}
606
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatetime.h:283
QString absoluteFilePath() const
qint64 size() const
Returns the file size in bytes.
\inmodule QtCore
Definition qfile.h:93
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
value_type takeLast()
Definition qlist.h:567
void reserve(qsizetype size)
Definition qlist.h:753
void append(parameter_type t)
Definition qlist.h:458
NetworkError
Indicates all possible error conditions found during the processing of the request.
@ ProxyConnectionRefusedError
@ ProxyAuthenticationRequiredError
@ AuthenticationRequiredError
DataType
Specifies where URL interception is taking place.
QDateTime sourceTimeStamp() const
QString readAll(QString *error) const
The QQmlDataBlob encapsulates a data request that can be issued to a QQmlTypeLoader.
bool isLoading() const
Returns true if the status is Loading.
bool isError() const
Returns true if the status is Error.
qreal progress() const
Returns the data download progress from 0 to 1.
bool isCompleteOrError() const
Returns true if the status is Complete or Error.
bool isNull() const
Returns true if the status is Null.
void addDependency(QQmlDataBlob *)
Wait for blob to become complete or to error.
QList< QQmlError > errors() const
Return the errors on this blob.
bool isComplete() const
Returns true if the status is Complete.
QUrl url() const
Returns the physical url of the data.
QQmlTypeLoader * typeLoader() const
QUrl finalUrl() const
Returns the logical URL to be used for resolving further URLs referred to in the code.
Type
This enum describes the type of the data blob.
Status status() const
Returns the blob's status.
QList< QQmlDataBlob * > m_waitingOnMe
virtual void allDependenciesDone()
Called when all blobs waited for have completed.
QString finalUrlString() const
Returns the finalUrl() as a string.
bool isWaiting() const
Returns true if the status is WaitingForDependencies.
void startLoading()
Must be called before loading can occur.
virtual void dependencyError(QQmlDataBlob *)
Called if blob, which was previously waited for, has an error.
virtual void dependencyComplete(QQmlDataBlob *)
Called if blob, which was previously waited for, has completed.
virtual void completed()
Invoked on the main thread sometime after done() was called on the load thread.
Type type() const
Returns the type provided to the constructor.
QQmlDataBlob(const QUrl &, Type, QQmlTypeLoader *manager)
Create a new QQmlDataBlob for url and of the provided type.
virtual ~QQmlDataBlob()
void setError(const QQmlError &)
Mark this blob as having errors.
QString urlString() const
virtual void done()
Invoked once data has either been received or a network error occurred, and all dependencies are comp...
QQmlTypeLoader * m_typeLoader
Status
This enum describes the status of the data blob.
virtual void downloadProgressChanged(qreal)
Called when the download progress of this blob changes.
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
Run the current URL interceptors on the given url of the given type and return the result.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
void setColumn(int)
Sets the error column number.
void setLine(int)
Sets the error line number.
void setDescription(const QString &)
Sets the error description.
QString toString() const
Returns the error as a human readable string.
void setUrl(const QUrl &)
Sets the url for the file that caused this error.
void addref() const
bool isThisThread() const
void callCompleted(const QQmlDataBlob::Ptr &b)
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
QQmlEngine * engine() const
Return the QQmlEngine associated with this loader.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
\inmodule QtCore
Definition qurl.h:94
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
DBusConnection const char DBusError * error
#define qWarning
Definition qlogging.h:166
#define qCWarning(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum type
GLsizei GLsizei GLchar * source
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:80
#define ASSERT_CALLBACK()
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define Q_UNUSED(x)
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
unsigned char uchar
Definition qtypes.h:32
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
unsigned char quint8
Definition qtypes.h:46
QUrl url("example.com")
[constructor-url-reference]
QNetworkAccessManager manager
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962
Definition moc.h:23