diff options
-rw-r--r-- | src/quick/items/qquickloader.cpp | 93 | ||||
-rw-r--r-- | src/quick/items/qquickloader_p_p.h | 7 | ||||
-rw-r--r-- | tests/auto/quick/qquickloader/data/statusChanged.qml | 16 | ||||
-rw-r--r-- | tests/auto/quick/qquickloader/tst_qquickloader.cpp | 14 |
4 files changed, 91 insertions, 39 deletions
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index b389e7a11b..8c15b60712 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -55,7 +55,7 @@ static const QQuickItemPrivate::ChangeTypes watchedChanges QQuickLoaderPrivate::QQuickLoaderPrivate() : item(nullptr), object(nullptr), itemContext(nullptr), incubator(nullptr), updatingSize(false), - active(true), loadingFromSource(false), asynchronous(false) + active(true), loadingFromSource(false), asynchronous(false), status(computeStatus()) { } @@ -378,7 +378,7 @@ void QQuickLoader::setActive(bool newVal) d->object = nullptr; emit itemChanged(); } - emit statusChanged(); + d->updateStatus(); } emit activeChanged(); } @@ -431,7 +431,7 @@ void QQuickLoader::loadFromSource() Q_D(QQuickLoader); if (d->source.isEmpty()) { emit sourceChanged(); - emit statusChanged(); + d->updateStatus(); emit progressChanged(); emit itemChanged(); return; @@ -502,7 +502,7 @@ void QQuickLoader::loadFromSourceComponent() Q_D(QQuickLoader); if (!d->component) { emit sourceComponentChanged(); - emit statusChanged(); + d->updateStatus(); emit progressChanged(); emit itemChanged(); return; @@ -618,7 +618,7 @@ void QQuickLoaderPrivate::load() q, SLOT(_q_sourceLoaded())); QObject::connect(component, SIGNAL(progressChanged(qreal)), q, SIGNAL(progressChanged())); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); if (loadingFromSource) emit q->sourceChanged(); @@ -705,7 +705,7 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status) emit q->sourceChanged(); else emit q->sourceComponentChanged(); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); if (status == QQmlIncubator::Ready) emit q->loaded(); @@ -722,7 +722,7 @@ void QQuickLoaderPrivate::_q_sourceLoaded() emit q->sourceChanged(); else emit q->sourceComponentChanged(); - emit q->statusChanged(); + updateStatus(); emit q->progressChanged(); emit q->itemChanged(); //Like clearing source, emit itemChanged even if previous item was also null disposeInitialPropertyValues(); // cleanup @@ -740,7 +740,7 @@ void QQuickLoaderPrivate::_q_sourceLoaded() component->create(*incubator, itemContext); if (incubator && incubator->status() == QQmlIncubator::Loading) - emit q->statusChanged(); + updateStatus(); } /*! @@ -787,37 +787,7 @@ QQuickLoader::Status QQuickLoader::status() const { Q_D(const QQuickLoader); - if (!d->active) - return Null; - - if (d->component) { - switch (d->component->status()) { - case QQmlComponent::Loading: - return Loading; - case QQmlComponent::Error: - return Error; - case QQmlComponent::Null: - return Null; - default: - break; - } - } - - if (d->incubator) { - switch (d->incubator->status()) { - case QQmlIncubator::Loading: - return Loading; - case QQmlIncubator::Error: - return Error; - default: - break; - } - } - - if (d->object) - return Ready; - - return d->source.isEmpty() ? Null : Error; + return static_cast<Status>(d->status); } void QQuickLoader::componentComplete() @@ -1018,6 +988,51 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct return valuemap->asReturnedValue(); } +QQuickLoader::Status QQuickLoaderPrivate::computeStatus() const +{ + if (!active) + return QQuickLoader::Status::Null; + + if (component) { + switch (component->status()) { + case QQmlComponent::Loading: + return QQuickLoader::Status::Loading; + case QQmlComponent::Error: + return QQuickLoader::Status::Error; + case QQmlComponent::Null: + return QQuickLoader::Status::Null; + default: + break; + } + } + + if (incubator) { + switch (incubator->status()) { + case QQmlIncubator::Loading: + return QQuickLoader::Status::Loading; + case QQmlIncubator::Error: + return QQuickLoader::Status::Error; + default: + break; + } + } + + if (object) + return QQuickLoader::Status::Ready; + + return source.isEmpty() ? QQuickLoader::Status::Null : QQuickLoader::Status::Error; +} + +void QQuickLoaderPrivate::updateStatus() +{ + Q_Q(QQuickLoader); + auto newStatus = computeStatus(); + if (status != newStatus) { + status = newStatus; + emit q->statusChanged(); + } +} + #include <moc_qquickloader_p.cpp> QT_END_NAMESPACE diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index 349b5c6c06..39d50280c5 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -96,6 +96,8 @@ public: void disposeInitialPropertyValues(); static QUrl resolveSourceUrl(QQmlV4Function *args); QV4::ReturnedValue extractInitialPropertyValues(QQmlV4Function *args, QObject *loader, bool *error); + QQuickLoader::Status computeStatus() const; + void updateStatus(); qreal getImplicitWidth() const override; qreal getImplicitHeight() const override; @@ -112,6 +114,11 @@ public: bool active : 1; bool loadingFromSource : 1; bool asynchronous : 1; + // We need to use char instead of QQuickLoader::Status + // as otherwise the size of the class would increase + // on 32-bit systems, as sizeof(Status) == sizeof(int) + // and sizeof(int) > remaining padding on 32 bit + char status; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); diff --git a/tests/auto/quick/qquickloader/data/statusChanged.qml b/tests/auto/quick/qquickloader/data/statusChanged.qml new file mode 100644 index 0000000000..fe46bc7b24 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/statusChanged.qml @@ -0,0 +1,16 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 + +Window { + id: root + property int statusChangedCounter: 0 + property alias status: loader.status + visible: true; width: 640; height: 480 + Loader { + id: loader + anchors.fill: parent + asynchronous: true + source: "./RedRect.qml" + onStatusChanged: root.statusChangedCounter++ + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index d0a1a8a45b..7bd6f9466a 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -39,6 +39,7 @@ #include "testhttpserver.h" #include "../../shared/util.h" #include "../shared/geometrytestutil.h" +#include <QQmlApplicationEngine> Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") @@ -128,6 +129,7 @@ private slots: void rootContext(); void sourceURLKeepComponent(); + void statusChangeOnlyEmittedOnce(); }; Q_DECLARE_METATYPE(QList<QQmlError>) @@ -1446,6 +1448,18 @@ void tst_QQuickLoader::sourceURLKeepComponent() } +// QTBUG-82002 +void tst_QQuickLoader::statusChangeOnlyEmittedOnce() +{ + QQmlApplicationEngine engine; + auto url = testFileUrl("statusChanged.qml"); + engine.load(url); + auto root = engine.rootObjects().at(0); + QVERIFY(root); + QTRY_COMPARE(QQuickLoader::Status(root->property("status").toInt()), QQuickLoader::Ready); + QCOMPARE(root->property("statusChangedCounter").toInt(), 2); // 1xLoading + 1xReady*/ +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" |