Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlfile.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant
4
5#include "qqmlfile.h"
6
7#include <QtCore/qurl.h>
8#include <QtCore/qobject.h>
9#include <QtCore/qmetaobject.h>
10#include <QtCore/qfile.h>
11#include <private/qqmlengine_p.h>
12#include <private/qqmlglobal_p.h>
13
15
16/*!
17 \class QQmlFile
18 \inmodule QtQml
19 \since 5.0
20 \brief The QQmlFile class provides static utility methods to categorize URLs.
21
22 QQmlFile provides some static utility methods to categorize URLs
23 and file names the way \l{QQmlEngine} does when loading content from them.
24*/
25
26static char qrc_string[] = "qrc";
27static char file_string[] = "file";
28
29#if defined(Q_OS_ANDROID)
30static char assets_string[] = "assets";
31static char content_string[] = "content";
32static char authority_externalstorage[] = "com.android.externalstorage.documents";
33static char authority_downloads_documents[] = "com.android.providers.downloads.documents";
34static char authority_media_documents[] = "com.android.providers.media.documents";
35#endif
36
37#if QT_DEPRECATED_SINCE(6, 11)
38QT_WARNING_PUSH
39QT_WARNING_DISABLE_DEPRECATED
40
41/*!
42 \internal
43 \deprecated [6.11]
44
45 \enum QQmlFile::Status
46 \value Null
47 \value Ready
48 \value Error
49 \value Loading
50 */
51
52class QQmlFilePrivate;
53
54#if QT_CONFIG(qml_network)
55class QQmlFileNetworkReply : public QObject
56{
57Q_OBJECT
58public:
59 QQmlFileNetworkReply(QQmlEngine *, QQmlFilePrivate *, const QUrl &);
60 ~QQmlFileNetworkReply();
61
62signals:
63 void finished();
64 void downloadProgress(qint64, qint64);
65
66public slots:
67 void networkFinished();
68 void networkDownloadProgress(qint64, qint64);
69
70public:
71 static int finishedIndex;
72 static int downloadProgressIndex;
73 static int networkFinishedIndex;
74 static int networkDownloadProgressIndex;
75 static int replyFinishedIndex;
76 static int replyDownloadProgressIndex;
77
78private:
79 QQmlEngine *m_engine;
80 QQmlFilePrivate *m_p;
81
82 QNetworkReply *m_reply;
83};
84#endif
85
86class QQmlFilePrivate
87{
88public:
89 QQmlFilePrivate();
90
91 mutable QUrl url;
92 mutable QString urlString;
93
94 QByteArray data;
95
96 enum Error {
97 None, NotFound, Network
98 };
99
100 Error error;
101 QString errorString;
102#if QT_CONFIG(qml_network)
103 QQmlFileNetworkReply *reply;
104#endif
105};
106
107#if QT_CONFIG(qml_network)
108int QQmlFileNetworkReply::finishedIndex = -1;
109int QQmlFileNetworkReply::downloadProgressIndex = -1;
110int QQmlFileNetworkReply::networkFinishedIndex = -1;
111int QQmlFileNetworkReply::networkDownloadProgressIndex = -1;
112int QQmlFileNetworkReply::replyFinishedIndex = -1;
113int QQmlFileNetworkReply::replyDownloadProgressIndex = -1;
114
115QQmlFileNetworkReply::QQmlFileNetworkReply(QQmlEngine *e, QQmlFilePrivate *p, const QUrl &url)
116: m_engine(e), m_p(p), m_reply(nullptr)
117{
118 if (finishedIndex == -1) {
119 finishedIndex = QMetaMethod::fromSignal(&QQmlFileNetworkReply::finished).methodIndex();
120 downloadProgressIndex = QMetaMethod::fromSignal(&QQmlFileNetworkReply::downloadProgress).methodIndex();
121 const QMetaObject *smo = &staticMetaObject;
122 networkFinishedIndex = smo->indexOfMethod("networkFinished()");
123 networkDownloadProgressIndex = smo->indexOfMethod("networkDownloadProgress(qint64,qint64)");
124
125 replyFinishedIndex = QMetaMethod::fromSignal(&QNetworkReply::finished).methodIndex();
126 replyDownloadProgressIndex = QMetaMethod::fromSignal(&QNetworkReply::downloadProgress).methodIndex();
127 }
128 Q_ASSERT(finishedIndex != -1 && downloadProgressIndex != -1 &&
129 networkFinishedIndex != -1 && networkDownloadProgressIndex != -1 &&
130 replyFinishedIndex != -1 && replyDownloadProgressIndex != -1);
131
132 QNetworkRequest req(url);
133 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
134
135 m_reply = m_engine->networkAccessManager()->get(req);
136 QMetaObject::connect(m_reply, replyFinishedIndex, this, networkFinishedIndex);
137 QMetaObject::connect(m_reply, replyDownloadProgressIndex, this, networkDownloadProgressIndex);
138}
139
140QQmlFileNetworkReply::~QQmlFileNetworkReply()
141{
142 if (m_reply) {
143 m_reply->disconnect();
144 m_reply->deleteLater();
145 }
146}
147
148void QQmlFileNetworkReply::networkFinished()
149{
150 if (m_reply->error()) {
151 m_p->errorString = m_reply->errorString();
152 m_p->error = QQmlFilePrivate::Network;
153 } else {
154 m_p->data = m_reply->readAll();
155 }
156
157 m_reply->deleteLater();
158 m_reply = nullptr;
159
160 m_p->reply = nullptr;
161 emit finished();
162 delete this;
163}
164
165void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b)
166{
167 emit downloadProgress(a, b);
168}
169#endif // qml_network
170
171QQmlFilePrivate::QQmlFilePrivate()
172: error(None)
173#if QT_CONFIG(qml_network)
174, reply(nullptr)
175#endif
176{
177}
178
179/*!
180 \internal
181 */
182QQmlFile::QQmlFile()
183: d(new QQmlFilePrivate)
184{
185}
186
187/*!
188 \internal
189 Constructs a QQmlFile for content at \a url, using \a engine to retrieve it.
190 */
191QQmlFile::QQmlFile(QQmlEngine *engine, const QUrl &url)
192: d(new QQmlFilePrivate)
193{
194 load(engine, url);
195}
196
197/*!
198 \internal
199 Constructs a QQmlFile for content at \a url, using \a engine to retrieve it.
200 */
201QQmlFile::QQmlFile(QQmlEngine *engine, const QString &url)
202 : QQmlFile(engine, QUrl(url))
203{
204}
205
206/*!
207 \internal
208 */
209QQmlFile::~QQmlFile()
210{
211#if QT_CONFIG(qml_network)
212 delete d->reply;
213#endif
214 delete d;
215 d = nullptr;
216}
217
218/*!
219 \internal
220 */
221bool QQmlFile::isNull() const
222{
223 return status() == Null;
224}
225
226/*!
227 \internal
228 */
229bool QQmlFile::isReady() const
230{
231 return status() == Ready;
232}
233
234/*!
235 \internal
236 */
237bool QQmlFile::isError() const
238{
239 return status() == Error;
240}
241
242/*!
243 \internal
244 */
245bool QQmlFile::isLoading() const
246{
247 return status() == Loading;
248}
249
250/*!
251 \internal
252 */
253QUrl QQmlFile::url() const
254{
255 if (!d->urlString.isEmpty()) {
256 d->url = QUrl(d->urlString);
257 d->urlString = QString();
258 }
259 return d->url;
260}
261
262/*!
263 \internal
264 */
265QQmlFile::Status QQmlFile::status() const
266{
267 if (d->url.isEmpty() && d->urlString.isEmpty())
268 return Null;
269#if QT_CONFIG(qml_network)
270 else if (d->reply)
271 return Loading;
272#endif
273 else if (d->error != QQmlFilePrivate::None)
274 return Error;
275 else
276 return Ready;
277}
278
279/*!
280 \internal
281 \deprecated [6.11]
282 */
283QString QQmlFile::error() const
284{
285 switch (d->error) {
286 default:
287 case QQmlFilePrivate::None:
288 return QString();
289 case QQmlFilePrivate::NotFound:
290 return QLatin1String("File not found");
291 }
292}
293
294/*!
295 \internal
296 \deprecated [6.11]
297 */
298qint64 QQmlFile::size() const
299{
300 return d->data.size();
301}
302
303/*!
304 \internal
305 \deprecated [6.11]
306 */
307const char *QQmlFile::data() const
308{
309 return d->data.constData();
310}
311
312/*!
313 \internal
314 \deprecated [6.11]
315 */
316QByteArray QQmlFile::dataByteArray() const
317{
318 return d->data;
319}
320
321/*!
322 \internal
323 \deprecated [6.11]
324
325 Loads content at \a url using \a engine.
326 */
327void QQmlFile::load(QQmlEngine *engine, const QUrl &url)
328{
329 Q_ASSERT(engine);
330
331 clear();
332 d->url = url;
333
334 if (isLocalFile(url)) {
335 const QString lf = urlToLocalFileOrQrc(url);
336 if (!QQmlTypeLoader::get(engine)->fileExists(lf)) {
337 d->error = QQmlFilePrivate::NotFound;
338 return;
339 }
340
341 QFile file(lf);
342 if (file.open(QFile::ReadOnly)) {
343 d->data = file.readAll();
344 } else {
345 d->error = QQmlFilePrivate::NotFound;
346 }
347 } else {
348#if QT_CONFIG(qml_network)
349 d->reply = new QQmlFileNetworkReply(engine, d, url);
350#else
351 d->error = QQmlFilePrivate::NotFound;
352#endif
353 }
354}
355
356/*!
357 \internal
358 \deprecated [6.11]
359
360 Loads content at \a url using \a engine.
361 */
362void QQmlFile::load(QQmlEngine *engine, const QString &url)
363{
364 Q_ASSERT(engine);
365
366 clear();
367
368 d->urlString = url;
369
370 if (isLocalFile(url)) {
371 const QString lf = urlToLocalFileOrQrc(url);
372 if (!QQmlTypeLoader::get(engine)->fileExists(lf)) {
373 d->error = QQmlFilePrivate::NotFound;
374 return;
375 }
376
377 QFile file(lf);
378 if (file.open(QFile::ReadOnly)) {
379 d->data = file.readAll();
380 } else {
381 d->error = QQmlFilePrivate::NotFound;
382 }
383 } else {
384#if QT_CONFIG(qml_network)
385 QUrl qurl(url);
386 d->url = qurl;
387 d->urlString = QString();
388 d->reply = new QQmlFileNetworkReply(engine, d, qurl);
389#else
390 d->error = QQmlFilePrivate::NotFound;
391#endif
392 }
393}
394
395/*!
396 \internal
397 \deprecated [6.11]
398 */
399void QQmlFile::clear()
400{
401 d->url = QUrl();
402 d->urlString = QString();
403 d->data = QByteArray();
404 d->error = QQmlFilePrivate::None;
405}
406
407/*!
408 \internal
409 \deprecated [6.11]
410
411 Redirects to the other clear() overload, ignoring \a object.
412 */
413void QQmlFile::clear(QObject *object)
414{
415 Q_UNUSED(object);
416 clear();
417}
418
419#if QT_CONFIG(qml_network)
420
421/*!
422 \internal
423 Connects \a method of \a object to the internal \c{finished} signal.
424 */
425bool QQmlFile::connectFinished(QObject *object, const char *method)
426{
427 if (!d || !d->reply) {
428 qWarning("QQmlFile: connectFinished() called when not loading.");
429 return false;
430 }
431
432 return QObject::connect(d->reply, SIGNAL(finished()), object, method);
433}
434
435/*!
436 \internal
437 \deprecated [6.11]
438
439 Connects \a method of \a object to the internal \c{finished} signal.
440 */
441bool QQmlFile::connectFinished(QObject *object, int method)
442{
443 if (!d || !d->reply) {
444 qWarning("QQmlFile: connectFinished() called when not loading.");
445 return false;
446 }
447
448 return QMetaObject::connect(d->reply, QQmlFileNetworkReply::finishedIndex,
449 object, method);
450}
451
452/*!
453 \internal
454 \deprecated [6.11]
455
456 Connects \a method of \a object to the internal \c{downloadProgress} signal.
457 */
458bool QQmlFile::connectDownloadProgress(QObject *object, const char *method)
459{
460 if (!d || !d->reply) {
461 qWarning("QQmlFile: connectDownloadProgress() called when not loading.");
462 return false;
463 }
464
465 return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
466 object, method);
467}
468
469/*!
470 \internal
471 \deprecated [6.11]
472
473 Connects \a method of \a object to the internal \c{downloadProgress} signal.
474 */
475bool QQmlFile::connectDownloadProgress(QObject *object, int method)
476{
477 if (!d || !d->reply) {
478 qWarning("QQmlFile: connectDownloadProgress() called when not loading.");
479 return false;
480 }
481
482 return QMetaObject::connect(d->reply, QQmlFileNetworkReply::downloadProgressIndex,
483 object, method);
484}
485#endif
486
487QT_WARNING_POP
488#endif // QT_DEPRECATED_SINCE(6, 11)
489
490/*!
491 \internal
492
493 Returns \c true if QQmlFile will open \a url synchronously.
494 Otherwise returns \c false. Synchronous urls have a \c{qrc:} or \c{file:}
495 scheme.
496
497 \note On Android, urls with \c{assets:} or \c{content:} scheme are also
498 considered synchronous.
499*/
500bool QQmlFile::isSynchronous(const QUrl &url)
501{
502 QString scheme = url.scheme();
503
504 if ((scheme.size() == 4 && 0 == scheme.compare(QLatin1String(file_string), Qt::CaseInsensitive)) ||
505 (scheme.size() == 3 && 0 == scheme.compare(QLatin1String(qrc_string), Qt::CaseInsensitive))) {
506 return true;
507
508#if defined(Q_OS_ANDROID)
509 } else if (scheme.length() == 6 && 0 == scheme.compare(QLatin1String(assets_string), Qt::CaseInsensitive)) {
510 return true;
511 } else if (scheme.length() == 7 && 0 == scheme.compare(QLatin1String(content_string), Qt::CaseInsensitive)) {
512 return true;
513#endif
514
515 } else {
516 return false;
517 }
518}
519
520/*!
521 \internal
522
523 Returns \c true if QQmlFile will open \a url synchronously.
524 Otherwise returns \c false. Synchronous urls have a \c{qrc:} or \c{file:}
525 scheme.
526
527 \note On Android, urls with \c{assets:} or \c{content:} scheme are also
528 considered synchronous.
529*/
530bool QQmlFile::isSynchronous(const QString &url)
531{
532 if (url.size() < 5 /* qrc:/ */)
533 return false;
534
535 QChar f = url[0];
536
537 if (f == QLatin1Char('f') || f == QLatin1Char('F')) {
538
539 return url.size() >= 7 /* file:// */ &&
540 url.startsWith(QLatin1String(file_string), Qt::CaseInsensitive) &&
541 url[4] == QLatin1Char(':') && url[5] == QLatin1Char('/') && url[6] == QLatin1Char('/');
542
543 } else if (f == QLatin1Char('q') || f == QLatin1Char('Q')) {
544
545 return url.size() >= 5 /* qrc:/ */ &&
546 url.startsWith(QLatin1String(qrc_string), Qt::CaseInsensitive) &&
547 url[3] == QLatin1Char(':') && url[4] == QLatin1Char('/');
548
549 }
550
551#if defined(Q_OS_ANDROID)
552 else if (f == QLatin1Char('a') || f == QLatin1Char('A')) {
553 return url.length() >= 8 /* assets:/ */ &&
554 url.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive) &&
555 url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/');
556 } else if (f == QLatin1Char('c') || f == QLatin1Char('C')) {
557 return url.length() >= 9 /* content:/ */ &&
558 url.startsWith(QLatin1String(content_string), Qt::CaseInsensitive) &&
559 url[7] == QLatin1Char(':') && url[8] == QLatin1Char('/');
560 }
561#endif
562
563 return false;
564}
565
566#if defined(Q_OS_ANDROID)
567static bool hasLocalContentAuthority(const QUrl &url)
568{
569 const QString authority = url.authority();
570 return authority.isEmpty()
571 || authority == QLatin1String(authority_externalstorage)
572 || authority == QLatin1String(authority_downloads_documents)
573 || authority == QLatin1String(authority_media_documents);
574}
575#endif
576
577/*!
578 Returns \c true if \a url is a local file that can be opened with \l{QFile}.
579 Otherwise returns \c false. Local file urls have either a \c{qrc:} or
580 \c{file:} scheme.
581
582 \note On Android, urls with \c{assets:} or \c{content:} scheme are also
583 considered local files.
584*/
585bool QQmlFile::isLocalFile(const QUrl &url)
586{
587 QString scheme = url.scheme();
588
589 // file: URLs with two slashes following the scheme can be interpreted as local files
590 // where the slashes are part of the path. Therefore, disregard the authority.
591 // See QUrl::toLocalFile().
592 if (scheme.size() == 4 && scheme.startsWith(QLatin1String(file_string), Qt::CaseInsensitive))
593 return true;
594
595 if (scheme.size() == 3 && scheme.startsWith(QLatin1String(qrc_string), Qt::CaseInsensitive))
596 return url.authority().isEmpty();
597
598#if defined(Q_OS_ANDROID)
599 if (scheme.length() == 6
600 && scheme.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive))
601 return url.authority().isEmpty();
602 if (scheme.length() == 7
603 && scheme.startsWith(QLatin1String(content_string), Qt::CaseInsensitive))
604 return hasLocalContentAuthority(url);
605#endif
606
607 return false;
608}
609
610static bool hasScheme(const QString &url, const char *scheme, qsizetype schemeLength)
611{
612 const qsizetype urlLength = url.size();
613
614 if (urlLength < schemeLength + 1)
615 return false;
616
617 if (!url.startsWith(QLatin1String(scheme, scheme + schemeLength), Qt::CaseInsensitive))
618 return false;
619
620 if (url[schemeLength] != QLatin1Char(':'))
621 return false;
622
623 return true;
624}
625
626static qsizetype authorityOffset(const QString &url, qsizetype schemeLength)
627{
628 const qsizetype urlLength = url.size();
629
630 if (urlLength < schemeLength + 3)
631 return -1;
632
633 const QLatin1Char slash('/');
634 if (url[schemeLength + 1] == slash && url[schemeLength + 2] == slash) {
635 // Exactly two slashes denote an authority.
636 if (urlLength < schemeLength + 4 || url[schemeLength + 3] != slash)
637 return schemeLength + 3;
638 }
639
640 return -1;
641}
642
643#if defined(Q_OS_ANDROID)
644static bool hasLocalContentAuthority(const QString &url, qsizetype schemeLength)
645{
646 const qsizetype offset = authorityOffset(url, schemeLength);
647 if (offset == -1)
648 return true; // no authority is a local authority.
649
650 const QString authorityAndPath = url.sliced(offset);
651 return authorityAndPath.startsWith(QLatin1String(authority_externalstorage))
652 || authorityAndPath.startsWith(QLatin1String(authority_downloads_documents))
653 || authorityAndPath.startsWith(QLatin1String(authority_media_documents));
654}
655
656#endif
657
658/*!
659 Returns \c true if \a url is a local file that can be opened with \l{QFile}.
660 Otherwise returns \c false. Local file urls have either a \c{qrc:} or
661 \c{file:} scheme.
662
663 \note On Android, urls with \c{assets:} or \c{content:} scheme are also considered
664 local files.
665*/
666bool QQmlFile::isLocalFile(const QString &url)
667{
668 if (url.size() < 4 /* qrc: */)
669 return false;
670
671 switch (url[0].toLatin1()) {
672 case 'f':
673 case 'F': {
674 // file: URLs with two slashes following the scheme can be interpreted as local files
675 // where the slashes are part of the path. Therefore, disregard the authority.
676 // See QUrl::toLocalFile().
677 const qsizetype fileLength = strlen(file_string);
678 return url.startsWith(QLatin1String(file_string, file_string + fileLength),
679 Qt::CaseInsensitive)
680 && url.size() > fileLength
681 && url[fileLength] == QLatin1Char(':');
682 }
683 case 'q':
684 case 'Q':
685 return hasScheme(url, qrc_string, strlen(qrc_string))
686 && authorityOffset(url, strlen(qrc_string)) == -1;
687#if defined(Q_OS_ANDROID)
688 case 'a':
689 case 'A':
690 return hasScheme(url, assets_string, strlen(assets_string))
691 && authorityOffset(url, strlen(assets_string)) == -1;
692 case 'c':
693 case 'C':
694 return hasScheme(url, content_string, strlen(content_string))
695 && hasLocalContentAuthority(url, strlen(content_string));
696#endif
697 default:
698 break;
699 }
700
701 return false;
702}
703
704/*!
705 If \a url is a local file returns a path suitable for passing to \l{QFile}.
706 Otherwise returns an empty string.
707
708 \sa isLocalFile
709*/
710QString QQmlFile::urlToLocalFileOrQrc(const QUrl& url)
711{
712 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
713 if (url.authority().isEmpty())
714 return QLatin1Char(':') + url.path();
715 return QString();
716 }
717
718#if defined(Q_OS_ANDROID)
719 if (url.scheme().compare(QLatin1String("assets"), Qt::CaseInsensitive) == 0)
720 return url.authority().isEmpty() ? url.toString() : QString();
721 if (url.scheme().compare(QLatin1String("content"), Qt::CaseInsensitive) == 0) {
722 if (hasLocalContentAuthority(url))
723 return url.toString();
724 return QString();
725 }
726#endif
727 return url.toLocalFile();
728}
729
730static QString toLocalFile(const QString &url)
731{
732 const QUrl file(url);
733 if (!file.isLocalFile())
734 return QString();
735
736 // QUrl::toLocalFile() interprets two slashes as part of the path.
737 // Therefore windows hostnames like "//servername/path/to/file.txt" are preserved.
738
739 return file.toLocalFile();
740}
741
742static bool isDoubleSlashed(const QString &url, qsizetype offset)
743{
744 const qsizetype urlLength = url.size();
745 if (urlLength < offset + 2)
746 return false;
747
748 const QLatin1Char slash('/');
749 if (url[offset] != slash || url[offset + 1] != slash)
750 return false;
751
752 if (urlLength < offset + 3)
753 return true;
754
755 return url[offset + 2] != slash;
756}
757
758/*!
759 If \a url is a local file returns a path suitable for passing to \l{QFile}.
760 Otherwise returns an empty string.
761
762 \sa isLocalFile
763*/
764QString QQmlFile::urlToLocalFileOrQrc(const QString& url)
765{
766 if (url.startsWith(QLatin1String("qrc://"), Qt::CaseInsensitive)) {
767 // Exactly two slashes are bad because that's a URL authority.
768 // One slash is fine and >= 3 slashes are file.
769 if (url.size() == 6 || url[6] != QLatin1Char('/')) {
770 Q_ASSERT(isDoubleSlashed(url, strlen("qrc:")));
771 return QString();
772 }
773 Q_ASSERT(!isDoubleSlashed(url, strlen("qrc:")));
774 return QLatin1Char(':') + QStringView{url}.mid(6);
775 }
776
777 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
778 Q_ASSERT(!isDoubleSlashed(url, strlen("qrc:")));
779 if (url.size() > 4)
780 return QLatin1Char(':') + QStringView{url}.mid(4);
781 return QStringLiteral(":");
782 }
783
784#if defined(Q_OS_ANDROID)
785 if (url.startsWith(QLatin1String("assets:"), Qt::CaseInsensitive))
786 return isDoubleSlashed(url, strlen("assets:")) ? QString() : url;
787 if (hasScheme(url, content_string, strlen(content_string)))
788 return hasLocalContentAuthority(url, strlen(content_string)) ? url : QString();
789#endif
790
791 return toLocalFile(url);
792}
793
794QT_END_NAMESPACE
795
796#include "qqmlfile.moc"
Combined button and popup list for selecting options.
static QString toLocalFile(const QString &url)
Definition qqmlfile.cpp:730
static bool isDoubleSlashed(const QString &url, qsizetype offset)
Definition qqmlfile.cpp:742
static qsizetype authorityOffset(const QString &url, qsizetype schemeLength)
Definition qqmlfile.cpp:626
static char qrc_string[]
Definition qqmlfile.cpp:26
static char file_string[]
Definition qqmlfile.cpp:27
static bool hasScheme(const QString &url, const char *scheme, qsizetype schemeLength)
Definition qqmlfile.cpp:610