32#include <QtCore/QApplicationStatic>
33#include <QtCore/QRegularExpression>
40 : QQmlPropertyMap(this, parent)
42 qCDebug(SettingsManagerLog) <<
this;
47 qCDebug(SettingsManagerLog) <<
this;
52 return _settingsManagerInstance();
91 static const QRegularExpression validAccessorRe(QStringLiteral(
"^[a-z_][A-Za-z0-9_]*$"));
92 if (!validAccessorRe.match(accessorName).hasMatch() || !group) {
93 qCWarning(SettingsManagerLog) <<
"registerCustomSettingsGroup: invalid accessor name or null group" << accessorName;
97 if (contains(accessorName)) {
98 qCWarning(SettingsManagerLog) <<
"registerCustomSettingsGroup: accessor already registered" << accessorName;
100 if (group != value(accessorName).value<QObject*>()) {
105 if (staticMetaObject.indexOfProperty(accessorName.toUtf8().constData()) != -1) {
106 qCWarning(SettingsManagerLog) <<
"registerCustomSettingsGroup: accessor collides with a built-in settings group" << accessorName;
111 group->setParent(
this);
112 insert(accessorName, QVariant::fromValue<QObject*>(group));
113 qCDebug(SettingsManagerLog) <<
"Registered custom settings group" << accessorName;
141void SettingsManager::_loadSettingsFiles()
163 if (!settingsDir.exists()) {
164 qCWarning(SettingsManagerLog) <<
"Settings directory does not exist:" << settingsDir.absolutePath();
168 QStringList settingsFiles = settingsDir.entryList(QStringList() << QString(
"*.%1").arg(_appSettings->
settingsFileExtension), QDir::Files);
169 for (
const QString &fileName : settingsFiles) {
170 QFileInfo fileInfo(settingsDir, fileName);
171 if (!fileInfo.isFile())
continue;
174 qCDebug(SettingsManagerLog) <<
"Loading settings file:" << fileInfo.absoluteFilePath();
176 QJsonDocument jsonDoc;
179 qCWarning(SettingsManagerLog) <<
"Failed to load settings file:" << fileInfo.absoluteFilePath() <<
errorString;
183 QJsonObject jsonObject = jsonDoc.object();
188 qCWarning(SettingsManagerLog) <<
"Settings file failed validation:" << fileInfo.absoluteFilePath() <<
errorString;
195 static const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
196 { kJsonGroupsObjectKey, QJsonValue::Object,
true },
199 qCWarning(SettingsManagerLog) <<
"Settings file incorrect format:" << fileInfo.absoluteFilePath() <<
errorString;
203 auto groupsObject = jsonObject[kJsonGroupsObjectKey].toObject();
204 for (
const QString &groupName : groupsObject.keys()) {
205 qCDebug(SettingsManagerLog) <<
" Loading settings group:" << groupName;
207 const QJsonValue &groupValue = groupsObject[groupName];
208 if (!groupValue.isObject()) {
209 qCWarning(SettingsManagerLog) <<
"Settings file incorrect format, group is not an object:" << fileInfo.absoluteFilePath()
214 auto groupObject = groupValue.toObject();
215 for (
const QString &settingName : groupObject.keys()) {
216 qCDebug(SettingsManagerLog) <<
" Loading settings:" << groupName << settingName;
218 if (!groupObject[settingName].isObject()) {
219 qCWarning(SettingsManagerLog) <<
"Settings file incorrect format, setting is not an object:" << fileInfo.absoluteFilePath()
220 << groupName << settingName;
225 QJsonObject metaDataObject = groupObject[settingName].toObject();
226 _settingsFileOverrides[groupName][settingName] = metaDataObject;
237 if (!settingsManager) {
238 qCWarning(SettingsManagerLog) <<
"SettingsManager instance not available";
244 const auto &groupOverrides = settingsManager->_settingsFileOverrides;
245 if (groupOverrides.contains(settingsGroup) && groupOverrides[settingsGroup].contains(metaData.
name())) {
246 QJsonObject settingOverrideJsonObject = groupOverrides[settingsGroup][metaData.
name()];
249 settingOverrideJsonObject[
"name"] = metaData.
name();
252 qCDebug(SettingsManagerLog) <<
"Applying settings file override for" << settingsGroup << metaData.
name();
256 QJsonObject factMetaDataJsonObject = settingOverrideJsonObject;
257 factMetaDataJsonObject.remove(kJsonVisibleKey);
258 factMetaDataJsonObject.remove(kJsonForceRawValueKey);
262 if (settingOverrideJsonObject.contains(kJsonForceRawValueKey) && settingOverrideJsonObject.contains(kJsonVisibleKey)) {
264 qCWarning(SettingsManagerLog) <<
"Ignoring settings file override which combines 'forceRawValue' and 'visible' keys:" << settingsGroup << metaData.
name();
265 }
else if (overrideMetaData->name() != metaData.
name()) {
268 qCWarning(SettingsManagerLog) <<
"Ignoring settings file override which failed validation:" << settingsGroup << metaData.
name();
271 for (
const QString &metaDataName : factMetaDataJsonObject.keys()) {
272 if (metaDataName == FactMetaData::_defaultValueJsonKey) {
273 qCDebug(SettingsManagerLog) <<
" Setting default to" << overrideMetaData->rawDefaultValue();
275 }
else if (metaDataName == FactMetaData::_minJsonKey) {
276 qCDebug(SettingsManagerLog) <<
" Setting min to" << overrideMetaData->rawMin();
277 metaData.
setRawMin(overrideMetaData->rawMin());
278 }
else if (metaDataName == FactMetaData::_maxJsonKey) {
279 qCDebug(SettingsManagerLog) <<
" Setting max to" << overrideMetaData->rawMax();
280 metaData.
setRawMax(overrideMetaData->rawMax());
281 }
else if (metaDataName == FactMetaData::_decimalPlacesJsonKey) {
282 qCDebug(SettingsManagerLog) <<
" Setting decimalPlaces to" << overrideMetaData->decimalPlaces();
284 }
else if (metaDataName == FactMetaData::_enumValuesJsonKey) {
285 qCDebug(SettingsManagerLog) <<
" Setting enumInfo to" << overrideMetaData->enumValues() << overrideMetaData->enumStrings();
286 metaData.
setEnumInfo(overrideMetaData->enumStrings(), overrideMetaData->enumValues());
287 }
else if (metaDataName == FactMetaData::_enumBitmaskArrayJsonKey) {
288 qCDebug(SettingsManagerLog) <<
" Setting bitmaskInfo to" << overrideMetaData->bitmaskValues() << overrideMetaData->bitmaskStrings();
289 metaData.
setBitmaskInfo(overrideMetaData->bitmaskStrings(), overrideMetaData->bitmaskValues());
290 }
else if (metaDataName == FactMetaData::_longDescriptionJsonKey) {
291 qCDebug(SettingsManagerLog) <<
" Setting longDesc to" << overrideMetaData->longDescription();
293 }
else if (metaDataName == FactMetaData::_shortDescriptionJsonKey) {
294 qCDebug(SettingsManagerLog) <<
" Setting shortDesc to" << overrideMetaData->shortDescription();
300 if (settingOverrideJsonObject.contains(kJsonForceRawValueKey)) {
301 qCDebug(SettingsManagerLog) <<
" Setting forceRawValue to" << settingOverrideJsonObject[kJsonForceRawValueKey];
302 metaData.
setRawDefaultValue(settingOverrideJsonObject[kJsonForceRawValueKey].toVariant());
305 if (settingOverrideJsonObject.contains(kJsonVisibleKey)) {
306 qCDebug(SettingsManagerLog) <<
" Setting visibility to" << settingOverrideJsonObject[kJsonVisibleKey].toBool();
307 userVisible = settingOverrideJsonObject[kJsonVisibleKey].toBool();
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Q_APPLICATION_STATIC(SettingsManager, _settingsManagerInstance)
QString settingsSavePath()
static constexpr const char * settingsFileExtension
virtual void registerCustomSettings(SettingsManager *settingsManager)
virtual void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
static QGCCorePlugin * instance()
Provides access to group of settings.
Provides access to all app settings.
AutoConnectSettings * autoConnectSettings() const
void registerCustomSettingsGroup(const QString &accessorName, SettingsGroup *group)
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.