summaryrefslogtreecommitdiff
path: root/src/plugins/geoservices/osm
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2016-12-05 12:43:52 +0100
committerAlex Blasche <alexander.blasche@qt.io>2016-12-05 12:43:52 +0100
commit335116ea024f51e1693bba39f78e15131870f1b0 (patch)
tree148ccdb4703b4a35afb1b0e3875573b1eb90d0ce /src/plugins/geoservices/osm
parent5e4bc1fe908896e9b90e8ad9c3896f35b5ec37be (diff)
parentba9b7b9ef674d93680070f6c4bb1053d0d2325dd (diff)
downloadqtlocation-335116ea024f51e1693bba39f78e15131870f1b0.tar.gz
Merge remote-tracking branch 'gerrit/5.8' into dev
Conflicts: src/imports/location/qdeclarativegeomap.cpp src/location/maps/maps.pri src/location/maps/qgeomap_p_p.h src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp src/plugins/geoservices/osm/qgeoroutereplyosm.cpp Change-Id: I18d31cff9233648178fe3e2636ce294026dfaeb7
Diffstat (limited to 'src/plugins/geoservices/osm')
-rw-r--r--src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp109
-rw-r--r--src/plugins/geoservices/osm/qgeofiletilecacheosm.h11
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp86
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.cpp59
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.h5
5 files changed, 227 insertions, 43 deletions
diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp
index 5028a82b..a563cced 100644
--- a/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp
+++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp
@@ -45,13 +45,16 @@
QT_BEGIN_NAMESPACE
-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)
+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();
+ m_mapIdFutures[providers[i]->mapType().mapId()].isFinished(); // To construct a default future for this mapId
connect(providers[i], &QGeoTileProviderOsm::resolutionFinished, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
connect(providers[i], &QGeoTileProviderOsm::resolutionError, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
}
@@ -61,6 +64,8 @@ QGeoFileTileCacheOsm::~QGeoFileTileCacheOsm()
{
m_requestCancel = 1;
m_future.waitForFinished();
+ for (const QGeoTileProviderOsm *p : m_providers)
+ m_mapIdFutures[p->mapType().mapId()].waitForFinished();
}
QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::get(const QGeoTileSpec &spec)
@@ -75,9 +80,10 @@ QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::get(const QGeoTileSpec &sp
void QGeoFileTileCacheOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider)
{
+ clearObsoleteTiles(provider);
Q_UNUSED(provider)
for (int i = 0; i < m_providers.size(); i++) {
- if (m_providers[i]->isHighDpi() != m_highDpi[i]) {
+ if (m_providers[i]->isHighDpi() != m_highDpi[i]) { // e.g., HiDpi was requested but only LoDpi is available
int mapId = m_providers[i]->mapType().mapId();
m_highDpi[i] = m_providers[i]->isHighDpi();
@@ -85,17 +91,60 @@ void QGeoFileTileCacheOsm::onProviderResolutionFinished(const QGeoTileProviderOs
dropTiles(mapId);
loadTiles(mapId);
+ // reload offline registry for mapId i
+ m_mapIdFutures[mapId] = QtConcurrent::run(this, &QGeoFileTileCacheOsm::initOfflineRegistry, mapId);
+
// send signal to clear scene in all maps created through this provider that use the reloaded tiles
emit mapDataUpdated(mapId);
}
}
}
+// On resolution error the provider is removed ONLY if there is no enabled hardcoded fallback.
+// Hardcoded fallbacks also have a timestamp, that can get updated with Qt releases.
+void QGeoFileTileCacheOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+ clearObsoleteTiles(provider); // this still removes tiles who happen to be older than qgeotileproviderosm.cpp defaultTs
+}
+
void QGeoFileTileCacheOsm::init()
{
+ if (directory_.isEmpty())
+ directory_ = baseLocationCacheDirectory();
+ QDir::root().mkpath(directory_);
+
+ // find max mapId
+ int max = 0;
+ for (auto p: m_providers)
+ if (p->mapType().mapId() > max)
+ max = p->mapType().mapId();
+ // Create a mapId to maxTimestamp LUT..
+ m_maxMapIdTimestamps.resize(max+1); // initializes to invalid QDateTime
+
+ // .. by finding the newest file in each tileset (tileset = mapId).
+ QDir dir(directory_);
+ QStringList formats;
+ formats << QLatin1String("*.*");
+ QStringList files = dir.entryList(formats, QDir::Files);
+
+ for (const QString &tileFileName : files) {
+ QGeoTileSpec spec = filenameToTileSpec(tileFileName);
+ if (spec.zoom() == -1)
+ continue;
+ QFileInfo fi(dir.filePath(tileFileName));
+ if (fi.lastModified() > m_maxMapIdTimestamps[spec.mapId()])
+ m_maxMapIdTimestamps[spec.mapId()] = fi.lastModified();
+ }
+
+ // Base class ::init()
QGeoFileTileCache::init();
+
+ for (QGeoTileProviderOsm * p: m_providers)
+ clearObsoleteTiles(p);
+
if (!m_offlineDirectory.isEmpty())
- m_future = QtConcurrent::run(this, &QGeoFileTileCacheOsm::initOfflineRegistry);
+ m_future = QtConcurrent::run(this, &QGeoFileTileCacheOsm::initOfflineRegistry, -1);
}
QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::getFromOfflineStorage(const QGeoTileSpec &spec)
@@ -159,7 +208,7 @@ void QGeoFileTileCacheOsm::loadTiles(int mapId)
}
}
-void QGeoFileTileCacheOsm::initOfflineRegistry()
+void QGeoFileTileCacheOsm::initOfflineRegistry(int mapId)
{
// Dealing with duplicates: picking the newest
QMap<QString, QPair<QString, QDateTime> > fileDates; // key is filename, value is <filepath, lastmodified>
@@ -173,11 +222,33 @@ void QGeoFileTileCacheOsm::initOfflineRegistry()
return;
}
+ // Clear the content of the index. Entirely (at startup), or selectively (when a provider resolution changes the highDpi status).
+ if (mapId < 0) {
+ storageLock.lock();
+ m_tilespecToOfflineFilepath.clear();
+ storageLock.unlock();
+ } else {
+ QList<QGeoTileSpec> toRemove;
+ for (auto i = m_tilespecToOfflineFilepath.constBegin(); i != m_tilespecToOfflineFilepath.constEnd(); ++i) {
+ if (i.key().mapId() == mapId)
+ toRemove.append(i.key());
+ }
+ storageLock.lock();
+ for (const auto &i : toRemove)
+ m_tilespecToOfflineFilepath.remove(i);
+ storageLock.unlock();
+ }
+ if (m_requestCancel)
+ return;
+
+ // Fill the index entirely or selectively
int count = 0;
- for (auto i= fileDates.begin(); i != fileDates.end(); ++i) {
+ for (auto i= fileDates.constBegin(); i != fileDates.constEnd(); ++i) {
QGeoTileSpec spec = filenameToTileSpec(i.key());
if (spec.zoom() == -1)
continue;
+ if (mapId >= 0 && spec.mapId() != mapId) // if mapId != -1, pick up only those files with that mapId.
+ continue;
count++;
storageLock.lock();
m_tilespecToOfflineFilepath[spec] = i.value().first;
@@ -185,7 +256,7 @@ void QGeoFileTileCacheOsm::initOfflineRegistry()
if (m_requestCancel)
return;
}
- qWarning() << "OSM Offline tiles: "<<count;
+ //qInfo() << "OSM plugin has found and is using "<< count <<" offline tiles";
}
QString QGeoFileTileCacheOsm::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const
@@ -264,4 +335,26 @@ QGeoTileSpec QGeoFileTileCacheOsm::filenameToTileSpec(const QString &filename) c
numbers.at(4));
}
+void QGeoFileTileCacheOsm::clearObsoleteTiles(const QGeoTileProviderOsm *p)
+{
+ // process initialized providers, and connect the others
+
+ if (p->isResolved()) {
+ if (m_maxMapIdTimestamps[p->mapType().mapId()].isValid() && // there are tiles in the cache
+ p->timestamp() > m_maxMapIdTimestamps[p->mapType().mapId()]) { // and they are older than the provider
+ qInfo() << "provider for " << p->mapType().name() << " timestamp: " << p->timestamp()
+ << " -- data last modified: " << m_maxMapIdTimestamps[p->mapType().mapId()] << ". Clearing.";
+ clearMapId(p->mapType().mapId());
+ m_maxMapIdTimestamps[p->mapType().mapId()] = p->timestamp(); // don't do it again.
+ }
+ } else {
+ connect(p, &QGeoTileProviderOsm::resolutionFinished,
+ this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
+#if 0 // If resolution fails, better not try to remove anything. Beside, on error, resolutionFinished is also emitted.
+ connect(p, &QGeoTileProviderOsm::resolutionError,
+ this, &QGeoFileTileCacheOsm::onProviderResolutionError);
+#endif
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.h b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h
index 52d57747..d26cad4a 100644
--- a/src/plugins/geoservices/osm/qgeofiletilecacheosm.h
+++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h
@@ -49,7 +49,10 @@ class QGeoFileTileCacheOsm : public QGeoFileTileCache
{
Q_OBJECT
public:
- QGeoFileTileCacheOsm(const QVector<QGeoTileProviderOsm *> &providers, 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;
@@ -59,6 +62,7 @@ Q_SIGNALS:
protected Q_SLOTS:
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
protected:
void init() Q_DECL_OVERRIDE;
@@ -68,15 +72,18 @@ protected:
void dropTiles(int mapId);
void loadTiles(int mapId);
- void initOfflineRegistry();
+ void initOfflineRegistry(int mapId = -1);
+ void clearObsoleteTiles(const QGeoTileProviderOsm *p);
QString m_offlineDirectory;
QHash<QGeoTileSpec, QString> m_tilespecToOfflineFilepath;
QAtomicInt m_requestCancel;
QFuture<void> m_future;
+ QMap<int, QFuture<void>> m_mapIdFutures;
QMutex storageLock;
QVector<QGeoTileProviderOsm *> m_providers;
QVector<bool> m_highDpi;
+ QVector<QDateTime> m_maxMapIdTimestamps;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
index f8e18de9..ff79c261 100644
--- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
@@ -70,7 +70,10 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
customAddress = QStringLiteral("http://") + customAddress;
if (customAddress[customAddress.length()-1] != QLatin1Char('/'))
customAddress += QLatin1Char('/');
- domain = customAddress;
+ if (QUrl(customAddress).isValid())
+ domain = customAddress;
+ else
+ qWarning() << "Invalid custom providers repository address: " << customAddress;
}
bool highdpi = false;
@@ -105,37 +108,50 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
providers_terrain.push_back(new TileProvider(domain + "terrain"));
providers_hiking.push_back(new TileProvider(domain + "hiking"));
// Backups
+ const QDateTime defaultTs = QDateTime::fromString(QStringLiteral("2016-06-01T00:00:00"), Qt::ISODate);
providers_street.push_back(
new TileProvider(QStringLiteral("http://c.tile.openstreetmap.org/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap.org</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
- // No available satellite backup
+ providers_street.back()->setTimestamp(defaultTs);
+
+ // No available open access satellite backup with satisfactory level of details at the present.
+
providers_cycle.push_back(
new TileProvider(QStringLiteral("http://c.tile.opencyclemap.org/cycle/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_cycle.back()->setTimestamp(defaultTs);
+
providers_transit.push_back(
new TileProvider(QStringLiteral("http://c.tile2.opencyclemap.org/transport/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_transit.back()->setTimestamp(defaultTs);
+
providers_nighttransit.push_back(
new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/transport-dark/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")) );
+ providers_nighttransit.back()->setTimestamp(defaultTs);
+
providers_terrain.push_back(
new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/landscape/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_terrain.back()->setTimestamp(defaultTs);
+
providers_hiking.push_back(
new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/outdoors/%z/%x/%y.png"),
QStringLiteral("png"),
QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_hiking.back()->setTimestamp(defaultTs);
/* QGeoTileProviderOsms setup */
@@ -208,15 +224,8 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
}
updateMapTypes();
- QGeoTileFetcherOsm *tileFetcher = new QGeoTileFetcherOsm(m_providers, nm, this);
- if (parameters.contains(QStringLiteral("osm.useragent"))) {
- const QByteArray ua = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1();
- tileFetcher->setUserAgent(ua);
- }
-
-
- setTileFetcher(tileFetcher);
+ /* TILE CACHE */
if (parameters.contains(QStringLiteral("osm.mapping.cache.directory"))) {
m_cacheDirectory = parameters.value(QStringLiteral("osm.mapping.cache.directory")).toString();
} else {
@@ -225,19 +234,38 @@ 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_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);
-
+ QGeoFileTileCacheOsm *tileCache = new QGeoFileTileCacheOsm(m_providers, m_offlineDirectory, m_cacheDirectory);
+
+ /*
+ * Disk cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.disk.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.disk.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ }
if (parameters.contains(QStringLiteral("osm.mapping.cache.disk.size"))) {
bool ok = false;
int cacheSize = parameters.value(QStringLiteral("osm.mapping.cache.disk.size")).toString().toInt(&ok);
if (ok)
tileCache->setMaxDiskUsage(cacheSize);
+ }
+
+ /*
+ * Memory cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.memory.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.memory.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary);
} else {
- tileCache->setMaxDiskUsage(100 * 1024 * 1024);
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
}
if (parameters.contains(QStringLiteral("osm.mapping.cache.memory.size"))) {
bool ok = false;
@@ -245,14 +273,38 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
if (ok)
tileCache->setMaxMemoryUsage(cacheSize);
}
+
+ /*
+ * Texture cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.texture.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.texture.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ }
if (parameters.contains(QStringLiteral("osm.mapping.cache.texture.size"))) {
bool ok = false;
int cacheSize = parameters.value(QStringLiteral("osm.mapping.cache.texture.size")).toString().toInt(&ok);
if (ok)
tileCache->setExtraTextureUsage(cacheSize);
}
+
+
setTileCache(tileCache);
+
+ /* TILE FETCHER */
+ QGeoTileFetcherOsm *tileFetcher = new QGeoTileFetcherOsm(m_providers, nm, this);
+ if (parameters.contains(QStringLiteral("osm.useragent"))) {
+ const QByteArray ua = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1();
+ tileFetcher->setUserAgent(ua);
+ }
+ setTileFetcher(tileFetcher);
+
*error = QGeoServiceProvider::NoError;
errorString->clear();
}
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
index 0d99c828..1989c44f 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
@@ -43,6 +43,7 @@
QT_BEGIN_NAMESPACE
static const int maxValidZoom = 30;
+static const QDateTime defaultTs = QDateTime::fromString(QStringLiteral("2016-06-01T00:00:00"), Qt::ISODate);
QGeoTileProviderOsm::QGeoTileProviderOsm(QNetworkAccessManager *nm,
const QGeoMapType &mapType,
@@ -120,6 +121,13 @@ bool QGeoTileProviderOsm::isHighDpi() const
return m_provider->isHighDpi();
}
+const QDateTime QGeoTileProviderOsm::timestamp() const
+{
+ if (!m_provider)
+ return QDateTime();
+ return m_provider->timestamp();
+}
+
const QGeoMapType &QGeoTileProviderOsm::mapType() const
{
return m_mapType;
@@ -190,8 +198,10 @@ void QGeoTileProviderOsm::onResolutionError(TileProvider *provider)
m_provider = p;
if (!p->isValid()) {
m_status = Idle;
-// m_status = Resolving;
-// p->resolveProvider();
+#if 0 // leaving triggering the retry to the tile fetcher, instead of constantly spinning it in here.
+ m_status = Resolving;
+ p->resolveProvider();
+#endif
emit resolutionRequired();
}
break;
@@ -204,7 +214,9 @@ void QGeoTileProviderOsm::onResolutionError(TileProvider *provider)
emit resolutionFinished(this);
} else { // still not resolved. But network error is recoverable.
m_status = Idle;
- //m_provider->resolveProvider();
+#if 0 // leaving triggering the retry to the tile fetcher
+ m_provider->resolveProvider();
+#endif
}
}
@@ -226,7 +238,7 @@ void QGeoTileProviderOsm::addProvider(TileProvider *provider)
/*
- QGeoTileProviderOsm::TileProvder
+ Class TileProvder
*/
static void sort2(int &a, int &b)
@@ -238,13 +250,13 @@ static void sort2(int &a, int &b)
}
}
-TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr), m_highDpi(false)
+TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(false)
{
}
TileProvider::TileProvider(const QUrl &urlRedirector, bool highDpi)
-: m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr), m_highDpi(highDpi)
+: m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(highDpi)
{
if (!m_urlRedirector.isValid())
m_status = Invalid;
@@ -259,7 +271,7 @@ TileProvider::TileProvider(const QString &urlTemplate,
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_highDpi(highDpi)
+ m_minimumZoomLevel(minimumZoomLevel), m_maximumZoomLevel(maximumZoomLevel), m_timestamp(defaultTs), m_highDpi(highDpi)
{
setupProvider();
}
@@ -352,6 +364,7 @@ void TileProvider::onNetworkReplyFinished()
* "StyleCopyRight" : "<copyright>", (optional)
* "MinimumZoomLevel" : <minimumZoomLevel>, (optional)
* "MaximumZoomLevel" : <maximumZoomLevel>, (optional)
+ * "Timestamp" : <timestamp>, (optional)
* }
*
* Enabled is optional, and allows to temporarily disable a tile provider if it becomes
@@ -361,27 +374,31 @@ void TileProvider::onNetworkReplyFinished()
* requests to the providers, if they do not support the specific ZL. Default is 0 and 20,
* respectively.
*
- * <server address template> is required, and is the tile url template, with %x, %y and %z as
+ * UrlTemplate is required, and is the tile url template, with %x, %y and %z as
* placeholders for the actual parameters.
* Example:
* http://localhost:8080/maps/%z/%x/%y.png
*
- * <image format> is required, and is the format of the tile.
+ * ImageFormat is required, and is the format of the tile.
* Examples:
* "png", "jpg"
*
- * <MapCopyRight> is required and is the string that will be displayed in the "Map (c)" part
+ * MapCopyRight is required and is the string that will be displayed in the "Map (c)" part
* of the on-screen copyright notice. Can be an empty string.
* Example:
* "<a href='http://www.mapquest.com/'>MapQuest</a>"
*
- * <DataCopyRight> is required and is the string that will be displayed in the "Data (c)" part
+ * DataCopyRight is required and is the string that will be displayed in the "Data (c)" part
* of the on-screen copyright notice. Can be an empty string.
* Example:
* "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
*
- * <StyleCopyRight> is optional and is the string that will be displayed in the optional "Style (c)" part
+ * StyleCopyRight is optional and is the string that will be displayed in the optional "Style (c)" part
* of the on-screen copyright notice.
+ *
+ * Timestamp is optional, and if set will cause QtLocation to clear the content of the cache older
+ * than this timestamp. The purpose is to prevent mixing tiles from different providers in the cache
+ * upon provider change. The value must be a string in ISO 8601 format (see Qt::ISODate)
*/
QJsonParseError error;
@@ -435,6 +452,10 @@ void TileProvider::onNetworkReplyFinished()
if (maxZoom.isDouble())
m_maximumZoomLevel = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
+ const QJsonValue ts = json.value(QLatin1String("Timestamp"));
+ if (ts.isString())
+ m_timestamp = QDateTime::fromString(ts.toString(), Qt::ISODate);
+
setupProvider();
if (isValid()) {
QObject::disconnect(errorEmitterConnection);
@@ -553,6 +574,11 @@ int TileProvider::maximumZoomLevel() const
return m_maximumZoomLevel;
}
+const QDateTime &TileProvider::timestamp() const
+{
+ return m_timestamp;
+}
+
bool TileProvider::isHighDpi() const
{
return m_highDpi;
@@ -563,6 +589,11 @@ void TileProvider::setStyleCopyRight(const QString &copyright)
m_copyRightStyle = copyright;
}
+void TileProvider::setTimestamp(const QDateTime &timestamp)
+{
+ m_timestamp = timestamp;
+}
+
QUrl TileProvider::tileAddress(int x, int y, int z) const
{
if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
@@ -591,7 +622,3 @@ TileProvider::Status TileProvider::status() const
QT_END_NAMESPACE
-
-
-
-
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.h b/src/plugins/geoservices/osm/qgeotileproviderosm.h
index cea832f0..b8647244 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.h
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.h
@@ -48,6 +48,7 @@
#include <algorithm>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
+#include <QDateTime>
QT_BEGIN_NAMESPACE
@@ -90,11 +91,13 @@ public:
inline QString format() const;
inline int minimumZoomLevel() const;
inline int maximumZoomLevel() const;
+ inline const QDateTime &timestamp() const;
inline bool isHighDpi() const;
QUrl tileAddress(int x, int y, int z) const;
// Optional properties, not needed to construct a provider
void setStyleCopyRight(const QString &copyright);
+ void setTimestamp(const QDateTime &timestamp);
Status m_status;
QUrl m_urlRedirector; // The URL from where to fetch the URL template in case of a provider to resolve.
@@ -108,6 +111,7 @@ public:
QString m_urlSuffix;
int m_minimumZoomLevel;
int m_maximumZoomLevel;
+ QDateTime m_timestamp;
bool m_highDpi;
int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z
@@ -152,6 +156,7 @@ public:
const QGeoMapType &mapType() const;
bool isValid() const;
bool isResolved() const;
+ const QDateTime timestamp() const;
Q_SIGNALS:
void resolutionFinished(const QGeoTileProviderOsm *provider);