* add MapViewTileProviderBase - base class for tile server provider * migrate OSM to new class * add MapTiler provider * add offlineMode for MapView
164 lines
4.0 KiB
C++
164 lines
4.0 KiB
C++
#include "mapview.h"
|
|
#include "mapview_tile_cache_p.h"
|
|
#include "mapview_tile_downloader_p.h"
|
|
#include "qad_locations.h"
|
|
|
|
|
|
MapViewTileCache::MapViewTileCache(MapView * p): QThread() {
|
|
qRegisterMetaType<OSM::TileIndex>();
|
|
qRegisterMetaType<OSM::TilePixmap>();
|
|
parent = p;
|
|
setCacheRoot(QAD::userPath(QAD::ltCache, "mapview") + "/");
|
|
setAdditionalCacheSize(64);
|
|
start();
|
|
}
|
|
|
|
|
|
MapViewTileCache::~MapViewTileCache() {
|
|
requestInterruption();
|
|
cond.wakeAll();
|
|
wait();
|
|
}
|
|
|
|
|
|
void MapViewTileCache::tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap) {
|
|
auto * tile = new OSM::TilePixmap();
|
|
tile->index = index;
|
|
tile->pixmap = pixmap;
|
|
saveTile(tile);
|
|
}
|
|
|
|
|
|
OSM::TilePixmap MapViewTileCache::getTile(OSM::TileIndex index, QRectF & rect_src) {
|
|
OSM::TilePixmap ret = getTileFromCache(index);
|
|
if (ret.isEmpty() || ret.obsolete) {
|
|
if (!is_offline) parent->downloader->queueTile(index);
|
|
}
|
|
if (ret.isEmpty()) {
|
|
QVector<QPointF> offsets;
|
|
while (index.z >= 0) {
|
|
index.z--;
|
|
offsets << QPointF(index.x % 2, index.y % 2);
|
|
index.x /= 2;
|
|
index.y /= 2;
|
|
ret = getTileFromCache(index);
|
|
if (!ret.isEmpty()) {
|
|
for (int i = offsets.size() - 1; i >= 0; --i) {
|
|
rect_src.setSize(rect_src.size() / 2.);
|
|
rect_src.translate(offsets[i].x() * rect_src.width(), offsets[i].y() * rect_src.height());
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
} else
|
|
rect_src = ret.pixmap.rect();
|
|
return ret;
|
|
}
|
|
|
|
|
|
void MapViewTileCache::clearCache() {
|
|
tile_cache.clear();
|
|
}
|
|
|
|
|
|
bool MapViewTileCache::isTileFileExists(OSM::TileIndex index) const {
|
|
QString hashdir = index.cacheDir();
|
|
if (!cache_dir.exists(hashdir)) return false;
|
|
QString hashname = hashdir + "/" + index.hashName();
|
|
return cache_dir.exists(hashname);
|
|
}
|
|
|
|
|
|
void MapViewTileCache::setCacheRoot(const QString & p) {
|
|
cache_root = p;
|
|
tileProviderChanged();
|
|
}
|
|
|
|
|
|
void MapViewTileCache::tileProviderChanged() {
|
|
cache_dir.setPath(cache_root);
|
|
auto * provider = parent->downloader->provider;
|
|
if (provider) {
|
|
cache_dir.setPath(cache_root + "/" + provider->name());
|
|
}
|
|
qDebug() << "[MapViewTileCache] Cache dir" << cache_dir.absolutePath();
|
|
if (!cache_dir.exists()) cache_dir.mkpath(".");
|
|
}
|
|
|
|
|
|
void MapViewTileCache::setOfflineMode(bool yes) {
|
|
is_offline = yes;
|
|
}
|
|
|
|
|
|
OSM::TilePixmap MapViewTileCache::getTileFromCache(OSM::TileIndex index) {
|
|
OSM::TilePixmap ret;
|
|
ret.index = index;
|
|
auto * tile = tile_cache[index.hash()];
|
|
if (tile) {
|
|
ret.pixmap = tile->pixmap;
|
|
} else {
|
|
QString hashdir = index.cacheDir();
|
|
if (cache_dir.exists(hashdir)) {
|
|
QString hashname = hashdir + "/" + index.hashName();
|
|
if (cache_dir.exists(hashname)) {
|
|
QString fname = cache_dir.absoluteFilePath(hashname);
|
|
ret.pixmap.load(fname, "png");
|
|
tile = new OSM::TilePixmap();
|
|
tile->index = index;
|
|
tile->pixmap = ret.pixmap;
|
|
if (secs_obsolete > 0) {
|
|
int secs_old = QFileInfo(fname).lastModified().secsTo(QDateTime::currentDateTime());
|
|
ret.obsolete = secs_old >= secs_obsolete;
|
|
}
|
|
tile_cache.insert(tile->index.hash(), tile, tile->pixmapBytes());
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
void MapViewTileCache::updateCacheSize() {
|
|
tile_cache.setMaxCost(fixed_size_b + add_size_b);
|
|
}
|
|
|
|
|
|
void MapViewTileCache::saveTile(OSM::TilePixmap * tile) {
|
|
tile_cache.insert(tile->index.hash(), tile, tile->pixmapBytes());
|
|
emit tileReady(*tile);
|
|
cond_mutex.lock();
|
|
if (!queue.contains(*tile)) {
|
|
queue.enqueue(*tile);
|
|
cond.wakeOne();
|
|
}
|
|
cond_mutex.unlock();
|
|
}
|
|
|
|
|
|
void MapViewTileCache::writeToDisk(const OSM::TilePixmap & tile) {
|
|
QString hashdir = tile.index.cacheDir();
|
|
if (!cache_dir.exists(hashdir)) cache_dir.mkdir(hashdir);
|
|
QFile f(cache_dir.absoluteFilePath(hashdir + "/" + tile.index.hashName()));
|
|
if (!f.open(QIODevice::ReadWrite)) return;
|
|
f.resize(0);
|
|
tile.pixmap.save(&f, "png");
|
|
}
|
|
|
|
|
|
void MapViewTileCache::run() {
|
|
while (!isInterruptionRequested()) {
|
|
OSM::TilePixmap tile;
|
|
cond_mutex.lock();
|
|
if (queue.isEmpty()) {
|
|
cond.wait(&cond_mutex);
|
|
cond_mutex.unlock();
|
|
} else {
|
|
tile = queue.dequeue();
|
|
cond_mutex.unlock();
|
|
writeToDisk(tile);
|
|
}
|
|
}
|
|
}
|