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