QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MavlinkActionManager.cc
Go to the documentation of this file.
2#include "MavlinkAction.h"
3#include "Fact.h"
4#include "JsonHelper.h"
5#include "QGCApplication.h"
6#include "SettingsManager.h"
7#include "AppSettings.h"
10
11#include <QtCore/QDir>
12#include <QtCore/QJsonArray>
13#include <QtQml/QQmlEngine>
14
15QGC_LOGGING_CATEGORY(MavlinkActionManagerLog, "QMLControls.MavlinkActionManager")
16
18 : QObject(parent)
19 , _actions(new QmlObjectListModel(this))
20{
21 // qCDebug(MavlinkActionManagerLog) << Q_FUNC_INFO << this;
22}
23
24MavlinkActionManager::MavlinkActionManager(Fact *actionFileNameFact, QObject *parent)
25 : QObject(parent)
26 , _actions(new QmlObjectListModel(this))
27{
28 setActionFileNameFact(actionFileNameFact);
29}
30
31MavlinkActionManager::~MavlinkActionManager()
32{
33 // qCDebug(MavlinkActionManagerLog) << Q_FUNC_INFO << this;
34}
35
36void MavlinkActionManager::setActionFileNameFact(Fact *actionFileNameFact)
37{
38 _actionFileNameFact = actionFileNameFact;
40 (void) connect(_actionFileNameFact, &Fact::rawValueChanged, this, &MavlinkActionManager::_loadActionsFile);
41
42 _loadActionsFile();
43}
44
45void MavlinkActionManager::_loadActionsFile()
46{
47 _actions->clearAndDeleteContents();
48 const QString actionFileName = _actionFileNameFact->rawValue().toString();
49 if (actionFileName.isEmpty()) {
50 return;
51 }
52
53 // Custom actions are always loaded from the custom actions save path
54 const QString savePath = SettingsManager::instance()->appSettings()->mavlinkActionsSavePath();
55 const QDir saveDir = QDir(savePath);
56 const QString fullPath = saveDir.absoluteFilePath(actionFileName);
57
58 // It's ok for the file to not exist
59 const QFileInfo fileInfo = QFileInfo(fullPath);
60 if (!fileInfo.exists()) {
61 return;
62 }
63
64 constexpr const char *kQgcFileType = "MavlinkActions";
65 constexpr const char *kActionListKey = "actions";
66
67 _actions->clearAndDeleteContents();
68
69 QString errorString;
70 int version;
71 const QJsonObject jsonObject = JsonHelper::openInternalQGCJsonFile(fullPath, kQgcFileType, 1, 1, version, errorString);
72 if (!errorString.isEmpty()) {
73 qgcApp()->showAppMessage(tr("Failed to load custom actions file: `%1` error: `%2`").arg(fullPath, errorString));
74 return;
75 }
76
77 const QList<JsonHelper::KeyValidateInfo> keyInfoList = {
78 { kActionListKey, QJsonValue::Array, /* required= */ true },
79 };
80 if (!JsonHelper::validateKeys(jsonObject, keyInfoList, errorString)) {
81 qgcApp()->showAppMessage(tr("Custom actions file - incorrect format: %1").arg(errorString));
82 return;
83 }
84
85 const QJsonArray actionList = jsonObject[kActionListKey].toArray();
86 for (const auto &actionJson: actionList) {
87 if (!actionJson.isObject()) {
88 qgcApp()->showAppMessage(tr("Custom actions file - incorrect format: JsonValue not an object"));
89 _actions->clearAndDeleteContents();
90 return;
91 }
92
93 const QList<JsonHelper::KeyValidateInfo> actionKeyInfoList = {
94 { "label", QJsonValue::String, /* required= */ true },
95 { "description", QJsonValue::String, /* required= */ true },
96 { "mavCmd", QJsonValue::Double, /* required= */ true },
97
98 { "compId", QJsonValue::Double, /* required= */ false },
99 { "param1", QJsonValue::Double, /* required= */ false },
100 { "param2", QJsonValue::Double, /* required= */ false },
101 { "param3", QJsonValue::Double, /* required= */ false },
102 { "param4", QJsonValue::Double, /* required= */ false },
103 { "param5", QJsonValue::Double, /* required= */ false },
104 { "param6", QJsonValue::Double, /* required= */ false },
105 { "param7", QJsonValue::Double, /* required= */ false },
106 };
107
108 const auto actionObj = actionJson.toObject();
109 if (!JsonHelper::validateKeys(actionObj, actionKeyInfoList, errorString)) {
110 qgcApp()->showAppMessage(tr("Custom actions file - incorrect format: %1").arg(errorString));
111 _actions->clearAndDeleteContents();
112 return;
113 }
114
115 const auto label = actionObj["label"].toString();
116 const auto description = actionObj["description"].toString();
117 const auto mavCmd = (MAV_CMD)actionObj["mavCmd"].toInt();
118 const auto compId = (MAV_COMPONENT)actionObj["compId"].toInt(MAV_COMP_ID_AUTOPILOT1);
119 const auto param1 = actionObj["param1"].toDouble(0.0);
120 const auto param2 = actionObj["param2"].toDouble(0.0);
121 const auto param3 = actionObj["param3"].toDouble(0.0);
122 const auto param4 = actionObj["param4"].toDouble(0.0);
123 const auto param5 = actionObj["param5"].toDouble(0.0);
124 const auto param6 = actionObj["param6"].toDouble(0.0);
125 const auto param7 = actionObj["param7"].toDouble(0.0);
126
127 MavlinkAction *const action = new MavlinkAction(label, description, mavCmd, compId, param1, param2, param3, param4, param5, param6, param7, this);
128 QQmlEngine::setObjectOwnership(action, QQmlEngine::CppOwnership);
129 (void) _actions->append(action);
130 }
131}
#define qgcApp()
QString errorString
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QString mavlinkActionsSavePath()
A Fact is used to hold a single value within the system.
Definition Fact.h:19
void rawValueChanged(const QVariant &value)
void actionFileNameFactChanged()
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
void clearAndDeleteContents() override final
Clears the list and calls deleteLater on each entry.
QJsonObject openInternalQGCJsonFile(const QString &jsonFilename, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString)
returned error string if validation fails
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)