Allow for private properties to be implemented using QProperty
Recently the moc learned that Q_PROPERTY(int x ...) can mean that "x" is implemented as QProperty and then allows installing bindings, etc. - this works by scanning the same class' members. For our own use of QProperty, we need to place the QProperty member itself into the d-pointer to be able to maintain the ability to add new properties without breaking binary compatibility. That however means that moc can't know that a certain property is backed by QProperty - we don't scan the members of the private class. As a workaround, this change enables the syntax where the property type used in Q_PRIVATE_PROPERTY may be wrapped with QProperty<T>. In addition this patch fixes the compilation of such declared properties by ensuring the accessor prefix (t->$accessor) is applied also for the QProperty related meta call variants. Change-Id: I8fbdc49319048b57f4eb0b65b56daba0459e9598 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
382577419a
commit
b480acb372
@ -1504,8 +1504,12 @@ void Generator::generateStaticMetacall()
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (!p.isQProperty)
|
||||
continue;
|
||||
fprintf(out, " case %d: observer->setSource(_t->%s); break;\n",
|
||||
propindex, p.name.constData());
|
||||
QByteArray prefix = "_t->";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
}
|
||||
fprintf(out, " case %d: observer->setSource(%s%s); break;\n",
|
||||
propindex, prefix.constData(), p.name.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
@ -1521,8 +1525,12 @@ void Generator::generateStaticMetacall()
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (!p.isQProperty)
|
||||
continue;
|
||||
fprintf(out, " case %d: _t->%s.setBinding(*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
||||
propindex, p.name.constData(), p.type.constData());
|
||||
QByteArray prefix = "_t->";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
}
|
||||
fprintf(out, " case %d: %s%s.setBinding(*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
||||
propindex, prefix.constData(), p.name.constData(), p.type.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
|
@ -1228,9 +1228,23 @@ void Moc::createPropertyDef(PropertyDef &propDef)
|
||||
{
|
||||
propDef.location = index;
|
||||
|
||||
const bool isPrivateProperty = !propDef.inPrivateClass.isEmpty();
|
||||
bool typeWrappedInQProperty = false;
|
||||
if (isPrivateProperty) {
|
||||
const int rewind = index;
|
||||
if (test(IDENTIFIER) && lexem() == "QProperty" && test(LANGLE)) {
|
||||
typeWrappedInQProperty = true;
|
||||
propDef.isQProperty = true;
|
||||
} else {
|
||||
index = rewind;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray type = parseType().name;
|
||||
if (type.isEmpty())
|
||||
error();
|
||||
if (typeWrappedInQProperty)
|
||||
next(RANGLE);
|
||||
propDef.designable = propDef.scriptable = propDef.stored = "true";
|
||||
propDef.user = "false";
|
||||
|
||||
@ -1806,7 +1820,7 @@ void Moc::checkProperties(ClassDef *cdef)
|
||||
definedProperties.insert(p.name);
|
||||
|
||||
if (p.read.isEmpty() && p.member.isEmpty()) {
|
||||
if (!cdef->qPropertyMembers.contains(p.name)) {
|
||||
if (!cdef->qPropertyMembers.contains(p.name) && !p.isQProperty) {
|
||||
const int rewind = index;
|
||||
if (p.location >= 0)
|
||||
index = p.location;
|
||||
|
@ -1542,6 +1542,7 @@ class PrivatePropertyTest : public QObject
|
||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub4 MEMBER mBlub NOTIFY blub4Changed)
|
||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub5 MEMBER mBlub NOTIFY blub5Changed)
|
||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub6 MEMBER mConst CONSTANT)
|
||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QProperty<int> x)
|
||||
class MyDPointer {
|
||||
public:
|
||||
MyDPointer() : mConst("const"), mBar(0), mPlop(0) {}
|
||||
@ -1555,6 +1556,7 @@ class PrivatePropertyTest : public QObject
|
||||
void setBlub(const QString &value) { mBlub = value; }
|
||||
QString mBlub;
|
||||
const QString mConst;
|
||||
QProperty<int> x;
|
||||
private:
|
||||
int mBar;
|
||||
int mPlop;
|
||||
@ -1590,6 +1592,9 @@ void tst_Moc::qprivateproperties()
|
||||
test.setProperty("baz", 4);
|
||||
QCOMPARE(test.property("baz"), QVariant::fromValue(4));
|
||||
|
||||
test.setProperty("x", 100);
|
||||
QCOMPARE(test.property("x"), QVariant::fromValue(100));
|
||||
QVERIFY(test.metaObject()->property(test.metaObject()->indexOfProperty("x")).isQProperty());
|
||||
}
|
||||
|
||||
void tst_Moc::warnOnPropertyWithoutREAD()
|
||||
|
Loading…
Reference in New Issue
Block a user