#include "mapview.h" #include "osm_downloader_p.h" #include "osm_tile_cache_p.h" #include "qad_locations.h" OSMTileCache::OSMTileCache(MapView * p): QThread() { qRegisterMetaType(); qRegisterMetaType(); parent = p; setCacheRoot(QAD::userPath(QAD::ltCache, "map_osm") + "/"); setAdditionalCacheSize(64); start(); } OSMTileCache::~OSMTileCache() { requestInterruption(); cond.wakeAll(); wait(); } void OSMTileCache::tileDownloaded(OSM::TileIndex index, const QPixmap & pixmap) { auto * tile = new OSM::TilePixmap(); tile->index = index; tile->pixmap = pixmap; saveTile(tile); } OSM::TilePixmap OSMTileCache::getTile(OSM::TileIndex index, QRectF & rect_src) { OSM::TilePixmap ret = getTileFromCache(index); if (ret.isEmpty()) { parent->downloader->queueTile(index); QVector 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 OSMTileCache::setCacheRoot(const QString & p) { cache_root = p; cache_dir.setPath(cache_root); qDebug() << "[OSMTileCache] Cache dir" << cache_root; if (!cache_dir.exists()) cache_dir.mkpath("."); } OSM::TilePixmap OSMTileCache::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)) { ret.pixmap.load(cache_dir.absoluteFilePath(hashname), "png"); tile = new OSM::TilePixmap(); tile->index = index; tile->pixmap = ret.pixmap; tile_cache.insert(tile->index.hash(), tile, tile->pixmapBytes()); return ret; } } } return ret; } void OSMTileCache::updateCacheSize() { tile_cache.setMaxCost(fixed_size_b + add_size_b); } void OSMTileCache::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 OSMTileCache::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 OSMTileCache::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); } } }