summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorBrett Stottlemyer <bstottle@ford.com>2018-04-03 13:44:01 -0400
committerBrett Stottlemyer <bstottle@ford.com>2018-04-04 01:39:37 +0000
commit35dd08098f8a4b422d523792261aefe039358f6a (patch)
tree3c626bca824b869d2008e00978496c731fc5e4d6 /tools
parent6e5e4df3c65e01bae143887fb4eff409c846023a (diff)
Rework REPC QObject* handlingv5.11.0-beta3
The MODEL and CLASS types were originally tacked on top of repc's property handling mechanism. That is, separate lists for models and subclasses were created instead of including the types in repc's list of property metadata. This was convenient for proving out the functionality, but led to a bunch of one-off code (generating Q_PROPERTY code manually, needing separate replica getter functions, etc). This change incorporates the pointer types back into the property list in repc, simplifying the code. This does require extensions because pointer types are not symmetric (i.e., for MODEL, the type is QAbstractItemModel* on the source side, QAbstractItemModelReplica* on the replica side). The generated SourceApi code is enhanced to compile-time check subclass types as well as take an optional name parameter (which allows a class to have multiple subclass pointers). SimpleSource handling of CONSTANT properties is also extended, providing constructor parameters to set the initial values. Change-Id: I91f542ef936abe4459962ae759ba3b0571464d5f Reviewed-by: Michael Brasser <michael.brasser@live.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/repc/repcodegenerator.cpp318
-rw-r--r--tools/repc/repcodegenerator.h1
2 files changed, 130 insertions, 189 deletions
diff --git a/tools/repc/repcodegenerator.cpp b/tools/repc/repcodegenerator.cpp
index 00cc481..8f8cfb3 100644
--- a/tools/repc/repcodegenerator.cpp
+++ b/tools/repc/repcodegenerator.cpp
@@ -201,8 +201,11 @@ void RepCodeGenerator::generate(const AST &ast, Mode mode, QString fileName)
metaTypes << attribute.type;
}
Q_FOREACH (const ASTClass &astClass, ast.classes) {
- Q_FOREACH (const ASTProperty &property, astClass.properties)
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ if (property.isPointer)
+ continue;
metaTypes << property.type;
+ }
Q_FOREACH (const ASTFunction &function, astClass.signalsList + astClass.slotsList) {
metaTypes << function.returnType;
Q_FOREACH (const ASTDeclaration &decl, function.params) {
@@ -248,7 +251,7 @@ void RepCodeGenerator::generateHeader(Mode mode, QTextStream &out, const AST &as
bool hasModel = false;
for (auto c : ast.classes)
{
- if (c.models.count() > 0)
+ if (c.modelMetadata.count() > 0)
{
hasModel = true;
break;
@@ -362,6 +365,25 @@ QString RepCodeGenerator::formatMarshallingOperators(const POD &pod)
;
}
+QString RepCodeGenerator::typeForMode(const ASTProperty &property, RepCodeGenerator::Mode mode)
+{
+ if (!property.isPointer)
+ return property.type;
+
+ if (property.type.startsWith(QStringLiteral("QAbstractItemModel")))
+ return mode == REPLICA ? property.type + QStringLiteral("Replica*") : property.type + QStringLiteral("*");
+
+ switch (mode) {
+ case REPLICA: return property.type + QStringLiteral("Replica*");
+ case SIMPLE_SOURCE:
+ Q_FALLTHROUGH();
+ case SOURCE: return property.type + QStringLiteral("Source*");
+ default: qCritical("Invalid mode");
+ }
+
+ return QStringLiteral("InvalidPropertyName");
+}
+
void RepCodeGenerator::generateSimpleSetter(QTextStream &out, const ASTProperty &property, bool generateOverride)
{
out << " virtual void set" << cap(property.name) << "(" << property.type << " " << property.name << ")";
@@ -594,20 +616,21 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
if (mode != SIMPLE_SOURCE) {
out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, \"" << astClass.name << "\")" << endl;
out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_SIGNATURE, \"" << QLatin1String(classSignature(astClass)) << "\")" << endl;
- for (int i = 0; i < astClass.models.count(); i++) {
- const auto model = astClass.models.at(i);
+ for (int i = 0; i < astClass.modelMetadata.count(); i++) {
+ const auto model = astClass.modelMetadata.at(i);
+ const auto modelName = astClass.properties.at(model.propertyIndex).name;
if (!model.roles.isEmpty()) {
QStringList list;
for (auto role : model.roles)
list << role.name;
- out << QString::fromLatin1(" Q_CLASSINFO(\"%1_ROLES\", \"%2\")").arg(model.name.toUpper(), list.join(QChar::fromLatin1('|'))) << endl;
+ out << QString::fromLatin1(" Q_CLASSINFO(\"%1_ROLES\", \"%2\")").arg(modelName.toUpper(), list.join(QChar::fromLatin1('|'))) << endl;
}
}
//First output properties
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " Q_PROPERTY(" << property.type << " " << property.name << " READ " << property.name;
+ out << " Q_PROPERTY(" << typeForMode(property, mode) << " " << property.name << " READ " << property.name;
if (property.modifier == ASTProperty::Constant)
out << " CONSTANT";
else if (property.modifier == ASTProperty::ReadOnly)
@@ -622,18 +645,6 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
out << ")" << endl;
}
- for (auto model : astClass.models) {
- if (mode == REPLICA)
- out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModelReplica *%1 READ %1 NOTIFY %1Changed)").arg(model.name) << endl;
- else
- out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModel *%1 READ %1 CONSTANT)").arg(model.name) << endl;
- }
- for (auto child : astClass.children) {
- if (mode == REPLICA)
- out << QString::fromLatin1(" Q_PROPERTY(%1Replica *%2 READ %2 NOTIFY %2Changed)").arg(child.type, child.name) << endl;
- else
- out << QString::fromLatin1(" Q_PROPERTY(%1Source *%2 READ %2 CONSTANT)").arg(child.type, child.name) << endl;
- }
if (!astClass.enums.isEmpty()) {
out << "" << endl;
@@ -659,47 +670,42 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
out << " }" << endl;
- if (!astClass.models.isEmpty() || !astClass.children.isEmpty())
+ if (astClass.hasPointerObjects())
{
out << " void setNode(QRemoteObjectNode *node) override" << endl;
out << " {" << endl;
- for (auto model : astClass.models) {
- out << QString::fromLatin1(" m_%1.reset(node->acquireModel(\"Model::%1\"));")
- .arg(model.name) << endl;
- out << " emit " << model.name << "Changed();" << endl;
- }
- for (auto child : astClass.children) {
- out << QString::fromLatin1(" m_%1.reset(node->acquire<%2Replica>(\"Class::%1\"));")
- .arg(child.name, child.type) << endl;
- out << " emit " << child.name << "Changed();" << endl;
- }
- if (!astClass.children.isEmpty()) {
- out << " // This relies on finalize being called before any other slots connected to initialized to ensure" << endl;
- out << " // any child replicas that don't have sources are null instead of the replica defaults." << endl;
- out << " connect(this, &" << className << "::initialized, [this]() { finalize(); });" << endl;
- }
out << " QRemoteObjectReplica::setNode(node);" << endl;
+ for (int index = 0; index < astClass.properties.count(); ++index) {
+ const ASTProperty &property = astClass.properties.at(index);
+ if (!property.isPointer)
+ continue;
+ if (astClass.subClassPropertyIndices.contains(index))
+ out << QString::fromLatin1(" setChild(%1, QVariant::fromValue(node->acquire<%2Replica>(\"Class::%3\")));")
+ .arg(QString::number(index), property.type, property.name) << endl;
+ else
+ out << QString::fromLatin1(" setChild(%1, QVariant::fromValue(node->acquireModel(\"Model::%2\")));")
+ .arg(QString::number(index), property.name) << endl;
+ }
out << " }" << endl;
}
out << "" << endl;
out << "private:" << endl;
out << " " << className << "(QRemoteObjectNode *node, const QString &name = QString())" << endl;
out << " : QRemoteObjectReplica(ConstructWithNode)" << endl;
- for (auto model : astClass.models)
- out << QString::fromLatin1(" , m_%1(node->acquireModel(\"Model::%1\"))")
- .arg(model.name) << endl;
- for (auto child : astClass.children)
- out << QString::fromLatin1(" , m_%1(node->acquire<%2Replica>(\"Class::%1\"))")
- .arg(child.name, child.type) << endl;
- if (astClass.children.count()) {
- out << " {" << endl;
- out << " // This relies on finalize being called before any other slots connected to initialized to ensure" << endl;
- out << " // any child replicas that don't have sources are null instead of the replica defaults." << endl;
- out << " connect(this, &" << className << "::initialized, [this]() { finalize(); });" << endl;
- out << " initializeNode(node, name);" << endl;
- out << " }" << endl;
- } else
- out << " { initializeNode(node, name); }" << endl;
+ out << " {" << endl;
+ out << " initializeNode(node, name);" << endl;
+ for (int index = 0; index < astClass.properties.count(); ++index) {
+ const ASTProperty &property = astClass.properties.at(index);
+ if (!property.isPointer)
+ continue;
+ if (astClass.subClassPropertyIndices.contains(index))
+ out << QString::fromLatin1(" setChild(%1, QVariant::fromValue(node->acquire<%2Replica>(\"Class::%3\")));")
+ .arg(QString::number(index), property.type, property.name) << endl;
+ else
+ out << QString::fromLatin1(" setChild(%1, QVariant::fromValue(node->acquireModel(\"Model::%2\")));")
+ .arg(QString::number(index), property.name) << endl;
+ }
+ out << " }" << endl;
out << "" << endl;
@@ -709,7 +715,10 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
out << " QVariantList properties;" << endl;
out << " properties.reserve(" << astClass.properties.size() << ");" << endl;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " properties << QVariant::fromValue(" << property.type << "(" << property.defaultValue << "));" << endl;
+ if (property.isPointer)
+ out << " properties << QVariant::fromValue((" << typeForMode(property, mode) << ")" << property.defaultValue << ");" << endl;
+ else
+ out << " properties << QVariant::fromValue(" << typeForMode(property, mode) << "(" << property.defaultValue << "));" << endl;
}
int nPersisted = 0;
if (astClass.hasPersisted) {
@@ -725,46 +734,37 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
out << " setProperties(properties);" << endl;
out << " }" << endl;
+ } else if (mode == SOURCE) {
+ out << " explicit " << className << "(QObject *parent = nullptr) : QObject(parent)" << endl;
+ out << " {" << endl;
+ if (!metaTypeRegistrationCode.isEmpty())
+ out << metaTypeRegistrationCode << endl;
+ out << " }" << endl;
} else {
- if ( (astClass.models.isEmpty() && astClass.children.isEmpty()) || mode == SOURCE) {
- if (mode == SOURCE)
- out << " explicit " << className << "(QObject *parent = nullptr) : QObject(parent)" << endl;
- else
- out << " explicit " << className << "(QObject *parent = nullptr) : " << astClass.name << "Source(parent)" << endl;
+ QVector<int> constIndices;
+ for (int index = 0; index < astClass.properties.count(); ++index) {
+ const ASTProperty &property = astClass.properties.at(index);
+ if (property.modifier == ASTProperty::Constant)
+ constIndices.append(index);
+ }
+ if (constIndices.isEmpty()) {
+ out << " explicit " << className << "(QObject *parent = nullptr) : " << astClass.name << "Source(parent)" << endl;
} else {
- int childIndex = 0;
- if (astClass.models.count())
- out << " explicit " << className << "(QAbstractItemModel *model0";
- else {
- out << " explicit " << className << "(" << astClass.children.at(0).type << "Source *sub0";
- childIndex = 1;
- }
- for (int i = 1; i < astClass.models.count(); i++)
- out << QString::fromLatin1(", QAbstractItemModel *model%1").arg(QString::number(i));
- for (int i = childIndex; i < astClass.children.count(); i++)
- out << QString::fromLatin1(", %1Source *sub%2").arg(astClass.children.at(childIndex).type, QString::number(i));
- out << ", QObject *parent = nullptr) : " << astClass.name << "Source(parent)" << endl;
- for (int i = 0; i < astClass.models.count(); i++)
- {
- out << " , m_" << astClass.models[i].name
- << QString::fromLatin1("(model%1)").arg(QString::number(i)) << endl;
- }
- for (int i = 0; i < astClass.children.count(); i++)
- {
- out << " , m_" << astClass.children[i].name
- << QString::fromLatin1("(sub%1)").arg(QString::number(i)) << endl;
+ QStringList parameters;
+ for (int index : constIndices) {
+ const ASTProperty &property = astClass.properties.at(index);
+ parameters.append(QString::fromLatin1("%1 %2 = %3").arg(typeForMode(property, SOURCE), property.name, property.defaultValue));
}
+ parameters.append(QStringLiteral("QObject *parent = nullptr"));
+ out << " explicit " << className << "(" << parameters.join(QStringLiteral(", ")) << ") : " << astClass.name << "Source(parent)" << endl;
}
-
- if (mode == SIMPLE_SOURCE) {
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ if (property.modifier == ASTProperty::Constant)
+ out << " , m_" << property.name << "(" << property.name << ")" << endl;
+ else
out << " , m_" << property.name << "(" << property.defaultValue << ")" << endl;
- }
}
-
out << " {" << endl;
- if (mode != SIMPLE_SOURCE && !metaTypeRegistrationCode.isEmpty())
- out << metaTypeRegistrationCode << endl;
out << " }" << endl;
}
@@ -793,13 +793,14 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
if (mode == REPLICA) {
int i = 0;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " " << property.type << " " << property.name << "() const" << endl;
+ auto type = typeForMode(property, mode);
+ out << " " << type << " " << property.name << "() const" << endl;
out << " {" << endl;
out << " const QVariant variant = propAsVariant(" << i << ");" << endl;
- out << " if (!variant.canConvert<" << property.type << ">()) {" << endl;
- out << " qWarning() << \"QtRO cannot convert the property " << property.name << " to type " << property.type << "\";" << endl;
+ out << " if (!variant.canConvert<" << type << ">()) {" << endl;
+ out << " qWarning() << \"QtRO cannot convert the property " << property.name << " to type " << type << "\";" << endl;
out << " }" << endl;
- out << " return variant.value<" << property.type << " >();" << endl;
+ out << " return variant.value<" << type << " >();" << endl;
out << " }" << endl;
i++;
if (property.modifier == ASTProperty::ReadWrite) {
@@ -816,16 +817,16 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
} else if (mode == SOURCE) {
Q_FOREACH (const ASTProperty &property, astClass.properties)
- out << " virtual " << property.type << " " << property.name << "() const = 0;" << endl;
+ out << " virtual " << typeForMode(property, mode) << " " << property.name << "() const = 0;" << endl;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadWrite ||
property.modifier == ASTProperty::ReadPush)
out << " virtual void set" << cap(property.name) << "(" << property.type << " " << property.name << ") = 0;" << endl;
}
} else {
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " virtual " << property.type << " " << property.name << "() const override { return m_" << property.name << "; }" << endl;
- }
+ Q_FOREACH (const ASTProperty &property, astClass.properties)
+ out << " " << typeForMode(property, mode) << " " << property.name << "() const override { return m_"
+ << property.name << "; }" << endl;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadWrite ||
property.modifier == ASTProperty::ReadPush) {
@@ -834,42 +835,6 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
}
- if (!astClass.models.isEmpty()) {
- Q_FOREACH (const ASTModel &model, astClass.models) {
- if (mode != SOURCE) {
- if (mode == REPLICA)
- out << " QAbstractItemModelReplica *" << model.name << "()" << endl;
- else
- out << " QAbstractItemModel *" << model.name << "() override" << endl;
- out << " {" << endl;
- out << " return m_" << model.name << ".data();" << endl;
- out << " }" << endl;
- } else {
- out << " virtual QAbstractItemModel *" << model.name << "() = 0;" << endl;
- }
- }
- }
-
- if (!astClass.children.isEmpty()) {
- Q_FOREACH (const ASTChildRep &child, astClass.children) {
- if (mode != SOURCE) {
- if (mode == REPLICA) {
- out << " " << child.type << "Replica *" << child.name << "()" << endl;
- out << " {" << endl;
- out << " return m_" << child.name << ".data();" << endl;
- out << " }" << endl;
- } else {
- out << " " << child.type << "Source *" << child.name << "() override" << endl;
- out << " {" << endl;
- out << " return m_" << child.name << ";" << endl;
- out << " }" << endl;
- }
- } else {
- out << " virtual " << child.type << "Source *" << child.name << "() = 0;" << endl;
- }
- }
- }
-
if (mode != SIMPLE_SOURCE) {
//Next output property signals
if (!astClass.properties.isEmpty() || !astClass.signalsList.isEmpty()) {
@@ -877,23 +842,12 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
out << "Q_SIGNALS:" << endl;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
if (property.modifier != ASTProperty::Constant)
- out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, property.type) << " " << property.name << ");" << endl;
+ out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, typeForMode(property, mode)) << " " << property.name << ");" << endl;
}
QVector<ASTFunction> signalsList = transformEnumParams(astClass, astClass.signalsList, className);
Q_FOREACH (const ASTFunction &signal, signalsList)
out << " void " << signal.name << "(" << signal.paramsAsString() << ");" << endl;
- for (auto model : astClass.models)
- out << " void " << model.name << "Changed();" << endl;
- for (auto child : astClass.children)
- out << " void " << child.name << "Changed();" << endl;
- } else if (!astClass.models.isEmpty() || !astClass.children.isEmpty()) {
- out << "" << endl;
- out << "Q_SIGNALS:" << endl;
- for (auto model : astClass.models)
- out << " void " << model.name << "Changed();" << endl;
- for (auto child : astClass.children)
- out << " void " << child.name << "Changed();" << endl;
}
bool hasWriteSlots = false;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
@@ -972,32 +926,8 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
//Next output data members
if (mode == SIMPLE_SOURCE) {
- Q_FOREACH (const ASTModel &model, astClass.models)
- out << " QScopedPointer<QAbstractItemModel> m_" << model.name << ";" << endl;
- Q_FOREACH (const ASTChildRep &child, astClass.children)
- out << " " << child.type << "Source *m_" << child.name << ";" << endl;
-
- if (!astClass.properties.isEmpty()) {
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " " << property.type << " " << "m_" << property.name << ";" << endl;
- }
- }
- } else if (mode == REPLICA) {
- if (astClass.children.count()) {
- out << " void finalize()" << endl;
- out << " {" << endl;
- Q_FOREACH (const ASTChildRep &child, astClass.children) {
- out << " if (!m_" << child.name << "->isInitialized()) {" << endl;
- out << " m_" << child.name << ".reset(nullptr);" << endl;
- out << " emit " << child.name << "Changed();" << endl;
- out << " }" << endl;
- }
- out << " }" << endl << endl;
- }
- Q_FOREACH (const ASTModel &model, astClass.models)
- out << " QScopedPointer<QAbstractItemModelReplica> m_" << model.name << ";" << endl;
- Q_FOREACH (const ASTChildRep &child, astClass.children)
- out << " QScopedPointer<" << child.type << "Replica> m_" << child.name << ";" << endl;
+ Q_FOREACH (const ASTProperty &property, astClass.properties)
+ out << " " << typeForMode(property, SOURCE) << " " << "m_" << property.name << ";" << endl;
}
if (mode != SIMPLE_SOURCE)
@@ -1029,13 +959,18 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
// Include enum definition in SourceAPI
generateDeclarationsForEnums(out, astClass.enums, false);
}
- out << QString::fromLatin1(" %1(ObjectType *object)").arg(className) << endl;
- out << QStringLiteral(" : SourceApiMap()") << endl;
+ out << QString::fromLatin1(" %1(ObjectType *object, const QString &name = QStringLiteral(\"%2\"))").arg(className, astClass.name) << endl;
+ out << QStringLiteral(" : SourceApiMap(), m_name(name)") << endl;
out << QStringLiteral(" {") << endl;
- if (astClass.models.isEmpty() && astClass.children.isEmpty())
+ if (!astClass.hasPointerObjects())
out << QStringLiteral(" Q_UNUSED(object);") << endl;
const int enumCount = astClass.enums.count();
+ for (int i : astClass.subClassPropertyIndices) {
+ const ASTProperty &child = astClass.properties.at(i);
+ out << QString::fromLatin1(" using %1_type_t = typename std::remove_pointer<decltype(object->%1())>::type;")
+ .arg(child.name) << endl;
+ }
out << QString::fromLatin1(" m_enums[0] = %1;").arg(enumCount) << endl;
for (int i = 0; i < enumCount; ++i) {
const auto enumerator = astClass.enums.at(i);
@@ -1044,11 +979,11 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
}
const int propCount = astClass.properties.count();
out << QString::fromLatin1(" m_properties[0] = %1;").arg(propCount) << endl;
- QStringList changeSignals;
+ QList<ASTProperty> onChangeProperties;
QList<int> propertyChangeIndex;
for (int i = 0; i < propCount; ++i) {
const ASTProperty &prop = astClass.properties.at(i);
- const QString propTypeName = fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), prop.type);
+ const QString propTypeName = fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), typeForMode(prop, SOURCE));
out << QString::fromLatin1(" m_properties[%1] = QtPrivate::qtro_property_index<ObjectType>(&ObjectType::%2, "
"static_cast<%3 (QObject::*)()>(0),\"%2\");")
.arg(QString::number(i+1), prop.name, propTypeName) << endl;
@@ -1058,17 +993,19 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
if (prop.modifier != prop.Constant) { //Make sure we have an onChange signal
out << QStringLiteral(" QtPrivate::qtro_method_test<ObjectType>(&ObjectType::%1Changed, static_cast<void (QObject::*)()>(0));")
.arg(prop.name) << endl;
- changeSignals << QString::fromLatin1("%1Changed").arg(prop.name);
+ onChangeProperties << prop;
propertyChangeIndex << i + 1; //m_properties[0] is the count, so index is one higher
}
}
const int signalCount = astClass.signalsList.count();
- const int changedCount = changeSignals.size();
- out << QString::fromLatin1(" m_signals[0] = %1;").arg(signalCount+changeSignals.size()) << endl;
+ const int changedCount = onChangeProperties.size();
+ out << QString::fromLatin1(" m_signals[0] = %1;").arg(signalCount+onChangeProperties.size()) << endl;
for (int i = 0; i < changedCount; ++i)
- out << QString::fromLatin1(" m_signals[%1] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::%2, "
- "static_cast<void (QObject::*)()>(0),m_signalArgCount+%4,&m_signalArgTypes[%4]);")
- .arg(i+1).arg(changeSignals.at(i)).arg(i) << endl;
+ out << QString::fromLatin1(" m_signals[%1] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::%2Changed, "
+ "static_cast<void (QObject::*)(%3)>(0),m_signalArgCount+%4,&m_signalArgTypes[%4]);")
+ .arg(QString::number(i+1), onChangeProperties.at(i).name,
+ fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), onChangeProperties.at(i).type),
+ QString::number(i)) << endl;
QVector<ASTFunction> signalsList = transformEnumParams(astClass, astClass.signalsList, QStringLiteral("typename ObjectType"));
for (int i = 0; i < signalCount; ++i) {
@@ -1090,8 +1027,10 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
const ASTProperty &prop = pushProps.at(i);
const QString propTypeName = fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), prop.type);
out << QString::fromLatin1(" m_methods[%1] = QtPrivate::qtro_method_index<ObjectType>(&ObjectType::push%2, "
- "static_cast<void (QObject::*)(%3)>(0),\"push%2(%3)\",m_methodArgCount+%4,&m_methodArgTypes[%4]);")
- .arg(QString::number(i+1), cap(prop.name), propTypeName, QString::number(i)) << endl;
+ "static_cast<void (QObject::*)(%3)>(0),\"push%2(%4)\",m_methodArgCount+%5,&m_methodArgTypes[%5]);")
+ .arg(QString::number(i+1), cap(prop.name), propTypeName,
+ QString(propTypeName).remove(QStringLiteral("typename ObjectType::")), // we don't want this in the string signature
+ QString::number(i)) << endl;
}
QVector<ASTFunction> slotsList = transformEnumParams(astClass, astClass.slotsList, QStringLiteral("typename ObjectType"));
@@ -1104,11 +1043,10 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
QString(params).remove(QStringLiteral("typename ObjectType::")), // we don't want this in the string signature
QString::number(i+pushCount)) << endl;
}
- const int modelCount = astClass.models.count();
- for (int i = 0; i < modelCount; ++i) {
- const ASTModel &model = astClass.models.at(i);
- out << QString::fromLatin1(" m_models << ModelInfo({object->%1(),").arg(model.name) << endl;
- out << QString::fromLatin1(" QStringLiteral(\"%1\"),").arg(model.name) << endl;
+ for (const auto &model : astClass.modelMetadata) {
+ const ASTProperty &property = astClass.properties.at(model.propertyIndex);
+ out << QString::fromLatin1(" m_models << ModelInfo({object->%1(),").arg(property.name) << endl;
+ out << QString::fromLatin1(" QStringLiteral(\"%1\"),").arg(property.name) << endl;
QStringList list;
if (!model.roles.isEmpty()) {
for (auto role : model.roles)
@@ -1116,14 +1054,14 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
}
out << QString::fromLatin1(" QByteArrayLiteral(\"%1\")});").arg(list.join(QChar::fromLatin1('|'))) << endl;
}
- const int subclassCount = astClass.children.count();
- for (int i = 0; i < subclassCount; ++i) {
- const ASTChildRep &child = astClass.children.at(i);
- out << QString::fromLatin1(" m_subclasses << SubclassInfo({object->%1(), QStringLiteral(\"%1\")});").arg(child.name) << endl;
+ for (int i : astClass.subClassPropertyIndices) {
+ const ASTProperty &child = astClass.properties.at(i);
+ out << QString::fromLatin1(" m_subclasses << SubclassInfo{object->%1(), QStringLiteral(\"%1\"), new %2SourceAPI<%1_type_t>(object->%1(), QStringLiteral(\"%1\"))};")
+ .arg(child.name, child.type) << endl;
}
out << QStringLiteral(" }") << endl;
out << QStringLiteral("") << endl;
- out << QString::fromLatin1(" QString name() const override { return QStringLiteral(\"%1\"); }").arg(astClass.name) << endl;
+ out << QString::fromLatin1(" QString name() const override { return m_name; }") << endl;
out << QString::fromLatin1(" QString typeName() const override { return QStringLiteral(\"%1\"); }").arg(astClass.name) << endl;
out << QStringLiteral(" int enumCount() const override { return m_enums[0]; }") << endl;
out << QStringLiteral(" int propertyCount() const override { return m_properties[0]; }") << endl;
@@ -1220,7 +1158,8 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
if (signalCount+changedCount > 0) {
out << QStringLiteral(" switch (index) {") << endl;
for (int i = 0; i < changedCount; ++i)
- out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2()\");").arg(i).arg(changeSignals.at(i)) << endl;
+ out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2Changed(%3)\");")
+ .arg(QString::number(i), onChangeProperties.at(i).name, onChangeProperties.at(i).type) << endl;
for (int i = 0; i < signalCount; ++i)
{
const ASTFunction &sig = astClass.signalsList.at(i);
@@ -1310,6 +1249,7 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
out << QString::fromLatin1(" int m_properties[%1];").arg(propCount+1) << endl;
out << QString::fromLatin1(" int m_signals[%1];").arg(signalCount+changedCount+1) << endl;
out << QString::fromLatin1(" int m_methods[%1];").arg(methodCount+1) << endl;
+ out << QString::fromLatin1(" const QString m_name;") << endl;
if (signalCount+changedCount > 0) {
out << QString::fromLatin1(" int m_signalArgCount[%1];").arg(signalCount+changedCount) << endl;
out << QString::fromLatin1(" const int* m_signalArgTypes[%1];").arg(signalCount+changedCount) << endl;
diff --git a/tools/repc/repcodegenerator.h b/tools/repc/repcodegenerator.h
index 18af23c..d7ec4c8 100644
--- a/tools/repc/repcodegenerator.h
+++ b/tools/repc/repcodegenerator.h
@@ -79,6 +79,7 @@ private:
QString formatSignals(const POD &pod);
QString formatDataMembers(const POD &pod);
QString formatMarshallingOperators(const POD &pod);
+ QString typeForMode(const ASTProperty &property, Mode mode);
void generateClass(Mode mode, QTextStream &out, const ASTClass &astClasses, const QString &metaTypeRegistrationCode);
void generateSourceAPI(QTextStream &out, const ASTClass &astClass);