summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/remoteobjects/qremoteobjectnode.cpp36
-rw-r--r--src/remoteobjects/qremoteobjectreplica.cpp12
-rw-r--r--src/remoteobjects/qremoteobjectreplica.h1
-rw-r--r--src/remoteobjects/qremoteobjectsource.cpp7
-rw-r--r--src/remoteobjects/qremoteobjectsource.h7
-rw-r--r--src/remoteobjects/qtremoteobjectglobal.h2
-rw-r--r--src/repparser/parser.g60
-rw-r--r--tests/auto/integration/engine.cpp4
-rw-r--r--tests/auto/integration/engine.h2
-rw-r--r--tests/auto/repparser/tst_parser.cpp11
-rw-r--r--tools/repc/repcodegenerator.cpp318
-rw-r--r--tools/repc/repcodegenerator.h1
12 files changed, 211 insertions, 250 deletions
diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp
index c035e37..97abf89 100644
--- a/src/remoteobjects/qremoteobjectnode.cpp
+++ b/src/remoteobjects/qremoteobjectnode.cpp
@@ -62,6 +62,23 @@ static QString name(const QMetaObject * const mobj)
return ind >= 0 ? QString::fromLatin1(mobj->classInfo(ind).value()) : QString();
}
+QString QtRemoteObjects::getTypeNameAndMetaobjectFromClassInfo(const QMetaObject *& meta) {
+ QString typeName;
+ const int ind = meta->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE);
+ if (ind != -1) { //We have an object created from repc or at least with QCLASSINFO defined
+ typeName = QString::fromLatin1(meta->classInfo(ind).value());
+ while (true) {
+ Q_ASSERT(meta->superClass());//This recurses to QObject, which doesn't have QCLASSINFO_REMOTEOBJECT_TYPE
+ //At the point superclass doesn't have the same QCLASSINFO_REMOTEOBJECT_TYPE,
+ //we have the metaobject we should work from
+ if (ind != meta->superClass()->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE))
+ break;
+ meta = meta->superClass();
+ }
+ }
+ return typeName;
+}
+
template <typename K, typename V, typename Query>
bool map_contains(const QMap<K,V> &map, const Query &key, typename QMap<K,V>::const_iterator &result)
{
@@ -1329,20 +1346,8 @@ bool QRemoteObjectHostBase::enableRemoting(QObject *object, const QString &name)
const QMetaObject *meta = object->metaObject();
QString _name = name;
- QString typeName;
- const int ind = meta->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE);
- if (ind != -1) { //We have an object created from repc or at least with QCLASSINFO defined
- typeName = QString::fromLatin1(meta->classInfo(ind).value());
- if (_name.isEmpty())
- _name = typeName;
- while (true) {
- Q_ASSERT(meta->superClass()); //This recurses to QObject, which doesn't have QCLASSINFO_REMOTEOBJECT_TYPE
- if (ind != meta->superClass()->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE)) //At the point we don't find the same QCLASSINFO_REMOTEOBJECT_TYPE,
- //we have the metaobject we should work from
- break;
- meta = meta->superClass();
- }
- } else { //This is a passed in QObject, use its API
+ QString typeName = getTypeNameAndMetaobjectFromClassInfo(meta);
+ if (typeName.isEmpty()) { //This is a passed in QObject, use its API
if (_name.isEmpty()) {
_name = object->objectName();
if (_name.isEmpty()) {
@@ -1351,7 +1356,8 @@ bool QRemoteObjectHostBase::enableRemoting(QObject *object, const QString &name)
return false;
}
}
- }
+ } else if (_name.isEmpty())
+ _name = typeName;
return d->remoteObjectIo->enableRemoting(object, meta, _name, typeName, this);
}
diff --git a/src/remoteobjects/qremoteobjectreplica.cpp b/src/remoteobjects/qremoteobjectreplica.cpp
index 292e6db..3d15502 100644
--- a/src/remoteobjects/qremoteobjectreplica.cpp
+++ b/src/remoteobjects/qremoteobjectreplica.cpp
@@ -129,6 +129,10 @@ QConnectedReplicaImplementation::~QConnectedReplicaImplementation()
serializeRemoveObjectPacket(m_packet, m_objectName);
sendCommand();
}
+ for (auto prop : m_propertyStorage) {
+ if (prop.canConvert<QObject*>())
+ prop.value<QObject *>()->deleteLater();
+ }
}
bool QRemoteObjectReplicaImplementation::needsDynamicInitialization() const
@@ -640,6 +644,14 @@ void QRemoteObjectReplica::setProperties(const QVariantList &properties)
}
/*!
+ \internal
+*/
+void QRemoteObjectReplica::setChild(int i, const QVariant &value)
+{
+ d_impl->setProperty(i, value);
+}
+
+/*!
Returns \c true if this replica has been initialized with data from the \l {Source} object. Returns \c false otherwise.
\sa state()
diff --git a/src/remoteobjects/qremoteobjectreplica.h b/src/remoteobjects/qremoteobjectreplica.h
index a6b7d56..04c5db6 100644
--- a/src/remoteobjects/qremoteobjectreplica.h
+++ b/src/remoteobjects/qremoteobjectreplica.h
@@ -92,6 +92,7 @@ protected:
protected:
void setProperties(const QVariantList &);
+ void setChild(int i, const QVariant &);
const QVariant propAsVariant(int i) const;
void persistProperties(const QString &repName, const QByteArray &repSig, const QVariantList &props) const;
QVariantList retrieveProperties(const QString &repName, const QByteArray &repSig) const;
diff --git a/src/remoteobjects/qremoteobjectsource.cpp b/src/remoteobjects/qremoteobjectsource.cpp
index d28c59e..3a91922 100644
--- a/src/remoteobjects/qremoteobjectsource.cpp
+++ b/src/remoteobjects/qremoteobjectsource.cpp
@@ -275,7 +275,12 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con
QString::fromLatin1(property.name()),
roleInfo});
} else {
- m_subclasses << SubclassInfo({child, QString::fromLatin1(property.name())});
+ const QMetaObject *meta = child->metaObject();
+ QString typeName = QtRemoteObjects::getTypeNameAndMetaobjectFromClassInfo(meta);
+ if (typeName.isNull())
+ typeName = QString::fromLatin1(propertyMeta->className());
+
+ m_subclasses << SubclassInfo{child, QString::fromLatin1(property.name()), new DynamicApiMap(child, meta, QString::fromLatin1(property.name()), typeName)};
}
continue;
}
diff --git a/src/remoteobjects/qremoteobjectsource.h b/src/remoteobjects/qremoteobjectsource.h
index a5b738b..bd57dad 100644
--- a/src/remoteobjects/qremoteobjectsource.h
+++ b/src/remoteobjects/qremoteobjectsource.h
@@ -131,18 +131,19 @@ struct ModelInfo
QByteArray roles;
};
+class SourceApiMap;
struct SubclassInfo
{
+ SubclassInfo(QObject *_ptr = nullptr, QString _name = QString(), SourceApiMap *_api = nullptr) : ptr(_ptr), name(_name), api(_api) {}
QObject *ptr;
QString name;
+ SourceApiMap *api;
};
class SourceApiMap
{
protected:
SourceApiMap() {}
- QVector<ModelInfo> m_models;
- QVector<SubclassInfo> m_subclasses;
public:
virtual ~SourceApiMap() {}
virtual QString name() const = 0;
@@ -173,6 +174,8 @@ public:
virtual bool isAdapterMethod(int) const { return false; }
virtual bool isAdapterProperty(int) const { return false; }
void qobjectSetup(QRemoteObjectHostBase *node) const;
+ QVector<ModelInfo> m_models;
+ QVector<SubclassInfo> m_subclasses;
};
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qtremoteobjectglobal.h b/src/remoteobjects/qtremoteobjectglobal.h
index 69ba108..4a9ca81 100644
--- a/src/remoteobjects/qtremoteobjectglobal.h
+++ b/src/remoteobjects/qtremoteobjectglobal.h
@@ -136,6 +136,8 @@ Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, const vo
Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, const void *src, QDataStream &dst);
Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, QDataStream &src, void *dst);
+QString getTypeNameAndMetaobjectFromClassInfo(const QMetaObject *& meta);
+
template <typename T>
void copyStoredProperties(const T *src, T *dst)
{
diff --git a/src/repparser/parser.g b/src/repparser/parser.g
index 6736b67..0343576 100644
--- a/src/repparser/parser.g
+++ b/src/repparser/parser.g
@@ -87,13 +87,15 @@ struct ASTProperty
};
ASTProperty();
- ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted);
+ ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted,
+ bool isPointer=false);
QString type;
QString name;
QString defaultValue;
Modifier modifier;
bool persisted;
+ bool isPointer;
};
Q_DECLARE_TYPEINFO(ASTProperty, Q_MOVABLE_TYPE);
@@ -178,29 +180,20 @@ Q_DECLARE_TYPEINFO(ASTModelRole, Q_MOVABLE_TYPE);
struct ASTModel
{
- explicit ASTModel(const QString &name = QString());
+ ASTModel(int index = -1) : propertyIndex(index) {}
QVector<ASTModelRole> roles;
- QString name;
+ int propertyIndex;
};
Q_DECLARE_TYPEINFO(ASTModel, Q_MOVABLE_TYPE);
-struct ASTChildRep
-{
- explicit ASTChildRep(const QString &name = QString(),
- const QString &type = QString());
-
- QString name;
- QString type;
-};
-Q_DECLARE_TYPEINFO(ASTChildRep, Q_MOVABLE_TYPE);
-
/// A Class declaration
struct ASTClass
{
explicit ASTClass(const QString& name = QString());
bool isValid() const;
+ bool hasPointerObjects() const;
QString name;
QVector<ASTProperty> properties;
@@ -208,8 +201,8 @@ struct ASTClass
QVector<ASTFunction> slotsList;
QVector<ASTEnum> enums;
bool hasPersisted;
- QVector<ASTModel> models;
- QVector<ASTChildRep> children;
+ QVector<ASTModel> modelMetadata;
+ QVector<int> subClassPropertyIndices;
};
Q_DECLARE_TYPEINFO(ASTClass, Q_MOVABLE_TYPE);
@@ -328,12 +321,12 @@ static QByteArray normalizeType(const QByteArray &ba, bool fixScope = false)
}
ASTProperty::ASTProperty()
- : modifier(ReadPush), persisted(false)
+ : modifier(ReadPush), persisted(false), isPointer(false)
{
}
-ASTProperty::ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted)
- : type(type), name(name), defaultValue(defaultValue), modifier(modifier), persisted(persisted)
+ASTProperty::ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted, bool isPointer)
+ : type(type), name(name), defaultValue(defaultValue), modifier(modifier), persisted(persisted), isPointer(isPointer)
{
}
@@ -387,16 +380,6 @@ ASTEnum::ASTEnum(const QString &name)
{
}
-ASTModel::ASTModel(const QString &name)
- : name(name)
-{
-}
-
-ASTChildRep::ASTChildRep(const QString &name, const QString &type)
- : name(name), type(type)
-{
-}
-
ASTClass::ASTClass(const QString &name)
: name(name), hasPersisted(false)
{
@@ -407,6 +390,12 @@ bool ASTClass::isValid() const
return !name.isEmpty();
}
+bool ASTClass::hasPointerObjects() const
+{
+ int count = modelMetadata.size() + subClassPropertyIndices.size();
+ return count > 0;
+}
+
RepParser::RepParser(QIODevice &outputDevice)
: QRegexParser(), m_astEnumValue(-1)
{
@@ -841,14 +830,15 @@ Model: model;
/.
case $rule_number:
{
- ASTModel model;
- model.name = captured().value(QLatin1String("name")).trimmed();
+ ASTModel model(m_astClass.properties.size());
+ const QString name = captured().value(QLatin1String("name")).trimmed();
const QString argString = captured().value(QLatin1String("args")).trimmed();
if (!parseRoles(model, argString))
return false;
- m_astClass.models << model;
+ m_astClass.modelMetadata << model;
+ m_astClass.properties << ASTProperty(QStringLiteral("QAbstractItemModel"), name, QStringLiteral("nullptr"), ASTProperty::Constant, false, true);
}
break;
./
@@ -857,11 +847,11 @@ ChildRep: childrep;
/.
case $rule_number:
{
- ASTChildRep child;
- child.name = captured().value(QLatin1String("name")).trimmed();
- child.type = captured().value(QLatin1String("type")).trimmed();
+ const QString name = captured().value(QLatin1String("name")).trimmed();
+ const QString type = captured().value(QLatin1String("type")).trimmed();
- m_astClass.children << child;
+ m_astClass.subClassPropertyIndices << m_astClass.properties.size();
+ m_astClass.properties << ASTProperty(type, name, QStringLiteral("nullptr"), ASTProperty::Constant, false, true);
}
break;
./
diff --git a/tests/auto/integration/engine.cpp b/tests/auto/integration/engine.cpp
index d59b2d5..9f1c103 100644
--- a/tests/auto/integration/engine.cpp
+++ b/tests/auto/integration/engine.cpp
@@ -28,8 +28,8 @@
#include "engine.h"
-Engine::Engine(QObject *parent) :
- EngineSimpleSource(parent)
+Engine::Engine(int cylinders, QObject *parent) :
+ EngineSimpleSource(cylinders, parent)
{
setRpm(0);
setpurchasedPart(false);
diff --git a/tests/auto/integration/engine.h b/tests/auto/integration/engine.h
index 7252f38..12ef36a 100644
--- a/tests/auto/integration/engine.h
+++ b/tests/auto/integration/engine.h
@@ -37,7 +37,7 @@ class Engine : public EngineSimpleSource
Q_PROPERTY(bool purchasedPart READ purchasedPart WRITE setpurchasedPart)
public:
- Engine(QObject *parent = nullptr);
+ Engine(int cylinders = 4, QObject *parent = nullptr);
~Engine() override;
bool start() override;
diff --git a/tests/auto/repparser/tst_parser.cpp b/tests/auto/repparser/tst_parser.cpp
index 58162ce..46211a2 100644
--- a/tests/auto/repparser/tst_parser.cpp
+++ b/tests/auto/repparser/tst_parser.cpp
@@ -386,8 +386,9 @@ void tst_Parser::testModels()
QCOMPARE(ast.classes.count(), 1);
const ASTClass astClass = ast.classes.first();
- ASTModel model = astClass.models.first();
- QCOMPARE(model.name, expectedModel);
+ ASTModel model = astClass.modelMetadata.first();
+ ASTProperty property = astClass.properties.at(model.propertyIndex);
+ QCOMPARE(property.name, expectedModel);
int i = 0;
for (auto role : model.roles) {
QCOMPARE(role.name, expectedRoles.at(i).name);
@@ -430,9 +431,9 @@ void tst_Parser::testClasses()
const ASTClass astSub = ast.classes.value(0);
const ASTClass astObj = ast.classes.value(1);
- const ASTChildRep child = astObj.children.first();
- QCOMPARE(child.name, expectedName);
- QCOMPARE(child.type, expectedType);
+ const ASTProperty property = astObj.properties.at(astObj.subClassPropertyIndices.at(0));
+ QCOMPARE(property.name, expectedName);
+ QCOMPARE(property.type, expectedType);
}
void tst_Parser::testInvalid_data()
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);