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
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
4#include "qqmlfile.h"
5
6#include <QtCore/qurl.h>
7#include <QtCore/qobject.h>
8#include <QtCore/qmetaobject.h>
9#include <QtCore/qfile.h>
10#include <private/qqmlengine_p.h>
11#include <private/qqmlglobal_p.h>
12
14
35static char qrc_string[] = "qrc";
36static char file_string[] = "file";
37
38#if defined(Q_OS_ANDROID)
39static char assets_string[] = "assets";
40static char content_string[] = "content";
41static char authority_externalstorage[] = "com.android.externalstorage.documents";
42static char authority_downloads_documents[] = "com.android.providers.downloads.documents";
43static char authority_media_documents[] = "com.android.providers.media.documents";
44#endif
45
46class QQmlFilePrivate;
47
48#if QT_CONFIG(qml_network)
49class QQmlFileNetworkReply : public QObject
50{
52public:
53 QQmlFileNetworkReply(QQmlEngine *, QQmlFilePrivate *, const QUrl &);
54 ~QQmlFileNetworkReply();
55
57 void finished();
58 void downloadProgress(qint64, qint64);
59
60public slots:
61 void networkFinished();
62 void networkDownloadProgress(qint64, qint64);
63
64public:
65 static int finishedIndex;
66 static int downloadProgressIndex;
67 static int networkFinishedIndex;
68 static int networkDownloadProgressIndex;
69 static int replyFinishedIndex;
70 static int replyDownloadProgressIndex;
71
72private:
73 QQmlEngine *m_engine;
74 QQmlFilePrivate *m_p;
75
76 QNetworkReply *m_reply;
77};
78#endif
79
81{
82public:
84
85 mutable QUrl url;
87
89
90 enum Error {
92 };
93
96#if QT_CONFIG(qml_network)
97 QQmlFileNetworkReply *reply;
98#endif
99};
100
101#if QT_CONFIG(qml_network)
102int QQmlFileNetworkReply::finishedIndex = -1;
103int QQmlFileNetworkReply::downloadProgressIndex = -1;
104int QQmlFileNetworkReply::networkFinishedIndex = -1;
105int QQmlFileNetworkReply::networkDownloadProgressIndex = -1;
106int QQmlFileNetworkReply::replyFinishedIndex = -1;
107int QQmlFileNetworkReply::replyDownloadProgressIndex = -1;
108
109QQmlFileNetworkReply::QQmlFileNetworkReply(QQmlEngine *e, QQmlFilePrivate *p, const QUrl &url)
110: m_engine(e), m_p(p), m_reply(nullptr)
111{
112 if (finishedIndex == -1) {
113 finishedIndex = QMetaMethod::fromSignal(&QQmlFileNetworkReply::finished).methodIndex();
114 downloadProgressIndex = QMetaMethod::fromSignal(&QQmlFileNetworkReply::downloadProgress).methodIndex();
115 const QMetaObject *smo = &staticMetaObject;
116 networkFinishedIndex = smo->indexOfMethod("networkFinished()");
117 networkDownloadProgressIndex = smo->indexOfMethod("networkDownloadProgress(qint64,qint64)");
118
119 replyFinishedIndex = QMetaMethod::fromSignal(&QNetworkReply::finished).methodIndex();
120 replyDownloadProgressIndex = QMetaMethod::fromSignal(&QNetworkReply::downloadProgress).methodIndex();
121 }
122 Q_ASSERT(finishedIndex != -1 && downloadProgressIndex != -1 &&
123 networkFinishedIndex != -1 && networkDownloadProgressIndex != -1 &&
124 replyFinishedIndex != -1 && replyDownloadProgressIndex != -1);
125
126 QNetworkRequest req(url);
128
129 m_reply = m_engine->networkAccessManager()->get(req);
130 QMetaObject::connect(m_reply, replyFinishedIndex, this, networkFinishedIndex);
131 QMetaObject::connect(m_reply, replyDownloadProgressIndex, this, networkDownloadProgressIndex);
132}
133
134QQmlFileNetworkReply::~QQmlFileNetworkReply()
135{
136 if (m_reply) {
137 m_reply->disconnect();
138 m_reply->deleteLater();
139 }
140}
141
142void QQmlFileNetworkReply::networkFinished()
143{
144 if (m_reply->error()) {
145 m_p->errorString = m_reply->errorString();
146 m_p->error = QQmlFilePrivate::Network;
147 } else {
148 m_p->data = m_reply->readAll();
149 }
150
151 m_reply->deleteLater();
152 m_reply = nullptr;
153
154 m_p->reply = nullptr;
155 emit finished();
156 delete this;
157}
158
159void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b)
160{
161 emit downloadProgress(a, b);
162}
163#endif // qml_network
164
166: error(None)
167#if QT_CONFIG(qml_network)
168, reply(nullptr)
169#endif
170{
171}
172
180
190
199
204{
205#if QT_CONFIG(qml_network)
206 delete d->reply;
207#endif
208 delete d;
209 d = nullptr;
210}
211
216{
217 return status() == Null;
218}
219
224{
225 return status() == Ready;
226}
227
232{
233 return status() == Error;
234}
235
240{
241 return status() == Loading;
242}
243
248{
249 if (!d->urlString.isEmpty()) {
250 d->url = QUrl(d->urlString);
251 d->urlString = QString();
252 }
253 return d->url;
254}
255
260{
261 if (d->url.isEmpty() && d->urlString.isEmpty())
262 return Null;
263#if QT_CONFIG(qml_network)
264 else if (d->reply)
265 return Loading;
266#endif
267 else if (d->error != QQmlFilePrivate::None)
268 return Error;
269 else
270 return Ready;
271}
272
277{
278 switch (d->error) {
279 default:
281 return QString();
283 return QLatin1String("File not found");
285 return QLatin1String("File name case mismatch");
286 }
287}
288
293{
294 return d->data.size();
295}
296
300const char *QQmlFile::data() const
301{
302 return d->data.constData();
303}
304
309{
310 return d->data;
311}
312
318{
320
321 clear();
322 d->url = url;
323
324 if (isLocalFile(url)) {
326
327 if (!QQml_isFileCaseCorrect(lf)) {
329 return;
330 }
331
332 QFile file(lf);
334 d->data = file.readAll();
335 } else {
337 }
338 } else {
339#if QT_CONFIG(qml_network)
340 d->reply = new QQmlFileNetworkReply(engine, d, url);
341#else
343#endif
344 }
345}
346
352{
354
355 clear();
356
357 d->urlString = url;
358
359 if (isLocalFile(url)) {
361
362 if (!QQml_isFileCaseCorrect(lf)) {
364 return;
365 }
366
367 QFile file(lf);
369 d->data = file.readAll();
370 } else {
372 }
373 } else {
374#if QT_CONFIG(qml_network)
375 QUrl qurl(url);
376 d->url = qurl;
377 d->urlString = QString();
378 d->reply = new QQmlFileNetworkReply(engine, d, qurl);
379#else
381#endif
382 }
383}
384
389{
390 d->url = QUrl();
391 d->urlString = QString();
392 d->data = QByteArray();
394}
395
401{
402 Q_UNUSED(object);
403 clear();
404}
405
406#if QT_CONFIG(qml_network)
407
412bool QQmlFile::connectFinished(QObject *object, const char *method)
413{
414 if (!d || !d->reply) {
415 qWarning("QQmlFile: connectFinished() called when not loading.");
416 return false;
417 }
418
419 return QObject::connect(d->reply, SIGNAL(finished()), object, method);
420}
421
426bool QQmlFile::connectFinished(QObject *object, int method)
427{
428 if (!d || !d->reply) {
429 qWarning("QQmlFile: connectFinished() called when not loading.");
430 return false;
431 }
432
433 return QMetaObject::connect(d->reply, QQmlFileNetworkReply::finishedIndex,
434 object, method);
435}
436
441bool QQmlFile::connectDownloadProgress(QObject *object, const char *method)
442{
443 if (!d || !d->reply) {
444 qWarning("QQmlFile: connectDownloadProgress() called when not loading.");
445 return false;
446 }
447
448 return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
449 object, method);
450}
451
456bool QQmlFile::connectDownloadProgress(QObject *object, int method)
457{
458 if (!d || !d->reply) {
459 qWarning("QQmlFile: connectDownloadProgress() called when not loading.");
460 return false;
461 }
462
463 return QMetaObject::connect(d->reply, QQmlFileNetworkReply::downloadProgressIndex,
464 object, method);
465}
466#endif
467
479{
480 QString scheme = url.scheme();
481
482 if ((scheme.size() == 4 && 0 == scheme.compare(QLatin1String(file_string), Qt::CaseInsensitive)) ||
483 (scheme.size() == 3 && 0 == scheme.compare(QLatin1String(qrc_string), Qt::CaseInsensitive))) {
484 return true;
485
486#if defined(Q_OS_ANDROID)
487 } else if (scheme.length() == 6 && 0 == scheme.compare(QLatin1String(assets_string), Qt::CaseInsensitive)) {
488 return true;
489 } else if (scheme.length() == 7 && 0 == scheme.compare(QLatin1String(content_string), Qt::CaseInsensitive)) {
490 return true;
491#endif
492
493 } else {
494 return false;
495 }
496}
497
509{
510 if (url.size() < 5 /* qrc:/ */)
511 return false;
512
513 QChar f = url[0];
514
515 if (f == QLatin1Char('f') || f == QLatin1Char('F')) {
516
517 return url.size() >= 7 /* file:// */ &&
519 url[4] == QLatin1Char(':') && url[5] == QLatin1Char('/') && url[6] == QLatin1Char('/');
520
521 } else if (f == QLatin1Char('q') || f == QLatin1Char('Q')) {
522
523 return url.size() >= 5 /* qrc:/ */ &&
525 url[3] == QLatin1Char(':') && url[4] == QLatin1Char('/');
526
527 }
528
529#if defined(Q_OS_ANDROID)
530 else if (f == QLatin1Char('a') || f == QLatin1Char('A')) {
531 return url.length() >= 8 /* assets:/ */ &&
532 url.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive) &&
533 url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/');
534 } else if (f == QLatin1Char('c') || f == QLatin1Char('C')) {
535 return url.length() >= 9 /* content:/ */ &&
536 url.startsWith(QLatin1String(content_string), Qt::CaseInsensitive) &&
537 url[7] == QLatin1Char(':') && url[8] == QLatin1Char('/');
538 }
539#endif
540
541 return false;
542}
543
544#if defined(Q_OS_ANDROID)
545static bool hasLocalContentAuthority(const QUrl &url)
546{
547 const QString authority = url.authority();
548 return authority.isEmpty()
549 || authority == QLatin1String(authority_externalstorage)
550 || authority == QLatin1String(authority_downloads_documents)
551 || authority == QLatin1String(authority_media_documents);
552}
553#endif
554
564{
565 QString scheme = url.scheme();
566
567 // file: URLs with two slashes following the scheme can be interpreted as local files
568 // where the slashes are part of the path. Therefore, disregard the authority.
569 // See QUrl::toLocalFile().
570 if (scheme.size() == 4 && scheme.startsWith(QLatin1String(file_string), Qt::CaseInsensitive))
571 return true;
572
573 if (scheme.size() == 3 && scheme.startsWith(QLatin1String(qrc_string), Qt::CaseInsensitive))
574 return url.authority().isEmpty();
575
576#if defined(Q_OS_ANDROID)
577 if (scheme.length() == 6
578 && scheme.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive))
579 return url.authority().isEmpty();
580 if (scheme.length() == 7
581 && scheme.startsWith(QLatin1String(content_string), Qt::CaseInsensitive))
582 return hasLocalContentAuthority(url);
583#endif
584
585 return false;
586}
587
588static bool hasScheme(const QString &url, const char *scheme, qsizetype schemeLength)
589{
590 const qsizetype urlLength = url.size();
591
592 if (urlLength < schemeLength + 1)
593 return false;
594
595 if (!url.startsWith(QLatin1String(scheme, scheme + schemeLength), Qt::CaseInsensitive))
596 return false;
597
598 if (url[schemeLength] != QLatin1Char(':'))
599 return false;
600
601 return true;
602}
603
604static qsizetype authorityOffset(const QString &url, qsizetype schemeLength)
605{
606 const qsizetype urlLength = url.size();
607
608 if (urlLength < schemeLength + 3)
609 return -1;
610
611 const QLatin1Char slash('/');
612 if (url[schemeLength + 1] == slash && url[schemeLength + 2] == slash) {
613 // Exactly two slashes denote an authority.
614 if (urlLength < schemeLength + 4 || url[schemeLength + 3] != slash)
615 return schemeLength + 3;
616 }
617
618 return -1;
619}
620
621#if defined(Q_OS_ANDROID)
622static bool hasLocalContentAuthority(const QString &url, qsizetype schemeLength)
623{
624 const qsizetype offset = authorityOffset(url, schemeLength);
625 if (offset == -1)
626 return true; // no authority is a local authority.
627
628 const QString authorityAndPath = url.sliced(offset);
629 return authorityAndPath.startsWith(QLatin1String(authority_externalstorage))
630 || authorityAndPath.startsWith(QLatin1String(authority_downloads_documents))
631 || authorityAndPath.startsWith(QLatin1String(authority_media_documents));
632}
633
634#endif
635
645{
646 if (url.size() < 4 /* qrc: */)
647 return false;
648
649 switch (url[0].toLatin1()) {
650 case 'f':
651 case 'F': {
652 // file: URLs with two slashes following the scheme can be interpreted as local files
653 // where the slashes are part of the path. Therefore, disregard the authority.
654 // See QUrl::toLocalFile().
655 const qsizetype fileLength = strlen(file_string);
656 return url.startsWith(QLatin1String(file_string, file_string + fileLength),
658 && url.size() > fileLength
659 && url[fileLength] == QLatin1Char(':');
660 }
661 case 'q':
662 case 'Q':
663 return hasScheme(url, qrc_string, strlen(qrc_string))
664 && authorityOffset(url, strlen(qrc_string)) == -1;
665#if defined(Q_OS_ANDROID)
666 case 'a':
667 case 'A':
668 return hasScheme(url, assets_string, strlen(assets_string))
669 && authorityOffset(url, strlen(assets_string)) == -1;
670 case 'c':
671 case 'C':
672 return hasScheme(url, content_string, strlen(content_string))
673 && hasLocalContentAuthority(url, strlen(content_string));
674#endif
675 default:
676 break;
677 }
678
679 return false;
680}
681
689{
690 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
691 if (url.authority().isEmpty())
692 return QLatin1Char(':') + url.path();
693 return QString();
694 }
695
696#if defined(Q_OS_ANDROID)
697 if (url.scheme().compare(QLatin1String("assets"), Qt::CaseInsensitive) == 0)
698 return url.authority().isEmpty() ? url.toString() : QString();
699 if (url.scheme().compare(QLatin1String("content"), Qt::CaseInsensitive) == 0) {
700 if (hasLocalContentAuthority(url))
701 return url.toString();
702 return QString();
703 }
704#endif
705 return url.toLocalFile();
706}
707
709{
710 const QUrl file(url);
711 if (!file.isLocalFile())
712 return QString();
713
714 // QUrl::toLocalFile() interprets two slashes as part of the path.
715 // Therefore windows hostnames like "//servername/path/to/file.txt" are preserved.
716
717 return file.toLocalFile();
718}
719
721{
722 const qsizetype urlLength = url.size();
723 if (urlLength < offset + 2)
724 return false;
725
726 const QLatin1Char slash('/');
727 if (url[offset] != slash || url[offset + 1] != slash)
728 return false;
729
730 if (urlLength < offset + 3)
731 return true;
732
733 return url[offset + 2] != slash;
734}
735
743{
744 if (url.startsWith(QLatin1String("qrc://"), Qt::CaseInsensitive)) {
745 // Exactly two slashes are bad because that's a URL authority.
746 // One slash is fine and >= 3 slashes are file.
747 if (url.size() == 6 || url[6] != QLatin1Char('/')) {
748 Q_ASSERT(isDoubleSlashed(url, strlen("qrc:")));
749 return QString();
750 }
751 Q_ASSERT(!isDoubleSlashed(url, strlen("qrc:")));
752 return QLatin1Char(':') + QStringView{url}.mid(6);
753 }
754
755 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
756 Q_ASSERT(!isDoubleSlashed(url, strlen("qrc:")));
757 if (url.size() > 4)
758 return QLatin1Char(':') + QStringView{url}.mid(4);
759 return QStringLiteral(":");
760 }
761
762#if defined(Q_OS_ANDROID)
763 if (url.startsWith(QLatin1String("assets:"), Qt::CaseInsensitive))
764 return isDoubleSlashed(url, strlen("assets:")) ? QString() : url;
765 if (hasScheme(url, content_string, strlen(content_string)))
766 return hasLocalContentAuthority(url, strlen(content_string)) ? url : QString();
767#endif
768
769 return toLocalFile(url);
770}
771
773
774#include "qqmlfile.moc"
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
\inmodule QtCore
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
static QMetaMethod fromSignal(PointerToMemberFunction signal)
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
This signal is emitted to indicate the progress of the download part of this network request,...
void finished()
This signal is emitted when the reply has finished processing.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QByteArray data
Definition qqmlfile.cpp:88
QString errorString
Definition qqmlfile.cpp:95
QString urlString
Definition qqmlfile.cpp:86
\inmodule QtQml
Definition qqmlfile.h:18
qint64 size() const
Definition qqmlfile.cpp:292
static bool isLocalFile(const QString &url)
Returns true if url is a local file that can be opened with \l{QFile}.
Definition qqmlfile.cpp:644
static bool isSynchronous(const QString &url)
Definition qqmlfile.cpp:508
bool isReady() const
Definition qqmlfile.cpp:223
QString error() const
Definition qqmlfile.cpp:276
bool isError() const
Definition qqmlfile.cpp:231
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
bool isNull() const
Definition qqmlfile.cpp:215
QUrl url() const
Definition qqmlfile.cpp:247
const char * data() const
Definition qqmlfile.cpp:300
QByteArray dataByteArray() const
Definition qqmlfile.cpp:308
Status status() const
Definition qqmlfile.cpp:259
@ Loading
Definition qqmlfile.h:25
bool isLoading() const
Definition qqmlfile.cpp:239
void load(QQmlEngine *, const QUrl &)
Definition qqmlfile.cpp:317
void clear()
Definition qqmlfile.cpp:388
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
\inmodule QtCore
Definition qurl.h:94
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1896
QString authority(ComponentFormattingOptions options=PrettyDecoded) const
Returns the authority of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2055
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
Combined button and popup list for selecting options.
@ CaseInsensitive
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
@ None
Definition qhash.cpp:531
#define qWarning
Definition qlogging.h:166
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLfloat GLfloat f
GLenum GLuint GLintptr offset
GLfloat GLfloat p
[1]
bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn)
Returns true if the case of fileName is equivalent to the file case of fileName on disk,...
static char qrc_string[]
Definition qqmlfile.cpp:35
static QString toLocalFile(const QString &url)
Definition qqmlfile.cpp:708
static bool isDoubleSlashed(const QString &url, qsizetype offset)
Definition qqmlfile.cpp:720
static char file_string[]
Definition qqmlfile.cpp:36
static qsizetype authorityOffset(const QString &url, qsizetype schemeLength)
Definition qqmlfile.cpp:604
static bool hasScheme(const QString &url, const char *scheme, qsizetype schemeLength)
Definition qqmlfile.cpp:588
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define QT_CONFIG(feature)
#define Q_OBJECT
#define slots
#define signals
#define emit
#define Q_UNUSED(x)
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
QObject::connect nullptr
QNetworkReply * reply
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
\inmodule QtCore
static Connection connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Definition qobject.cpp:3556
int indexOfMethod(const char *method) const
Finds method and returns its index; otherwise returns -1.