62void QGeoFileTileCache::init()
64 const QString basePath = baseCacheDirectory() + QLatin1String(
"QtLocation/");
69 QDir baseDir(basePath);
70 if (baseDir.exists()) {
71 const QStringList oldCacheFiles = baseDir.entryList(QDir::Files);
72 for (
const QString& file : oldCacheFiles)
74 const QStringList oldCacheDirs = { QStringLiteral(
"osm"), QStringLiteral(
"mapbox"), QStringLiteral(
"here") };
75 for (
const QString& d : oldCacheDirs) {
76 QDir oldCacheDir(basePath + QLatin1Char(
'/') + d);
77 if (oldCacheDir.exists())
78 oldCacheDir.removeRecursively();
82 if (directory_.isEmpty()) {
83 directory_ = baseLocationCacheDirectory();
84 qWarning() <<
"Plugin uses uninitialized QGeoFileTileCache directory which was deleted during startup";
87 const bool directoryCreated = QDir::root().mkpath(directory_);
88 if (!directoryCreated)
89 qWarning() <<
"Failed to create cache directory " << directory_;
92 if (!isDiskCostSet_) {
93 if (costStrategyDisk_ == ByteSize)
94 setMaxDiskUsage(50 * 1024 * 1024);
96 setMaxDiskUsage(1000);
99 if (!isMemoryCostSet_) {
100 if (costStrategyMemory_ == ByteSize)
101 setMaxMemoryUsage(3 * 1024 * 1024);
103 setMaxMemoryUsage(100);
106 if (!isTextureCostSet_) {
107 if (costStrategyTexture_ == ByteSize)
108 setExtraTextureUsage(6 * 1024 * 1024);
110 setExtraTextureUsage(30);
116void QGeoFileTileCache::loadTiles()
119 formats << QLatin1String(
"*.*");
121 QDir dir(directory_);
122 const QStringList files = dir.entryList(formats, QDir::Files);
127 for (
int i = 1; i<=4; i++) {
128 QString filename = dir.filePath(QString::fromLatin1(
"queue") + QString::number(i));
129 QFile file(filename);
130 if (!file.open(QIODevice::ReadOnly))
132 QList<QSharedPointer<QGeoCachedTileDisk> > queue;
133 QList<QGeoTileSpec> specs;
135 while (!file.atEnd()) {
136 QByteArray line = file.readLine().trimmed();
137 QString filename = QString::fromLatin1(line.constData(), line.length());
138 if (dir.exists(filename)){
139 files.removeOne(filename);
140 QGeoTileSpec spec = filenameToTileSpec(filename);
141 if (spec.zoom() == -1)
143 QSharedPointer<QGeoCachedTileDisk> tileDisk(
new QGeoCachedTileDisk);
144 tileDisk->filename = dir.filePath(filename);
145 tileDisk->cache =
this;
146 tileDisk->spec = spec;
147 QFileInfo fi(tileDisk->filename);
149 queue.append(tileDisk);
150 if (costStrategyDisk_ == ByteSize)
151 costs.append(fi.size());
158 diskCache_.deserializeQueue(i, specs, queue, costs);
165 for (
const auto &file : files) {
166 QGeoTileSpec spec = filenameToTileSpec(file);
167 if (spec.zoom() == -1)
169 QString filename = dir.filePath(file);
170 addToDiskCache(spec, filename);
174QGeoFileTileCache::~QGeoFileTileCache()
178 QDir dir(directory_);
179 for (
int i = 1; i<=4; i++) {
180 QString filename = dir.filePath(QString::fromLatin1(
"queue") + QString::number(i));
181 QFile file(filename);
182 if (!file.open(QIODevice::WriteOnly)){
183 qWarning() <<
"Unable to write tile cache file " << filename;
186 QList<QSharedPointer<QGeoCachedTileDisk> > queue;
187 diskCache_.serializeQueue(i, queue);
188 for (
const QSharedPointer<QGeoCachedTileDisk> &tile : queue) {
193 int index = tile->filename.lastIndexOf(QLatin1Char(
'/'));
194 QByteArray filename = tile->filename.mid(index + 1).toLatin1() +
'\n';
195 file.write(filename);
283void QGeoFileTileCache::clearMapId(
const int mapId)
285 for (
const QGeoTileSpec &k : diskCache_.keys())
286 if (k.mapId() == mapId)
287 diskCache_.remove(k,
true);
288 for (
const QGeoTileSpec &k : memoryCache_.keys())
289 if (k.mapId() == mapId)
290 memoryCache_.remove(k);
291 for (
const QGeoTileSpec &k : textureCache_.keys())
292 if (k.mapId() == mapId)
293 textureCache_.remove(k);
298 QDir dir(directory_);
300 formats << QLatin1String(
"*.*");
301 const QStringList files = dir.entryList(formats, QDir::Files);
302 qWarning() <<
"Old tile data detected. Cache eviction left out "<< files.size() <<
"tiles";
303 for (
const QString &tileFileName : files) {
304 QGeoTileSpec spec = filenameToTileSpec(tileFileName);
305 if (spec.mapId() != mapId)
307 QFile::remove(dir.filePath(tileFileName));
349void QGeoFileTileCache::insert(
const QGeoTileSpec &spec,
350 const QByteArray &bytes,
351 const QString &format,
352 QAbstractGeoTileCache::CacheAreas areas)
357 if (areas & QAbstractGeoTileCache::DiskCache) {
358 QString filename = tileSpecToFilename(spec, format, directory_);
359 addToDiskCache(spec, filename, bytes);
362 if (areas & QAbstractGeoTileCache::MemoryCache) {
363 addToMemoryCache(spec, bytes, format);
367
368
371QString QGeoFileTileCache::tileSpecToFilenameDefault(
const QGeoTileSpec &spec,
const QString &format,
const QString &directory)
373 QString filename = spec.plugin();
374 filename += QLatin1String(
"-");
375 filename += QString::number(spec.mapId());
376 filename += QLatin1String(
"-");
377 filename += QString::number(spec.zoom());
378 filename += QLatin1String(
"-");
379 filename += QString::number(spec.x());
380 filename += QLatin1String(
"-");
381 filename += QString::number(spec.y());
384 if (spec.version() != -1) {
385 filename += QLatin1String(
"-");
386 filename += QString::number(spec.version());
389 filename += QLatin1String(
".");
392 QDir dir = QDir(directory);
394 return dir.filePath(filename);
397QGeoTileSpec QGeoFileTileCache::filenameToTileSpecDefault(
const QString &filename)
399 QGeoTileSpec emptySpec;
401 const QStringList parts = filename.split(QLatin1Char(
'.'));
403 if (parts.length() != 2)
406 const QString name = parts.at(0);
407 const QStringList fields = name.split(QLatin1Char(
'-'));
409 qsizetype length = fields.length();
410 if (length != 5 && length != 6)
416 for (qsizetype i = 1; i < length; ++i) {
418 int value = fields.at(i).toInt(&ok);
421 numbers.append(value);
425 if (numbers.length() < 5)
428 return QGeoTileSpec(fields.at(0),
445QSharedPointer<QGeoCachedTileDisk> QGeoFileTileCache::addToDiskCache(
const QGeoTileSpec &spec,
const QString &filename)
447 QSharedPointer<QGeoCachedTileDisk> td(
new QGeoCachedTileDisk);
449 td->filename = filename;
453 if (costStrategyDisk_ == ByteSize) {
454 QFileInfo fi(filename);
457 diskCache_.insert(spec, td, cost);
461bool QGeoFileTileCache::addToDiskCache(
const QGeoTileSpec &spec,
const QString &filename,
const QByteArray &bytes)
464 if (costStrategyDisk_ == ByteSize)
467 if (cost > diskCache_.maxCost())
470 QSaveFile file(filename);
471 if (!file.open(QIODevice::WriteOnly))
477 QSharedPointer<QGeoCachedTileDisk> td(
new QGeoCachedTileDisk);
479 td->filename = filename;
482 [[maybe_unused]]
const bool inserted = diskCache_.insert(spec, td, cost);
488void QGeoFileTileCache::addToMemoryCache(
const QGeoTileSpec &spec,
const QByteArray &bytes,
const QString &format)
490 if (isTileBogus(bytes))
493 QSharedPointer<QGeoCachedTileMemory> tm(
new QGeoCachedTileMemory);
500 if (costStrategyMemory_ == ByteSize)
502 memoryCache_.insert(spec, tm, cost);
505QSharedPointer<QGeoTileTexture> QGeoFileTileCache::addToTextureCache(
const QGeoTileSpec &spec,
const QImage &image)
507 QSharedPointer<QGeoTileTexture> tt(
new QGeoTileTexture);
512 if (costStrategyTexture_ == ByteSize)
513 cost = image.width() * image.height() * image.depth() / 8;
514 textureCache_.insert(spec, tt, cost);
519QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromMemory(
const QGeoTileSpec &spec)
521 QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec);
525 QSharedPointer<QGeoCachedTileMemory> tm = memoryCache_.object(spec);
528 if (!image.loadFromData(tm->bytes)) {
529 handleError(spec, QLatin1String(
"Problem with tile image"));
530 return QSharedPointer<QGeoTileTexture>();
532 QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);
536 return QSharedPointer<QGeoTileTexture>();
539QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromDisk(
const QGeoTileSpec &spec)
541 QSharedPointer<QGeoCachedTileDisk> td = diskCache_.object(spec);
543 const QString format = QFileInfo(td->filename).suffix();
544 QFile file(td->filename);
545 if (!file.open(QIODevice::ReadOnly)) {
546 handleError(spec,
"Cannot open file %1: %2"_L1.arg(file.fileName(), file.errorString()));
549 QByteArray bytes = file.readAll();
556 if (isTileBogus(bytes)) {
557 QSharedPointer<QGeoTileTexture> tt(
new QGeoTileTexture);
564 if (!image.loadFromData(bytes)) {
565 handleError(spec, QLatin1String(
"Problem with tile image"));
566 return QSharedPointer<QGeoTileTexture>();
570 if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied)
571 image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
573 addToMemoryCache(spec, bytes, format);
574 QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, image);
579 return QSharedPointer<QGeoTileTexture>();