Add support for QNotifiedProperty to the moc
Change the meaning of Q_PRIVATE_QPROPERTY to imply that the property is implemented using a QNotifiedProperty. That requires passing the owner object instance to the value and binding setters. Similarly, detect QNotifiedProperty members like QProperty. Change-Id: If49bbb04c8ccd4a661973888c50d2d556c25034f Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
31d2804e7a
commit
b0f445a152
@ -1335,8 +1335,18 @@ void Generator::generateStaticMetacall()
|
||||
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData());
|
||||
} else if (!p.write.isEmpty()) {
|
||||
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
||||
QByteArray optionalQPropertyOwner;
|
||||
if (p.isQPropertyWithNotifier) {
|
||||
optionalQPropertyOwner = "_t";
|
||||
if (p.inPrivateClass.size()) {
|
||||
optionalQPropertyOwner += "->";
|
||||
optionalQPropertyOwner += p.inPrivateClass;
|
||||
}
|
||||
optionalQPropertyOwner += ", ";
|
||||
}
|
||||
|
||||
fprintf(out, " case %d: %s%s(%s*reinterpret_cast< %s*>(_v)); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData(), optionalQPropertyOwner.constData(), p.type.constData());
|
||||
} else {
|
||||
fprintf(out, " case %d:\n", propindex);
|
||||
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
|
||||
@ -1416,11 +1426,18 @@ void Generator::generateStaticMetacall()
|
||||
if (!p.isQProperty)
|
||||
continue;
|
||||
QByteArray prefix = "_t->";
|
||||
QByteArray objectAccessor = "_t";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
objectAccessor += "->";
|
||||
objectAccessor += 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());
|
||||
if (p.isQPropertyWithNotifier)
|
||||
objectAccessor += ", ";
|
||||
else
|
||||
objectAccessor.clear();
|
||||
fprintf(out, " case %d: %s%s.setBinding(%s*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
||||
propindex, prefix.constData(), p.name.constData(), objectAccessor.constData(), p.type.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
@ -1535,7 +1552,7 @@ void Generator::generateQPropertyApi()
|
||||
property.name.constData(),
|
||||
property.type.name.constData());
|
||||
printAccessor();
|
||||
fprintf(out, " return thisPtr->%s->%s.setValue(value);\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, value);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData());
|
||||
fprintf(out, "}\n");
|
||||
|
||||
// property value move setter
|
||||
@ -1544,7 +1561,7 @@ void Generator::generateQPropertyApi()
|
||||
property.name.constData(),
|
||||
property.type.name.constData());
|
||||
printAccessor();
|
||||
fprintf(out, " return thisPtr->%s->%s.setValue(std::move(value));\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " return thisPtr->%s->%s.setValue(thisPtr->%s, std::move(value));\n", property.accessor.constData(), property.name.constData(), property.accessor.constData());
|
||||
fprintf(out, "}\n");
|
||||
|
||||
// binding setter
|
||||
@ -1554,7 +1571,7 @@ void Generator::generateQPropertyApi()
|
||||
property.name.constData(),
|
||||
property.type.name.constData());
|
||||
printAccessor();
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData());
|
||||
fprintf(out, "}\n");
|
||||
|
||||
// binding move setter
|
||||
@ -1564,7 +1581,7 @@ void Generator::generateQPropertyApi()
|
||||
property.name.constData(),
|
||||
property.type.name.constData());
|
||||
printAccessor();
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(std::move(binding));\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, std::move(binding));\n", property.accessor.constData(), property.name.constData(), property.accessor.constData());
|
||||
fprintf(out, "}\n");
|
||||
|
||||
// untyped binding setter
|
||||
@ -1572,7 +1589,7 @@ void Generator::generateQPropertyApi()
|
||||
cdef->qualified.constData(),
|
||||
property.name.constData());
|
||||
printAccessor();
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.name.constData(), property.accessor.constData());
|
||||
fprintf(out, "}\n");
|
||||
|
||||
// binding bool getter
|
||||
@ -1606,7 +1623,7 @@ void Generator::generateQPropertyApi()
|
||||
cdef->qualified.constData(),
|
||||
property.setter.constData(),
|
||||
property.type.name.constData());
|
||||
fprintf(out, " %s->%s.setValue(value);\n", property.accessor.constData(), property.name.constData());
|
||||
fprintf(out, " this->%s.setValue(value);\n", property.name.constData());
|
||||
fprintf(out, "}\n\n");
|
||||
}
|
||||
}
|
||||
|
@ -582,8 +582,12 @@ bool Moc::parseMaybeQProperty(ClassDef *def)
|
||||
if (!test(IDENTIFIER))
|
||||
return false;
|
||||
|
||||
if (lexem() != "QProperty")
|
||||
bool hasNotifier = false;
|
||||
if (lexem() == "QNotifiedProperty") {
|
||||
hasNotifier = true;
|
||||
} else if (lexem() != "QProperty") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!test(LANGLE))
|
||||
return false;
|
||||
@ -596,7 +600,7 @@ bool Moc::parseMaybeQProperty(ClassDef *def)
|
||||
if (!test(SEMIC))
|
||||
return false;
|
||||
|
||||
def->qPropertyMembers.insert(propName);
|
||||
def->qPropertyMembersMaybeWithNotifier.insert(propName, hasNotifier);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1525,6 +1529,7 @@ void Moc::parsePrivateQProperty(ClassDef *def)
|
||||
propDef.read = name + ".value";
|
||||
propDef.write = name + ".setValue";
|
||||
propDef.isQProperty = true;
|
||||
propDef.isQPropertyWithNotifier = true;
|
||||
propDef.inPrivateClass = accessor;
|
||||
propDef.designable = propDef.scriptable = propDef.stored = "true";
|
||||
propDef.user = "false";
|
||||
@ -1868,7 +1873,10 @@ void Moc::checkProperties(ClassDef *cdef)
|
||||
}
|
||||
|
||||
if (p.read.isEmpty() && p.member.isEmpty()) {
|
||||
if (!cdef->qPropertyMembers.contains(p.name) && !p.isQProperty) {
|
||||
|
||||
auto qPropertyMemberIt = cdef->qPropertyMembersMaybeWithNotifier.constFind(p.name);
|
||||
const bool knownQPropertyMember = qPropertyMemberIt != cdef->qPropertyMembersMaybeWithNotifier.constEnd();
|
||||
if (!knownQPropertyMember && !p.isQProperty) {
|
||||
const int rewind = index;
|
||||
if (p.location >= 0)
|
||||
index = p.location;
|
||||
@ -1885,6 +1893,8 @@ void Moc::checkProperties(ClassDef *cdef)
|
||||
p.read = p.name + ".value";
|
||||
p.write = p.name + ".setValue";
|
||||
p.isQProperty = true;
|
||||
const bool hasNotifier = knownQPropertyMember && qPropertyMemberIt.value();
|
||||
p.isQPropertyWithNotifier = hasNotifier;
|
||||
p.designable = p.scriptable = p.stored = "true";
|
||||
p.user = "false";
|
||||
}
|
||||
|
@ -141,6 +141,7 @@ struct PropertyDef
|
||||
bool final = false;
|
||||
bool required = false;
|
||||
bool isQProperty = false;
|
||||
bool isQPropertyWithNotifier = false;
|
||||
|
||||
int location = -1; // token index, used for error reporting
|
||||
|
||||
@ -200,7 +201,7 @@ struct ClassDef : BaseDef {
|
||||
QVector<QByteArray> nonClassSignalList;
|
||||
QVector<PropertyDef> propertyList;
|
||||
QVector<PrivateQPropertyDef> privateQProperties;
|
||||
QSet<QByteArray> qPropertyMembers;
|
||||
QHash<QByteArray, bool> qPropertyMembersMaybeWithNotifier;
|
||||
int revisionedMethods = 0;
|
||||
|
||||
bool hasQObject = false;
|
||||
|
@ -4116,19 +4116,20 @@ class ClassWithQPropertyMembers : public QObject
|
||||
Q_PROPERTY(int privateExposedProperty)
|
||||
public:
|
||||
|
||||
QProperty<int> publicProperty;
|
||||
QProperty<int> notExposed;
|
||||
|
||||
signals:
|
||||
void publicPropertyChanged();
|
||||
|
||||
public:
|
||||
QNotifiedProperty<int, &ClassWithQPropertyMembers::publicPropertyChanged> publicProperty;
|
||||
QProperty<int> notExposed;
|
||||
|
||||
|
||||
protected:
|
||||
QProperty<int> protectedProperty;
|
||||
|
||||
private:
|
||||
QProperty<int> privateProperty;
|
||||
QProperty<int> privateExposedProperty;
|
||||
QPropertyMemberChangeHandler<&ClassWithQPropertyMembers::publicProperty, &ClassWithQPropertyMembers::publicPropertyChanged> connector{this};
|
||||
};
|
||||
|
||||
void tst_Moc::qpropertyMembers()
|
||||
@ -4151,7 +4152,7 @@ void tst_Moc::qpropertyMembers()
|
||||
|
||||
QSignalSpy publicPropertySpy(&instance, SIGNAL(publicPropertyChanged()));
|
||||
|
||||
instance.publicProperty.setValue(100);
|
||||
instance.publicProperty.setValue(&instance, 100);
|
||||
QCOMPARE(prop.read(&instance).toInt(), 100);
|
||||
QCOMPARE(publicPropertySpy.count(), 1);
|
||||
|
||||
@ -4182,9 +4183,9 @@ void tst_Moc::observerMetaCall()
|
||||
instance.qt_metacall(QMetaObject::RegisterQPropertyObserver, prop.propertyIndex(), argv);
|
||||
}
|
||||
|
||||
instance.publicProperty.setValue(100);
|
||||
instance.publicProperty.setValue(&instance, 100);
|
||||
QCOMPARE(observerCallCount, 1);
|
||||
instance.publicProperty.setValue(101);
|
||||
instance.publicProperty.setValue(&instance, 101);
|
||||
QCOMPARE(observerCallCount, 2);
|
||||
}
|
||||
|
||||
@ -4235,9 +4236,8 @@ public:
|
||||
|
||||
ClassWithPrivateQPropertyShim *q = nullptr;
|
||||
|
||||
QProperty<int> testProperty;
|
||||
void onTestPropertyChanged() { q->testPropertyChanged(); }
|
||||
QPropertyMemberChangeHandler<&Private::testProperty, &Private::onTestPropertyChanged> testChangeHandler{this};
|
||||
QNotifiedProperty<int, &Private::onTestPropertyChanged> testProperty;
|
||||
};
|
||||
Private priv{this};
|
||||
|
||||
@ -4257,7 +4257,7 @@ void tst_Moc::privateQPropertyShim()
|
||||
QVERIFY(prop.notifySignal().isValid());
|
||||
}
|
||||
|
||||
testObject.priv.testProperty.setValue(42);
|
||||
testObject.priv.testProperty.setValue(&testObject.priv, 42);
|
||||
QCOMPARE(testObject.property("testProperty").toInt(), 42);
|
||||
|
||||
// Behave like a QProperty
|
||||
|
Loading…
Reference in New Issue
Block a user