aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickloader.cpp93
-rw-r--r--src/quick/items/qquickloader_p_p.h7
-rw-r--r--tests/auto/quick/qquickloader/data/statusChanged.qml16
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp14
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"