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