diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1e4a5cb51a682ae308bb4bc66aa04bc5dded9a33..418de16bdb77a6fe9e3032f6f2dc1a65c8d6d814 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -93,7 +93,8 @@
"qpair": "cpp",
"qstring": "cpp",
"qregularexpression": "cpp",
- "qmessagebox": "cpp"
+ "qmessagebox": "cpp",
+ "regex": "cpp"
},
"editor.defaultFormatter": "chiehyu.vscode-astyle",
"[xml]": {
diff --git a/Core/xmlobject.cpp b/Core/xmlobject.cpp
index 2c6692e767e4c6942246e5ed7b3cf79192450b66..e452463fcd42b93d2894a469c891a2af88bf9d91 100644
--- a/Core/xmlobject.cpp
+++ b/Core/xmlobject.cpp
@@ -1,22 +1,21 @@
#include "xmlobject.h"
-#include <QTextStream>
#include <QFile>
+#include <QTextStream>
-XmlObject::XmlObject(const QString& objectName) {
- setObjectName(objectName);
-}
+XmlObject::XmlObject(const QString& objectName) { setObjectName(objectName); }
-XmlObject::XmlObject(const XmlObject& other) {
- copy(other);
-}
+XmlObject::XmlObject(const XmlObject& other) { copy(other); }
-bool XmlObject::loadFromFile(const QString& filePath) {
+bool XmlObject::loadFromFile(const QString& filePath)
+{
bool result = false;
QFile file(filePath);
- if(file.exists() && file.open(QIODevice::ReadOnly)) {
+ if (file.exists() && file.open(QIODevice::ReadOnly))
+ {
QString msgDefFileContent = QTextStream(&file).readAll();
- if(msgDefFileContent != "") {
+ if (msgDefFileContent != "")
+ {
this->fromXml(msgDefFileContent);
result = true;
}
@@ -25,10 +24,12 @@ bool XmlObject::loadFromFile(const QString& filePath) {
return result;
}
-bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const {
+bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const
+{
bool result = false;
QFile file(filePath);
- if(file.open(QIODevice::WriteOnly)) {
+ if (file.open(QIODevice::WriteOnly))
+ {
QTextStream textStream(&file);
textStream.setCodec(codec.toUtf8());
textStream << this->toXml();
@@ -38,7 +39,8 @@ bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const
return result;
}
-QString XmlObject::toXml() const {
+QString XmlObject::toXml() const
+{
QString output;
QXmlStreamWriter xWriter(&output);
xWriter.setAutoFormatting(true);
@@ -46,93 +48,108 @@ QString XmlObject::toXml() const {
return output;
}
-
-void XmlObject::toXml(QXmlStreamWriter* xmlWriter) const {
+void XmlObject::toXml(QXmlStreamWriter* xmlWriter) const
+{
xmlWriter->writeStartElement(xmlObjectName);
- for(QString key : attributes.keys()) {
+ for (QString key : attributes.keys())
+ {
xmlWriter->writeAttribute(key, attributes[key]);
}
- if(getTextValue() != "" && childCount() == 0) {
+ if (getTextValue() != "" && childCount() == 0)
+ {
xmlWriter->writeCharacters(getTextValue());
}
- for(XmlObject c : childList) {
+ for (XmlObject c : childList)
+ {
c.toXml(xmlWriter);
}
xmlWriter->writeEndElement();
}
-void XmlObject::fromXml(const QString& txt) {
+void XmlObject::fromXml(const QString& txt)
+{
QXmlStreamReader xReader(txt);
xReader.readNextStartElement();
fromXml(&xReader);
}
-void XmlObject::fromXml(QXmlStreamReader* xmlReader) {
+void XmlObject::fromXml(QXmlStreamReader* xmlReader)
+{
childList.clear();
attributes.clear();
- if(xmlReader->isStartElement()) {
+ if (xmlReader->isStartElement())
+ {
setObjectName(xmlReader->name().toString());
- for(auto attr : xmlReader->attributes()) {
+ for (auto attr : xmlReader->attributes())
+ {
attributes[attr.name().toString()] = attr.value().toString();
}
}
- while(!xmlReader->atEnd()) {
+ while (!xmlReader->atEnd())
+ {
xmlReader->readNext();
- if(xmlReader->isCharacters() && !xmlReader->isWhitespace()) {
+ if (xmlReader->isCharacters() && !xmlReader->isWhitespace())
+ {
setTextValue(xmlReader->text().toString());
- } else if(xmlReader->isStartElement()) {
+ }
+ else if (xmlReader->isStartElement())
+ {
XmlObject c;
c.fromXml(xmlReader);
childList.append(c);
- } else if(xmlReader->isEndElement()) {
+ }
+ else if (xmlReader->isEndElement())
+ {
return;
}
}
}
-void XmlObject::copy(const XmlObject& other) {
+void XmlObject::copy(const XmlObject& other)
+{
childList.clear();
attributes.clear();
setObjectName(other.getObjectName());
setTextValue(other.getTextValue());
- for(QString attr : other.attributes.keys()) {
+ for (QString attr : other.attributes.keys())
+ {
attributes[attr] = other.attributes[attr];
}
- for(int i = 0; i < other.childCount(); i++) {
+ for (int i = 0; i < other.childCount(); i++)
+ {
addChild(other.childAt(i));
}
}
+QString XmlObject::getTextValue() const { return textValue; }
-QString XmlObject::getTextValue() const {
- return textValue;
-}
+void XmlObject::setTextValue(const QString& value) { textValue = value; }
-void XmlObject::setTextValue(const QString& value) {
- textValue = value;
-}
-
-QList<XmlObject*> XmlObject::deepSearchObjects(const QString& objectName) {
- auto pred = [objectName](const XmlObject * obj) {
- return obj->getObjectName() == objectName;
- };
+QList<XmlObject*> XmlObject::deepSearchObjects(const QString& objectName)
+{
+ auto pred = [objectName](const XmlObject* obj)
+ { return obj->getObjectName() == objectName; };
return deepSearchObjects(pred);
}
-QList<XmlObject*> XmlObject::deepSearchObjects(std::function<bool (const XmlObject* obj)> predicate) {
+QList<XmlObject*> XmlObject::deepSearchObjects(
+ std::function<bool(const XmlObject* obj)> predicate)
+{
QList<XmlObject*> results;
- if(predicate(this)) {
+ if (predicate(this))
+ {
results.append(this);
}
- for(int i = 0; i < childCount(); i++) {
+ for (int i = 0; i < childCount(); i++)
+ {
XmlObject* child = getChild(i);
results.append(child->deepSearchObjects(predicate));
}
@@ -140,75 +157,83 @@ QList<XmlObject*> XmlObject::deepSearchObjects(std::function<bool (const XmlObje
return results;
}
-void XmlObject::operator =(const XmlObject& other) {
- copy(other);
-}
+void XmlObject::operator=(const XmlObject& other) { copy(other); }
-void XmlObject::removeChild(int i) {
- if( i < childCount())
+void XmlObject::removeChild(int i)
+{
+ if (i < childCount())
childList.removeAt(i);
}
-void XmlObject::swapChildAt(int i, int j) {
- if(i > 0 && j > 0 && i < childCount() && j < childCount()) {
+void XmlObject::swapChildAt(int i, int j)
+{
+ if (i > 0 && j > 0 && i < childCount() && j < childCount())
+ {
childList.swapItemsAt(i, j);
}
}
-QString XmlObject::getChildObjectValue(const QString& objectName) {
- for(XmlObject child : childList) {
- if(child.getObjectName() == objectName) {
+QString XmlObject::getChildObjectValue(const QString& objectName)
+{
+ for (XmlObject child : childList)
+ {
+ if (child.getObjectName() == objectName)
+ {
return child.getTextValue();
}
}
return "";
}
-void XmlObject::clearAttributes() {
- attributes.clear();
-}
+void XmlObject::clearAttributes() { attributes.clear(); }
-void XmlObject::clearChilds() {
- childList.clear();
-}
+void XmlObject::clearChilds() { childList.clear(); }
-void XmlObject::reset() {
+void XmlObject::reset()
+{
setObjectName("");
clearChilds();
clearAttributes();
}
-bool XmlObject::isEmpty() {
- return getObjectName() == "" && childList.isEmpty() && getTextValue() == "" && attributes.isEmpty();
+bool XmlObject::isEmpty()
+{
+ return getObjectName() == "" && childList.isEmpty() &&
+ getTextValue() == "" && attributes.isEmpty();
}
-
-QString XmlObject::getAttribute(const QString& name, const QString& defaultValue) const {
- if(attributes.contains(name)) {
+QString XmlObject::getAttribute(const QString& name,
+ const QString& defaultValue) const
+{
+ if (attributes.contains(name))
+ {
return attributes[name];
}
return defaultValue;
}
-bool XmlObject::hasAttribute(const QString& name) const {
+bool XmlObject::hasAttribute(const QString& name) const
+{
return attributes.contains(name);
}
-int XmlObject::attributeCount() const {
- return attributes.count();
-}
+int XmlObject::attributeCount() const { return attributes.count(); }
-QMapIterator<QString, QString> XmlObject::attributesIterator() const {
+QMapIterator<QString, QString> XmlObject::attributesIterator() const
+{
return QMapIterator<QString, QString>(attributes);
}
-bool XmlObject::getIntAttribute(const QString& name, int& value) const {
+bool XmlObject::getAttribute(const QString& name, int& value) const
+{
QString val = getAttribute(name);
bool ok;
- if(val != "") {
+ if (val != "")
+ {
int temp = val.toInt(&ok);
- if(ok) {
+ if (ok)
+ {
value = temp;
return true;
}
@@ -216,12 +241,15 @@ bool XmlObject::getIntAttribute(const QString& name, int& value) const {
return false;
}
-bool XmlObject::getFloatAttribute(const QString& name, float& value) const {
+bool XmlObject::getAttribute(const QString& name, float& value) const
+{
QString val = getAttribute(name);
bool ok;
- if(val != "") {
+ if (val != "")
+ {
float temp = val.toFloat(&ok);
- if(ok) {
+ if (ok)
+ {
value = temp;
return true;
}
@@ -229,48 +257,49 @@ bool XmlObject::getFloatAttribute(const QString& name, float& value) const {
return false;
}
-void XmlObject::addAttribute(const QString& name, const QString& value) {
+void XmlObject::addAttribute(const QString& name, const QString& value)
+{
attributes[name] = value;
}
-void XmlObject::addAttribute(const QString& name, int value) {
+void XmlObject::addAttribute(const QString& name, int value)
+{
addAttribute(name, QString::number(value));
}
-int XmlObject::addChild(const XmlObject& c) {
+void XmlObject::addAttribute(const QString& name, float value)
+{
+ addAttribute(name, QString::number(value));
+}
+
+int XmlObject::addChild(const XmlObject& c)
+{
childList.append(c);
return childList.count() - 1;
}
-void XmlObject::addChilds(const QList<XmlObject>& childs) {
+void XmlObject::addChilds(const QList<XmlObject>& childs)
+{
childList.append(childs);
}
-QString XmlObject::getObjectName() const {
- return xmlObjectName;
-}
+QString XmlObject::getObjectName() const { return xmlObjectName; }
-void XmlObject::setObjectName(const QString& value) {
- xmlObjectName = value;
-}
+void XmlObject::setObjectName(const QString& value) { xmlObjectName = value; }
-int XmlObject::childCount() const {
- return childList.count();
-}
+int XmlObject::childCount() const { return childList.count(); }
-XmlObject XmlObject::childAt(int index) const {
- return childList.at(index);
-}
+XmlObject XmlObject::childAt(int index) const { return childList.at(index); }
-XmlObject XmlObject::searchChild(const QString& name) const {
- for(int i = 0; i < childCount(); i++) {
- if(childList[i].getObjectName() == name) {
- return childList[i];
- }
- }
- return XmlObject();
-}
+int XmlObject::searchChild(const QString& name) const
+{
+ for (int i = 0; i < childCount(); i++)
+ if (childList[i].getObjectName() == name)
+ return i;
-XmlObject* XmlObject::getChild(int index) {
- return &childList[index];
+ return -1;
}
+
+XmlObject* XmlObject::getChild(int index) { return &childList[index]; }
+
+QMap<QString, QString> XmlObject::getAttributes() const { return attributes; }
\ No newline at end of file
diff --git a/Core/xmlobject.h b/Core/xmlobject.h
index 9f133a17d46379b6555e88e2c203cb5a9e073462..22080dbc0475d4379c70d8523fb9177363fac9d6 100644
--- a/Core/xmlobject.h
+++ b/Core/xmlobject.h
@@ -1,39 +1,43 @@
#ifndef XMLOBJECT_H
#define XMLOBJECT_H
-
#include <QMap>
-#include <QXmlStreamWriter>
-#include <QXmlStreamReader>
#include <QMapIterator>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
-class XmlObject {
- public:
+class XmlObject
+{
+public:
XmlObject(const QString& objectName = "Object");
XmlObject(const XmlObject& other);
bool loadFromFile(const QString& filePath);
- bool writeToFile(const QString& filePath, const QString& codec = "UTF-8") const;
+ bool writeToFile(const QString& filePath,
+ const QString& codec = "UTF-8") const;
QString toXml() const;
void fromXml(const QString& txt);
- QString getAttribute(const QString& name, const QString& defaultValue = "") const;
+ QString getAttribute(const QString& name,
+ const QString& defaultValue = "") const;
bool hasAttribute(const QString& name) const;
int attributeCount() const;
QMapIterator<QString, QString> attributesIterator() const;
/*
- * Get the value of "value" if the attribute with name "name" exist and is an integer
+ * Get the value of "value" if the attribute with name "name" exist and is
+ * an integer
*/
- bool getIntAttribute(const QString& name, int& value) const;
- bool getFloatAttribute(const QString& name, float& value) const;
+ bool getAttribute(const QString& name, int& value) const;
+ bool getAttribute(const QString& name, float& value) const;
/*
* addAttribute create a new attribute with name "name" and value "value"
* If the attribute already exist, it change its value
*/
void addAttribute(const QString& name, const QString& value);
void addAttribute(const QString& name, int value);
+ void addAttribute(const QString& name, float value);
int addChild(const XmlObject& c);
void addChilds(const QList<XmlObject>& childs);
@@ -42,7 +46,7 @@ class XmlObject {
int childCount() const;
XmlObject childAt(int index) const;
- XmlObject searchChild(const QString& name) const;
+ int searchChild(const QString& name) const;
/*
* getChild Returns the child at index position as a modifiable reference.
* index must be a valid index position in the list
@@ -59,10 +63,11 @@ class XmlObject {
/*
* deepSearchObjects return all the child objects that satisfy the predicate
*/
- QList<XmlObject*> deepSearchObjects(std::function<bool(const XmlObject* obj)> predicate);
+ QList<XmlObject*> deepSearchObjects(
+ std::function<bool(const XmlObject* obj)> predicate);
QList<XmlObject*> deepSearchObjects(const QString& objectName);
- void operator = (const XmlObject& other );
+ void operator=(const XmlObject& other);
void removeChild(int i);
/*
@@ -78,17 +83,19 @@ class XmlObject {
void reset();
bool isEmpty();
- protected:
+
+ QMap<QString, QString> getAttributes() const;
+
+protected:
void toXml(QXmlStreamWriter* xmlWriter) const;
void fromXml(QXmlStreamReader* xmlReader);
void copy(const XmlObject& other);
- private:
+private:
QMap<QString, QString> attributes;
QList<XmlObject> childList;
- QString textValue = "";
+ QString textValue = "";
QString xmlObjectName = "";
-
};
-#endif // XMLOBJECT_H
+#endif // XMLOBJECT_H
diff --git a/Modules/CommandPad/MessageFormElement.cpp b/Modules/CommandPad/MessageFormElement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b0feed91cf32e1ae82f6f13785ef53af601ac59b
--- /dev/null
+++ b/Modules/CommandPad/MessageFormElement.cpp
@@ -0,0 +1,311 @@
+#include "MessageFormElement.h"
+
+#include <Modules/skywardhubstrings.h>
+
+MessageFormElement::MessageFormElement() {}
+
+MessageFormElement::~MessageFormElement()
+{
+ for (auto key : comboBoxMap.keys())
+ {
+ delete comboBoxMap[key].first;
+ delete comboBoxMap[key].second;
+ }
+
+ for (auto key : floatMap.keys())
+ {
+ delete std::get<0>(floatMap[key]);
+ delete std::get<1>(floatMap[key]);
+ }
+
+ for (auto key : integerMap.keys())
+ {
+ delete std::get<0>(integerMap[key]);
+ delete std::get<1>(integerMap[key]);
+ }
+}
+
+bool MessageFormElement::addComboBox(QString id, QString label,
+ const QMap<QString, int>& options)
+{
+ if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+ !integerMap.contains(id))
+ {
+ auto* comboBox = new QComboBox;
+ comboBox->setSizePolicy(
+ QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ for (auto key : options.keys())
+ comboBox->addItem(key, options[key]);
+
+ comboBoxMap[id] = {new QLabel(label), comboBox};
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool MessageFormElement::addFloat(QString id, QString label, float min,
+ float max, int decimals)
+{
+ if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+ !integerMap.contains(id))
+ {
+ auto* lineEdit = new QLineEdit;
+ lineEdit->setSizePolicy(
+ QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+ lineEdit->setValidator(new QDoubleValidator(min, max, decimals));
+ floatMap[id] = {new QLabel(label), lineEdit, min, max, decimals};
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool MessageFormElement::addInteger(QString id, QString label, int min, int max)
+{
+ if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+ !integerMap.contains(id))
+ {
+ auto* lineEdit = new QLineEdit;
+ lineEdit->setSizePolicy(
+ QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+ lineEdit->setValidator(new QIntValidator(min, max));
+ integerMap[id] = {new QLabel(label), lineEdit, min, max};
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+XmlObject MessageFormElement::toXmlObject()
+{
+ XmlObject comboBoxList("combo_box_list");
+ for (auto key : comboBoxMap.keys())
+ {
+ auto comboBox = comboBoxMap[key];
+ XmlObject comboBoxXml("combo_box");
+ comboBoxXml.addAttribute("id", key);
+ comboBoxXml.addAttribute("label", comboBox.first->text());
+ comboBoxXml.addAttribute("text", comboBox.second->currentText());
+ comboBoxList.addChild(comboBoxXml);
+ }
+
+ XmlObject floatList("float_list");
+ for (auto key : floatMap.keys())
+ {
+ auto floatField = floatMap[key];
+ XmlObject floatFieldXml("float_field");
+ floatFieldXml.addAttribute("id", key);
+ floatFieldXml.addAttribute("label", std::get<0>(floatField)->text());
+ floatFieldXml.addAttribute("text", std::get<1>(floatField)->text());
+ floatFieldXml.addAttribute("min", std::get<2>(floatField));
+ floatFieldXml.addAttribute("max", std::get<3>(floatField));
+ floatFieldXml.addAttribute("decimals", std::get<4>(floatField));
+ floatList.addChild(floatFieldXml);
+ }
+
+ XmlObject integerList("integer_list");
+ for (auto key : floatMap.keys())
+ {
+ auto integerField = floatMap[key];
+ XmlObject integerFieldXml("integer_field");
+ integerFieldXml.addAttribute("id", key);
+ integerFieldXml.addAttribute("label",
+ std::get<0>(integerField)->text());
+ integerFieldXml.addAttribute("text", std::get<1>(integerField)->text());
+ integerFieldXml.addAttribute("min", std::get<2>(integerField));
+ integerFieldXml.addAttribute("max", std::get<3>(integerField));
+ integerList.addChild(integerFieldXml);
+ }
+
+ XmlObject configuration("configuration");
+ configuration.addChild(comboBoxList);
+ configuration.addChild(floatList);
+ configuration.addChild(integerList);
+
+ return configuration;
+}
+
+void MessageFormElement::fromXmlObject(const XmlObject& obj)
+{
+ int comboBoxListIndex = obj.searchChild("combo_box_list");
+ if (comboBoxListIndex != -1)
+ {
+ auto comboBoxList = obj.childAt(comboBoxListIndex);
+ for (int i = 0; i < comboBoxList.childCount(); i++)
+ {
+ auto comboBoxXml = comboBoxList.childAt(i);
+ auto key = comboBoxXml.getAttribute("id");
+ if (comboBoxMap.contains(key))
+ {
+ auto comboBox = comboBoxMap[key];
+ comboBox.first->setText(comboBoxXml.getAttribute("label"));
+ comboBox.second->setCurrentText(
+ comboBoxXml.getAttribute("text"));
+ }
+ }
+ }
+
+ int floatListIndex = obj.searchChild("float_list");
+ if (floatListIndex != -1)
+ {
+ auto floatList = obj.childAt(floatListIndex);
+ for (int i = 0; i < floatList.childCount(); i++)
+ {
+ auto floatFieldXml = floatList.childAt(i);
+ auto key = floatFieldXml.getAttribute("id");
+ if (floatMap.contains(key))
+ {
+ auto floatField = floatMap[key];
+ std::get<0>(floatField)
+ ->setText(floatFieldXml.getAttribute("label"));
+ std::get<1>(floatField)
+ ->setText(floatFieldXml.getAttribute("text"));
+ floatFieldXml.getAttribute("min", std::get<2>(floatField));
+ floatFieldXml.getAttribute("max", std::get<3>(floatField));
+ floatFieldXml.getAttribute("decimals", std::get<4>(floatField));
+ std::get<1>(floatField)
+ ->setValidator(new QDoubleValidator(
+ std::get<2>(floatField), std::get<3>(floatField),
+ std::get<4>(floatField)));
+ }
+ }
+ }
+
+ int integerListIndex = obj.searchChild("integer_list");
+ if (integerListIndex != -1)
+ {
+ auto floatList = obj.childAt(integerListIndex);
+ for (int i = 0; i < floatList.childCount(); i++)
+ {
+ auto integerFieldXml = floatList.childAt(i);
+ auto key = integerFieldXml.getAttribute("id");
+ if (integerMap.contains(key))
+ {
+ auto integerField = integerMap[key];
+ std::get<0>(integerField)
+ ->setText(integerFieldXml.getAttribute("label"));
+ std::get<1>(integerField)
+ ->setText(integerFieldXml.getAttribute("text"));
+ integerFieldXml.getAttribute("min", std::get<2>(integerField));
+ integerFieldXml.getAttribute("max", std::get<3>(integerField));
+ std::get<1>(integerField)
+ ->setValidator(new QIntValidator(
+ std::get<2>(integerField), std::get<3>(integerField)));
+ }
+ }
+ }
+}
+
+void MessageFormElement::applyToGridLayout(QGridLayout* layout)
+{
+ for (auto key : comboBoxMap.keys())
+ {
+ auto label = comboBoxMap[key].first;
+ auto comboBox = comboBoxMap[key].second;
+
+ int rows = layout->rowCount();
+ layout->addWidget(label, rows, 0, Qt::AlignRight);
+ layout->addWidget(comboBox, rows, 1);
+
+ label->show();
+ comboBox->show();
+ }
+
+ for (auto key : floatMap.keys())
+ {
+ auto label = std::get<0>(floatMap[key]);
+ auto floatField = std::get<1>(floatMap[key]);
+
+ int rows = layout->rowCount();
+ layout->addWidget(label, rows, 0, Qt::AlignRight);
+ layout->addWidget(floatField, rows, 1);
+
+ label->show();
+ floatField->show();
+ }
+
+ for (auto key : integerMap.keys())
+ {
+ auto label = std::get<0>(integerMap[key]);
+ auto integerField = std::get<1>(integerMap[key]);
+
+ int rows = layout->rowCount();
+ layout->addWidget(label, rows, 0, Qt::AlignRight);
+ layout->addWidget(integerField, rows, 1);
+
+ label->show();
+ integerField->show();
+ }
+}
+
+void MessageFormElement::removeFromGridLayout(QGridLayout* layout)
+{
+ for (auto key : comboBoxMap.keys())
+ {
+ auto label = comboBoxMap[key].first;
+ auto comboBox = comboBoxMap[key].second;
+
+ layout->removeWidget(label);
+ layout->removeWidget(comboBox);
+
+ label->hide();
+ comboBox->hide();
+ }
+
+ for (auto key : floatMap.keys())
+ {
+ auto label = std::get<0>(floatMap[key]);
+ auto floatField = std::get<1>(floatMap[key]);
+
+ layout->removeWidget(label);
+ layout->removeWidget(floatField);
+
+ label->hide();
+ floatField->hide();
+ }
+
+ for (auto key : integerMap.keys())
+ {
+ auto label = std::get<0>(integerMap[key]);
+ auto integerField = std::get<1>(integerMap[key]);
+
+ layout->removeWidget(label);
+ layout->removeWidget(integerField);
+
+ label->hide();
+ integerField->hide();
+ }
+}
+
+ModuleMessage MessageFormElement::prepareMessage(const QString& messageId)
+{
+ ModuleMessage message(SkywardHubStrings::commandsTopic + "/" + messageId);
+
+ for (auto key : comboBoxMap.keys())
+ {
+ auto comboBox = comboBoxMap[key].second;
+ message.setField(key, (uint64_t)comboBox->currentData().toInt());
+ }
+
+ for (auto key : floatMap.keys())
+ {
+ auto floatField = std::get<1>(floatMap[key]);
+ message.setField(key, floatField->text());
+ }
+
+ for (auto key : integerMap.keys())
+ {
+ auto integerField = std::get<1>(integerMap[key]);
+ message.setField(key, integerField->text());
+ }
+
+ return message;
+}
\ No newline at end of file
diff --git a/Modules/CommandPad/MessageFormElement.h b/Modules/CommandPad/MessageFormElement.h
new file mode 100644
index 0000000000000000000000000000000000000000..81946d49e7000e38e15db99bd564601a6fbd796a
--- /dev/null
+++ b/Modules/CommandPad/MessageFormElement.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <Core/Message/modulemessage.h>
+#include <Core/xmlobject.h>
+
+#include <QComboBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QMap>
+#include <QString>
+
+class MessageFormElement
+{
+public:
+ MessageFormElement();
+
+ ~MessageFormElement();
+
+ /**
+ * @brief Adds a new combo box field to the form.
+ *
+ * @return false if there is already a field with the given id.
+ */
+ bool addComboBox(QString id, QString label,
+ const QMap<QString, int>& options);
+
+ /**
+ * @brief Adds a new float field to the form.
+ *
+ * @return false if there is already a field with the given id.
+ */
+ bool addFloat(QString id, QString label,
+ float min = std::numeric_limits<float>::min(),
+ float max = std::numeric_limits<float>::max(),
+ int decimals = 2);
+
+ /**
+ * @brief Adds a new integer field to the form.
+ *
+ * @return false if there is already a field with the given id.
+ */
+ bool addInteger(QString id, QString label,
+ int min = std::numeric_limits<int>::min(),
+ int max = std::numeric_limits<int>::max());
+
+ XmlObject toXmlObject();
+
+ void fromXmlObject(const XmlObject& obj);
+
+ void applyToGridLayout(QGridLayout* layout);
+
+ void removeFromGridLayout(QGridLayout* layout);
+
+ ModuleMessage prepareMessage(const QString& messageId);
+
+private:
+ QMap<QString, QPair<QLabel*, QComboBox*>> comboBoxMap;
+ QMap<QString, std::tuple<QLabel*, QLineEdit*, float, float, int>> floatMap;
+ QMap<QString, std::tuple<QLabel*, QLineEdit*, int, int>> integerMap;
+};
diff --git a/Modules/CommandPad/commandpad.cpp b/Modules/CommandPad/commandpad.cpp
index 2967182168f612c798885e882ea226846d73a83b..411d82bf656926ab6b537a71f289c051d8ef1830 100644
--- a/Modules/CommandPad/commandpad.cpp
+++ b/Modules/CommandPad/commandpad.cpp
@@ -2,253 +2,252 @@
#include <QVBoxLayout>
-const QMap<QString, uint8_t> CommandPad::systemTMList{
- {"MAV_SYS_ID", 1}, {"MAV_FSM_ID", 2},
- {"MAV_PIN_OBS_ID", 3}, {"MAV_LOGGER_ID", 4},
- {"MAV_MAVLINK_STATS", 5}, {"MAV_TASK_STATS_ID", 6},
- {"MAV_ADA_ID", 8}, {"MAV_NAS_ID", 9},
- {"MAV_CAN_ID", 10}, {"MAV_FLIGHT_ID", 11},
- {"MAV_FLIGHT_STATS_ID", 12}, {"MAV_SENSORS_STATE_ID", 13}};
-
-const QMap<QString, uint8_t> CommandPad::sensorsTMList = {
- {"MAV_GPS_ID", 1},
- {"MAV_BMX160_ID", 2},
- {"MAV_VN100_ID", 3},
- {"MAV_MPU9250_ID", 4},
- {"MAV_ADS_ID", 5},
- {"MAV_MS5803_ID", 6},
- {"MAV_BME280_ID", 7},
- {"MAV_CURRENT_SENSE_ID", 8},
- {"MAV_LIS3MDL_ID", 9},
- {"MAV_DPL_PRESS_ID", 10},
- {"MAV_STATIC_PRESS_ID", 11},
- {"MAV_PITOT_PRESS_ID", 12},
- {"MAV_BATTERY_VOLTAGE_ID", 13},
- {"MAV_STRAIN_GAUGE_ID", 14},
+#include "Modules/Mavlink/mavlinkversionheader.h"
+
+const QStringList CommandPad::messagesList{
+ "PING_TC",
+ "COMMAND_TC",
+ "SYSTEM_TM_REQUEST_TC",
+ "SENSOR_TM_REQUEST_TC",
+ "SERVO_TM_REQUEST_TC",
+ "SET_SERVO_ANGLE_TC",
+ "WIGGLE_SERVO_TC",
+ "RESET_SERVO_TC",
+ "SET_REFERENCE_ALTITUDE_TC",
+ "SET_REFERENCE_TEMPERATURE_TC",
+ "SET_ORIENTATION_TC",
+ "SET_COORDINATES_TC",
+ "RAW_EVENT_TC",
+ "SET_DEPLOYMENT_ALTITUDE_TC",
+ "SET_TARGET_COORDINATES_TC",
+ "SET_ALGORITHM_TC",
};
-const QMap<QString, uint8_t> CommandPad::mavCommandList = {
- {"MAV_CMD_ARM", 1},
- {"MAV_CMD_DISARM", 2},
- {"MAV_CMD_CALIBRATE", 3},
- {"MAV_CMD_FORCE_INIT", 4},
- {"MAV_CMD_FORCE_LAUNCH", 5},
- {"MAV_CMD_FORCE_LANDING", 6},
- {"MAV_CMD_FORCE_APOGEE", 7},
- {"MAV_CMD_FORCE_EXPULSION", 8},
- {"MAV_CMD_FORCE_MAIN", 9},
- {"MAV_CMD_START_LOGGING", 10},
- {"MAV_CMD_CLOSE_LOG", 11},
- {"MAV_CMD_FORCE_REBOOT", 12},
- {"MAV_CMD_ENTER_TEST_MODE", 13},
- {"MAV_CMD_EXIT_TEST_MODE", 14},
- {"MAV_CMD_START_RECORDING", 15},
- {"MAV_CMD_STOP_RECORDING", 16},
+const QMap<QString, int> CommandPad::systemTmList{
+ {"MAV_SYS_ID", MAV_SYS_ID},
+ {"MAV_FSM_ID", MAV_FSM_ID},
+ {"MAV_PIN_OBS_ID", MAV_PIN_OBS_ID},
+ {"MAV_LOGGER_ID", MAV_LOGGER_ID},
+ {"MAV_MAVLINK_STATS", MAV_MAVLINK_STATS},
+ {"MAV_TASK_STATS_ID", MAV_TASK_STATS_ID},
+ {"MAV_ADA_ID", MAV_ADA_ID},
+ {"MAV_NAS_ID", MAV_NAS_ID},
+ {"MAV_CAN_ID", MAV_CAN_ID},
+ {"MAV_FLIGHT_ID", MAV_FLIGHT_ID},
+ {"MAV_STATS_ID", MAV_STATS_ID},
+ {"MAV_SENSORS_STATE_ID", MAV_SENSORS_STATE_ID},
};
-const QMap<QString, uint8_t> CommandPad::servosList = {
- {"AIRBRAKES_SERVO", 1},
- {"EXPULSION_SERVO", 2},
- {"PARAFOIL_SERVO1", 3},
- {"PARAFOIL_SERVO2", 4},
+const QMap<QString, int> CommandPad::sensorsList{
+ {"MAV_GPS_ID", MAV_GPS_ID},
+ {"MAV_BMX160_ID", MAV_BMX160_ID},
+ {"MAV_VN100_ID", MAV_VN100_ID},
+ {"MAV_MPU9250_ID", MAV_MPU9250_ID},
+ {"MAV_ADS_ID", MAV_ADS_ID},
+ {"MAV_MS5803_ID", MAV_MS5803_ID},
+ {"MAV_BME280_ID", MAV_BME280_ID},
+ {"MAV_CURRENT_SENSE_ID", MAV_CURRENT_SENSE_ID},
+ {"MAV_LIS3MDL_ID", MAV_LIS3MDL_ID},
+ {"MAV_DPL_PRESS_ID", MAV_DPL_PRESS_ID},
+ {"MAV_STATIC_PRESS_ID", MAV_STATIC_PRESS_ID},
+ {"MAV_PITOT_PRESS_ID", MAV_PITOT_PRESS_ID},
+ {"MAV_BATTERY_VOLTAGE_ID", MAV_BATTERY_VOLTAGE_ID},
+ {"MAV_STRAIN_GAUGE_ID", MAV_STRAIN_GAUGE_ID},
};
-CommandPad::CommandPad(QWidget *parent) : DefaultModule(parent) {
+const QMap<QString, int> CommandPad::commandsList{
+ {"MAV_CMD_ARM", MAV_CMD_ARM},
+ {"MAV_CMD_DISARM", MAV_CMD_DISARM},
+ {"MAV_CMD_CALIBRATE", MAV_CMD_CALIBRATE},
+ {"MAV_CMD_FORCE_INIT", MAV_CMD_FORCE_INIT},
+ {"MAV_CMD_FORCE_LAUNCH", MAV_CMD_FORCE_LAUNCH},
+ {"MAV_CMD_FORCE_LANDING", MAV_CMD_FORCE_LANDING},
+ {"MAV_CMD_FORCE_APOGEE", MAV_CMD_FORCE_APOGEE},
+ {"MAV_CMD_FORCE_EXPULSION", MAV_CMD_FORCE_EXPULSION},
+ {"MAV_CMD_FORCE_MAIN", MAV_CMD_FORCE_MAIN},
+ {"MAV_CMD_START_LOGGING", MAV_CMD_START_LOGGING},
+ {"MAV_CMD_CLOSE_LOG", MAV_CMD_CLOSE_LOG},
+ {"MAV_CMD_FORCE_REBOOT", MAV_CMD_FORCE_REBOOT},
+ {"MAV_CMD_ENTER_TEST_MODE", MAV_CMD_ENTER_TEST_MODE},
+ {"MAV_CMD_EXIT_TEST_MODE", MAV_CMD_EXIT_TEST_MODE},
+ {"MAV_CMD_START_RECORDING", MAV_CMD_START_RECORDING},
+ {"MAV_CMD_STOP_RECORDING", MAV_CMD_STOP_RECORDING},
+};
+
+const QMap<QString, int> CommandPad::servosList{
+ {"AIRBRAKES_SERVO", AIRBRAKES_SERVO},
+ {"EXPULSION_SERVO", EXPULSION_SERVO},
+ {"PARAFOIL_SERVO1", PARAFOIL_SERVO1},
+ {"PARAFOIL_SERVO2", PARAFOIL_SERVO2},
+};
+
+CommandPad::CommandPad(QWidget *parent) : DefaultModule(parent)
+{
setupUi();
defaultContextMenuSetup();
}
-CommandPad::~CommandPad() {}
+CommandPad::~CommandPad()
+{
+ delete messagesListComboBox;
+ for (auto key : formElements.keys())
+ delete formElements[key];
+ delete formGridLayout;
+}
QWidget *CommandPad::toWidget() { return this; }
-XmlObject CommandPad::toXmlObject() {
- return XmlObject(getName(ModuleId::COMMANDPAD));
-}
+XmlObject CommandPad::toXmlObject()
+{
+ XmlObject obj = XmlObject(getName(ModuleId::COMMANDPAD));
-void CommandPad::fromXmlObject(const XmlObject &xmlObject) {
- Q_UNUSED(xmlObject);
+ auto key = messagesListComboBox->currentText();
+ if (formElements.contains(key))
+ {
+ obj.addAttribute("message_id", key);
+ obj.addChild(formElements[key]->toXmlObject());
+ }
+
+ return obj;
}
-#define _CMD(id, strName) \
- QWidget *id = new QWidget; \
- QFormLayout *id##_form = new QFormLayout; \
- id->setLayout(id##_form); \
- stacked->addWidget(id); \
- commandComboBox->addItem(strName);
-
-#define _CMD_FLOAT_PROP(id, idProperty) \
- QLineEdit *id##_##idProperty = new QLineEdit; \
- id##_##idProperty->setValidator( \
- new QDoubleValidator(-10000.0, 10000.0, 3, this)); \
- id##_##idProperty->setSizePolicy( \
- QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); \
- id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_UINT8_PROP(id, idProperty) \
- QLineEdit *id##_##idProperty = new QLineEdit; \
- id##_##idProperty->setValidator(new QIntValidator(0, 255, this)); \
- id##_##idProperty->setSizePolicy( \
- QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); \
- id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_COMBO_PROP(id, idProperty, map) \
- QComboBox *id##_##idProperty = new QComboBox; \
- id##_##idProperty->setSizePolicy( \
- QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); \
- id##_##idProperty->insertItems(0, map.keys()); \
- id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_END
-
-#define _SEND(id, strName) \
- if (commandComboBox->currentText() == strName) { \
- QTime time = QTime::currentTime(); \
- ModuleMessage message(SkywardHubStrings::commandsTopic + "/" + \
- strName); \
- message.setField("timestamp", (uint64_t)time.msecsSinceStartOfDay());
-
-#define _SEND_FLOAT_PROP(id, idProperty) \
- message.setField(#idProperty, id##_##idProperty->text().toDouble());
-
-#define _SEND_UINT8_PROP(id, idProperty) \
- message.setField(#idProperty, (uint64_t)id##_##idProperty->text().toInt());
-
-#define _SEND_COMBO_PROP(id, idProperty, map) \
- message.setField(#idProperty, \
- (uint64_t)map[id##_##idProperty->currentText()]);
-
-#define _SEND_END \
- getCore()->getModuleMessagesBroker()->publish(message); \
+void CommandPad::fromXmlObject(const XmlObject &obj)
+{
+ int configurationIndex = obj.searchChild("configuration");
+ if (obj.hasAttribute("message_id") && configurationIndex != -1)
+ {
+ auto key = obj.getAttribute("message_id");
+
+ if (formElements.contains(key))
+ {
+ auto configuration = obj.childAt(configurationIndex);
+ formElements[key]->fromXmlObject(configuration);
+ messagesListComboBox->setCurrentText(key);
+ }
}
+}
+
+void CommandPad::removeWidgetsFromForm()
+{
+ QLayoutItem *child;
+ while ((child = formGridLayout->takeAt(0)) != nullptr)
+ formGridLayout->removeWidget(child->widget());
+}
-void CommandPad::setupUi() {
- QStackedWidget *stacked = new QStackedWidget;
+void CommandPad::setupUi()
+{
+ QVBoxLayout *outerLayout = new QVBoxLayout;
+ outerLayout->addStretch();
- QComboBox *commandComboBox = new QComboBox;
- commandComboBox->setSizePolicy(
+ messagesListComboBox = new QComboBox;
+ messagesListComboBox->setSizePolicy(
QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
- connect(commandComboBox,
- QOverload<int>::of(&QComboBox::currentIndexChanged), this,
- [=](int idx) { stacked->setCurrentIndex(idx); });
-
- QFormLayout *form = new QFormLayout;
- form->addRow(tr("Select command: "), commandComboBox);
-
- _CMD(ping, "PING_TC")
- _CMD_END
- _CMD(command, "COMMAND_TC")
- _CMD_COMBO_PROP(command, command_id, mavCommandList)
- _CMD_END
- _CMD(systemTelemetry, "SYSTEM_TM_REQUEST_TC")
- _CMD_COMBO_PROP(systemTelemetry, tm_id, systemTMList)
- _CMD_END
- _CMD(sensorTelemetry, "SENSOR_TM_REQUEST_TC")
- _CMD_COMBO_PROP(sensorTelemetry, sensor_id, sensorsTMList)
- _CMD_END
- _CMD(servoTelemetry, "SERVO_TM_REQUEST_TC")
- _CMD_COMBO_PROP(servoTelemetry, servo_id, servosList)
- _CMD_END
- _CMD(setServoAngle, "SET_SERVO_ANGLE_TC")
- _CMD_COMBO_PROP(setServoAngle, servo_id, servosList)
- _CMD_FLOAT_PROP(setServoAngle, angle)
- _CMD_END
- _CMD(wiggleServo, "WIGGLE_SERVO_TC")
- _CMD_COMBO_PROP(wiggleServo, servo_id, servosList)
- _CMD_END
- _CMD(resetServo, "RESET_SERVO_TC")
- _CMD_COMBO_PROP(resetServo, servo_id, servosList)
- _CMD_END
- _CMD(setReferenceAltitude, "SET_REFERENCE_ALTITUDE_TC")
- _CMD_FLOAT_PROP(setReferenceAltitude, ref_altitude)
- _CMD_END
- _CMD(setReferenceTemperature, "SET_REFERENCE_TEMPERATURE_TC")
- _CMD_FLOAT_PROP(setReferenceTemperature, ref_temp)
- _CMD_END
- _CMD(setDeploymentAltitude, "SET_DEPLOYMENT_ALTITUDE_TC")
- _CMD_FLOAT_PROP(setDeploymentAltitude, dpl_altitude)
- _CMD_END
- _CMD(setOrientation, "SET_ORIENTATION_TC")
- _CMD_FLOAT_PROP(setOrientation, yaw)
- _CMD_FLOAT_PROP(setOrientation, pitch)
- _CMD_FLOAT_PROP(setOrientation, roll)
- _CMD_END
- _CMD(setCoordinates, "SET_COORDINATES_TC")
- _CMD_FLOAT_PROP(setCoordinates, latitude)
- _CMD_FLOAT_PROP(setCoordinates, longitude)
- _CMD_END
- _CMD(rawEvent, "RAW_EVENT_TC")
- _CMD_UINT8_PROP(rawEvent, topic_id)
- _CMD_UINT8_PROP(rawEvent, event_id)
- _CMD_END
- _CMD(targetCoordinates, "SET_TARGET_COORDINATES_TC")
- _CMD_FLOAT_PROP(targetCoordinates, latitude)
- _CMD_FLOAT_PROP(targetCoordinates, longitude)
- _CMD_END
- _CMD(algorithm, "SET_ALGORITHM_TC")
- _CMD_UINT8_PROP(algorithm, algorithm_number)
- _CMD_END
-
- QPushButton *send = new QPushButton(tr("Send"));
- connect(send, &QPushButton::clicked, [=]() {
- _SEND(ping, "PING_TC")
- _SEND_END
- _SEND(command, "COMMAND_TC")
- _SEND_COMBO_PROP(command, command_id, mavCommandList)
- _SEND_END
- _SEND(systemTelemetry, "SYSTEM_TM_REQUEST_TC")
- _SEND_COMBO_PROP(systemTelemetry, tm_id, systemTMList)
- _SEND_END
- _SEND(sensorTelemetry, "SENSOR_TM_REQUEST_TC")
- _SEND_COMBO_PROP(sensorTelemetry, sensor_id, sensorsTMList)
- _SEND_END
- _SEND(servoTelemetry, "SERVO_TM_REQUEST_TC")
- _SEND_COMBO_PROP(servoTelemetry, servo_id, servosList)
- _SEND_END
- _SEND(setServoAngle, "SET_SERVO_ANGLE_TC")
- _SEND_COMBO_PROP(setServoAngle, servo_id, servosList)
- _SEND_FLOAT_PROP(setServoAngle, angle)
- _SEND_END
- _SEND(wiggleServo, "WIGGLE_SERVO_TC")
- _SEND_COMBO_PROP(wiggleServo, servo_id, servosList)
- _SEND_END
- _SEND(resetServo, "RESET_SERVO_TC")
- _SEND_COMBO_PROP(resetServo, servo_id, servosList)
- _SEND_END
- _SEND(setReferenceAltitude, "SET_REFERENCE_ALTITUDE_TC")
- _SEND_FLOAT_PROP(setReferenceAltitude, ref_altitude)
- _SEND_END
- _SEND(setReferenceTemperature, "SET_REFERENCE_TEMPERATURE_TC")
- _SEND_FLOAT_PROP(setReferenceTemperature, ref_temp)
- _SEND_END
- _SEND(setDeploymentAltitude, "SET_DEPLOYMENT_ALTITUDE_TC")
- _SEND_FLOAT_PROP(setDeploymentAltitude, dpl_altitude)
- _SEND_END
- _SEND(setOrientation, "SET_ORIENTATION_TC")
- _SEND_FLOAT_PROP(setOrientation, yaw)
- _SEND_FLOAT_PROP(setOrientation, pitch)
- _SEND_FLOAT_PROP(setOrientation, roll)
- _SEND_END
- _SEND(setCoordinates, "SET_COORDINATES_TC")
- _SEND_FLOAT_PROP(setCoordinates, latitude)
- _SEND_FLOAT_PROP(setCoordinates, longitude)
- _SEND_END
- _SEND(rawEvent, "RAW_EVENT_TC")
- _SEND_UINT8_PROP(rawEvent, topic_id)
- _SEND_UINT8_PROP(rawEvent, event_id)
- _SEND_END
- _SEND(targetCoordinates, "SET_TARGET_COORDINATES_TC")
- _SEND_FLOAT_PROP(targetCoordinates, latitude)
- _SEND_FLOAT_PROP(targetCoordinates, longitude)
- _SEND_END
- _SEND(algorithm, "SET_ALGORITHM_TC")
- _SEND_UINT8_PROP(algorithm, algorithm_number)
- _SEND_END
- });
-
- QVBoxLayout *layout = new QVBoxLayout;
- layout->addLayout(form);
- layout->addWidget(stacked);
- layout->addWidget(send);
- setLayout(layout);
+ messagesListComboBox->addItems(messagesList);
+ outerLayout->addWidget(messagesListComboBox);
+
+ formGridLayout = new QGridLayout;
+ outerLayout->addLayout(formGridLayout);
+
+ QPushButton *sendButton = new QPushButton("Send");
+ outerLayout->addWidget(sendButton);
+
+ setLayout(outerLayout);
+
+ MessageFormElement *element;
+
+ element = new MessageFormElement();
+ formElements["PING_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("command_id", "Command:", commandsList);
+ formElements["COMMAND_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("tm_id", "Telemetry:", systemTmList);
+ formElements["SYSTEM_TM_REQUEST_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("sensor_id", "Sensor:", sensorsList);
+ formElements["SENSOR_TM_REQUEST_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("servo_id", "Servo:", servosList);
+ formElements["SERVO_TM_REQUEST_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("servo_id", "Servo:", servosList);
+ element->addFloat("angle", "Angle:", 0, 180, 2);
+ formElements["SET_SERVO_ANGLE_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("servo_id", "Servo:", servosList);
+ formElements["WIGGLE_SERVO_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addComboBox("servo_id", "Servo:", servosList);
+ formElements["RESET_SERVO_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("ref_altitude", "Altitude:", 0, 9999, 2);
+ formElements["SET_REFERENCE_ALTITUDE_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("ref_temp", "Temperature:", 0, 999, 2);
+ formElements["SET_REFERENCE_TEMPERATURE_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("yaw", "Yaw:", -180, 180, 2);
+ element->addFloat("pitch", "Pitch:", -180, 180, 2);
+ element->addFloat("roll", "Roll:", -180, 180, 2);
+ formElements["SET_ORIENTATION_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("latitude", "Latitude:", -90, 90, 6);
+ element->addFloat("longitude", "Longitude:", -90, 90, 6);
+ formElements["SET_COORDINATES_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addInteger("topic_id", "Topic:", 0, 999);
+ element->addInteger("event_id", "Event:", 0, 999);
+ formElements["RAW_EVENT_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("ref_altitude", "Altitude:", 0, 9999, 2);
+ formElements["SET_DEPLOYMENT_ALTITUDE_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addFloat("latitude", "Latitude:", -90, 90, 6);
+ element->addFloat("longitude", "Longitude:", -90, 90, 6);
+ formElements["SET_TARGET_COORDINATES_TC"] = element;
+
+ element = new MessageFormElement();
+ element->addInteger("algorithm_number", "Algorithm:", 0, 999);
+ formElements["SET_ALGORITHM_TC"] = element;
+
+ // Set default value
+ currentMessage = "PING_TC";
+ messagesListComboBox->setCurrentText(currentMessage);
+
+ connect(messagesListComboBox, &QComboBox::currentTextChanged, this,
+ [=](QString key)
+ {
+ if (formElements.contains(key))
+ {
+ formElements[currentMessage]->removeFromGridLayout(
+ formGridLayout);
+ formElements[key]->applyToGridLayout(formGridLayout);
+ currentMessage = key;
+ }
+ });
+
+ connect(sendButton, &QPushButton::clicked,
+ [=]()
+ {
+ auto key = messagesListComboBox->currentText();
+ if (formElements.contains(key))
+ {
+ auto message = formElements[key]->prepareMessage(key);
+ getCore()->getModuleMessagesBroker()->publish(message);
+ }
+ });
}
diff --git a/Modules/CommandPad/commandpad.h b/Modules/CommandPad/commandpad.h
index 44bb73ef8f88130789c817bd18bca72e7a1ade4c..32427b2562aab947ec5cb3a389a1afdca87e98a7 100644
--- a/Modules/CommandPad/commandpad.h
+++ b/Modules/CommandPad/commandpad.h
@@ -1,16 +1,22 @@
#ifndef COMMANDPAD_H
#define COMMANDPAD_H
+#include <tuple>
+
+#include "MessageFormElement.h"
#include "Modules/DefaultModule/defaultmodule.h"
-class CommandPad : public DefaultModule {
+class CommandPad : public DefaultModule
+{
Q_OBJECT
- public:
- static const QMap<QString, uint8_t> systemTMList;
- static const QMap<QString, uint8_t> sensorsTMList;
- static const QMap<QString, uint8_t> mavCommandList;
- static const QMap<QString, uint8_t> servosList;
+public:
+ static const QStringList messagesList;
+
+ static const QMap<QString, int> systemTmList;
+ static const QMap<QString, int> sensorsList;
+ static const QMap<QString, int> commandsList;
+ static const QMap<QString, int> servosList;
explicit CommandPad(QWidget* parent = nullptr);
~CommandPad();
@@ -20,10 +26,14 @@ class CommandPad : public DefaultModule {
XmlObject toXmlObject() override;
void fromXmlObject(const XmlObject& xmlObject) override;
- private:
+private:
+ void removeWidgetsFromForm();
void setupUi();
- QComboBox* commandComboBox;
+ QString currentMessage;
+ QComboBox* messagesListComboBox;
+ QMap<QString, MessageFormElement*> formElements;
+ QGridLayout* formGridLayout;
};
-#endif // COMMANDPAD_H
+#endif // COMMANDPAD_H
diff --git a/Modules/Splitter/splittermodule.cpp b/Modules/Splitter/splittermodule.cpp
index 7818a89c17cc264dc308d45754dad682efd4af0e..0b1d7e300c65d0755fa8e200ca9d38f64dac6df6 100644
--- a/Modules/Splitter/splittermodule.cpp
+++ b/Modules/Splitter/splittermodule.cpp
@@ -113,7 +113,7 @@ void SplitterModule::fromXmlObject(const XmlObject& xmlObject)
void SplitterModule::initialize(const XmlObject& params)
{
int orientation;
- if (params.getIntAttribute("Orientation", orientation))
+ if (params.getAttribute("Orientation", orientation))
{
if (orientation == Qt::Vertical)
{
diff --git a/Modules/ValuesConverterViewer/valueelement.cpp b/Modules/ValuesConverterViewer/valueelement.cpp
index 91a42b4b08abd1108c75c423d8bd2513c769a2f8..31d3f425927e4623da877eeebdc5d05db5d59eb1 100644
--- a/Modules/ValuesConverterViewer/valueelement.cpp
+++ b/Modules/ValuesConverterViewer/valueelement.cpp
@@ -1,22 +1,19 @@
#include "valueelement.h"
-#include <QRadioButton>
-
#include <QDebug>
+#include <QRadioButton>
-ValueElement::ValueElement() {
+ValueElement::ValueElement() {}
-}
+ValueElement::~ValueElement() {}
-ValueElement::~ValueElement() {
+ValueElement::ValueElement(const ValueElement& other) { copy(other); }
-}
-
-ValueElement::ValueElement(const ValueElement& other) {
- copy(other);
-}
-
-ValueElement::ValueElement(const QString& name, const QString& topic, const QString& receivedValue, const QString& displayedValue, const QString& color, const QString& outputTopic) {
+ValueElement::ValueElement(const QString& name, const QString& topic,
+ const QString& receivedValue,
+ const QString& displayedValue, const QString& color,
+ const QString& outputTopic)
+{
setName(name);
setTopic(topic);
setReceivedValue(receivedValue);
@@ -25,56 +22,46 @@ ValueElement::ValueElement(const QString& name, const QString& topic, const QStr
setOutputTopic(outputTopic);
}
-ValueElement ValueElement::operator=(const ValueElement& other) {
+ValueElement ValueElement::operator=(const ValueElement& other)
+{
copy(other);
return *this;
}
-QString ValueElement::getName() const {
- return name;
-}
+QString ValueElement::getName() const { return name; }
-void ValueElement::setName(const QString& value) {
- name = value;
-}
+void ValueElement::setName(const QString& value) { name = value; }
-QString ValueElement::getTopic() const {
- return topic;
-}
+QString ValueElement::getTopic() const { return topic; }
-void ValueElement::setTopic(const QString& value) {
- topic = value;
-}
+void ValueElement::setTopic(const QString& value) { topic = value; }
-QString ValueElement::getReceivedValue() const {
- return receivedValue;
-}
+QString ValueElement::getReceivedValue() const { return receivedValue; }
-void ValueElement::setReceivedValue(const QString& value) {
+void ValueElement::setReceivedValue(const QString& value)
+{
receivedValue = value;
}
-QString ValueElement::getDisplayedValue() const {
- return displayedValue;
-}
+QString ValueElement::getDisplayedValue() const { return displayedValue; }
-void ValueElement::setDisplayedValue(const QString& value) {
+void ValueElement::setDisplayedValue(const QString& value)
+{
displayedValue = value;
}
-QString ValueElement::getColor() const {
- return color;
-}
+QString ValueElement::getColor() const { return color; }
-void ValueElement::setColor(const QString& value) {
- color = value;
-}
+void ValueElement::setColor(const QString& value) { color = value; }
-QString ValueElement::toString() const {
- return getName() + ": " + getTopic() + " [" + getReceivedValue() + " = " + getDisplayedValue() + "] color=" + getColor();
+QString ValueElement::toString() const
+{
+ return getName() + ": " + getTopic() + " [" + getReceivedValue() + " = " +
+ getDisplayedValue() + "] color=" + getColor();
}
-XmlObject ValueElement::toXmlObject() const {
+XmlObject ValueElement::toXmlObject() const
+{
XmlObject obj("Rule");
obj.addAttribute("name", getName());
obj.addAttribute("topic", getTopic());
@@ -86,11 +73,14 @@ XmlObject ValueElement::toXmlObject() const {
return obj;
}
-bool ValueElement::fromXmlObject(const XmlObject& xmlObject) {
+bool ValueElement::fromXmlObject(const XmlObject& xmlObject)
+{
bool result = false;
- if(xmlObject.getObjectName() == "Rule" && xmlObject.hasAttribute("name")) {
+ if (xmlObject.getObjectName() == "Rule" && xmlObject.hasAttribute("name"))
+ {
QString name = xmlObject.getAttribute("name");
- if(name != "") {
+ if (name != "")
+ {
setName(name);
result = true;
}
@@ -102,14 +92,17 @@ bool ValueElement::fromXmlObject(const XmlObject& xmlObject) {
setOutputTopic(xmlObject.getAttribute("outputTopic"));
int display = 1;
- if(xmlObject.getIntAttribute("displayInView", display) && (display == 0 || display == 1)) {
+ if (xmlObject.getAttribute("displayInView", display) &&
+ (display == 0 || display == 1))
+ {
setDisplayInView(display);
}
}
return result;
}
-void ValueElement::copy(const ValueElement& other) {
+void ValueElement::copy(const ValueElement& other)
+{
setName(other.getName());
setTopic(other.getTopic());
setReceivedValue(other.getReceivedValue());
@@ -119,39 +112,31 @@ void ValueElement::copy(const ValueElement& other) {
setDisplayInView(other.isDisplayInView());
}
-bool ValueElement::isDisplayInView() const {
- return displayInView;
-}
+bool ValueElement::isDisplayInView() const { return displayInView; }
-void ValueElement::setDisplayInView(bool value) {
- displayInView = value;
-}
+void ValueElement::setDisplayInView(bool value) { displayInView = value; }
-QString ValueElement::getOutputTopic() const {
- return outputTopic;
-}
+QString ValueElement::getOutputTopic() const { return outputTopic; }
-void ValueElement::setOutputTopic(const QString& value) {
- outputTopic = value;
-}
+void ValueElement::setOutputTopic(const QString& value) { outputTopic = value; }
-bool ValueElement::isEmitActive() const {
- return outputTopic != "";
-}
+bool ValueElement::isEmitActive() const { return outputTopic != ""; }
-QString ValueElement::getCurrentValue() const {
- return currentValue;
-}
+QString ValueElement::getCurrentValue() const { return currentValue; }
-bool ValueElement::updateCurrentValue(const QString& value) {
- if(getReceivedValue() == "" || value == getReceivedValue()) {
- if(getDisplayedValue() != "") {
+bool ValueElement::updateCurrentValue(const QString& value)
+{
+ if (getReceivedValue() == "" || value == getReceivedValue())
+ {
+ if (getDisplayedValue() != "")
+ {
currentValue = getDisplayedValue();
- } else {
+ }
+ else
+ {
currentValue = value;
}
return true;
}
return false;
}
-
diff --git a/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp b/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
index 8adf3113eb150c68806b4b4061f5de5fcb912d70..21c6361ead1e1ea8ebc63b677f047a3debdbf504 100644
--- a/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
+++ b/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
@@ -1,53 +1,59 @@
#include "valuesconverterviewermodule.h"
-#include "ui_valuesconverterviewermodule.h"
-#include "valuesviewerconfigpanel.h"
-#include "Core/modulemessagesbroker.h"
#include "Core/Message/topicandfieldfilter.h"
+#include "Core/modulemessagesbroker.h"
+#include "ui_valuesconverterviewermodule.h"
+#include "valuesviewerconfigpanel.h"
-ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent) : DefaultModule(parent), ui(new Ui::ValuesConverterViewerModule) {
+ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent)
+ : DefaultModule(parent), ui(new Ui::ValuesConverterViewerModule)
+{
ui->setupUi(this);
defaultContextMenuSetup();
- getCore()->getModuleMessagesBroker()->subscribe({"*"}, this, [this](const ModuleMessage & msg) {
- onMsgReceived(msg);
- });
+ getCore()->getModuleMessagesBroker()->subscribe(
+ {"*"}, this, [this](const ModuleMessage& msg) { onMsgReceived(msg); });
}
-ValuesConverterViewerModule::~ValuesConverterViewerModule() {
+ValuesConverterViewerModule::~ValuesConverterViewerModule()
+{
clearLabels();
getCore()->getModuleMessagesBroker()->unsubscribe({"*"}, this);
delete ui;
}
+QWidget* ValuesConverterViewerModule::toWidget() { return this; }
-QWidget* ValuesConverterViewerModule::toWidget() {
- return this;
-}
-
-XmlObject ValuesConverterViewerModule::toXmlObject() {
+XmlObject ValuesConverterViewerModule::toXmlObject()
+{
XmlObject obj(getName(ModuleId::VALUESCONVERTERVIEWER));
obj.addAttribute("Columns", QString::number(columns));
- for(int i = 0; i < rules.count(); i++) {
+ for (int i = 0; i < rules.count(); i++)
+ {
obj.addChild(rules[i].toXmlObject());
}
return obj;
}
-void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject) {
- if(xmlObject.getObjectName() == getName(ModuleId::VALUESCONVERTERVIEWER)) {
+void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject)
+{
+ if (xmlObject.getObjectName() == getName(ModuleId::VALUESCONVERTERVIEWER))
+ {
int col;
- if(xmlObject.getIntAttribute("Columns", col)) {
+ if (xmlObject.getAttribute("Columns", col))
+ {
columns = col;
}
- for(int i = 0; i < xmlObject.childCount(); i++) {
+ for (int i = 0; i < xmlObject.childCount(); i++)
+ {
XmlObject child = xmlObject.childAt(i);
ValueElement el;
- if(el.fromXmlObject(child)) {
+ if (el.fromXmlObject(child))
+ {
addRule(el);
}
}
@@ -55,101 +61,129 @@ void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject) {
}
}
-void ValuesConverterViewerModule::onConfigureClicked() {
+void ValuesConverterViewerModule::onConfigureClicked()
+{
ValuesViewerConfigPanel* sPanel = new ValuesViewerConfigPanel();
sPanel->setRules(rules);
sPanel->setColumnsCount(columns);
- connect(sPanel, &ValuesViewerConfigPanel::configurationSaved, this, &ValuesConverterViewerModule::onConfigurationSaved);
+ connect(sPanel, &ValuesViewerConfigPanel::configurationSaved, this,
+ &ValuesConverterViewerModule::onConfigurationSaved);
sPanel->show();
}
-void ValuesConverterViewerModule::onConfigurationSaved(ValuesViewerConfigPanel* sPanel) {
+void ValuesConverterViewerModule::onConfigurationSaved(
+ ValuesViewerConfigPanel* sPanel)
+{
setRules(sPanel->getRules());
columns = sPanel->getColumnsCount();
createLabels();
}
-void ValuesConverterViewerModule::addCustomActionsToMenu() {
+void ValuesConverterViewerModule::addCustomActionsToMenu()
+{
QAction* configure = new QAction("Configure");
- connect(configure, &QAction::triggered, this, &ValuesConverterViewerModule::onConfigureClicked);
+ connect(configure, &QAction::triggered, this,
+ &ValuesConverterViewerModule::onConfigureClicked);
addActionToMenu(configure);
}
-QLabel* ValuesConverterViewerModule::createView(const ValueElement& el) const {
+QLabel* ValuesConverterViewerModule::createView(const ValueElement& el) const
+{
QLabel* label = new QLabel();
label->setText(el.getName());
label->setAlignment(Qt::AlignCenter);
return label;
}
-void ValuesConverterViewerModule::clearLabels() {
- while(labels.count() > 0) {
+void ValuesConverterViewerModule::clearLabels()
+{
+ while (labels.count() > 0)
+ {
QLabel* l = labels[0];
labels.removeAll(l);
delete l;
}
}
-void ValuesConverterViewerModule::createLabels() {
+void ValuesConverterViewerModule::createLabels()
+{
clearLabels();
- if(columns <= 0) {
+ if (columns <= 0)
+ {
columns = minColNumber;
}
int col = 0;
int row = 0;
- for (int i = 0; i < rules.count(); i++ ) {
+ for (int i = 0; i < rules.count(); i++)
+ {
QLabel* label;
int labelIndex = findLabelIndexByName(rules[i].getName());
- if(labelIndex >= 0 && labelIndex < labels.count()) {
+ if (labelIndex >= 0 && labelIndex < labels.count())
+ {
label = labels[labelIndex];
- } else {
+ }
+ else
+ {
label = createView(rules[i]);
- if(col == columns) {
+ if (col == columns)
+ {
col = 0;
row++;
}
- if(rules[i].isDisplayInView()) {
+ if (rules[i].isDisplayInView())
+ {
ui->mainLayout_grid->addWidget(label, row, col);
col++;
}
}
labels.append(label);
-
}
}
-void ValuesConverterViewerModule::addRule(const ValueElement& el) {
+void ValuesConverterViewerModule::addRule(const ValueElement& el)
+{
rules.append(el);
}
-void ValuesConverterViewerModule::setRules(const QList<ValueElement>& rList) {
+void ValuesConverterViewerModule::setRules(const QList<ValueElement>& rList)
+{
clearRules();
- for (int i = 0; i < rList.count(); i++ ) {
+ for (int i = 0; i < rList.count(); i++)
+ {
addRule(rList[i]);
}
}
-void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg) {
+void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg)
+{
MessageField value;
- for (int i = 0; i < rules.count(); i++ ) {
- if(TopicAndFieldFilter::fromStringUnsafe(rules[i].getTopic()).matchMessage(msg, value)) {
- if(rules[i].updateCurrentValue(value.getString())) {
+ for (int i = 0; i < rules.count(); i++)
+ {
+ if (TopicAndFieldFilter::fromStringUnsafe(rules[i].getTopic())
+ .matchMessage(msg, value))
+ {
+ if (rules[i].updateCurrentValue(value.getString()))
+ {
QTime time(0, 0, 0, 0);
uint64_t ms = msg.getField("timestamp").getUInteger(0);
- time = time.addMSecs(ms);
+ time = time.addMSecs(ms);
QString str = "(" + time.toString("HH:mm:ss") + ")\n";
- labels[i]->setText(rules[i].getName() + "\n" + str + rules[i].getCurrentValue());
- if(rules[i].getColor() != "") {
- labels[i]->setStyleSheet("color:" + rules[i].getColor() + ";");
+ labels[i]->setText(rules[i].getName() + "\n" + str +
+ rules[i].getCurrentValue());
+ if (rules[i].getColor() != "")
+ {
+ labels[i]->setStyleSheet("color:" + rules[i].getColor() +
+ ";");
}
- if(rules[i].isEmitActive()) {
+ if (rules[i].isEmitActive())
+ {
ModuleMessage convertedMsg(msg);
convertedMsg.setField("value", rules[i].getCurrentValue());
convertedMsg.setTopic(rules[i].getOutputTopic());
@@ -160,27 +194,37 @@ void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg) {
}
}
-void ValuesConverterViewerModule::clearRules() {
- for (int i = 0; i < rules.count(); i++ ) {
- if(rules[i].getTopic() != "") {
- getCore()->getModuleMessagesBroker()->unsubscribe(rules[i].getTopic(), this);
+void ValuesConverterViewerModule::clearRules()
+{
+ for (int i = 0; i < rules.count(); i++)
+ {
+ if (rules[i].getTopic() != "")
+ {
+ getCore()->getModuleMessagesBroker()->unsubscribe(
+ rules[i].getTopic(), this);
}
}
rules.clear();
}
-int ValuesConverterViewerModule::findLabelIndexByName(const QString& name) {
- for (int i = 0; i < labels.count(); i++ ) {
- if(labels[i]->text() == name) {
+int ValuesConverterViewerModule::findLabelIndexByName(const QString& name)
+{
+ for (int i = 0; i < labels.count(); i++)
+ {
+ if (labels[i]->text() == name)
+ {
return i;
}
}
return -1;
}
-bool ValuesConverterViewerModule::isTopicPresent(const QString& topic) {
- for (int i = 0; i < rules.count(); i++ ) {
- if(rules[i].getTopic() == topic) {
+bool ValuesConverterViewerModule::isTopicPresent(const QString& topic)
+{
+ for (int i = 0; i < rules.count(); i++)
+ {
+ if (rules[i].getTopic() == topic)
+ {
return true;
}
}
diff --git a/Modules/skywardhubstrings.h b/Modules/skywardhubstrings.h
index d4270ebe3cfa52e1ede46f49daccdebe0592e309..6c8739ebd3d0dc814d7042bad3c4f24c1dba1f81 100644
--- a/Modules/skywardhubstrings.h
+++ b/Modules/skywardhubstrings.h
@@ -6,14 +6,19 @@
namespace SkywardHubStrings
{
-static const QString defaultConfigurationFolder = "SkywardHubConfig";
-static const QString defaultSettingsFilePath = defaultConfigurationFolder + "/" + "settings.xml";
-static const QString defaultPrefabsFolderName = "Prefabs";
-static const QString defaultLogsFolder = defaultConfigurationFolder + "/" + "Logs";
-static const QString defaultStreamFile = defaultConfigurationFolder + "/" + "StreamFile.txt";
-static const QString defaultPrefabsFolder = defaultConfigurationFolder + "/" + defaultPrefabsFolderName + "/";
+static const QString defaultConfigurationFolder = "SkywardHubConfig";
+static const QString defaultSettingsFilePath =
+ defaultConfigurationFolder + "/" + "settings.xml";
+static const QString defaultPrefabsFolderName = "Prefabs";
+static const QString defaultLogsFolder =
+ defaultConfigurationFolder + "/" + "Logs";
+static const QString defaultStreamFile =
+ defaultConfigurationFolder + "/" + "StreamFile.txt";
+static const QString defaultPrefabsFolder =
+ defaultConfigurationFolder + "/" + defaultPrefabsFolderName + "/";
static const QString defaultConfigurationFileName = "default.xml";
-static const QString defaultConfigurationIconPath = defaultConfigurationFolder + "/" + "defaultConfigIcon.svg";
+static const QString defaultConfigurationIconPath =
+ defaultConfigurationFolder + "/" + "defaultConfigIcon.svg";
// Xml Tags Name
static const QString skywardHubInitFileTag = "LoadOnLaunch";
@@ -25,26 +30,31 @@ static const QString configurationDescriptionAttribute = "Description";
// Output Messages
static const QString settingsSavedCorrectlyMsg = "Settings saved";
-static const QString serialPortClosedErrorMsg = "Mavlink >> Error, Serial port closed, impossible to write msg";
-static const QString imageViewerInfo = "Double click on a label to open the settings panel";
+static const QString serialPortClosedErrorMsg =
+ "Mavlink >> Error, Serial port closed, impossible to write msg";
+static const QString imageViewerInfo =
+ "Double click on a label to open the settings panel";
// Topics
static const QString commandsTopic = "TelemetryCommand";
static const QString treeViewerReceivingBaseTopic = "TreeViewer";
-static const QString logCommandsTopic = "LogCommands";
-static const QString raw_event_id = "event_id";
-static const QString raw_event_topic_id = "topic_id";
-static const QString mavlink_orientation_tc_yaw_name = "yaw";
-static const QString mavlink_orientation_tc_pitch_name = "pitch";
-static const QString mavlink_orientation_tc_roll_name = "roll";
-static const QString mavlink_quality_link_topic = "MavlinkLinkQuality";
-static const QString mavlink_received_msg_topic = "Mav";
-static const QString mavlink_initial_coordinates_tc_latitude_name = "latitude";
-static const QString mavlink_initial_coordinates_tc_longitude_name = "longitude";
-
-static const QString mavlink_received_msg_ACK_topic = mavlink_received_msg_topic + "/ACK_TM";
-static const QString mavlink_received_msg_NACK_topic = mavlink_received_msg_topic + "/NACK_TM";
+static const QString logCommandsTopic = "LogCommands";
+static const QString raw_event_id = "event_id";
+static const QString raw_event_topic_id = "topic_id";
+static const QString mavlink_orientation_tc_yaw_name = "yaw";
+static const QString mavlink_orientation_tc_pitch_name = "pitch";
+static const QString mavlink_orientation_tc_roll_name = "roll";
+static const QString mavlink_quality_link_topic = "MavlinkLinkQuality";
+static const QString mavlink_received_msg_topic = "Mav";
+static const QString mavlink_initial_coordinates_tc_latitude_name = "latitude";
+static const QString mavlink_initial_coordinates_tc_longitude_name =
+ "longitude";
+
+static const QString mavlink_received_msg_ACK_topic =
+ mavlink_received_msg_topic + "/ACK_TM";
+static const QString mavlink_received_msg_NACK_topic =
+ mavlink_received_msg_topic + "/NACK_TM";
}; // namespace SkywardHubStrings
diff --git a/SkywardHub.pro b/SkywardHub.pro
index 40c31260621626001c693ee0ce75fe98dfa1aa74..bd2e71e719ca89dc814b4eb93b197b42ecff0079 100644
--- a/SkywardHub.pro
+++ b/SkywardHub.pro
@@ -31,6 +31,7 @@ SOURCES += \
Core/skywardhubcore.cpp \
Core/xmlobject.cpp \
Modules/CommandPad/commandpad.cpp \
+ Modules/CommandPad/MessageFormElement.cpp \
Modules/DefaultModule/defaultmodule.cpp \
Modules/Empty/emptymodule.cpp \
Modules/FileStream/filestreammodule.cpp \
@@ -84,6 +85,7 @@ HEADERS += \
Core/skywardhubcore.h \
Core/xmlobject.h \
Modules/CommandPad/commandpad.h \
+ Modules/CommandPad/MessageFormElement.h \
Modules/DefaultModule/defaultmodule.h \
Modules/Empty/emptymodule.h \
Modules/FileStream/filestreammodule.h \