// Copyright (C) 2015 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qgeotiledmappingmanagerengine_p.h" #include "qgeotiledmappingmanagerengine_p_p.h" #include "qgeotilefetcher_p.h" #include "qgeotiledmap_p.h" #include "qgeotilerequestmanager_p.h" #include "qgeofiletilecache_p.h" #include "qgeotilespec_p.h" #include #include #include #include QT_BEGIN_NAMESPACE QGeoTiledMappingManagerEngine::QGeoTiledMappingManagerEngine(QObject *parent) : QGeoMappingManagerEngine(parent), d_ptr(new QGeoTiledMappingManagerEnginePrivate) { } /*! Destroys this mapping manager. */ QGeoTiledMappingManagerEngine::~QGeoTiledMappingManagerEngine() { delete d_ptr; } /*! Sets the tile fetcher. Takes ownership of the QObject. */ void QGeoTiledMappingManagerEngine::setTileFetcher(QGeoTileFetcher *fetcher) { Q_D(QGeoTiledMappingManagerEngine); if (d->fetcher_) d->fetcher_->deleteLater(); fetcher->setParent(this); d->fetcher_ = fetcher; qRegisterMetaType(); connect(d->fetcher_, &QGeoTileFetcher::tileFinished, this, &QGeoTiledMappingManagerEngine::engineTileFinished, Qt::QueuedConnection); connect(d->fetcher_, &QGeoTileFetcher::tileError, this, &QGeoTiledMappingManagerEngine::engineTileError, Qt::QueuedConnection); engineInitialized(); } QGeoTileFetcher *QGeoTiledMappingManagerEngine::tileFetcher() { Q_D(QGeoTiledMappingManagerEngine); return d->fetcher_; } QGeoMap *QGeoTiledMappingManagerEngine::createMap() { return NULL; } void QGeoTiledMappingManagerEngine::releaseMap(QGeoTiledMap *map) { d_ptr->mapHash_.remove(map); QHash > newTileHash = d_ptr->tileHash_; typedef QHash >::const_iterator h_iter; h_iter hi = d_ptr->tileHash_.constBegin(); h_iter hend = d_ptr->tileHash_.constEnd(); for (; hi != hend; ++hi) { QSet maps = hi.value(); if (maps.contains(map)) { maps.remove(map); if (maps.isEmpty()) newTileHash.remove(hi.key()); else newTileHash.insert(hi.key(), maps); } } d_ptr->tileHash_ = newTileHash; } void QGeoTiledMappingManagerEngine::updateTileRequests(QGeoTiledMap *map, const QSet &tilesAdded, const QSet &tilesRemoved) { Q_D(QGeoTiledMappingManagerEngine); typedef QSet::const_iterator tile_iter; // add and remove tiles from tileset for this map QSet oldTiles = d->mapHash_.value(map); tile_iter rem = tilesRemoved.constBegin(); tile_iter remEnd = tilesRemoved.constEnd(); for (; rem != remEnd; ++rem) { oldTiles.remove(*rem); } tile_iter add = tilesAdded.constBegin(); tile_iter addEnd = tilesAdded.constEnd(); for (; add != addEnd; ++add) { oldTiles.insert(*add); } d->mapHash_.insert(map, oldTiles); // add and remove map from mapset for the tiles QSet reqTiles; QSet cancelTiles; rem = tilesRemoved.constBegin(); for (; rem != remEnd; ++rem) { QSet mapSet = d->tileHash_.value(*rem); mapSet.remove(map); if (mapSet.isEmpty()) { cancelTiles.insert(*rem); d->tileHash_.remove(*rem); } else { d->tileHash_.insert(*rem, mapSet); } } add = tilesAdded.constBegin(); for (; add != addEnd; ++add) { QSet mapSet = d->tileHash_.value(*add); if (mapSet.isEmpty()) { reqTiles.insert(*add); } mapSet.insert(map); d->tileHash_.insert(*add, mapSet); } cancelTiles -= reqTiles; QMetaObject::invokeMethod(d->fetcher_, "updateTileRequests", Qt::QueuedConnection, Q_ARG(QSet, reqTiles), Q_ARG(QSet, cancelTiles)); } void QGeoTiledMappingManagerEngine::engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) { Q_D(QGeoTiledMappingManagerEngine); QSet maps = d->tileHash_.value(spec); typedef QSet::const_iterator map_iter; map_iter map = maps.constBegin(); map_iter mapEnd = maps.constEnd(); for (; map != mapEnd; ++map) { QSet tileSet = d->mapHash_.value(*map); tileSet.remove(spec); if (tileSet.isEmpty()) d->mapHash_.remove(*map); else d->mapHash_.insert(*map, tileSet); } d->tileHash_.remove(spec); tileCache()->insert(spec, bytes, format, d->cacheHint_); map = maps.constBegin(); mapEnd = maps.constEnd(); for (; map != mapEnd; ++map) { (*map)->requestManager()->tileFetched(spec); } } void QGeoTiledMappingManagerEngine::engineTileError(const QGeoTileSpec &spec, const QString &errorString) { Q_D(QGeoTiledMappingManagerEngine); QSet maps = d->tileHash_.value(spec); typedef QSet::const_iterator map_iter; map_iter map = maps.constBegin(); map_iter mapEnd = maps.constEnd(); for (; map != mapEnd; ++map) { QSet tileSet = d->mapHash_.value(*map); tileSet.remove(spec); if (tileSet.isEmpty()) d->mapHash_.remove(*map); else d->mapHash_.insert(*map, tileSet); } d->tileHash_.remove(spec); for (map = maps.constBegin(); map != mapEnd; ++map) { (*map)->requestManager()->tileError(spec, errorString); } emit tileError(spec, errorString); } void QGeoTiledMappingManagerEngine::setTileSize(const QSize &tileSize) { Q_D(QGeoTiledMappingManagerEngine); d->tileSize_ = tileSize; } void QGeoTiledMappingManagerEngine::setTileVersion(int version) { Q_D(QGeoTiledMappingManagerEngine); if (d->m_tileVersion != version) { d->m_tileVersion = version; emit tileVersionChanged(); } } QSize QGeoTiledMappingManagerEngine::tileSize() const { Q_D(const QGeoTiledMappingManagerEngine); return d->tileSize_; } int QGeoTiledMappingManagerEngine::tileVersion() const { Q_D(const QGeoTiledMappingManagerEngine); return d->m_tileVersion; } QAbstractGeoTileCache::CacheAreas QGeoTiledMappingManagerEngine::cacheHint() const { Q_D(const QGeoTiledMappingManagerEngine); return d->cacheHint_; } void QGeoTiledMappingManagerEngine::setCacheHint(QAbstractGeoTileCache::CacheAreas cacheHint) { Q_D(QGeoTiledMappingManagerEngine); d->cacheHint_ = cacheHint; } /*! Sets the tile cache. Takes ownership of the QObject. */ void QGeoTiledMappingManagerEngine::setTileCache(QAbstractGeoTileCache *cache) { Q_D(QGeoTiledMappingManagerEngine); Q_ASSERT_X(!d->tileCache_, Q_FUNC_INFO, "This should be called only once"); cache->setParent(this); d->tileCache_.reset(cache); d->tileCache_->init(); } QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache() { Q_D(QGeoTiledMappingManagerEngine); if (!d->tileCache_) { QString cacheDirectory; if (!managerName().isEmpty()) cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + managerName(); d->tileCache_.reset(new QGeoFileTileCache(cacheDirectory)); d->tileCache_->init(); } return d->tileCache_.get(); } QSharedPointer QGeoTiledMappingManagerEngine::getTileTexture(const QGeoTileSpec &spec) { return d_ptr->tileCache_->get(spec); } QT_END_NAMESPACE