AppSettings.cc 10.8 KB
Newer Older
1 2
/****************************************************************************
 *
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9 10
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "AppSettings.h"
11 12
#include "QGCPalette.h"
#include "QGCApplication.h"
13
#include "ParameterManager.h"
14 15

#include <QQmlEngine>
Don Gagne's avatar
Don Gagne committed
16
#include <QtQml>
17
#include <QStandardPaths>
18

19
const char* AppSettings::parameterFileExtension =   "params";
20
const char* AppSettings::planFileExtension =        "plan";
21
const char* AppSettings::missionFileExtension =     "mission";
22
const char* AppSettings::waypointsFileExtension =   "waypoints";
23 24 25
const char* AppSettings::fenceFileExtension =       "fence";
const char* AppSettings::rallyPointFileExtension =  "rally";
const char* AppSettings::telemetryFileExtension =   "tlog";
26
const char* AppSettings::kmlFileExtension =         "kml";
27
const char* AppSettings::shpFileExtension =         "shp";
28
const char* AppSettings::logFileExtension =         "ulg";
29

30 31 32 33 34 35 36
const char* AppSettings::parameterDirectory =       QT_TRANSLATE_NOOP("AppSettings", "Parameters");
const char* AppSettings::telemetryDirectory =       QT_TRANSLATE_NOOP("AppSettings", "Telemetry");
const char* AppSettings::missionDirectory =         QT_TRANSLATE_NOOP("AppSettings", "Missions");
const char* AppSettings::logDirectory =             QT_TRANSLATE_NOOP("AppSettings", "Logs");
const char* AppSettings::videoDirectory =           QT_TRANSLATE_NOOP("AppSettings", "Video");
const char* AppSettings::photoDirectory =           QT_TRANSLATE_NOOP("AppSettings", "Photo");
const char* AppSettings::crashDirectory =           QT_TRANSLATE_NOOP("AppSettings", "CrashLogs");
37

38
DECLARE_SETTINGGROUP(App, "")
39
{
40
    qmlRegisterUncreatableType<AppSettings>("QGroundControl.SettingsManager", 1, 0, "AppSettings", "Reference only");
Don Gagne's avatar
Don Gagne committed
41
    QGCPalette::setGlobalTheme(indoorPalette()->rawValue().toBool() ? QGCPalette::Dark : QGCPalette::Light);
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    QSettings settings;

    // These two "type" keys were changed to "class" values
    static const char* deprecatedFirmwareTypeKey    = "offlineEditingFirmwareType";
    static const char* deprecatedVehicleTypeKey     = "offlineEditingVehicleType";
    if (settings.contains(deprecatedFirmwareTypeKey)) {
        settings.setValue(deprecatedFirmwareTypeKey, QGCMAVLink::firmwareClass(static_cast<MAV_AUTOPILOT>(settings.value(deprecatedFirmwareTypeKey).toInt())));
    }
    if (settings.contains(deprecatedVehicleTypeKey)) {
        settings.setValue(deprecatedVehicleTypeKey, QGCMAVLink::vehicleClass(static_cast<MAV_TYPE>(settings.value(deprecatedVehicleTypeKey).toInt())));
    }

    QStringList deprecatedKeyNames  = { "virtualJoystickCentralized",           "offlineEditingFirmwareType",   "offlineEditingVehicleType" };
    QStringList newKeyNames         = { "virtualJoystickAutoCenterThrottle",    "offlineEditingFirmwareClass",  "offlineEditingVehicleClass" };
    settings.beginGroup(_settingsGroup);
    for (int i=0; i<deprecatedKeyNames.count(); i++) {
        if (settings.contains(deprecatedKeyNames[i])) {
            settings.setValue(newKeyNames[i], settings.value(deprecatedKeyNames[i]));
            settings.remove(deprecatedKeyNames[i]);
        }
    }

65 66
    // Instantiate savePath so we can check for override and setup default path if needed

DonLakeFlyer's avatar
DonLakeFlyer committed
67
    SettingsFact* savePathFact = qobject_cast<SettingsFact*>(savePath());
68 69
    QString appName = qgcApp()->applicationName();
#ifdef __mobile__
70 71
    // Mobile builds always use the runtime generated location for savePath.
    bool userHasModifiedSavePath = false;
DonLakeFlyer's avatar
DonLakeFlyer committed
72
#else
73
    bool userHasModifiedSavePath = !savePathFact->rawValue().toString().isEmpty() || !_nameToMetaDataMap[savePathName]->rawDefaultValue().toString().isEmpty();
DonLakeFlyer's avatar
DonLakeFlyer committed
74
#endif
75 76 77 78 79 80 81 82 83 84 85

    if (!userHasModifiedSavePath) {
#ifdef __mobile__
    #ifdef __ios__
        // This will expose the directories directly to the File iOs app
        QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
        savePathFact->setRawValue(rootDir.absolutePath());
    #else
        QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
        savePathFact->setRawValue(rootDir.filePath(appName));
    #endif
86 87 88 89
        savePathFact->setVisible(false);
#else
        QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
        savePathFact->setRawValue(rootDir.filePath(appName));
90
#endif
91 92 93 94
    }

    connect(savePathFact, &Fact::rawValueChanged, this, &AppSettings::savePathsChanged);
    connect(savePathFact, &Fact::rawValueChanged, this, &AppSettings::_checkSavePathDirectories);
95

96
    _checkSavePathDirectories();
97 98 99
    //-- Keep track of language changes
    SettingsFact* languageFact = qobject_cast<SettingsFact*>(language());
    connect(languageFact, &Fact::rawValueChanged, this, &AppSettings::_languageChanged);
100 101
}

102 103
DECLARE_SETTINGSFACT(AppSettings, offlineEditingFirmwareClass)
DECLARE_SETTINGSFACT(AppSettings, offlineEditingVehicleClass)
104 105 106 107 108 109 110 111 112
DECLARE_SETTINGSFACT(AppSettings, offlineEditingCruiseSpeed)
DECLARE_SETTINGSFACT(AppSettings, offlineEditingHoverSpeed)
DECLARE_SETTINGSFACT(AppSettings, offlineEditingAscentSpeed)
DECLARE_SETTINGSFACT(AppSettings, offlineEditingDescentSpeed)
DECLARE_SETTINGSFACT(AppSettings, batteryPercentRemainingAnnounce)
DECLARE_SETTINGSFACT(AppSettings, defaultMissionItemAltitude)
DECLARE_SETTINGSFACT(AppSettings, telemetrySave)
DECLARE_SETTINGSFACT(AppSettings, telemetrySaveNotArmed)
DECLARE_SETTINGSFACT(AppSettings, audioMuted)
113
DECLARE_SETTINGSFACT(AppSettings, checkInternet)
114
DECLARE_SETTINGSFACT(AppSettings, virtualJoystick)
115
DECLARE_SETTINGSFACT(AppSettings, virtualJoystickAutoCenterThrottle)
116 117 118 119
DECLARE_SETTINGSFACT(AppSettings, appFontPointSize)
DECLARE_SETTINGSFACT(AppSettings, showLargeCompass)
DECLARE_SETTINGSFACT(AppSettings, savePath)
DECLARE_SETTINGSFACT(AppSettings, useChecklist)
120
DECLARE_SETTINGSFACT(AppSettings, enforceChecklist)
121
DECLARE_SETTINGSFACT(AppSettings, mapboxToken)
122 123
DECLARE_SETTINGSFACT(AppSettings, mapboxAccount)
DECLARE_SETTINGSFACT(AppSettings, mapboxStyle)
124 125 126 127
DECLARE_SETTINGSFACT(AppSettings, esriToken)
DECLARE_SETTINGSFACT(AppSettings, defaultFirmwareType)
DECLARE_SETTINGSFACT(AppSettings, gstDebugLevel)
DECLARE_SETTINGSFACT(AppSettings, followTarget)
128
DECLARE_SETTINGSFACT(AppSettings, apmStartMavlinkStreams)
129 130
DECLARE_SETTINGSFACT(AppSettings, enableTaisync)
DECLARE_SETTINGSFACT(AppSettings, enableTaisyncVideo)
131 132 133 134 135 136 137 138
DECLARE_SETTINGSFACT(AppSettings, enableMicrohard)
DECLARE_SETTINGSFACT(AppSettings, language)
DECLARE_SETTINGSFACT(AppSettings, disableAllPersistence)
DECLARE_SETTINGSFACT(AppSettings, usePairing)
DECLARE_SETTINGSFACT(AppSettings, saveCsvTelemetry)
DECLARE_SETTINGSFACT(AppSettings, firstRunPromptIdsShown)
DECLARE_SETTINGSFACT(AppSettings, forwardMavlink)
DECLARE_SETTINGSFACT(AppSettings, forwardMavlinkHostName)
139 140 141 142 143 144 145 146 147 148

DECLARE_SETTINGSFACT_NO_FUNC(AppSettings, indoorPalette)
{
    if (!_indoorPaletteFact) {
        _indoorPaletteFact = _createSettingsFact(indoorPaletteName);
        connect(_indoorPaletteFact, &Fact::rawValueChanged, this, &AppSettings::_indoorPaletteChanged);
    }
    return _indoorPaletteFact;
}

149 150 151 152 153
void AppSettings::_languageChanged()
{
    qgcApp()->setLanguage();
}

154 155 156 157 158 159 160 161 162 163
void AppSettings::_checkSavePathDirectories(void)
{
    QDir savePathDir(savePath()->rawValue().toString());
    if (!savePathDir.exists()) {
        QDir().mkpath(savePathDir.absolutePath());
    }
    if (savePathDir.exists()) {
        savePathDir.mkdir(parameterDirectory);
        savePathDir.mkdir(telemetryDirectory);
        savePathDir.mkdir(missionDirectory);
164
        savePathDir.mkdir(logDirectory);
165
        savePathDir.mkdir(videoDirectory);
166
        savePathDir.mkdir(photoDirectory);
167
        savePathDir.mkdir(crashDirectory);
168
    }
169 170
}

171 172
void AppSettings::_indoorPaletteChanged(void)
{
Don Gagne's avatar
Don Gagne committed
173
    QGCPalette::setGlobalTheme(indoorPalette()->rawValue().toBool() ? QGCPalette::Dark : QGCPalette::Light);
174
}
175

176 177 178 179 180 181 182
QString AppSettings::missionSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(missionDirectory);
    }
183
    return QString();
184 185 186 187 188 189 190 191 192
}

QString AppSettings::parameterSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(parameterDirectory);
    }
193
    return QString();
194 195 196 197 198 199 200 201 202
}

QString AppSettings::telemetrySavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(telemetryDirectory);
    }
203
    return QString();
204 205
}

206 207 208 209 210 211 212
QString AppSettings::logSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(logDirectory);
    }
213
    return QString();
214 215
}

216 217 218 219 220 221 222
QString AppSettings::videoSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(videoDirectory);
    }
223 224 225
    return QString();
}

226 227 228 229 230 231 232 233 234 235
QString AppSettings::photoSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(photoDirectory);
    }
    return QString();
}

236 237 238 239 240 241 242 243
QString AppSettings::crashSavePath(void)
{
    QString path = savePath()->rawValue().toString();
    if (!path.isEmpty() && QDir(path).exists()) {
        QDir dir(path);
        return dir.filePath(crashDirectory);
    }
    return QString();
244 245
}

246
QList<int> AppSettings::firstRunPromptsIdsVariantToList(const QVariant& firstRunPromptIds)
247
{
248 249 250 251 252 253 254 255 256 257
    QList<int> rgIds;

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    QStringList strIdList = firstRunPromptIds.toString().split(",", QString::SkipEmptyParts);
#else
    QStringList strIdList = firstRunPromptIds.toString().split(",", Qt::SkipEmptyParts);
#endif

    for (const QString& strId: strIdList) {
        rgIds.append(strId.toInt());
258
    }
259
    return rgIds;
260 261
}

262
QVariant AppSettings::firstRunPromptsIdsListToVariant(const QList<int>& rgIds)
263
{
264 265 266
    QStringList strList;
    for (int id: rgIds) {
        strList.append(QString::number(id));
267
    }
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    return QVariant(strList.join(","));
}

void AppSettings::firstRunPromptIdsMarkIdAsShown(int id)
{
    QList<int> rgIds = firstRunPromptsIdsVariantToList(firstRunPromptIdsShown()->rawValue());
    if (!rgIds.contains(id)) {
        rgIds.append(id);
        firstRunPromptIdsShown()->setRawValue(firstRunPromptsIdsListToVariant(rgIds));
    }
}

int AppSettings::_languageID(void)
{
    // Hack to provide language settings as early in the boot process as possible. Must be know
    // prior to loading any json files.
    QSettings settings;
    return settings.value("language", 0).toInt();
286
}