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>bb10
parent
eacf83594a
commit
0cd3820e4d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ struct PrivateQPropertyDef
|
|||
QByteArray name;
|
||||
QByteArray setter;
|
||||
QByteArray accessor;
|
||||
QByteArray storage;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(PrivateQPropertyDef, Q_MOVABLE_TYPE);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue