QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SettingsManager.cc
Go to the documentation of this file.
1#include "SettingsManager.h"
2#include "AppMessages.h"
5#ifndef QGC_NO_ARDUPILOT_DIALECT
7#endif
8#include "AppSettings.h"
13#include "FlightMapSettings.h"
14#include "FlightModeSettings.h"
15#include "FlyViewSettings.h"
17#include "MapsSettings.h"
18#include "OfflineMapsSettings.h"
19#include "PlanViewSettings.h"
20#include "RemoteIDSettings.h"
21#include "RTKSettings.h"
22#include "UnitsSettings.h"
23#include "NTRIPSettings.h"
24#include "VideoSettings.h"
25#include "MavlinkSettings.h"
27#include "Viewer3DSettings.h"
28#include "JsonParsing.h"
29#include "QGCCorePlugin.h"
30
31#include <QtCore/QApplicationStatic>
32
33QGC_LOGGING_CATEGORY(SettingsManagerLog, "Utilities.SettingsManager")
34
35Q_APPLICATION_STATIC(SettingsManager, _settingsManagerInstance);
36
38 : QObject(parent)
39{
40 qCDebug(SettingsManagerLog) << this;
41}
42
44{
45 qCDebug(SettingsManagerLog) << this;
46}
47
49{
50 return _settingsManagerInstance();
51}
52
54{
55 _unitsSettings = new UnitsSettings(this); // Must be first since AppSettings references it
56
57 _appSettings = new AppSettings(this);
58 _loadSettingsFiles();
59
60 _autoConnectSettings = new AutoConnectSettings(this);
61 _batteryIndicatorSettings = new BatteryIndicatorSettings(this);
62 _mavlinkActionsSettings = new MavlinkActionsSettings(this);
63 _firmwareUpgradeSettings = new FirmwareUpgradeSettings(this);
64 _flightMapSettings = new FlightMapSettings(this);
65 _flightModeSettings = new FlightModeSettings(this);
66 _flyViewSettings = new FlyViewSettings(this);
67 _gimbalControllerSettings = new GimbalControllerSettings(this);
68 _mapsSettings = new MapsSettings(this);
69 _offlineMapsSettings = new OfflineMapsSettings(this);
70 _planViewSettings = new PlanViewSettings(this);
71 _remoteIDSettings = new RemoteIDSettings(this);
72 _rtkSettings = new RTKSettings(this);
73 _ntripSettings = new NTRIPSettings(this);
74 _videoSettings = new VideoSettings(this);
75 _mavlinkSettings = new MavlinkSettings(this);
76 _joystickManagerSettings = new JoystickManagerSettings(this);
77 _viewer3DSettings = new Viewer3DSettings(this);
78 _adsbVehicleManagerSettings = new ADSBVehicleManagerSettings(this);
79#ifndef QGC_NO_ARDUPILOT_DIALECT
80 _apmMavlinkStreamRateSettings = new APMMavlinkStreamRateSettings(this);
81#endif
82}
83
84ADSBVehicleManagerSettings *SettingsManager::adsbVehicleManagerSettings() const { return _adsbVehicleManagerSettings; }
85#ifndef QGC_NO_ARDUPILOT_DIALECT
86APMMavlinkStreamRateSettings *SettingsManager::apmMavlinkStreamRateSettings() const { return _apmMavlinkStreamRateSettings; }
87#endif
88AppSettings *SettingsManager::appSettings() const { return _appSettings; }
89AutoConnectSettings *SettingsManager::autoConnectSettings() const { return _autoConnectSettings; }
90BatteryIndicatorSettings *SettingsManager::batteryIndicatorSettings() const { return _batteryIndicatorSettings; }
91MavlinkActionsSettings *SettingsManager::mavlinkActionsSettings() const { return _mavlinkActionsSettings; }
92FirmwareUpgradeSettings *SettingsManager::firmwareUpgradeSettings() const { return _firmwareUpgradeSettings; }
93FlightMapSettings *SettingsManager::flightMapSettings() const { return _flightMapSettings; }
94FlightModeSettings *SettingsManager::flightModeSettings() const { return _flightModeSettings; }
95FlyViewSettings *SettingsManager::flyViewSettings() const { return _flyViewSettings; }
96GimbalControllerSettings *SettingsManager::gimbalControllerSettings() const { return _gimbalControllerSettings; }
97MapsSettings *SettingsManager::mapsSettings() const { return _mapsSettings; }
98OfflineMapsSettings *SettingsManager::offlineMapsSettings() const { return _offlineMapsSettings; }
99PlanViewSettings *SettingsManager::planViewSettings() const { return _planViewSettings; }
100RemoteIDSettings *SettingsManager::remoteIDSettings() const { return _remoteIDSettings; }
101RTKSettings *SettingsManager::rtkSettings() const { return _rtkSettings; }
102UnitsSettings *SettingsManager::unitsSettings() const { return _unitsSettings; }
103NTRIPSettings *SettingsManager::ntripSettings() const { return _ntripSettings; }
104VideoSettings *SettingsManager::videoSettings() const { return _videoSettings; }
105MavlinkSettings *SettingsManager::mavlinkSettings() const { return _mavlinkSettings; }
106JoystickManagerSettings *SettingsManager::joystickManagerSettings() const { return _joystickManagerSettings; }
107Viewer3DSettings *SettingsManager::viewer3DSettings() const { return _viewer3DSettings; }
108
109void SettingsManager::_loadSettingsFiles()
110{
111 // Settings files can be found in the settingsSavePath() directory
112 // Settings files are json files which end in the settingsFileExtension extension
113 // The format for a settings file is:
114 // {
115 // "version": 1,
116 // "fileType": "Settings",
117 // "groups": {
118 // "groupName": {
119 // "settingName": {
120 // "forceRawValue": <value>, // Forces the rawValue for this setting to the specific value
121 // any FactMetaData json keys except for name and type,
122 // ...
123 // },
124 // "groupName": {
125 // ...
126 // }
127 // }
128 // }
129
130 QDir settingsDir(_appSettings->settingsSavePath());
131 if (!settingsDir.exists()) {
132 qCWarning(SettingsManagerLog) << "Settings directory does not exist:" << settingsDir.absolutePath();
133 return;
134 }
135
136 QStringList settingsFiles = settingsDir.entryList(QStringList() << QString("*.%1").arg(_appSettings->settingsFileExtension), QDir::Files);
137 for (const QString &fileName : settingsFiles) {
138 QFileInfo fileInfo(settingsDir, fileName);
139 if (!fileInfo.isFile()) continue;
140
141 // Load the settings file
142 qCDebug(SettingsManagerLog) << "Loading settings file:" << fileInfo.absoluteFilePath();
143
144 QJsonDocument jsonDoc;
145 QString errorString;
146 if (!JsonParsing::isJsonFile(fileInfo.absoluteFilePath(), jsonDoc, errorString)) {
147 qCWarning(SettingsManagerLog) << "Failed to load settings file:" << fileInfo.absoluteFilePath() << errorString;
148 continue;
149 }
150
151 QJsonObject jsonObject = jsonDoc.object();
152
153 // Validate the settings file
154 int version;
155 if (!JsonParsing::validateInternalQGCJsonFile(jsonObject, "Settings", 1, 1, version, errorString)) {
156 qCWarning(SettingsManagerLog) << "Settings file failed validation:" << fileInfo.absoluteFilePath() << errorString;
157 continue;
158 }
159
160 // Validate the remainder of the file
161
162 // groups key is an object
163 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
164 { kJsonGroupsObjectKey, QJsonValue::Object, true },
165 };
166 if (!JsonParsing::validateKeys(jsonObject, keyInfoList, errorString)) {
167 qCWarning(SettingsManagerLog) << "Settings file incorrect format:" << fileInfo.absoluteFilePath() << errorString;
168 continue;
169 }
170
171 auto groupsObject = jsonObject[kJsonGroupsObjectKey].toObject();
172 for (const QString &groupName : groupsObject.keys()) {
173 qCDebug(SettingsManagerLog) << " Loading settings group:" << groupName;
174
175 const QJsonValue &groupValue = groupsObject[groupName];
176 if (!groupValue.isObject()) {
177 qCWarning(SettingsManagerLog) << "Settings file incorrect format, group is not an object:" << fileInfo.absoluteFilePath()
178 << groupName;
179 continue;
180 }
181
182 auto groupObject = groupValue.toObject();
183 for (const QString &settingName : groupObject.keys()) {
184 qCDebug(SettingsManagerLog) << " Loading settings:" << groupName << settingName;
185
186 if (!groupObject[settingName].isObject()) {
187 qCWarning(SettingsManagerLog) << "Settings file incorrect format, setting is not an object:" << fileInfo.absoluteFilePath()
188 << groupName << settingName;
189 continue;
190 }
191
192 // Store the setting overrides. Note that last one wins if there are multiple settings files with the same setting.
193 QJsonObject metaDataObject = groupObject[settingName].toObject();
194 _settingsFileOverrides[groupName][settingName] = metaDataObject;
195 }
196 }
197 }
198}
199
200void SettingsManager::adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
201{
202 userVisible = true; // By default all settings are visible
203
204 SettingsManager *settingsManager = SettingsManager::instance();
205 if (!settingsManager) {
206 qCWarning(SettingsManagerLog) << "SettingsManager instance not available";
207 return;
208 }
209
210 if (!QGC::runningUnitTests()) {
211 // Apply settings file overrides
212 const auto &groupOverrides = settingsManager->_settingsFileOverrides;
213 if (groupOverrides.contains(settingsGroup) && groupOverrides[settingsGroup].contains(metaData.name())) {
214 QJsonObject settingOverrideJsonObject = groupOverrides[settingsGroup][metaData.name()];
215
216 // We need to stuff in name and type so settingOverrideJsonObject can parse properly
217 settingOverrideJsonObject["name"] = metaData.name();
218 settingOverrideJsonObject["type"] = FactMetaData::typeToString(metaData.type());
219
220 qCDebug(SettingsManagerLog) << "Applying settings file override for" << settingsGroup << metaData.name();
221
222 QScopedPointer<FactMetaData> overrideMetaData(FactMetaData::createFromJsonObject(settingOverrideJsonObject, {}, nullptr));
223
224 // Apply overrides
225 for (const QString &metaDataName : settingOverrideJsonObject.keys()) {
226 if (metaDataName == kJsonVisibleKey) {
227 qCDebug(SettingsManagerLog) << " Setting visibility to" << settingOverrideJsonObject[kJsonVisibleKey].toBool();
228 userVisible = settingOverrideJsonObject[kJsonVisibleKey].toBool();
229 } else if (metaDataName == kJsonForceRawValueKey) {
230 qCDebug(SettingsManagerLog) << " Setting forceRawValue to" << settingOverrideJsonObject[kJsonForceRawValueKey];
231 metaData.setRawDefaultValue(settingOverrideJsonObject[kJsonForceRawValueKey].toVariant());
232 userVisible = false;
233 } else if (metaDataName == FactMetaData::_defaultValueJsonKey) {
234 qCDebug(SettingsManagerLog) << " Setting default to" << overrideMetaData->rawDefaultValue();
235 metaData.setRawDefaultValue(overrideMetaData->rawDefaultValue());
236 } else if (metaDataName == FactMetaData::_minJsonKey) {
237 qCDebug(SettingsManagerLog) << " Setting min to" << overrideMetaData->rawMin();
238 metaData.setRawMin(overrideMetaData->rawMin());
239 } else if (metaDataName == FactMetaData::_maxJsonKey) {
240 qCDebug(SettingsManagerLog) << " Setting max to" << overrideMetaData->rawMax();
241 metaData.setRawMax(overrideMetaData->rawMax());
242 } else if (metaDataName == FactMetaData::_decimalPlacesJsonKey) {
243 qCDebug(SettingsManagerLog) << " Setting decimalPlaces to" << overrideMetaData->decimalPlaces();
244 metaData.setDecimalPlaces(overrideMetaData->decimalPlaces());
245 } else if (metaDataName == FactMetaData::_enumValuesJsonKey) {
246 qCDebug(SettingsManagerLog) << " Setting enumInfo to" << overrideMetaData->enumValues() << overrideMetaData->enumStrings();
247 metaData.setEnumInfo(overrideMetaData->enumStrings(), overrideMetaData->enumValues());
248 } else if (metaDataName == FactMetaData::_enumBitmaskArrayJsonKey) {
249 qCDebug(SettingsManagerLog) << " Setting bitmaskInfo to" << overrideMetaData->bitmaskValues() << overrideMetaData->bitmaskStrings();
250 metaData.setBitmaskInfo(overrideMetaData->bitmaskStrings(), overrideMetaData->bitmaskValues());
251 } else if (metaDataName == FactMetaData::_longDescriptionJsonKey) {
252 qCDebug(SettingsManagerLog) << " Setting longDesc to" << overrideMetaData->longDescription();
253 metaData.setLongDescription(overrideMetaData->longDescription());
254 } else if (metaDataName == FactMetaData::_shortDescriptionJsonKey) {
255 qCDebug(SettingsManagerLog) << " Setting shortDesc to" << overrideMetaData->shortDescription();
256 metaData.setShortDescription(overrideMetaData->shortDescription());
257 }
258 }
259 }
260 }
261
262 // Give QGCCorePlugin a whack at it too
263 QGCCorePlugin::instance()->adjustSettingMetaData(settingsGroup, metaData, userVisible);
264}
QString errorString
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Q_APPLICATION_STATIC(SettingsManager, _settingsManagerInstance)
Application Settings.
Definition AppSettings.h:10
QString settingsSavePath()
static constexpr const char * settingsFileExtension
Auto connect settings.
Holds the meta data associated with a Fact.
static FactMetaData * createFromJsonObject(const QJsonObject &json, const QMap< QString, QString > &defineMap, QObject *metaDataParent)
void setDecimalPlaces(int decimalPlaces)
void setShortDescription(const QString &shortDescription)
static QString typeToString(ValueType_t type)
void setLongDescription(const QString &longDescription)
void setRawMin(const QVariant &rawMin)
void setRawDefaultValue(const QVariant &rawDefaultValue)
void setEnumInfo(const QStringList &strings, const QVariantList &values)
void setBitmaskInfo(const QStringList &strings, const QVariantList &values)
void setRawMax(const QVariant &rawMax)
QString name() const
ValueType_t type() const
Application Settings.
virtual void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
static QGCCorePlugin * instance()
Provides access to all app settings.
AutoConnectSettings * autoConnectSettings() const
Viewer3DSettings * viewer3DSettings() const
JoystickManagerSettings * joystickManagerSettings() const
MapsSettings * mapsSettings() const
FlightMapSettings * flightMapSettings() const
ADSBVehicleManagerSettings * adsbVehicleManagerSettings() const
PlanViewSettings * planViewSettings() const
UnitsSettings * unitsSettings() const
RTKSettings * rtkSettings() const
BatteryIndicatorSettings * batteryIndicatorSettings() const
FirmwareUpgradeSettings * firmwareUpgradeSettings() const
FlightModeSettings * flightModeSettings() const
static SettingsManager * instance()
APMMavlinkStreamRateSettings * apmMavlinkStreamRateSettings() const
VideoSettings * videoSettings() const
static void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
AppSettings * appSettings() const
OfflineMapsSettings * offlineMapsSettings() const
RemoteIDSettings * remoteIDSettings() const
MavlinkActionsSettings * mavlinkActionsSettings() const
FlyViewSettings * flyViewSettings() const
GimbalControllerSettings * gimbalControllerSettings() const
MavlinkSettings * mavlinkSettings() const
NTRIPSettings * ntripSettings() const
bool validateInternalQGCJsonFile(const QJsonObject &jsonObject, const QString &expectedFileType, int minSupportedVersion, int maxSupportedVersion, int &version, QString &errorString)
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
bool isJsonFile(const QByteArray &bytes, QJsonDocument &jsonDoc, QString &errorString)
Determines whether an in-memory byte buffer contains parseable JSON content.
bool runningUnitTests()