diff options
author | Paolo Angelelli <paolo.angelelli@theqtcompany.com> | 2016-09-15 23:12:42 +0200 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2016-10-05 11:30:12 +0000 |
commit | 218e208bbf1c3112d2ea5781debc605fc76db80a (patch) | |
tree | 34812fb7c66e401bc288d4916ec6fed58d443022 /src | |
parent | a65d9b7acf62fdafd670b40c01425cedff61106c (diff) | |
download | qtlocation-218e208bbf1c3112d2ea5781debc605fc76db80a.tar.gz |
Fix cache mixing with high-dpi and low-dpi osm providers
This cache fixes the cache mixing problem that has been introduced
with the osm high dpi tiles support.
high dpi providers fall back to low dpi ones and ultimately
to hardcoded providers (also low dpi), and can also be enabled/disabled
via plugin parameter, thus leaving the cache for a given map id
dirty for the next run.
With this patch high dpi tiles are named differently from low dpi ones.
If high-dpi providers are selected, but become not available, the
cache can also change the tileset to load at runtime
Change-Id: I229692da07c1fc61c58fb0b6fae6ec5af16e43a7
Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Diffstat (limited to 'src')
20 files changed, 373 insertions, 34 deletions
diff --git a/src/location/location.pro b/src/location/location.pro index c47c411b..225df556 100644 --- a/src/location/location.pro +++ b/src/location/location.pro @@ -16,6 +16,9 @@ PUBLIC_HEADERS += \ qlocation.h \ qlocationglobal.h +PRIVATE_HEADERS += \ + qlocationglobal_p.h + SOURCES += \ qlocation.cpp diff --git a/src/location/maps/qcache3q_p.h b/src/location/maps/qcache3q_p.h index debce5d1..4348e14b 100644 --- a/src/location/maps/qcache3q_p.h +++ b/src/location/maps/qcache3q_p.h @@ -162,7 +162,7 @@ public: QSharedPointer<T> operator[](const Key &key) const; void remove(const Key &key); - + QList<Key> keys() const; void printStats(); // Copy data directly into a queue. Designed for single use after construction @@ -425,6 +425,15 @@ void QCache3Q<Key,T,EvPolicy>::remove(const Key &key) } template <class Key, class T, class EvPolicy> +QList<Key> QCache3Q<Key,T,EvPolicy>::keys() const +{ + QList<Key> keys; + for (auto i = lookup_.constBegin(); i != lookup_.constEnd(); ++i) + keys.append(i.key()); + return keys; +} + +template <class Key, class T, class EvPolicy> QSharedPointer<T> QCache3Q<Key,T,EvPolicy>::object(const Key &key) const { if (!lookup_.contains(key)) { diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp index 5eae7c0b..f3a36adf 100644 --- a/src/location/maps/qgeocameratiles.cpp +++ b/src/location/maps/qgeocameratiles.cpp @@ -169,6 +169,11 @@ void QGeoCameraTiles::setMapType(const QGeoMapType &mapType) d_ptr->m_mapType = mapType; } +QGeoMapType QGeoCameraTiles::activeMapType() const +{ + return d_ptr->m_mapType; +} + void QGeoCameraTiles::setMapVersion(int mapVersion) { if (d_ptr->m_mapVersion == mapVersion) diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h index d10895f8..8a26f28a 100644 --- a/src/location/maps/qgeocameratiles_p.h +++ b/src/location/maps/qgeocameratiles_p.h @@ -71,6 +71,7 @@ public: void setViewExpansion(double viewExpansion); void setPluginString(const QString &pluginString); void setMapType(const QGeoMapType &mapType); + QGeoMapType activeMapType() const; void setMapVersion(int mapVersion); const QSet<QGeoTileSpec>& createTiles(); diff --git a/src/location/maps/qgeofiletilecache_p.h b/src/location/maps/qgeofiletilecache_p.h index b6d4919f..fc023bc7 100644 --- a/src/location/maps/qgeofiletilecache_p.h +++ b/src/location/maps/qgeofiletilecache_p.h @@ -48,6 +48,7 @@ // #include <QtLocation/qlocationglobal.h> +#include <QtLocation/private/qlocationglobal_p.h> #include <QObject> #include <QCache> @@ -88,7 +89,7 @@ public: /* Custom eviction policy for the disk cache, to avoid deleting all the files * when the application closes */ -class QCache3QTileEvictionPolicy : public QCache3QDefaultEvictionPolicy<QGeoTileSpec,QGeoCachedTileDisk> +class Q_LOCATION_PRIVATE_EXPORT QCache3QTileEvictionPolicy : public QCache3QDefaultEvictionPolicy<QGeoTileSpec,QGeoCachedTileDisk> { protected: void aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer<QGeoCachedTileDisk> obj); diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index f59417f7..fedaecbc 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -116,6 +116,13 @@ void QGeoTiledMap::clearData() d->m_mapScene->clearTexturedTiles(); } +void QGeoTiledMap::clearScene(int mapId) +{ + Q_D(QGeoTiledMap); + if (activeMapType().mapId() == mapId) + d->clearScene(); +} + void QGeoTiledMap::handleTileVersionChanged() { Q_D(QGeoTiledMap); @@ -293,6 +300,11 @@ void QGeoTiledMapPrivate::prefetchTiles() } } +QGeoMapType QGeoTiledMapPrivate::activeMapType() +{ + return m_visibleTiles->activeMapType(); +} + void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &cameraData) { Q_Q(QGeoTiledMap); @@ -356,6 +368,13 @@ void QGeoTiledMapPrivate::changeTileVersion(int version) updateScene(); } +void QGeoTiledMapPrivate::clearScene() +{ + m_mapScene->clearTexturedTiles(); + m_mapScene->setVisibleTiles(QSet<QGeoTileSpec>()); + updateScene(); +} + void QGeoTiledMapPrivate::changeMapSize(const QSize& size) { Q_Q(QGeoTiledMap); diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index 220d422f..791384c7 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -96,6 +96,9 @@ public: void prefetchData() Q_DECL_OVERRIDE; void clearData() Q_DECL_OVERRIDE; +public Q_SLOTS: + virtual void clearScene(int mapId); + protected: QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) Q_DECL_OVERRIDE; virtual void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles); diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h index c1b190bf..ab36f6f7 100644 --- a/src/location/maps/qgeotiledmap_p_p.h +++ b/src/location/maps/qgeotiledmap_p_p.h @@ -80,12 +80,14 @@ public: void updateTile(const QGeoTileSpec &spec); void prefetchTiles(); + QGeoMapType activeMapType(); protected: void changeMapSize(const QSize& size) Q_DECL_OVERRIDE; void changeCameraData(const QGeoCameraData &cameraData) Q_DECL_OVERRIDE; void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE; void changeTileVersion(int version); + void clearScene(); private: void updateScene(); diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp index 3896a51e..d859c2af 100644 --- a/src/location/maps/qgeotiledmapscene.cpp +++ b/src/location/maps/qgeotiledmapscene.cpp @@ -101,6 +101,8 @@ public: bool m_verticalLock; bool m_linearScaling; + bool m_dropTextures; + void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture); QDoubleVector2D itemPositionToMercator(const QDoubleVector2D &pos) const; @@ -200,6 +202,7 @@ void QGeoTiledMapScene::clearTexturedTiles() { Q_D(QGeoTiledMapScene); d->m_textures.clear(); + d->m_dropTextures = true; } QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate() @@ -223,7 +226,8 @@ QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate() m_screenHeight(0.0), m_useVerticalLock(false), m_verticalLock(false), - m_linearScaling(false) + m_linearScaling(false), + m_dropTextures(false) { } @@ -718,6 +722,18 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win itemSpaceMatrix.scale(1, -1); mapRoot->root->setMatrix(itemSpaceMatrix); + if (d->m_dropTextures) { + foreach (const QGeoTileSpec &s, mapRoot->tiles->tiles.keys()) + delete mapRoot->tiles->tiles.take(s); + foreach (const QGeoTileSpec &s, mapRoot->wrapLeft->tiles.keys()) + delete mapRoot->wrapLeft->tiles.take(s); + foreach (const QGeoTileSpec &s, mapRoot->wrapRight->tiles.keys()) + delete mapRoot->wrapRight->tiles.take(s); + foreach (const QGeoTileSpec &spec, mapRoot->textures.keys()) + mapRoot->textures.take(spec)->deleteLater(); + d->m_dropTextures = false; + } + QSet<QGeoTileSpec> textures = QSet<QGeoTileSpec>::fromList(mapRoot->textures.keys()); QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles; QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures; diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp index 955839cb..34bf686c 100644 --- a/src/location/maps/qgeotilefetcher.cpp +++ b/src/location/maps/qgeotilefetcher.cpp @@ -46,20 +46,28 @@ QT_BEGIN_NAMESPACE QGeoTileFetcher::QGeoTileFetcher(QObject *parent) -: QObject(parent), d_ptr(new QGeoTileFetcherPrivate) +: QObject(*new QGeoTileFetcherPrivate(), parent) { Q_D(QGeoTileFetcher); d->enabled_ = true; - if (!d->queue_.isEmpty()) - d->timer_.start(0, this); +// if (!d->queue_.isEmpty()) +// d->timer_.start(0, this); } -QGeoTileFetcher::~QGeoTileFetcher() +QGeoTileFetcher::QGeoTileFetcher(QGeoTileFetcherPrivate &dd, QObject *parent) +: QObject(dd,parent) { + Q_D(QGeoTileFetcher); + d->enabled_ = true; - delete d_ptr; +// if (!d->queue_.isEmpty()) +// d->timer_.start(0, this); +} + +QGeoTileFetcher::~QGeoTileFetcher() +{ } void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded, @@ -194,7 +202,7 @@ void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec & *******************************************************************************/ QGeoTileFetcherPrivate::QGeoTileFetcherPrivate() -: enabled_(false) +: QObjectPrivate(), enabled_(false) { } diff --git a/src/location/maps/qgeotilefetcher_p.h b/src/location/maps/qgeotilefetcher_p.h index cbd8b995..e3621d3d 100644 --- a/src/location/maps/qgeotilefetcher_p.h +++ b/src/location/maps/qgeotilefetcher_p.h @@ -65,6 +65,7 @@ class QGeoTileSpec; class Q_LOCATION_EXPORT QGeoTileFetcher : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QGeoTileFetcher) public: QGeoTileFetcher(QObject *parent = 0); @@ -83,19 +84,18 @@ Q_SIGNALS: void tileError(const QGeoTileSpec &spec, const QString &errorString); protected: + QGeoTileFetcher(QGeoTileFetcherPrivate &dd, QObject *parent = 0); + void timerEvent(QTimerEvent *event); QGeoTiledMappingManagerEngine::CacheAreas cacheHint() const; virtual bool initialized() const; private: - QGeoTileFetcherPrivate *d_ptr; virtual QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) = 0; void handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec); - Q_DECLARE_PRIVATE(QGeoTileFetcher) Q_DISABLE_COPY(QGeoTileFetcher) - friend class QGeoTiledMappingManagerEngine; }; diff --git a/src/location/maps/qgeotilefetcher_p_p.h b/src/location/maps/qgeotilefetcher_p_p.h index acd7288e..7e9db527 100644 --- a/src/location/maps/qgeotilefetcher_p_p.h +++ b/src/location/maps/qgeotilefetcher_p_p.h @@ -48,6 +48,8 @@ // We mean it. // +#include <QtCore/private/qobject_p.h> +#include <QtLocation/private/qlocationglobal_p.h> #include <QSize> #include <QList> #include <QMap> @@ -64,8 +66,9 @@ class QGeoTileSpec; class QGeoTiledMapReply; class QGeoTiledMappingManagerEngine; -class QGeoTileFetcherPrivate +class Q_LOCATION_PRIVATE_EXPORT QGeoTileFetcherPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGeoTileFetcher) public: QGeoTileFetcherPrivate(); virtual ~QGeoTileFetcherPrivate(); diff --git a/src/location/qlocationglobal_p.h b/src/location/qlocationglobal_p.h new file mode 100644 index 00000000..afc0760b --- /dev/null +++ b/src/location/qlocationglobal_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCATIONGLOBAL_P_H +#define QLOCATIONGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qlocationglobal.h" + +QT_BEGIN_NAMESPACE + +#define Q_LOCATION_PRIVATE_EXPORT Q_LOCATION_EXPORT + +QT_END_NAMESPACE + + +#endif // QLOCATIONGLOBAL_P_H diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp index a780faa9..a8429f3d 100644 --- a/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp +++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp @@ -45,10 +45,16 @@ QT_BEGIN_NAMESPACE -QGeoFileTileCacheOsm::QGeoFileTileCacheOsm(const QString &offlineDirectory, const QString &directory, QObject *parent) - :QGeoFileTileCache(directory, parent), m_offlineDirectory(offlineDirectory), - m_requestCancel(0) +QGeoFileTileCacheOsm::QGeoFileTileCacheOsm(const QVector<QGeoTileProviderOsm *> &providers, const QString &offlineDirectory, const QString &directory, QObject *parent) +: QGeoFileTileCache(directory, parent), m_offlineDirectory(offlineDirectory), + m_requestCancel(0), m_providers(providers) { + m_highDpi.resize(providers.size()); + for (int i = 0; i < providers.size(); i++) { + m_highDpi[i] = providers[i]->isHighDpi(); + connect(providers[i], &QGeoTileProviderOsm::resolutionFinished, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished); + connect(providers[i], &QGeoTileProviderOsm::resolutionError, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished); + } } QGeoFileTileCacheOsm::~QGeoFileTileCacheOsm() @@ -67,6 +73,24 @@ QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::get(const QGeoTileSpec &sp return getFromDisk(spec); } +void QGeoFileTileCacheOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider) +{ + Q_UNUSED(provider) + for (int i = 0; i < m_providers.size(); i++) { + if (m_providers[i]->isHighDpi() != m_highDpi[i]) { + int mapId = m_providers[i]->mapType().mapId(); + m_highDpi[i] = m_providers[i]->isHighDpi(); + + // reload cache for mapId i + dropTiles(mapId); + loadTiles(mapId); + + // send signal to clear scene in all maps created through this provider that use the reloaded tiles + emit mapDataUpdated(mapId); + } + } +} + void QGeoFileTileCacheOsm::init() { QGeoFileTileCache::init(); @@ -99,6 +123,42 @@ QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::getFromOfflineStorage(cons return QSharedPointer<QGeoTileTexture>(); } +void QGeoFileTileCacheOsm::dropTiles(int mapId) +{ + QList<QGeoTileSpec> keys; + keys = textureCache_.keys(); + for (const QGeoTileSpec &k : keys) + if (k.mapId() == mapId) + textureCache_.remove(k); + + keys = memoryCache_.keys(); + for (const QGeoTileSpec &k : keys) + if (k.mapId() == mapId) + memoryCache_.remove(k); + + keys = diskCache_.keys(); + for (const QGeoTileSpec &k : keys) + if (k.mapId() == mapId) + diskCache_.remove(k); +} + +void QGeoFileTileCacheOsm::loadTiles(int mapId) +{ + QStringList formats; + formats << QLatin1String("*.*"); + + QDir dir(directory_); + QStringList files = dir.entryList(formats, QDir::Files); + + for (int i = 0; i < files.size(); ++i) { + QGeoTileSpec spec = filenameToTileSpec(files.at(i)); + if (spec.zoom() == -1 || spec.mapId() != mapId) + continue; + QString filename = dir.filePath(files.at(i)); + addToDiskCache(spec, filename); + } +} + void QGeoFileTileCacheOsm::initOfflineRegistry() { // Dealing with duplicates: picking the newest @@ -128,4 +188,80 @@ void QGeoFileTileCacheOsm::initOfflineRegistry() qWarning() << "OSM Offline tiles: "<<count; } +QString QGeoFileTileCacheOsm::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const +{ + int providerId = spec.mapId() - 1; + if (providerId < 0 || providerId >= m_providers.size()) + return QString(); + QString filename = spec.plugin(); + filename += QLatin1String("-"); + filename += (m_providers[providerId]->isHighDpi()) ? QLatin1Char('h') : QLatin1Char('l'); + filename += QLatin1String("-"); + filename += QString::number(spec.mapId()); + filename += QLatin1String("-"); + filename += QString::number(spec.zoom()); + filename += QLatin1String("-"); + filename += QString::number(spec.x()); + filename += QLatin1String("-"); + filename += QString::number(spec.y()); + + //Append version if real version number to ensure backwards compatibility and eviction of old tiles + if (spec.version() != -1) { + filename += QLatin1String("-"); + filename += QString::number(spec.version()); + } + + filename += QLatin1String("."); + filename += format; + + QDir dir = QDir(directory); + + return dir.filePath(filename); +} + +QGeoTileSpec QGeoFileTileCacheOsm::filenameToTileSpec(const QString &filename) const +{ + QGeoTileSpec emptySpec; + + QStringList parts = filename.split('.'); + + if (parts.length() != 2) + return emptySpec; + + QString name = parts.at(0); + QStringList fields = name.split('-'); + + int length = fields.length(); + if (length != 6 && length != 7) + return emptySpec; + + QList<int> numbers; + + bool ok = false; + for (int i = 2; i < length; ++i) { + ok = false; + int value = fields.at(i).toInt(&ok); + if (!ok) + return emptySpec; + numbers.append(value); + } + + bool highDpi = m_providers[numbers.at(0) - 1]->isHighDpi(); + if (highDpi && fields.at(1) != QLatin1Char('h')) + return emptySpec; + else if (!highDpi && fields.at(1) != QLatin1Char('l')) + return emptySpec; + + //File name without version, append default + if (numbers.length() < 5) + numbers.append(-1); + + return QGeoTileSpec(fields.at(0), + numbers.at(0), + numbers.at(1), + numbers.at(2), + numbers.at(3), + numbers.at(4)); +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.h b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h index f48fad7f..52d57747 100644 --- a/src/plugins/geoservices/osm/qgeofiletilecacheosm.h +++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h @@ -37,6 +37,7 @@ #ifndef QGEOFILETILECACHEOSM_H #define QGEOFILETILECACHEOSM_H +#include "qgeotileproviderosm.h" #include <QtLocation/private/qgeofiletilecache_p.h> #include <QHash> #include <QtConcurrent> @@ -48,14 +49,24 @@ class QGeoFileTileCacheOsm : public QGeoFileTileCache { Q_OBJECT public: - QGeoFileTileCacheOsm(const QString &offlineDirectory = QString(), const QString &directory = QString(), QObject *parent = 0); + QGeoFileTileCacheOsm(const QVector<QGeoTileProviderOsm *> &providers, const QString &offlineDirectory = QString(), const QString &directory = QString(), QObject *parent = 0); ~QGeoFileTileCacheOsm(); QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) Q_DECL_OVERRIDE; +Q_SIGNALS: + void mapDataUpdated(int mapId); + +protected Q_SLOTS: + void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); + protected: void init() Q_DECL_OVERRIDE; + QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const Q_DECL_OVERRIDE; + QGeoTileSpec filenameToTileSpec(const QString &filename) const Q_DECL_OVERRIDE; QSharedPointer<QGeoTileTexture> getFromOfflineStorage(const QGeoTileSpec &spec); + void dropTiles(int mapId); + void loadTiles(int mapId); void initOfflineRegistry(); @@ -64,6 +75,8 @@ protected: QAtomicInt m_requestCancel; QFuture<void> m_future; QMutex storageLock; + QVector<QGeoTileProviderOsm *> m_providers; + QVector<bool> m_highDpi; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp index 152df9b6..f8e18de9 100644 --- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp @@ -89,13 +89,13 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian QVector<TileProvider *> providers_terrain; QVector<TileProvider *> providers_hiking; if (highdpi) { - providers_street.push_back(new TileProvider(domain + "street-hires")); - providers_satellite.push_back(new TileProvider(domain + "satellite-hires")); - providers_cycle.push_back(new TileProvider(domain + "cycle-hires")); - providers_transit.push_back(new TileProvider(domain + "transit-hires")); - providers_nighttransit.push_back(new TileProvider(domain + "night-transit-hires")); - providers_terrain.push_back(new TileProvider(domain + "terrain-hires")); - providers_hiking.push_back(new TileProvider(domain + "hiking-hires")); + providers_street.push_back(new TileProvider(domain + "street-hires", true)); + providers_satellite.push_back(new TileProvider(domain + "satellite-hires", true)); + providers_cycle.push_back(new TileProvider(domain + "cycle-hires", true)); + providers_transit.push_back(new TileProvider(domain + "transit-hires", true)); + providers_nighttransit.push_back(new TileProvider(domain + "night-transit-hires", true)); + providers_terrain.push_back(new TileProvider(domain + "terrain-hires", true)); + providers_hiking.push_back(new TileProvider(domain + "hiking-hires", true)); } providers_street.push_back(new TileProvider(domain + "street")); providers_satellite.push_back(new TileProvider(domain + "satellite")); @@ -226,7 +226,7 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian if (parameters.contains(QStringLiteral("osm.mapping.offline.directory"))) m_offlineDirectory = parameters.value(QStringLiteral("osm.mapping.offline.directory")).toString(); - QAbstractGeoTileCache *tileCache = new QGeoFileTileCacheOsm(m_offlineDirectory, m_cacheDirectory); + QAbstractGeoTileCache *tileCache = new QGeoFileTileCacheOsm(m_providers, m_offlineDirectory, m_cacheDirectory); // 50mb of disk cache by default to minimize n. of accesses to public OSM servers tileCache->setMaxDiskUsage(50 * 1024 * 1024); @@ -263,7 +263,10 @@ QGeoTiledMappingManagerEngineOsm::~QGeoTiledMappingManagerEngineOsm() QGeoMap *QGeoTiledMappingManagerEngineOsm::createMap() { - return new QGeoTiledMapOsm(this); + QGeoTiledMap *map = new QGeoTiledMapOsm(this); + connect(qobject_cast<QGeoFileTileCacheOsm *>(tileCache()), &QGeoFileTileCacheOsm::mapDataUpdated + , map, &QGeoTiledMap::clearScene); + return map; } const QVector<QGeoTileProviderOsm *> &QGeoTiledMappingManagerEngineOsm::providers() diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp index c7de7cc9..f7c25d61 100644 --- a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp @@ -43,6 +43,7 @@ #include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkRequest> #include <QtLocation/private/qgeotilespec_p.h> +#include <QtLocation/private/qgeotilefetcher_p_p.h> QT_BEGIN_NAMESPACE @@ -55,10 +56,30 @@ static bool providersResolved(const QVector<QGeoTileProviderOsm *> &providers) return true; } +class QGeoTileFetcherOsmPrivate : public QGeoTileFetcherPrivate +{ + Q_DECLARE_PUBLIC(QGeoTileFetcherOsm) +public: + QGeoTileFetcherOsmPrivate(); + virtual ~QGeoTileFetcherOsmPrivate(); + +private: + Q_DISABLE_COPY(QGeoTileFetcherOsmPrivate) +}; + +QGeoTileFetcherOsmPrivate::QGeoTileFetcherOsmPrivate() : QGeoTileFetcherPrivate() +{ +} + +QGeoTileFetcherOsmPrivate::~QGeoTileFetcherOsmPrivate() +{ +} + + QGeoTileFetcherOsm::QGeoTileFetcherOsm(const QVector<QGeoTileProviderOsm *> &providers, QNetworkAccessManager *nm, QObject *parent) -: QGeoTileFetcher(parent), m_userAgent("Qt Location based application"), +: QGeoTileFetcher(*new QGeoTileFetcherOsmPrivate(), parent), m_userAgent("Qt Location based application"), m_providers(providers), m_nm(nm), m_ready(true) { m_nm->setParent(this); @@ -69,6 +90,8 @@ QGeoTileFetcherOsm::QGeoTileFetcherOsm(const QVector<QGeoTileProviderOsm *> &pro this, &QGeoTileFetcherOsm::onProviderResolutionFinished); connect(provider, &QGeoTileProviderOsm::resolutionError, this, &QGeoTileFetcherOsm::onProviderResolutionError); + connect(provider, &QGeoTileProviderOsm::resolutionRequired, + this, &QGeoTileFetcherOsm::restartTimer, Qt::QueuedConnection); provider->resolveProvider(); } } @@ -109,6 +132,14 @@ void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *pr emit providerDataUpdated(provider); } +void QGeoTileFetcherOsm::restartTimer() +{ + Q_D(QGeoTileFetcherOsm); + + if (!d->queue_.isEmpty()) + d->timer_.start(0, this); +} + QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec) { int id = spec.mapId(); diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.h b/src/plugins/geoservices/osm/qgeotilefetcherosm.h index c3f33faa..8897d8ed 100644 --- a/src/plugins/geoservices/osm/qgeotilefetcherosm.h +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.h @@ -47,10 +47,12 @@ QT_BEGIN_NAMESPACE class QNetworkAccessManager; +class QGeoTileFetcherOsmPrivate; class QGeoTileFetcherOsm : public QGeoTileFetcher { Q_OBJECT + Q_DECLARE_PRIVATE(QGeoTileFetcherOsm) friend class QGeoMapReplyOsm; friend class QGeoTiledMappingManagerEngineOsm; @@ -70,6 +72,7 @@ protected: protected Q_SLOTS: void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); void onProviderResolutionError(const QGeoTileProviderOsm *provider); + void restartTimer(); private: QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec); diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp index d0819bd6..0d99c828 100644 --- a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp +++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp @@ -113,6 +113,13 @@ int QGeoTileProviderOsm::maximumZoomLevel() const return m_provider->maximumZoomLevel(); } +bool QGeoTileProviderOsm::isHighDpi() const +{ + if (!m_provider) + return false; + return m_provider->isHighDpi(); +} + const QGeoMapType &QGeoTileProviderOsm::mapType() const { return m_mapType; @@ -183,8 +190,9 @@ void QGeoTileProviderOsm::onResolutionError(TileProvider *provider) m_provider = p; if (!p->isValid()) { m_status = Idle; - //m_status = Resolving; - //p->resolveProvider(); +// m_status = Resolving; +// p->resolveProvider(); + emit resolutionRequired(); } break; } @@ -230,12 +238,13 @@ static void sort2(int &a, int &b) } } -TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr) +TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr), m_highDpi(false) { } -TileProvider::TileProvider(const QUrl &urlRedirector) : m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr) +TileProvider::TileProvider(const QUrl &urlRedirector, bool highDpi) +: m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr), m_highDpi(highDpi) { if (!m_urlRedirector.isValid()) m_status = Invalid; @@ -245,11 +254,12 @@ TileProvider::TileProvider(const QString &urlTemplate, const QString &format, const QString ©RightMap, const QString ©RightData, + bool highDpi, int minimumZoomLevel, int maximumZoomLevel) : m_status(Invalid), m_nm(nullptr), m_urlTemplate(urlTemplate), m_format(format), m_copyRightMap(copyRightMap), m_copyRightData(copyRightData), - m_minimumZoomLevel(minimumZoomLevel), m_maximumZoomLevel(maximumZoomLevel) + m_minimumZoomLevel(minimumZoomLevel), m_maximumZoomLevel(maximumZoomLevel), m_highDpi(highDpi) { setupProvider(); } @@ -299,7 +309,7 @@ void TileProvider::handleError(QNetworkReply::NetworkError error) // prevent accessing the redirection info but not the actual providers. m_status = Invalid; default: - qWarning() << "QGeoTileProviderOsm network error:" << error; + //qWarning() << "QGeoTileProviderOsm network error:" << error; break; } } @@ -543,6 +553,11 @@ int TileProvider::maximumZoomLevel() const return m_maximumZoomLevel; } +bool TileProvider::isHighDpi() const +{ + return m_highDpi; +} + void TileProvider::setStyleCopyRight(const QString ©right) { m_copyRightStyle = copyright; diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.h b/src/plugins/geoservices/osm/qgeotileproviderosm.h index 3e887965..cea832f0 100644 --- a/src/plugins/geoservices/osm/qgeotileproviderosm.h +++ b/src/plugins/geoservices/osm/qgeotileproviderosm.h @@ -62,12 +62,13 @@ public: TileProvider(); // "Online" constructor. Needs resolution to fetch the parameters - TileProvider(const QUrl &urlRedirector); + TileProvider(const QUrl &urlRedirector, bool highDpi = false); // Offline constructor. Doesn't need URLRedirector and networkmanager TileProvider(const QString &urlTemplate, const QString &format, const QString ©RightMap, const QString ©RightData, + bool highDpi = false, int minimumZoomLevel = 0, int maximumZoomLevel = 19); @@ -89,6 +90,7 @@ public: inline QString format() const; inline int minimumZoomLevel() const; inline int maximumZoomLevel() const; + inline bool isHighDpi() const; QUrl tileAddress(int x, int y, int z) const; // Optional properties, not needed to construct a provider @@ -106,6 +108,7 @@ public: QString m_urlSuffix; int m_minimumZoomLevel; int m_maximumZoomLevel; + bool m_highDpi; int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z QString paramsSep[2]; // what goes in between %x, %y and %z @@ -145,6 +148,7 @@ public: QString format() const; int minimumZoomLevel() const; int maximumZoomLevel() const; + bool isHighDpi() const; const QGeoMapType &mapType() const; bool isValid() const; bool isResolved() const; @@ -152,6 +156,7 @@ public: Q_SIGNALS: void resolutionFinished(const QGeoTileProviderOsm *provider); void resolutionError(const QGeoTileProviderOsm *provider); + void resolutionRequired(); public Q_SLOTS: void resolveProvider(); |