diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-07-07 16:54:44 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-07-08 11:01:38 +0200 |
commit | 0cd3820e4d62d91c006a807f04c77166b2dbc7f5 (patch) | |
tree | c2045a95f28b40dd2196f26637b57d330ffbbfb6 | |
parent | eacf83594a5bf063665fdecc6c438673dc9f2cf6 (diff) |
moc: Allow out-of-line storage for Q_PRIVATE_QPROPERTY
If you pass "STORED false" the name is interpreted as function to be
invoked in order to access the property. This allows storage of a
property in a lazily allocated data type.
Change-Id: I4d3a9cac6985c6419ce687868cb74b91921595a6
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/tools/moc/generator.cpp | 18 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 16 | ||||
-rw-r--r-- | src/tools/moc/moc.h | 1 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 38 |
4 files changed, 59 insertions, 14 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 39640b6f68..4f420b8467 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1555,7 +1555,7 @@ void Generator::generateQPropertyApi() cdef->qualified.constData(), property.name.constData()); printAccessor(/*const*/true); - fprintf(out, " return thisPtr->%s->%s.value();\n", property.accessor.constData(), property.name.constData()); + fprintf(out, " return thisPtr->%s->%s.value();\n", property.accessor.constData(), property.storage.constData()); fprintf(out, "}\n"); // property value setter @@ -1564,7 +1564,7 @@ void Generator::generateQPropertyApi() property.name.constData(), property.type.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, value);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData()); + fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, value);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData()); fprintf(out, "}\n"); // property value move setter @@ -1573,7 +1573,7 @@ void Generator::generateQPropertyApi() property.name.constData(), property.type.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, std::move(value));\n", property.accessor.constData(), property.name.constData(), property.accessor.constData()); + fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, std::move(value));\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData()); fprintf(out, "}\n"); // binding setter @@ -1583,7 +1583,7 @@ void Generator::generateQPropertyApi() property.name.constData(), property.type.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData()); + fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData()); fprintf(out, "}\n"); // binding move setter @@ -1593,7 +1593,7 @@ void Generator::generateQPropertyApi() property.name.constData(), property.type.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, std::move(binding));\n", property.accessor.constData(), property.name.constData(), property.accessor.constData()); + fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, std::move(binding));\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData()); fprintf(out, "}\n"); // untyped binding setter @@ -1601,7 +1601,7 @@ void Generator::generateQPropertyApi() cdef->qualified.constData(), property.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData()); + fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData()); fprintf(out, "}\n"); // binding bool getter @@ -1609,7 +1609,7 @@ void Generator::generateQPropertyApi() cdef->qualified.constData(), property.name.constData()); printAccessor(/*const*/true); - fprintf(out, " return thisPtr->%s->%s.hasBinding();\n", property.accessor.constData(), property.name.constData()); + fprintf(out, " return thisPtr->%s->%s.hasBinding();\n", property.accessor.constData(), property.storage.constData()); fprintf(out, "}\n"); // binding getter @@ -1618,7 +1618,7 @@ void Generator::generateQPropertyApi() cdef->qualified.constData(), property.name.constData()); printAccessor(/*const*/true); - fprintf(out, " return thisPtr->%s->%s.binding();\n", property.accessor.constData(), property.name.constData()); + fprintf(out, " return thisPtr->%s->%s.binding();\n", property.accessor.constData(), property.storage.constData()); fprintf(out, "}\n"); // binding taker @@ -1627,7 +1627,7 @@ void Generator::generateQPropertyApi() cdef->qualified.constData(), property.name.constData()); printAccessor(); - fprintf(out, " return thisPtr->%s->%s.takeBinding();\n", property.accessor.constData(), property.name.constData()); + fprintf(out, " return thisPtr->%s->%s.takeBinding();\n", property.accessor.constData(), property.storage.constData()); fprintf(out, "}\n"); // property setter function diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index e31bdfbb15..44e669a664 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1527,14 +1527,9 @@ void Moc::parsePrivateQProperty(ClassDef *def) next(IDENTIFIER); const QByteArray setter = lexem(); - def->privateQProperties += PrivateQPropertyDef{type, name, setter, accessor}; - PropertyDef propDef; propDef.name = name; - propDef.qpropertyname = name; propDef.type = type.name; - propDef.read = name + ".value"; - propDef.write = name + ".setValue"; propDef.isQProperty = true; propDef.isQPropertyWithNotifier = true; propDef.inPrivateClass = accessor; @@ -1544,6 +1539,17 @@ void Moc::parsePrivateQProperty(ClassDef *def) if (test(COMMA)) parsePropertyAttributes(propDef); + propDef.qpropertyname = (propDef.stored == "true") ? name : (name + "()"); + + def->privateQProperties += PrivateQPropertyDef { + type, name, setter, accessor, propDef.qpropertyname + }; + + if (propDef.read.isEmpty()) + propDef.read = propDef.qpropertyname + ".value"; + if (propDef.write.isEmpty()) + propDef.write = propDef.qpropertyname + ".setValue"; + next(RPAREN); def->propertyList += propDef; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 549b3cdd39..b4bb105601 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -155,6 +155,7 @@ struct PrivateQPropertyDef QByteArray name; QByteArray setter; QByteArray accessor; + QByteArray storage; }; Q_DECLARE_TYPEINFO(PrivateQPropertyDef, Q_MOVABLE_TYPE); diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 01d207b080..14c61d552d 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -4170,13 +4170,17 @@ class ClassWithPrivateQPropertyShim :public QObject Q_OBJECT public: Q_PRIVATE_QPROPERTY(d_func(), int, testProperty, setTestProperty, NOTIFY testPropertyChanged) + Q_PRIVATE_QPROPERTY(d_func(), int, lazyTestProperty, setLazyTestProperty, + NOTIFY lazyTestPropertyChanged STORED false) Q_PRIVATE_QPROPERTIES_BEGIN Q_PRIVATE_QPROPERTY_IMPL(testProperty) + Q_PRIVATE_QPROPERTY_IMPL(lazyTestProperty) Q_PRIVATE_QPROPERTIES_END signals: void testPropertyChanged(); + void lazyTestPropertyChanged(); public: struct Private { @@ -4188,6 +4192,22 @@ public: void onTestPropertyChanged() { q->testPropertyChanged(); } QNotifiedProperty<int, &Private::onTestPropertyChanged> testProperty; + + void onLazyTestPropertyChanged() { q->lazyTestPropertyChanged(); } + + QNotifiedProperty<int, &Private::onLazyTestPropertyChanged> &lazyTestProperty() { + if (!lazyTestPropertyStorage) + lazyTestPropertyStorage.reset(new QNotifiedProperty<int, &Private::onLazyTestPropertyChanged>); + return *lazyTestPropertyStorage; + } + + const QNotifiedProperty<int, &Private::onLazyTestPropertyChanged> &lazyTestProperty() const { + if (!lazyTestPropertyStorage) + lazyTestPropertyStorage.reset(new QNotifiedProperty<int, &Private::onLazyTestPropertyChanged>); + return *lazyTestPropertyStorage; + } + + mutable QScopedPointer<QNotifiedProperty<int, &Private::onLazyTestPropertyChanged>> lazyTestPropertyStorage; }; Private priv{this}; @@ -4220,6 +4240,24 @@ void tst_Moc::privateQPropertyShim() testObject.setTestProperty(400); QVERIFY(!testObject.testProperty.hasBinding()); QCOMPARE(testObject.testProperty(), 400); + + // Created and default-initialized, without nullptr access + QCOMPARE(testObject.lazyTestProperty(), 0); + + // Explicitly set to something + testObject.priv.lazyTestProperty().setValue(&testObject.priv, 42); + QCOMPARE(testObject.property("lazyTestProperty").toInt(), 42); + + // Behave like a QProperty + QVERIFY(!testObject.lazyTestProperty.hasBinding()); + testObject.lazyTestProperty.setBinding([]() { return 100; }); + QCOMPARE(testObject.lazyTestProperty.value(), 100); + QVERIFY(testObject.lazyTestProperty.hasBinding()); + + // Old style setter getters + testObject.setLazyTestProperty(400); + QVERIFY(!testObject.lazyTestProperty.hasBinding()); + QCOMPARE(testObject.lazyTestProperty(), 400); } QTEST_MAIN(tst_Moc) |