QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
QGeoFileTileCacheQGC.cpp
Go to the documentation of this file.
2
3#include <QtCore/QDir>
4#include <QtCore/QLoggingCategory>
5#include <QtCore/QStandardPaths>
6
7#include "AppSettings.h"
8#include "MapsSettings.h"
9#include "QGCApplication.h"
10#include "QGCFileHelper.h"
11#include "QGCLoggingCategory.h"
12#include "QGCMapEngine.h"
13#include "QGCMapTasks.h"
14#include "QGCMapUrlEngine.h"
15#include "SettingsManager.h"
16
17QGC_LOGGING_CATEGORY(QGeoFileTileCacheQGCLog, "QtLocationPlugin.QGeoFileTileCacheQGC")
18
19QString QGeoFileTileCacheQGC::_databaseFilePath;
20QString QGeoFileTileCacheQGC::_cachePath;
21std::atomic<bool> QGeoFileTileCacheQGC::_cacheWasReset = false;
22
23QGeoFileTileCacheQGC::QGeoFileTileCacheQGC(const QVariantMap &parameters, QObject *parent)
24 : QGeoFileTileCache(baseCacheDirectory(), parent)
25{
26 qCDebug(QGeoFileTileCacheQGCLog) << this;
27
28 setCostStrategyDisk(QGeoFileTileCache::ByteSize);
29 setMaxDiskUsage(_getDefaultMaxDiskCache());
30 setCostStrategyMemory(QGeoFileTileCache::ByteSize);
31 setMaxMemoryUsage(_getMemLimit(parameters));
32 setCostStrategyTexture(QGeoFileTileCache::ByteSize);
33 setMinTextureUsage(_getDefaultMinTexture());
34 setExtraTextureUsage(_getDefaultExtraTexture() - minTextureUsage());
35
36 static std::once_flag cacheInit;
37 std::call_once(cacheInit, [this]() {
38 _initCache();
39 });
40
41 directory_ = _getCachePath(parameters);
42}
43
45{
46 if (QGeoFileTileCacheQGCLog().isDebugEnabled()) {
47 printStats();
48 }
49
50 qCDebug(QGeoFileTileCacheQGCLog) << this;
51}
52
53uint32_t QGeoFileTileCacheQGC::_getMemLimit(const QVariantMap &parameters)
54{
55 uint32_t memLimit = 0;
56 if (parameters.contains(QStringLiteral("mapping.cache.memory.size"))) {
57 bool ok = false;
58 memLimit = parameters.value(QStringLiteral("mapping.cache.memory.size")).toString().toUInt(&ok);
59 if (!ok) {
60 memLimit = 0;
61 }
62 }
63
64 if (memLimit == 0) {
65 // Value saved in MB
66 memLimit = _getMaxMemCacheSetting() * qPow(1024, 2);
67 }
68 if (memLimit == 0) {
69 memLimit = _getDefaultMaxMemLimit();
70 }
71
72 // 1MB Minimum Memory Cache Required
73 // MaxMemoryUsage is 32bit Integer, Round down to 1GB
74 memLimit = qBound(static_cast<uint32_t>(qPow(1024, 2)), memLimit, static_cast<uint32_t>(qPow(1024, 3)));
75 return memLimit;
76}
77
78quint32 QGeoFileTileCacheQGC::_getMaxMemCacheSetting()
79{
80 return SettingsManager::instance()->mapsSettings()->maxCacheMemorySize()->rawValue().toUInt();
81}
82
84{
85 return SettingsManager::instance()->mapsSettings()->maxCacheDiskSize()->rawValue().toUInt();
86}
87
88void QGeoFileTileCacheQGC::cacheTile(const QString &type, int x, int y, int z, const QByteArray &image, const QString &format, qulonglong set)
89{
90 const QString hash = UrlFactory::getTileHash(type, x, y, z);
91 cacheTile(type, hash, image, format, set);
92}
93
94void QGeoFileTileCacheQGC::cacheTile(const QString &type, const QString &hash, const QByteArray &image, const QString &format, qulonglong set)
95{
96 AppSettings *appSettings = SettingsManager::instance()->appSettings();
97 if (!appSettings->disableAllPersistence()->rawValue().toBool()) {
98 QGCCacheTile *tile = new QGCCacheTile(hash, image, format, type, set);
99 QGCSaveTileTask *task = new QGCSaveTileTask(tile);
100 if (!getQGCMapEngine()->addTask(task)) {
101 task->deleteLater();
102 }
103 }
104}
105
106QGCFetchTileTask* QGeoFileTileCacheQGC::createFetchTileTask(const QString &type, int x, int y, int z)
107{
108 const QString hash = UrlFactory::getTileHash(type, x, y, z);
109 QGCFetchTileTask *task = new QGCFetchTileTask(hash);
110 return task;
111}
112
113QString QGeoFileTileCacheQGC::_getCachePath(const QVariantMap &parameters)
114{
115 QString cacheDir;
116 if (parameters.contains(QStringLiteral("mapping.cache.directory"))) {
117 cacheDir = parameters.value(QStringLiteral("mapping.cache.directory")).toString();
118 } else {
119 cacheDir = _cachePath + QLatin1String("/providers");
121 qCWarning(QGeoFileTileCacheQGCLog) << "Could not create mapping disk cache directory:" << cacheDir;
122 cacheDir = QDir::homePath() + QStringLiteral("/.qgcmapscache/");
123 }
124 }
125
127 qCWarning(QGeoFileTileCacheQGCLog) << "Could not create mapping disk cache directory:" << cacheDir;
128 cacheDir.clear();
129 }
130
131 return cacheDir;
132}
133
134bool QGeoFileTileCacheQGC::_wipeDirectory(const QString &dirPath)
135{
136 bool result = true;
137
138 const QDir dir(dirPath);
139 if (dir.exists(dirPath)) {
140 _cacheWasReset = true;
141
142 const QFileInfoList fileList = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
143 for (const QFileInfo &info : fileList) {
144 if (info.isDir()) {
145 result = _wipeDirectory(info.absoluteFilePath());
146 } else {
147 result = QFile::remove(info.absoluteFilePath());
148 }
149
150 if (!result) {
151 return result;
152 }
153 }
154 result = dir.rmdir(dirPath);
155 }
156
157 return result;
158}
159
160void QGeoFileTileCacheQGC::_wipeOldCaches()
161{
162 const QStringList oldCaches = {"/QGCMapCache55", "/QGCMapCache100", "/QGCMapCache300"};
163 for (const QString &cache : oldCaches) {
164 QString oldCacheDir;
165 #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
166 oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
167 #else
168 oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
169 #endif
170 oldCacheDir += cache;
171 _wipeDirectory(oldCacheDir);
172 }
173}
174
175void QGeoFileTileCacheQGC::_initCache()
176{
177 _wipeOldCaches();
178
179 // QString cacheDir = QAbstractGeoTileCache::baseCacheDirectory()
180#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
181 QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
182 cacheDir += QStringLiteral("/QGCMapCache");
183#else
184 QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
185 cacheDir += QStringLiteral("/QGCMapCache");
186#endif
188 qCWarning(QGeoFileTileCacheQGCLog) << "Could not create mapping disk cache directory:" << cacheDir;
189
190 cacheDir = QDir::homePath() + QStringLiteral("/.qgcmapscache/");
192 qCWarning(QGeoFileTileCacheQGCLog) << "Could not create mapping disk cache directory:" << cacheDir;
193 cacheDir.clear();
194 }
195 }
196
197 _cachePath = cacheDir;
198 if (!_cachePath.isEmpty()) {
199 _databaseFilePath = QString(_cachePath + QStringLiteral("/qgcMapCache.db"));
200
201 qCDebug(QGeoFileTileCacheQGCLog) << "Map Cache in:" << _databaseFilePath;
202 } else {
203 qCCritical(QGeoFileTileCacheQGCLog) << "Could not find suitable map cache directory.";
204 }
205
206 if (_cacheWasReset) {
207 qgcApp()->showAppMessage(tr(
208 "The Offline Map Cache database has been upgraded. "
209 "Your old map cache sets have been reset."));
210 }
211}
#define qgcApp()
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QGCMapEngine * getQGCMapEngine()
Application Settings.
Definition AppSettings.h:9
Fact *disableAllPersistence READ disableAllPersistence CONSTANT Fact * disableAllPersistence()
Fact *maxCacheDiskSize READ maxCacheDiskSize CONSTANT Fact * maxCacheDiskSize()
Fact *maxCacheMemorySize READ maxCacheMemorySize CONSTANT Fact * maxCacheMemorySize()
static QGCFetchTileTask * createFetchTileTask(const QString &type, int x, int y, int z)
static void cacheTile(const QString &type, int x, int y, int z, const QByteArray &image, const QString &format, qulonglong set=UINT64_MAX)
static quint32 getMaxDiskCacheSetting()
static QString getTileHash(QStringView type, int x, int y, int z)
bool ensureDirectoryExists(const QString &path)