aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-09-15 10:12:21 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-10-01 15:12:59 +0000
commitb34b0b0edb0e044a5827787be548ec936e820656 (patch)
tree55d4a7fc86c666a46414ada35e8770724b6cf925
parent5059809646ea93477557a43c4d0b0f1d5c8a0a10 (diff)
QQmlBinding::dependencies: Handle QProperty
The method did not consider QProperty properties, as those do not show up via the active guards mechanism. At some point, we probably also want to introduce QQmlAnyBinding::dependencies, as there are now bindings which do not derive from QQmlBinding. Change-Id: Ib4b227a440e9494c09d92028f9eaa5ad1e87342f Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> (cherry picked from commit de28bc00f514c3ee8d8fd3166973c063766e77fd) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/qml/qqmlbinding.cpp8
-rw-r--r--src/qml/qml/qqmlbinding_p.h1
-rw-r--r--src/qml/qml/qqmlengine_p.h3
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp10
-rw-r--r--tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp31
5 files changed, 52 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 62275c792e..c137a85654 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -772,11 +772,17 @@ QVector<QQmlProperty> QQmlBinding::dependencies() const
for (int i = 0; i < senderMeta->propertyCount(); i++) {
QMetaProperty property = senderMeta->property(i);
if (property.notifySignalIndex() == QMetaObjectPrivate::signal(senderMeta, guard->signalIndex()).methodIndex()) {
- dependencies.push_back(QQmlProperty(senderObject, QString::fromUtf8(senderObject->metaObject()->property(i).name())));
+ dependencies.push_back(QQmlProperty(senderObject, QString::fromUtf8(property.name())));
}
}
}
+ for (auto trigger = qpropertyChangeTriggers; trigger; trigger = trigger->next) {
+ QMetaProperty prop = trigger->property();
+ if (prop.isValid())
+ dependencies.push_back(QQmlProperty(trigger->target, QString::fromUtf8(prop.name())));
+ }
+
return dependencies;
}
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 6ba492f0e4..7c3dab98c2 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -133,6 +133,7 @@ public:
* Call this method from the UI thread.
*/
QVector<QQmlProperty> dependencies() const;
+ // This method is used internally to check whether a binding is constant and can be removed
virtual bool hasDependencies() const;
protected:
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 499f9dd492..18a0164028 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -75,6 +75,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qstring.h>
#include <QtCore/qthread.h>
+#include <QtCore/QMetaProperty>
#include <private/qobject_p.h>
@@ -132,6 +133,8 @@ struct QPropertyChangeTrigger : QPropertyObserver {
QObject *target = nullptr;
int propertyIndex = 0;
static void trigger(QPropertyObserver *, QUntypedPropertyData *);
+
+ QMetaProperty property() const;
};
struct TriggerList : QPropertyChangeTrigger {
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index d2f24166a9..1e32cd6926 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -541,6 +541,16 @@ void QPropertyChangeTrigger::trigger(QPropertyObserver *observer, QUntypedProper
This->m_expression->expressionChanged();
}
+QMetaProperty QPropertyChangeTrigger::property() const
+{
+ if (!target)
+ return {};
+ auto const mo = target->metaObject();
+ if (!mo)
+ return {};
+ return mo->property(propertyIndex);
+}
+
QPropertyChangeTrigger *QQmlJavaScriptExpression::allocatePropertyChangeTrigger(QObject *target, int propertyIndex)
{
auto trigger = QQmlEnginePrivate::get(engine())->qPropertyTriggerPool.New( this );
diff --git a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
index dfb595ffb0..81162c2c8a 100644
--- a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
+++ b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
@@ -48,6 +48,7 @@ private slots:
void testConditionalDependencies_data();
void testConditionalDependencies();
void testBindingLoop();
+ void testQproperty();
private:
bool findProperties(const QVector<QQmlProperty> &properties, QObject *obj, const QString &propertyName, const QVariant &value);
@@ -354,6 +355,36 @@ void tst_bindingdependencyapi::testBindingLoop()
delete rect;
}
+void tst_bindingdependencyapi::testQproperty()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData(QByteArray("import QtQuick 2.0\n"
+ "Item {\n"
+ "id: root\n"
+ "Text {\n"
+ "id: label\n"
+ "text: root.x\n"
+ "}\n"
+ "}"), QUrl());
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(!root.isNull());
+ QObject *text = root->findChildren<QQuickText *>().front();
+ QVERIFY(text);
+ auto data = QQmlData::get(text);
+ QVERIFY(data);
+ auto b = data->bindings;
+ QVERIFY(b);
+ auto binding = dynamic_cast<QQmlBinding*>(b);
+ QVERIFY(binding);
+ auto dependencies = binding->dependencies();
+ QCOMPARE(dependencies.size(), 1);
+ auto dependency = dependencies.front();
+ QVERIFY(dependency.isValid());
+ QCOMPARE(quintptr(dependency.object()), quintptr(root.get()));
+ QCOMPARE(dependency.property().name(), "x");
+}
+
QTEST_MAIN(tst_bindingdependencyapi)
#include "tst_bindingdependencyapi.moc"