mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-28 06:24:10 +01:00
Merged in mindnever/librepilot/LP-599_Extend_cloneof_attribute_functionality_in_uavobject_xml (pull request #514)
LP-599 Extend cloneof attribute functionality in uavobject xml Approved-by: Vladimir Zidar <mr_w@mindnever.org> Approved-by: Jan NIJS <dr.oblivium@gmail.com> Approved-by: Philippe Renon <philippe_renon@yahoo.fr> Approved-by: Lalanne Laurent <f5soh@free.fr>
This commit is contained in:
commit
230d770498
@ -40,6 +40,7 @@
|
||||
#ifndef $(NAMEUC)_H
|
||||
#define $(NAMEUC)_H
|
||||
#include <stdbool.h>
|
||||
$(INCLUDE)
|
||||
/* Object constants */
|
||||
#define $(NAMEUC)_OBJID $(OBJIDHEX)
|
||||
#define $(NAMEUC)_ISSINGLEINST $(ISSINGLEINST)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define $(NAMEUC)_H
|
||||
|
||||
#include "uavdataobject.h"
|
||||
$(INCLUDE)
|
||||
|
||||
class UAVObjectManager;
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <QSet>
|
||||
#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<QString> 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;
|
||||
|
@ -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 <QSet>
|
||||
#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<QString> 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);
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user