61void QGeoFileTileCache::init()
63 const QString basePath = baseCacheDirectory() + QLatin1String(
"QtLocation/");
68 QDir baseDir(basePath);
69 if (baseDir.exists()) {
70 const QStringList oldCacheFiles = baseDir.entryList(QDir::Files);
71 for (
const QString& file : oldCacheFiles)
73 const QStringList oldCacheDirs = { QStringLiteral(
"osm"), QStringLiteral(
"mapbox"), QStringLiteral(
"here") };
74 for (
const QString& d : oldCacheDirs) {
75 QDir oldCacheDir(basePath + QLatin1Char(
'/') + d);
76 if (oldCacheDir.exists())
77 oldCacheDir.removeRecursively();
81 if (directory_.isEmpty()) {
82 directory_ = baseLocationCacheDirectory();
83 qWarning() <<
"Plugin uses uninitialized QGeoFileTileCache directory which was deleted during startup";
86 const bool directoryCreated = QDir::root().mkpath(directory_);
87 if (!directoryCreated)
88 qWarning() <<
"Failed to create cache directory " << directory_;
91 if (!isDiskCostSet_) {
92 if (costStrategyDisk_ == ByteSize)
93 setMaxDiskUsage(50 * 1024 * 1024);
95 setMaxDiskUsage(1000);
98 if (!isMemoryCostSet_) {
99 if (costStrategyMemory_ == ByteSize)
100 setMaxMemoryUsage(3 * 1024 * 1024);
102 setMaxMemoryUsage(100);
105 if (!isTextureCostSet_) {
106 if (costStrategyTexture_ == ByteSize)
107 setExtraTextureUsage(6 * 1024 * 1024);
109 setExtraTextureUsage(30);
115void QGeoFileTileCache::loadTiles()
118 formats << QLatin1String(
"*.*");
120 QDir dir(directory_);
121 const QStringList files = dir.entryList(formats, QDir::Files);
126 for (
int i = 1; i<=4; i++) {
127 QString filename = dir.filePath(QString::fromLatin1(
"queue") + QString::number(i));
128 QFile file(filename);
129 if (!file.open(QIODevice::ReadOnly))
131 QList<QSharedPointer<QGeoCachedTileDisk> > queue;
132 QList<QGeoTileSpec> specs;
134 while (!file.atEnd()) {
135 QByteArray line = file.readLine().trimmed();
136 QString filename = QString::fromLatin1(line.constData(), line.length());
137 if (dir.exists(filename)){
138 files.removeOne(filename);
139 QGeoTileSpec spec = filenameToTileSpec(filename);
140 if (spec.zoom() == -1)
142 QSharedPointer<QGeoCachedTileDisk> tileDisk(
new QGeoCachedTileDisk);
143 tileDisk->filename = dir.filePath(filename);
144 tileDisk->cache =
this;
145 tileDisk->spec = spec;
146 QFileInfo fi(tileDisk->filename);
148 queue.append(tileDisk);
149 if (costStrategyDisk_ == ByteSize)
150 costs.append(fi.size());
157 diskCache_.deserializeQueue(i, specs, queue, costs);
164 for (
const auto &file : files) {
165 QGeoTileSpec spec = filenameToTileSpec(file);
166 if (spec.zoom() == -1)
168 QString filename = dir.filePath(file);
169 addToDiskCache(spec, filename);
173QGeoFileTileCache::~QGeoFileTileCache()
177 QDir dir(directory_);
178 for (
int i = 1; i<=4; i++) {
179 QString filename = dir.filePath(QString::fromLatin1(
"queue") + QString::number(i));
180 QFile file(filename);
181 if (!file.open(QIODevice::WriteOnly)){
182 qWarning() <<
"Unable to write tile cache file " << filename;
185 QList<QSharedPointer<QGeoCachedTileDisk> > queue;
186 diskCache_.serializeQueue(i, queue);
187 for (
const QSharedPointer<QGeoCachedTileDisk> &tile : queue) {
192 int index = tile->filename.lastIndexOf(QLatin1Char(
'/'));
193 QByteArray filename = tile->filename.mid(index + 1).toLatin1() +
'\n';
194 file.write(filename);
282void QGeoFileTileCache::clearMapId(
const int mapId)
284 for (
const QGeoTileSpec &k : diskCache_.keys())
285 if (k.mapId() == mapId)
286 diskCache_.remove(k,
true);
287 for (
const QGeoTileSpec &k : memoryCache_.keys())
288 if (k.mapId() == mapId)
289 memoryCache_.remove(k);
290 for (
const QGeoTileSpec &k : textureCache_.keys())
291 if (k.mapId() == mapId)
292 textureCache_.remove(k);
297 QDir dir(directory_);
299 formats << QLatin1String(
"*.*");
300 const QStringList files = dir.entryList(formats, QDir::Files);
301 qWarning() <<
"Old tile data detected. Cache eviction left out "<< files.size() <<
"tiles";
302 for (
const QString &tileFileName : files) {
303 QGeoTileSpec spec = filenameToTileSpec(tileFileName);
304 if (spec.mapId() != mapId)
306 QFile::remove(dir.filePath(tileFileName));
348void QGeoFileTileCache::insert(
const QGeoTileSpec &spec,
349 const QByteArray &bytes,
350 const QString &format,
351 QAbstractGeoTileCache::CacheAreas areas)
356 if (areas & QAbstractGeoTileCache::DiskCache) {
357 QString filename = tileSpecToFilename(spec, format, directory_);
358 addToDiskCache(spec, filename, bytes);
361 if (areas & QAbstractGeoTileCache::MemoryCache) {
362 addToMemoryCache(spec, bytes, format);
366
367
370QString QGeoFileTileCache::tileSpecToFilenameDefault(
const QGeoTileSpec &spec,
const QString &format,
const QString &directory)
372 QString filename = spec.plugin();
373 filename += QLatin1String(
"-");
374 filename += QString::number(spec.mapId());
375 filename += QLatin1String(
"-");
376 filename += QString::number(spec.zoom());
377 filename += QLatin1String(
"-");
378 filename += QString::number(spec.x());
379 filename += QLatin1String(
"-");
380 filename += QString::number(spec.y());
383 if (spec.version() != -1) {
384 filename += QLatin1String(
"-");
385 filename += QString::number(spec.version());
388 filename += QLatin1String(
".");
391 QDir dir = QDir(directory);
393 return dir.filePath(filename);
396QGeoTileSpec QGeoFileTileCache::filenameToTileSpecDefault(
const QString &filename)
398 QGeoTileSpec emptySpec;
400 const QStringList parts = filename.split(QLatin1Char(
'.'));
402 if (parts.length() != 2)
405 const QString name = parts.at(0);
406 const QStringList fields = name.split(QLatin1Char(
'-'));
408 qsizetype length = fields.length();
409 if (length != 5 && length != 6)
415 for (qsizetype i = 1; i < length; ++i) {
417 int value = fields.at(i).toInt(&ok);
420 numbers.append(value);
424 if (numbers.length() < 5)
427 return QGeoTileSpec(fields.at(0),
444QSharedPointer<QGeoCachedTileDisk> QGeoFileTileCache::addToDiskCache(
const QGeoTileSpec &spec,
const QString &filename)
446 QSharedPointer<QGeoCachedTileDisk> td(
new QGeoCachedTileDisk);
448 td->filename = filename;
452 if (costStrategyDisk_ == ByteSize) {
453 QFileInfo fi(filename);
456 diskCache_.insert(spec, td, cost);
460bool QGeoFileTileCache::addToDiskCache(
const QGeoTileSpec &spec,
const QString &filename,
const QByteArray &bytes)
463 if (costStrategyDisk_ == ByteSize)
466 if (cost > diskCache_.maxCost())
469 QSaveFile file(filename);
470 if (!file.open(QIODevice::WriteOnly))
476 QSharedPointer<QGeoCachedTileDisk> td(
new QGeoCachedTileDisk);
478 td->filename = filename;
481 [[maybe_unused]]
const bool inserted = diskCache_.insert(spec, td, cost);
487void QGeoFileTileCache::addToMemoryCache(
const QGeoTileSpec &spec,
const QByteArray &bytes,
const QString &format)
489 if (isTileBogus(bytes))
492 QSharedPointer<QGeoCachedTileMemory> tm(
new QGeoCachedTileMemory);
499 if (costStrategyMemory_ == ByteSize)
501 memoryCache_.insert(spec, tm, cost);
504QSharedPointer<QGeoTileTexture> QGeoFileTileCache::addToTextureCache(
const QGeoTileSpec &spec,
const QImage &image)
506 QSharedPointer<QGeoTileTexture> tt(
new QGeoTileTexture);
511 if (costStrategyTexture_ == ByteSize)
512 cost = image.width() * image.height() * image.depth() / 8;
513 textureCache_.insert(spec, tt, cost);
518QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromMemory(
const QGeoTileSpec &spec)
520 QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec);
524 QSharedPointer<QGeoCachedTileMemory> tm = memoryCache_.object(spec);
527 if (!image.loadFromData(tm->bytes)) {
528 handleError(spec, QLatin1String(
"Problem with tile image"));
529 return QSharedPointer<QGeoTileTexture>();
531 QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);
535 return QSharedPointer<QGeoTileTexture>();
538QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromDisk(
const QGeoTileSpec &spec)
540 QSharedPointer<QGeoCachedTileDisk> td = diskCache_.object(spec);
542 const QString format = QFileInfo(td->filename).suffix();
543 QFile file(td->filename);
544 if (!file.open(QIODevice::ReadOnly)) {
545 handleError(spec,
"Cannot open file %1: %2"_L1.arg(file.fileName(), file.errorString()));
548 QByteArray bytes = file.readAll();
555 if (isTileBogus(bytes)) {
556 QSharedPointer<QGeoTileTexture> tt(
new QGeoTileTexture);
563 if (!image.loadFromData(bytes)) {
564 handleError(spec, QLatin1String(
"Problem with tile image"));
565 return QSharedPointer<QGeoTileTexture>();
569 if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied)
570 image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
572 addToMemoryCache(spec, bytes, format);
573 QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, image);
578 return QSharedPointer<QGeoTileTexture>();