diff options
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(); |