File indexing completed on 2024-04-28 15:39:08
0001 // SPDX-FileCopyrightText: 2020-2022 Tobias Leupold <tl at stonemx dot de> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 // Local includes 0006 #include "Settings.h" 0007 0008 // KDE includes 0009 #include <KConfigGroup> 0010 0011 // Qt includes 0012 #include <QDebug> 0013 #include <QJsonArray> 0014 #include <QJsonObject> 0015 #include <QJsonDocument> 0016 0017 // Main 0018 static const QLatin1String s_main("main"); 0019 static const QLatin1String s_windowState("windowState"); 0020 static const QLatin1String s_lastOpenPath("lastOpenPath"); 0021 static const QLatin1String s_splitImagesList("splitImagesList"); 0022 0023 // Map 0024 static const QLatin1String s_map("map"); 0025 static const QLatin1String s_showCrosshairs("showCrosshairs"); 0026 static const QLatin1String s_centerLon("centerLon"); 0027 static const QLatin1String s_centerLat("centerLat"); 0028 static const QLatin1String s_zoom("zoom"); 0029 0030 // Floaters visibility 0031 static const QLatin1String s_floatersVisibility("floatersVisibility"); 0032 0033 // Tracks 0034 static const QLatin1String s_track("tracks"); 0035 static const QLatin1String s_color("color"); 0036 static const QLatin1String s_width("width"); 0037 static const QLatin1String s_style("style"); 0038 static const QVector<Qt::PenStyle> s_trackStyleEnum { 0039 Qt::SolidLine, 0040 Qt::DashLine, 0041 Qt::DotLine, 0042 Qt::DashDotLine, 0043 Qt::DashDotDotLine 0044 }; 0045 static const QVector<QString> s_trackStyleString { 0046 QStringLiteral("solid"), 0047 QStringLiteral("dashes"), 0048 QStringLiteral("dots"), 0049 QStringLiteral("dash_dot"), 0050 QStringLiteral("dash_dot_dot") 0051 }; 0052 0053 // Images 0054 static const QLatin1String s_images("images"); 0055 static const QLatin1String s_thumnailSize("thumbnailSize"); 0056 static const QLatin1String s_previewSize("previewSize"); 0057 0058 // Assignment 0059 0060 static const QLatin1String s_assignment("assignment"); 0061 0062 static const QLatin1String s_exactMatchTolerance("exactMatchTolerance"); 0063 static const QLatin1String s_maximumInterpolationInterval("maximumInterpolationInterval"); 0064 static const QLatin1String s_maximumInterpolationDistance("maximumInterpolationDistance"); 0065 static const QLatin1String s_excludeManuallyTaggedWhenReassigning( 0066 "excludeManuallyTaggedWhenReassigning"); 0067 0068 static const QLatin1String s_defaultMatchingMode("defaultMatchingMode"); 0069 static const QVector<KGeoTag::SearchType> s_defaultMatchingModeEnum { 0070 KGeoTag::CombinedMatchSearch, 0071 KGeoTag::ExactMatchSearch, 0072 KGeoTag::InterpolatedMatchSearch 0073 }; 0074 static const QVector<QString> s_defaultMatchingModeString { 0075 QStringLiteral("combinedSearch"), 0076 QStringLiteral("exactSearch"), 0077 QStringLiteral("interpolatedSearch") 0078 }; 0079 static const QString &s_defaultMatchingModePreset = s_defaultMatchingModeString.at(0); 0080 0081 // Elevation lookup 0082 static const QLatin1String s_elevationLookup("elevationLookup"); 0083 static const QLatin1String s_lookupElevationAutomatically("lookupElevationAutomatically"); 0084 static const QVector<QString> s_elevationDatasets = { 0085 QStringLiteral("aster30m"), 0086 QStringLiteral("etopo1"), 0087 QStringLiteral("eudem25m"), 0088 QStringLiteral("mapzen"), 0089 QStringLiteral("ned10m"), 0090 QStringLiteral("nzdem8m"), 0091 QStringLiteral("srtm30m"), 0092 QStringLiteral("srtm90m"), 0093 QStringLiteral("emod2018"), 0094 QStringLiteral("gebco2020") 0095 }; 0096 static const QString &s_defaultElevationDataset = s_elevationDatasets.at(0); 0097 static const QLatin1String s_dataset("dataset"); 0098 0099 // Saving 0100 static const QLatin1String s_saving("saving"); 0101 static const QVector<QString> s_writeModes = { 0102 QStringLiteral("WRITETOIMAGEONLY"), 0103 QStringLiteral("WRITETOSIDECARONLY"), 0104 QStringLiteral("WRITETOSIDECARANDIMAGE") 0105 }; 0106 static const QString &s_defaultWriteMode = s_writeModes.at(0); 0107 static const QLatin1String s_writeMode("writeMode"); 0108 static const QLatin1String s_allowWriteRawFiles("allowWriteRawFiles"); 0109 static const QLatin1String s_createBackups("createBackups"); 0110 0111 // Bookmarks 0112 0113 static const QLatin1String s_bookmarks("bookmarks"); 0114 static const QLatin1String s_version("version"); 0115 static const QLatin1String s_data("data"); 0116 0117 static constexpr int s_bookmarksDataVersion = 1; 0118 static const QString s_bookmarksDataLabel = QStringLiteral("label"); 0119 static const QString s_bookmarksDataLon = QStringLiteral("lon"); 0120 static const QString s_bookmarksDataLat = QStringLiteral("lat"); 0121 static const QString s_bookmarksDataAlt = QStringLiteral("alt"); 0122 0123 Settings::Settings(QObject *parent) : QObject(parent) 0124 { 0125 m_config = KSharedConfig::openConfig(); 0126 } 0127 0128 // Main 0129 0130 void Settings::saveMainWindowState(const QByteArray &data) 0131 { 0132 auto group = m_config->group(s_main); 0133 group.writeEntry(s_windowState, data); 0134 group.sync(); 0135 } 0136 0137 QByteArray Settings::mainWindowState() const 0138 { 0139 auto group = m_config->group(s_main); 0140 return group.readEntry(s_windowState, QByteArray()); 0141 } 0142 0143 void Settings::saveLastOpenPath(const QString &path) 0144 { 0145 auto group = m_config->group(s_main); 0146 group.writeEntry(s_lastOpenPath, path); 0147 group.sync(); 0148 } 0149 0150 QString Settings::lastOpenPath() const 0151 { 0152 auto group = m_config->group(s_main); 0153 return group.readEntry(s_lastOpenPath, QString()); 0154 } 0155 0156 void Settings::saveSplitImagesList(bool state) 0157 { 0158 auto group = m_config->group(s_main); 0159 group.writeEntry(s_splitImagesList, state); 0160 group.sync(); 0161 } 0162 0163 bool Settings::splitImagesList() const 0164 { 0165 auto group = m_config->group(s_main); 0166 return group.readEntry(s_splitImagesList, true); 0167 } 0168 0169 // Map 0170 0171 void Settings::saveShowCrosshairs(bool state) 0172 { 0173 auto group = m_config->group(s_map); 0174 group.writeEntry(s_showCrosshairs, state); 0175 group.sync(); 0176 } 0177 0178 bool Settings::showCrosshairs() const 0179 { 0180 auto group = m_config->group(s_map); 0181 return group.readEntry(s_showCrosshairs, true); 0182 } 0183 0184 void Settings::saveMapCenter(const Coordinates &coordinates) 0185 { 0186 auto group = m_config->group(s_map); 0187 group.writeEntry(s_centerLon, coordinates.lon()); 0188 group.writeEntry(s_centerLat, coordinates.lat()); 0189 group.sync(); 0190 } 0191 0192 Coordinates Settings::mapCenter() const 0193 { 0194 auto group = m_config->group(s_map); 0195 return Coordinates(group.readEntry(s_centerLon, 0.0), 0196 group.readEntry(s_centerLat, 0.0), 0197 0.0, 0198 true); 0199 } 0200 0201 void Settings::saveZoom(int zoom) 0202 { 0203 auto group = m_config->group(s_map); 0204 group.writeEntry(s_zoom, zoom); 0205 group.sync(); 0206 } 0207 0208 int Settings::zoom() const 0209 { 0210 auto group = m_config->group(s_map); 0211 return group.readEntry(s_zoom, 1520); 0212 } 0213 0214 // Floaters visibility 0215 0216 void Settings::saveFloatersVisibility(const QHash<QString, bool> &data) 0217 { 0218 auto group = m_config->group(s_floatersVisibility); 0219 const auto keys = data.keys(); 0220 for (const auto &key : keys) { 0221 group.writeEntry(key, data.value(key)); 0222 } 0223 group.sync(); 0224 } 0225 0226 QHash<QString, bool> Settings::floatersVisibility() 0227 { 0228 QHash<QString, bool> data; 0229 auto group = m_config->group(s_floatersVisibility); 0230 0231 const auto keys = group.keyList(); 0232 for (const auto &key : keys) { 0233 data.insert(key, group.readEntry(key, true)); 0234 } 0235 0236 return data; 0237 } 0238 0239 // Tracks 0240 0241 void Settings::saveTrackColor(const QColor &color) 0242 { 0243 auto group = m_config->group(s_track); 0244 group.writeEntry(s_color, color); 0245 group.sync(); 0246 } 0247 0248 QColor Settings::trackColor() const 0249 { 0250 auto group = m_config->group(s_track); 0251 return group.readEntry(s_color, QColor(255, 0, 255, 150)); 0252 } 0253 0254 void Settings::saveTrackStyle(Qt::PenStyle style) 0255 { 0256 auto group = m_config->group(s_track); 0257 group.writeEntry(s_style, s_trackStyleString.at(s_trackStyleEnum.indexOf(style))); 0258 group.sync(); 0259 } 0260 0261 Qt::PenStyle Settings::trackStyle() const 0262 { 0263 auto group = m_config->group(s_track); 0264 QString styleString = group.readEntry(s_style, QStringLiteral("dots")); 0265 if (s_trackStyleString.contains(styleString)) { 0266 return s_trackStyleEnum.at(s_trackStyleString.indexOf(styleString)); 0267 } else { 0268 return Qt::DotLine; 0269 } 0270 } 0271 0272 void Settings::saveTrackWidth(int width) 0273 { 0274 auto group = m_config->group(s_track); 0275 group.writeEntry(s_width, width); 0276 group.sync(); 0277 } 0278 0279 int Settings::trackWidth() const 0280 { 0281 auto group = m_config->group(s_track); 0282 return group.readEntry(s_width, 3); 0283 } 0284 0285 // Images 0286 0287 void Settings::saveThumbnailSize(int size) 0288 { 0289 auto group = m_config->group(s_images); 0290 group.writeEntry(s_thumnailSize, size); 0291 group.sync(); 0292 } 0293 0294 int Settings::thumbnailSize() const 0295 { 0296 auto group = m_config->group(s_images); 0297 return group.readEntry(s_thumnailSize, 32); 0298 } 0299 0300 void Settings::savePreviewSize(int size) 0301 { 0302 auto group = m_config->group(s_images); 0303 group.writeEntry(s_previewSize, size); 0304 group.sync(); 0305 } 0306 0307 int Settings::previewSize() const 0308 { 0309 auto group = m_config->group(s_images); 0310 return group.readEntry(s_previewSize, 400); 0311 } 0312 0313 // Assignment 0314 0315 void Settings::saveExactMatchTolerance(int seconds) 0316 { 0317 auto group = m_config->group(s_assignment); 0318 group.writeEntry(s_exactMatchTolerance, seconds); 0319 group.sync(); 0320 } 0321 0322 int Settings::exactMatchTolerance() const 0323 { 0324 auto group = m_config->group(s_assignment); 0325 return group.readEntry(s_exactMatchTolerance, 10); 0326 } 0327 0328 void Settings::saveMaximumInterpolationInterval(int seconds) 0329 { 0330 auto group = m_config->group(s_assignment); 0331 group.writeEntry(s_maximumInterpolationInterval, seconds); 0332 group.sync(); 0333 } 0334 0335 int Settings::maximumInterpolationInterval() const 0336 { 0337 auto group = m_config->group(s_assignment); 0338 return group.readEntry(s_maximumInterpolationInterval, -1); 0339 } 0340 0341 void Settings::saveMaximumInterpolationDistance(int meters) 0342 { 0343 auto group = m_config->group(s_assignment); 0344 group.writeEntry(s_maximumInterpolationDistance, meters); 0345 group.sync(); 0346 } 0347 0348 int Settings::maximumInterpolationDistance() const 0349 { 0350 auto group = m_config->group(s_assignment); 0351 return group.readEntry(s_maximumInterpolationDistance, -1); 0352 } 0353 0354 void Settings::saveExcludeManuallyTaggedWhenReassigning(bool state) 0355 { 0356 auto group = m_config->group(s_assignment); 0357 group.writeEntry(s_excludeManuallyTaggedWhenReassigning, state); 0358 group.sync(); 0359 } 0360 0361 bool Settings::excludeManuallyTaggedWhenReassigning() const 0362 { 0363 auto group = m_config->group(s_assignment); 0364 return group.readEntry(s_excludeManuallyTaggedWhenReassigning, true); 0365 } 0366 0367 // Elevation lookup 0368 0369 void Settings::saveLookupElevationAutomatically(bool state) 0370 { 0371 auto group = m_config->group(s_elevationLookup); 0372 group.writeEntry(s_lookupElevationAutomatically, state); 0373 group.sync(); 0374 } 0375 0376 bool Settings::lookupElevationAutomatically() const 0377 { 0378 auto group = m_config->group(s_elevationLookup); 0379 return group.readEntry(s_lookupElevationAutomatically, false); 0380 } 0381 0382 void Settings::saveElevationDataset(const QString &id) 0383 { 0384 auto group = m_config->group(s_elevationLookup); 0385 group.writeEntry(s_dataset, id); 0386 group.sync(); 0387 } 0388 0389 QString Settings::elevationDataset() const 0390 { 0391 auto group = m_config->group(s_elevationLookup); 0392 const auto dataset = group.readEntry(s_dataset, s_defaultElevationDataset); 0393 return s_elevationDatasets.contains(dataset) ? dataset : s_defaultElevationDataset; 0394 } 0395 0396 // Saving 0397 0398 void Settings::saveWriteMode(const QString &writeMode) 0399 { 0400 auto group = m_config->group(s_saving); 0401 group.writeEntry(s_writeMode, writeMode); 0402 group.sync(); 0403 } 0404 0405 QString Settings::writeMode() const 0406 { 0407 auto group = m_config->group(s_saving); 0408 const auto mode = group.readEntry(s_writeMode, s_defaultWriteMode); 0409 return s_writeModes.contains(mode) ? mode : s_defaultWriteMode; 0410 } 0411 0412 void Settings::saveCreateBackups(bool state) 0413 { 0414 auto group = m_config->group(s_saving); 0415 group.writeEntry(s_createBackups, state); 0416 group.sync(); 0417 } 0418 0419 bool Settings::createBackups() const 0420 { 0421 auto group = m_config->group(s_saving); 0422 return group.readEntry(s_createBackups, true); 0423 } 0424 0425 void Settings::saveAllowWriteRawFiles(bool state) 0426 { 0427 auto group = m_config->group(s_saving); 0428 group.writeEntry(s_allowWriteRawFiles, state); 0429 group.sync(); 0430 } 0431 0432 bool Settings::allowWriteRawFiles() const 0433 { 0434 auto group = m_config->group(s_saving); 0435 return group.readEntry(s_allowWriteRawFiles, false); 0436 } 0437 0438 // Bookmarks 0439 0440 void Settings::saveBookmarks(const QHash<QString, Coordinates> *bookmarks) 0441 { 0442 QJsonArray data; 0443 0444 const auto labels = bookmarks->keys(); 0445 for (const auto &label : labels) { 0446 const auto coordinates = bookmarks->value(label); 0447 data.append(QJsonObject { { s_bookmarksDataLabel, label }, 0448 { s_bookmarksDataLon, coordinates.lon() }, 0449 { s_bookmarksDataLat, coordinates.lat() }, 0450 { s_bookmarksDataAlt, coordinates.alt() } }); 0451 } 0452 0453 auto group = m_config->group(s_bookmarks); 0454 group.writeEntry(s_version, s_bookmarksDataVersion); 0455 group.writeEntry(s_data, QJsonDocument(data).toJson(QJsonDocument::Compact)); 0456 group.sync(); 0457 } 0458 0459 QHash<QString, Coordinates> Settings::bookmarks() const 0460 { 0461 auto group = m_config->group(s_bookmarks); 0462 0463 const auto version = group.readEntry(s_version, 0); 0464 if (version != s_bookmarksDataVersion) { 0465 return {}; 0466 } 0467 0468 QJsonParseError error; 0469 const auto document = QJsonDocument::fromJson(group.readEntry(s_data, QByteArray()), &error); 0470 if (error.error != QJsonParseError::NoError || ! document.isArray()) { 0471 return {}; 0472 } 0473 0474 QHash<QString, Coordinates> bookmarks; 0475 0476 const auto data = document.array(); 0477 for (const auto &entry : data) { 0478 auto entryData = entry.toObject(); 0479 const auto label = entryData.value(s_bookmarksDataLabel); 0480 const auto lon = entryData.value(s_bookmarksDataLon); 0481 const auto lat = entryData.value(s_bookmarksDataLat); 0482 const auto alt = entryData.value(s_bookmarksDataAlt); 0483 0484 if (! label.isString() || ! lon.isDouble() || ! lat.isDouble() || ! alt.isDouble()) { 0485 return {}; 0486 } 0487 0488 bookmarks.insert(label.toString(), 0489 Coordinates(lon.toDouble(), lat.toDouble(), alt.toDouble(), true)); 0490 } 0491 0492 return bookmarks; 0493 } 0494 0495 void Settings::saveDefaultMatchingMode(KGeoTag::SearchType mode) 0496 { 0497 auto group = m_config->group(s_assignment); 0498 group.writeEntry(s_defaultMatchingMode, 0499 s_defaultMatchingModeString.at(s_defaultMatchingModeEnum.indexOf(mode))); 0500 group.sync(); 0501 } 0502 0503 KGeoTag::SearchType Settings::defaultMatchingMode() const 0504 { 0505 auto group = m_config->group(s_assignment); 0506 const auto modeString = group.readEntry(s_defaultMatchingMode, s_defaultMatchingModePreset); 0507 if (s_defaultMatchingModeString.contains(modeString)) { 0508 return s_defaultMatchingModeEnum.at(s_defaultMatchingModeString.indexOf(modeString)); 0509 } else { 0510 return KGeoTag::CombinedMatchSearch; 0511 } 0512 }