From 9e9c9c8975f539ff34dc626dc29baacbd2f43812 Mon Sep 17 00:00:00 2001 From: Vladimir Zidar Date: Thu, 15 Feb 2018 21:46:06 +0100 Subject: [PATCH 1/2] LP-599 Allow "cloneof" attribute to reference other objects. Allow some other attributes to override cloned values (options, limits, defaultvalue). --- ground/uavobjgenerator/uavobjectparser.cpp | 128 ++++++++++++++++----- ground/uavobjgenerator/uavobjectparser.h | 3 + 2 files changed, 100 insertions(+), 31 deletions(-) diff --git a/ground/uavobjgenerator/uavobjectparser.cpp b/ground/uavobjgenerator/uavobjectparser.cpp index 33466eacf..ef9b9cd97 100644 --- a/ground/uavobjgenerator/uavobjectparser.cpp +++ b/ground/uavobjgenerator/uavobjectparser.cpp @@ -69,6 +69,15 @@ ObjectInfo *UAVObjectParser::getObjectByIndex(int objIndex) return objInfo[objIndex]; } +ObjectInfo *UAVObjectParser::getObjectByName(const QString & objName) +{ + foreach(ObjectInfo * info, objInfo) { + if (objName == info->name) { + return info; + } + } + return 0; +} /** * Get the name of the object */ @@ -404,6 +413,7 @@ QString UAVObjectParser::processObjectAccess(QDomNode & childNode, ObjectInfo *i */ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *info) { + bool isClone = false; // Create field FieldInfo *field = new FieldInfo; // Get name attribute @@ -419,20 +429,39 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i // field that has already been declared elemAttr = elemAttributes.namedItem("cloneof"); if (!elemAttr.isNull()) { - QString parentName = elemAttr.nodeValue(); + QString parentName = elemAttr.nodeValue().section('.', 1); + + ObjectInfo *parentObject; + + if (parentName.isEmpty()) { + parentName = elemAttr.nodeValue(); + parentObject = info; + } else { + QString objName = elemAttr.nodeValue().section('.', 0, 0); + parentObject = getObjectByName(objName); + if (!parentObject) { + return QString("Object:field:cloneof parent object unknown"); + } + } + if (!parentName.isEmpty()) { - foreach(FieldInfo * parent, info->fields) { + foreach(FieldInfo * parent, parentObject->fields) { if (parent->name == parentName) { // clone from this parent *field = *parent; // safe shallow copy, no ptrs in struct field->name = name; // set our name - // Add field to object - info->fields.append(field); - // Done - return QString(); + // Done, but allow certain overrides + field->parentObjectName = parentObject->name; + field->parentFieldName = parent->name; + isClone = true; + + break; } } - return QString("Object:field::cloneof parent unknown"); + + if (!isClone) { + return QString("Object:field:cloneof parent unknown"); + } } else { return QString("Object:field:cloneof attribute is empty"); } @@ -459,31 +488,45 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i // Get units attribute elemAttr = elemAttributes.namedItem("units"); if (elemAttr.isNull()) { - return QString("Object:field:units attribute is missing"); + if (!isClone) { + return QString("Object:field:units attribute is missing"); + } + } else { + if (isClone) { + return QString("Object:field:units attribute is not allowed for cloned fields"); + } + field->units = elemAttr.nodeValue(); + all_units << field->units; } - - field->units = elemAttr.nodeValue(); - all_units << field->units; - // Get type attribute elemAttr = elemAttributes.namedItem("type"); if (elemAttr.isNull()) { - return QString("Object:field:type attribute is missing"); - } - - int index = fieldTypeStrXML.indexOf(elemAttr.nodeValue()); - if (index >= 0) { - field->type = (FieldType)index; - field->numBytes = fieldTypeNumBytes[index]; + if (!isClone) { + return QString("Object:field:type attribute is missing"); + } } else { - return QString("Object:field:type attribute value is invalid"); + if (isClone) { + return QString("Object:field:type attribute is not allowed for cloned fields"); + } + int index = fieldTypeStrXML.indexOf(elemAttr.nodeValue()); + if (index >= 0) { + field->type = (FieldType)index; + field->numBytes = fieldTypeNumBytes[index]; + } else { + return QString("Object:field:type attribute value is invalid"); + } } // Get numelements or elementnames attribute - field->numElements = 0; + if (!isClone) { + field->numElements = 0; + } // Look for element names as an attribute first elemAttr = elemAttributes.namedItem("elementnames"); if (!elemAttr.isNull()) { + if (isClone) { + return QString("Object:field:elementnames attribute is not allowed for cloned fields"); + } // Get element names QStringList names = elemAttr.nodeValue().split(",", QString::SkipEmptyParts); for (int n = 0; n < names.length(); ++n) { @@ -497,6 +540,9 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i // Look for a list of child elementname nodes QDomNode listNode = childNode.firstChildElement("elementnames"); if (!listNode.isNull()) { + if (isClone) { + return QString("Object:field:elementnames element is not allowed for cloned fields"); + } for (QDomElement node = listNode.firstChildElement("elementname"); !node.isNull(); node = node.nextSiblingElement("elementname")) { QDomNode name = node.firstChild(); @@ -515,6 +561,9 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i if (elemAttr.isNull()) { return QString("Object:field:elements and Object:field:elementnames attribute/element is missing"); } else { + if (isClone) { + return QString("Object:field:elements attribute is not allowed for cloned fields"); + } field->numElements = elemAttr.nodeValue().toInt(); for (int n = 0; n < field->numElements; ++n) { field->elementNames.append(QString("%1").arg(n)); @@ -524,15 +573,18 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i } } // Get options attribute or child elements (only if an enum type) + // We allow "options" attribute/element for cloned fields also, but they work slightly different here - + // they set limits on parent options. + if (field->type == FIELDTYPE_ENUM) { // Look for options attribute + QStringList options; elemAttr = elemAttributes.namedItem("options"); if (!elemAttr.isNull()) { - QStringList options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts); + options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts); for (int n = 0; n < options.length(); ++n) { options[n] = options[n].trimmed(); } - field->options = options; } else { // Look for a list of child 'option' nodes QDomNode listNode = childNode.firstChildElement("options"); @@ -541,12 +593,28 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i !node.isNull(); node = node.nextSiblingElement("option")) { QDomNode name = node.firstChild(); if (!name.isNull() && name.isText() && !name.nodeValue().isEmpty()) { - field->options.append(name.nodeValue()); + options.append(name.nodeValue()); } } } } - field->numOptions = field->options.size(); + + if (isClone) { + if (!options.isEmpty()) { + // Verify options subset and build limits value from it. + foreach(const QString &option, options) { + if (!field->options.contains(option)) { + return QString("Object:field:options is not a subset of parent options"); + } + } + field->limitValues = QString("%EQ:") + options.join(':'); + qDebug() << "Created field->limitValues: " << field->limitValues; + } + } else { + field->numOptions = options.size(); + field->options = options; + } + if (field->numOptions == 0) { return QString("Object:field:options attribute/element is missing"); } @@ -554,12 +622,7 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i // Get the default value attribute (required for settings objects, optional for the rest) elemAttr = elemAttributes.namedItem("defaultvalue"); - if (elemAttr.isNull()) { - if (info->isSettings) { - return QString("Object:field:defaultvalue attribute is missing (required for settings objects)"); - } - field->defaultValues = QStringList(); - } else { + if (!elemAttr.isNull()) { QStringList defaults = elemAttr.nodeValue().split(",", QString::SkipEmptyParts); for (int n = 0; n < defaults.length(); ++n) { defaults[n] = defaults[n].trimmed(); @@ -578,6 +641,9 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i } field->defaultValues = defaults; } + if (field->defaultValues.isEmpty() && info->isSettings) { + return QString("Object:field:defaultvalue attribute is missing (required for settings objects)"); + } // Limits attribute elemAttr = elemAttributes.namedItem("limits"); diff --git a/ground/uavobjgenerator/uavobjectparser.h b/ground/uavobjgenerator/uavobjectparser.h index ee9d9460c..d8c140454 100644 --- a/ground/uavobjgenerator/uavobjectparser.h +++ b/ground/uavobjgenerator/uavobjectparser.h @@ -59,6 +59,8 @@ typedef struct { bool defaultElementNames; QStringList defaultValues; QString limitValues; + QString parentObjectName; + QString parentFieldName; } FieldInfo; /** @@ -113,6 +115,7 @@ public: quint32 getObjectID(int objIndex); ObjectInfo *getObjectByIndex(int objIndex); + ObjectInfo *getObjectByName(const QString & objName); int getNumBytes(int objIndex); QStringList all_units; From 8dbf25edc2ef317f6395864c031e2bafc7bc5806 Mon Sep 17 00:00:00 2001 From: Vladimir Zidar Date: Thu, 15 Feb 2018 21:50:02 +0100 Subject: [PATCH 2/2] LP-599 Make cloned fields as typedef's of parent types in flight & ground (c, c++) uavobjgenerators. --- flight/uavobjects/inc/uavobject.h.template | 1 + .../plugins/uavobjects/uavobject.h.template | 1 + .../flight/uavobjectgeneratorflight.cpp | 104 ++++++--- .../generators/gcs/uavobjectgeneratorgcs.cpp | 205 +++++++++++------- 4 files changed, 198 insertions(+), 113 deletions(-) diff --git a/flight/uavobjects/inc/uavobject.h.template b/flight/uavobjects/inc/uavobject.h.template index 147478671..d16f14d8c 100644 --- a/flight/uavobjects/inc/uavobject.h.template +++ b/flight/uavobjects/inc/uavobject.h.template @@ -40,6 +40,7 @@ #ifndef $(NAMEUC)_H #define $(NAMEUC)_H #include +$(INCLUDE) /* Object constants */ #define $(NAMEUC)_OBJID $(OBJIDHEX) #define $(NAMEUC)_ISSINGLEINST $(ISSINGLEINST) diff --git a/ground/gcs/src/plugins/uavobjects/uavobject.h.template b/ground/gcs/src/plugins/uavobjects/uavobject.h.template index a702d9580..6320a2ff5 100644 --- a/ground/gcs/src/plugins/uavobjects/uavobject.h.template +++ b/ground/gcs/src/plugins/uavobjects/uavobject.h.template @@ -35,6 +35,7 @@ #define $(NAMEUC)_H #include "uavdataobject.h" +$(INCLUDE) class UAVObjectManager; diff --git a/ground/uavobjgenerator/generators/flight/uavobjectgeneratorflight.cpp b/ground/uavobjgenerator/generators/flight/uavobjectgeneratorflight.cpp index 4e08017cd..6a0351baf 100644 --- a/ground/uavobjgenerator/generators/flight/uavobjectgeneratorflight.cpp +++ b/ground/uavobjgenerator/generators/flight/uavobjectgeneratorflight.cpp @@ -24,6 +24,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "uavobjectgeneratorflight.h" using namespace std; @@ -169,52 +170,91 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo *info) enums.append(QString("/* Field %1 information */\n").arg(info->fields[n]->name)); // Only for enum types if (info->fields[n]->type == FIELDTYPE_ENUM) { - enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name)); - enums.append("typedef enum __attribute__ ((__packed__)) {\n"); - // Go through each option - QStringList options = info->fields[n]->options; - for (int m = 0; m < options.length(); ++m) { - QString s = (m == (options.length() - 1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n"; - enums.append(s - .arg(info->name.toUpper()) - .arg(info->fields[n]->name.toUpper()) - .arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")) - .arg(m)); + if (info->fields[n]->parentObjectName.length() > 0) { + enums.append(QString("typedef %1%2Options %3%4Options;\n") + .arg(info->fields[n]->parentObjectName) + .arg(info->fields[n]->parentFieldName) + .arg(info->name) + .arg(info->fields[n]->name)); + } else { + enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name)); + enums.append("typedef enum __attribute__ ((__packed__)) {\n"); + // Go through each option + QStringList options = info->fields[n]->options; + for (int m = 0; m < options.length(); ++m) { + QString s = (m == (options.length() - 1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n"; + enums.append(s + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")) + .arg(m)); + } + enums.append(QString("} %1%2Options;\n") + .arg(info->name) + .arg(info->fields[n]->name)); } - enums.append(QString("} %1%2Options;\n") - .arg(info->name) - .arg(info->fields[n]->name)); } // Generate element names (only if field has more than one element) if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) { - enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name)); - enums.append("typedef enum {\n"); - // Go through the element names - QStringList elemNames = info->fields[n]->elementNames; - for (int m = 0; m < elemNames.length(); ++m) { - QString s = (m != (elemNames.length() - 1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n"; - enums.append(s - .arg(info->name.toUpper()) - .arg(info->fields[n]->name.toUpper()) - .arg(elemNames[m].toUpper()) - .arg(m)); + if (info->fields[n]->parentObjectName.length() > 0) { + enums.append(QString("typedef %1%2Elem %3%4Elem;\n") + .arg(info->fields[n]->parentObjectName) + .arg(info->fields[n]->parentFieldName) + .arg(info->name) + .arg(info->fields[n]->name)); + } else { + enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name)); + enums.append("typedef enum {\n"); + // Go through the element names + QStringList elemNames = info->fields[n]->elementNames; + for (int m = 0; m < elemNames.length(); ++m) { + QString s = (m != (elemNames.length() - 1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n"; + enums.append(s + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(elemNames[m].toUpper()) + .arg(m)); + } + enums.append(QString("} %1%2Elem;\n") + .arg(info->name) + .arg(info->fields[n]->name)); } - enums.append(QString("} %1%2Elem;\n") - .arg(info->name) - .arg(info->fields[n]->name)); } // Generate array information if (info->fields[n]->numElements > 1) { enums.append(QString("\n// Number of elements for field %1\n").arg(info->fields[n]->name)); - enums.append(QString("#define %1_%2_NUMELEM %3\n") - .arg(info->name.toUpper()) - .arg(info->fields[n]->name.toUpper()) - .arg(info->fields[n]->numElements)); + if (info->fields[n]->parentObjectName.length() > 0) { + enums.append(QString("#define %1_%2_NUMELEM %3_%4_NUMELEM\n") + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(info->fields[n]->parentObjectName.toUpper()) + .arg(info->fields[n]->parentFieldName.toUpper())); + } else { + enums.append(QString("#define %1_%2_NUMELEM %3\n") + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(info->fields[n]->numElements)); + } } enums.append(QString("\n")); } + + QString includes; + QSet parentObjects; + + for (int n = 0; n < info->fields.length(); ++n) { + if (info->fields[n]->parentObjectName.length() > 0) { + parentObjects.insert(info->fields[n]->parentObjectName); + } + } + + foreach(const QString &objectName, parentObjects) { + includes.append("#include \"" + objectName.toLower() + ".h\"\n"); + } + outInclude.replace(QString("$(DATAFIELDINFO)"), enums); + outInclude.replace(QString("$(INCLUDE)"), includes); // Replace the $(INITFIELDS) tag QString initfields; diff --git a/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp b/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp index 1796f1a1d..4c3dfbf94 100644 --- a/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp +++ b/ground/uavobjgenerator/generators/gcs/uavobjectgeneratorgcs.cpp @@ -24,7 +24,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - +#include #include "uavobjectgeneratorgcs.h" #define VERBOSE false @@ -52,27 +52,32 @@ void info(ObjectInfo *object, QString msg) } struct Context { - ObjectInfo *object; + ObjectInfo *object; + // parent objects + QSet parentObjects; // enums - QString enums; - QString enumsCount; - QString registerImpl; + QString enums; + QString enumsCount; + QString registerImpl; // interface - QString fields; - QString fieldsInfo; - QString properties; - QString deprecatedProperties; - QString getters; - QString setters; - QString notifications; + QString fields; + QString fieldsInfo; + QString properties; + QString deprecatedProperties; + QString getters; + QString setters; + QString notifications; // implementation - QString fieldsInit; - QString fieldsDefault; - QString propertiesImpl; - QString notificationsImpl; + QString fieldsInit; + QString fieldsDefault; + QString propertiesImpl; + QString notificationsImpl; }; struct FieldContext { + FieldContext(FieldInfo *fieldInfo, ObjectInfo *object); + FieldContext(const FieldContext &fieldContext); + FieldInfo *field; // field QString fieldName; @@ -82,6 +87,10 @@ struct FieldContext { QString ucPropName; QString propType; QString propRefType; + // + QString parentClassName; + QString parentFieldName; + QString ucParentPropName; // deprecation bool hasDeprecatedProperty; bool hasDeprecatedGetter; @@ -226,6 +235,10 @@ QString generate(Context &ctxt, FieldContext &fieldCtxt, const QString &fragment str.replace(":elementCount", QString::number(fieldCtxt.field->numElements)); str.replace(":enumCount", QString::number(fieldCtxt.field->numOptions)); + str.replace(":parentFieldName", fieldCtxt.parentFieldName); + str.replace(":parentClassName", fieldCtxt.parentClassName); + str.replace(":ParentPropName", fieldCtxt.ucParentPropName); + return str; } @@ -234,34 +247,42 @@ void generateFieldInfo(Context &ctxt, FieldContext &fieldCtxt) ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " // :fieldName\n"); if (fieldCtxt.field->type == FIELDTYPE_ENUM) { - QStringList options = fieldCtxt.field->options; - ctxt.fieldsInfo += " typedef enum { "; - for (int m = 0; m < options.length(); ++m) { - if (m > 0) { - ctxt.fieldsInfo.append(", "); + if (fieldCtxt.field->parentObjectName.length() > 0) { + ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " typedef :parentClassName:::parentFieldNameOptions :fieldNameOptions;\n"); + } else { + QStringList options = fieldCtxt.field->options; + ctxt.fieldsInfo += " typedef enum { "; + for (int m = 0; m < options.length(); ++m) { + if (m > 0) { + ctxt.fieldsInfo.append(", "); + } + ctxt.fieldsInfo += generate(ctxt, fieldCtxt, "%1_%2=%3") + .arg(fieldCtxt.field->name.toUpper()) + .arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")) + .arg(m); } - ctxt.fieldsInfo += generate(ctxt, fieldCtxt, "%1_%2=%3") - .arg(fieldCtxt.field->name.toUpper()) - .arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")) - .arg(m); + ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameOptions;\n"); } - ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameOptions;\n"); } // Generate element names (only if field has more than one element) if (fieldCtxt.field->numElements > 1 && !fieldCtxt.field->defaultElementNames) { - QStringList elemNames = fieldCtxt.field->elementNames; - ctxt.fieldsInfo += " typedef enum { "; - for (int m = 0; m < elemNames.length(); ++m) { - if (m > 0) { - ctxt.fieldsInfo.append(", "); + if (fieldCtxt.field->parentObjectName.length() > 0) { + ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " typedef :parentClassName:::parentFieldNameElem :fieldNameElem;\n"); + } else { + QStringList elemNames = fieldCtxt.field->elementNames; + ctxt.fieldsInfo += " typedef enum { "; + for (int m = 0; m < elemNames.length(); ++m) { + if (m > 0) { + ctxt.fieldsInfo.append(", "); + } + ctxt.fieldsInfo += QString("%1_%2=%3") + .arg(fieldCtxt.field->name.toUpper()) + .arg(elemNames[m].toUpper()) + .arg(m); } - ctxt.fieldsInfo += QString("%1_%2=%3") - .arg(fieldCtxt.field->name.toUpper()) - .arg(elemNames[m].toUpper()) - .arg(m); + ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameElem;\n"); } - ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameElem;\n"); } // Generate array information @@ -341,6 +362,9 @@ void generateFieldDefault(Context &ctxt, FieldContext &fieldCtxt) void generateField(Context &ctxt, FieldContext &fieldCtxt) { + if (fieldCtxt.parentClassName.length() > 0) { + ctxt.parentObjects.insert(fieldCtxt.parentClassName); + } if (fieldCtxt.field->numElements > 1) { ctxt.fields += generate(ctxt, fieldCtxt, " :fieldType :fieldName[:elementCount];\n"); } else { @@ -355,20 +379,24 @@ void generateEnum(Context &ctxt, FieldContext &fieldCtxt) { Q_ASSERT(fieldCtxt.field->type == FIELDTYPE_ENUM); - QString enumStringList = toEnumStringList(ctxt.object, fieldCtxt.field); + if (fieldCtxt.field->parentObjectName.length() > 0) { + ctxt.enums += generate(ctxt, fieldCtxt, "typedef :parentClassName_:ParentPropName :ClassName_:PropName;\n\n"); + } else { + QString enumStringList = toEnumStringList(ctxt.object, fieldCtxt.field); - ctxt.enums += generate(ctxt, fieldCtxt, - "class :ClassName_:PropName : public QObject {\n" - " Q_OBJECT\n" - "public:\n" - " enum Enum { %1 };\n" - " Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5\n" - "};\n\n").arg(enumStringList); + ctxt.enums += generate(ctxt, fieldCtxt, + "class :ClassName_:PropName : public QObject {\n" + " Q_OBJECT\n" + "public:\n" + " enum Enum { %1 };\n" + " Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5\n" + "};\n\n").arg(enumStringList); - ctxt.enumsCount += generate(ctxt, fieldCtxt, ":PropNameCount = :enumCount, "); + ctxt.enumsCount += generate(ctxt, fieldCtxt, ":PropNameCount = :enumCount, "); - ctxt.registerImpl += generate(ctxt, fieldCtxt, - " qmlRegisterType<:ClassName_:PropName>(\"%1.:ClassName\", 1, 0, \":PropName\");\n").arg("UAVTalk"); + ctxt.registerImpl += generate(ctxt, fieldCtxt, + " qmlRegisterType<:ClassName_:PropName>(\"%1.:ClassName\", 1, 0, \":PropName\");\n").arg("UAVTalk"); + } } void generateBaseProperty(Context &ctxt, FieldContext &fieldCtxt) @@ -507,14 +535,10 @@ void generateIndexedProperty(Context &ctxt, FieldContext &fieldCtxt) sep = "_"; } - FieldContext elementCtxt; - elementCtxt.field = fieldCtxt.field; - elementCtxt.fieldName = fieldCtxt.fieldName + "_" + elementName; - elementCtxt.fieldType = fieldCtxt.fieldType; - elementCtxt.propName = fieldCtxt.propName + sep + elementName; - elementCtxt.ucPropName = fieldCtxt.ucPropName + sep + elementName; - elementCtxt.propType = fieldCtxt.propType; - elementCtxt.propRefType = fieldCtxt.propRefType; + FieldContext elementCtxt(fieldCtxt); + elementCtxt.fieldName = fieldCtxt.fieldName + "_" + elementName; + elementCtxt.propName = fieldCtxt.propName + sep + elementName; + elementCtxt.ucPropName = fieldCtxt.ucPropName + sep + elementName; // deprecation elementCtxt.hasDeprecatedProperty = (elementCtxt.fieldName != elementCtxt.propName) && DEPRECATED; elementCtxt.hasDeprecatedGetter = DEPRECATED; @@ -593,6 +617,44 @@ bool UAVObjectGeneratorGCS::generate(UAVObjectParser *parser, QString templatepa return true; } +FieldContext::FieldContext(const FieldContext &fieldContext) +{ + *this = fieldContext; +} + +FieldContext::FieldContext(FieldInfo *fieldInfo, ObjectInfo *object) +{ + field = fieldInfo; + + // field properties + fieldName = field->name; + fieldType = fieldTypeStrCPP(field->type); + + parentClassName = field->parentObjectName; + parentFieldName = field->parentFieldName; + ucParentPropName = toPropertyName(field->parentFieldName); + + ucPropName = toPropertyName(field->name); + propName = toLowerCamelCase(ucPropName); + propType = fieldType; + if (field->type == FIELDTYPE_INT8) { + propType = fieldTypeStrCPP(FIELDTYPE_INT16); + } else if (field->type == FIELDTYPE_UINT8) { + propType = fieldTypeStrCPP(FIELDTYPE_UINT16); + } else if (field->type == FIELDTYPE_ENUM) { + QString enumClassName = object->name + "_" + ucPropName; + propType = enumClassName + "::Enum"; + } + // reference type + propRefType = propType; + + // deprecation + hasDeprecatedProperty = (fieldName != propName) && DEPRECATED; + hasDeprecatedGetter = DEPRECATED; + hasDeprecatedSetter = ((fieldName != ucPropName) || (fieldType != propType)) && DEPRECATED; + hasDeprecatedNotification = ((fieldName != propName) || (fieldType != propType)) && DEPRECATED; +} + /** * Generate the GCS object files * @@ -634,32 +696,7 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *object) FieldInfo *field = object->fields[n]; // field context - FieldContext fieldCtxt; - fieldCtxt.field = field; - - // field properties - fieldCtxt.fieldName = field->name; - fieldCtxt.fieldType = fieldTypeStrCPP(field->type); - - fieldCtxt.ucPropName = toPropertyName(field->name); - fieldCtxt.propName = toLowerCamelCase(fieldCtxt.ucPropName); - fieldCtxt.propType = fieldCtxt.fieldType; - if (field->type == FIELDTYPE_INT8) { - fieldCtxt.propType = fieldTypeStrCPP(FIELDTYPE_INT16); - } else if (field->type == FIELDTYPE_UINT8) { - fieldCtxt.propType = fieldTypeStrCPP(FIELDTYPE_UINT16); - } else if (field->type == FIELDTYPE_ENUM) { - QString enumClassName = object->name + "_" + fieldCtxt.ucPropName; - fieldCtxt.propType = enumClassName + "::Enum"; - } - // reference type - fieldCtxt.propRefType = fieldCtxt.propType; - - // deprecation - fieldCtxt.hasDeprecatedProperty = (fieldCtxt.fieldName != fieldCtxt.propName) && DEPRECATED; - fieldCtxt.hasDeprecatedGetter = DEPRECATED; - fieldCtxt.hasDeprecatedSetter = ((fieldCtxt.fieldName != fieldCtxt.ucPropName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED; - fieldCtxt.hasDeprecatedNotification = ((fieldCtxt.fieldName != fieldCtxt.propName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED; + FieldContext fieldCtxt(field, object); generateField(ctxt, fieldCtxt); @@ -671,6 +708,12 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *object) generateProperty(ctxt, fieldCtxt); } + QString includes; + foreach(const QString &objectName, ctxt.parentObjects) { + includes.append("#include \"" + objectName.toLower() + ".h\"\n"); + } + + outInclude.replace("$(INCLUDE)", includes); outInclude.replace("$(ENUMS)", ctxt.enums); outInclude.replace("$(ENUMS_COUNT)", ctxt.enumsCount); outInclude.replace("$(DATAFIELDS)", ctxt.fields);