summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-07-07 16:54:44 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-07-08 11:01:38 +0200
commit0cd3820e4d62d91c006a807f04c77166b2dbc7f5 (patch)
treec2045a95f28b40dd2196f26637b57d330ffbbfb6
parenteacf83594a5bf063665fdecc6c438673dc9f2cf6 (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.cpp18
-rw-r--r--src/tools/moc/moc.cpp16
-rw-r--r--src/tools/moc/moc.h1
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp38
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)