diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-23 09:50:53 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-23 14:08:28 +0200 |
commit | 797a8f2aaaa8133ea8a54d9e4b91ba531fab3070 (patch) | |
tree | 047eb128e093252ae120b64f2c4278088738857f | |
parent | 1596dbf081ff52d3fe07fdccfd69ffdf1b28e92c (diff) |
QQmlEngine: Add method to explicitly capture a property
Also, use that method to capture the uiLanguage notify signal.
Previously the wrong signal was captured. The test still happened to
pass because we manually re-evaluated all bindings when the uiLanguage
property changed. Add a test which avoid that.
Change-Id: I3961b60b365a8705930936f20881421bd4ceffe5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 15 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.h | 2 | ||||
-rw-r--r-- | src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 14 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 53 |
4 files changed, 55 insertions, 29 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 3f871d5c6a..b5b36cccb9 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1327,6 +1327,21 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled) } /*! + \internal + + Capture the given property as part of a binding. + */ +void QQmlEngine::captureProperty(QObject *object, const QMetaProperty &property) const +{ + Q_D(const QQmlEngine); + if (d->propertyCapture) { + d->propertyCapture->captureProperty( + object, property.propertyIndex(), + QMetaObjectPrivate::signalIndex(property.notifySignal())); + } +} + +/*! \qmlproperty string Qt::uiLanguage \since 5.15 diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 0f9e6da63f..37ca25779f 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -158,6 +158,8 @@ public: template<typename T> T singletonInstance(int qmlTypeId); + void captureProperty(QObject *object, const QMetaProperty &property) const; + public Q_SLOTS: void retranslate(); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 3b6c448e49..e77738d985 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1370,15 +1370,11 @@ ReturnedValue QtObject::method_get_uiLanguage(const FunctionObject *b, const Val QQmlEnginePrivate *ep = QQmlEnginePrivate::get(scope.engine); if (ep && ep->propertyCapture) { - static int propertyIndex = -1; - static int notifySignalIndex = -1; - if (propertyIndex < 0) { - QMetaProperty metaProperty = - QQmlEngine::staticMetaObject.property(QQmlEngine::staticMetaObject.indexOfProperty("uiLanguage")); - propertyIndex = metaProperty.propertyIndex(); - notifySignalIndex = metaProperty.notifySignalIndex(); - } - ep->propertyCapture->captureProperty(QQmlEnginePrivate::get(ep), propertyIndex, notifySignalIndex); + static const QMetaProperty metaProperty + = QQmlEngine::staticMetaObject.property( + QQmlEngine::staticMetaObject.indexOfProperty("uiLanguage")); + QQmlEngine *e = QQmlEnginePrivate::get(ep); + e->captureProperty(e, metaProperty); } return Encode(scope.engine->newString(QJSEnginePrivate::get(jsEngine)->uiLanguage)); diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index ff8d6e2b2c..1e9b6434c4 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -1195,34 +1195,47 @@ void tst_qqmlengine::createComponentOnSingletonDestruction() void tst_qqmlengine::uiLanguage() { - QQmlEngine engine; + { + QQmlEngine engine; - QObject::connect(&engine, &QJSEngine::uiLanguageChanged, [&engine]() { - engine.retranslate(); - }); + QObject::connect(&engine, &QJSEngine::uiLanguageChanged, [&engine]() { + engine.retranslate(); + }); - QSignalSpy uiLanguageChangeSpy(&engine, SIGNAL(uiLanguageChanged())); + QSignalSpy uiLanguageChangeSpy(&engine, SIGNAL(uiLanguageChanged())); - QQmlComponent component(&engine, testFileUrl("uiLanguage.qml")); + QQmlComponent component(&engine, testFileUrl("uiLanguage.qml")); - QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); - QScopedPointer<QObject> object(component.create()); - QVERIFY(!object.isNull()); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); - QVERIFY(engine.uiLanguage().isEmpty()); - QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 1); + QVERIFY(engine.uiLanguage().isEmpty()); + QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 1); - QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); - engine.setUiLanguage("TestLanguage"); - QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 2); - QCOMPARE(object->property("chosenLanguage").toString(), "TestLanguage"); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); + engine.setUiLanguage("TestLanguage"); + QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 2); + QCOMPARE(object->property("chosenLanguage").toString(), "TestLanguage"); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); + engine.evaluate("Qt.uiLanguage = \"anotherLanguage\""); + QCOMPARE(engine.uiLanguage(), QString("anotherLanguage")); + QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 3); + QCOMPARE(object->property("chosenLanguage").toString(), "anotherLanguage"); + } + + { + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("uiLanguage.qml")); - QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); - engine.evaluate("Qt.uiLanguage = \"anotherLanguage\""); - QCOMPARE(engine.uiLanguage(), QString("anotherLanguage")); - QCOMPARE(object->property("numberOfTranslationBindingEvaluations").toInt(), 3); - QCOMPARE(object->property("chosenLanguage").toString(), "anotherLanguage"); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, (component.url().toString() + ":2:1: QML QtObject: Binding loop detected for property \"textToTranslate\"").toLatin1()); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + engine.setUiLanguage("TestLanguage"); + QCOMPARE(object->property("chosenLanguage").toString(), "TestLanguage"); + } } QTEST_MAIN(tst_qqmlengine) |