summaryrefslogtreecommitdiff
path: root/src/plugins/geoservices/osm
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@theqtcompany.com>2016-08-15 12:12:25 +0200
committerPaolo Angelelli <paolo.angelelli@theqtcompany.com>2016-08-30 11:01:14 +0000
commit52c8bfa6be4fc6c47f99c9f37c142554932c7228 (patch)
treed70ffc9c7bc690c980a05e1c1d950d06b1db6919 /src/plugins/geoservices/osm
parent832030f271105a96bdde70b0526df659f21de565 (diff)
downloadqtlocation-52c8bfa6be4fc6c47f99c9f37c142554932c7228.tar.gz
Add OSM plugin parameter osm.mapping.highdpi_tiles
This patch adds a mean to enable/disable high dpi support for the OSM plugin too, following the same approach taken for the mapbox and here plugins. In order to do so, it has been necessary to rework QGeoTileProviderOsm. It can now be constructed with an arbitrary number of TileProviders, as opposed to the previous approach with one primary and one fallback tileprovider. It has also been necessary to disable Nearest interpolation for high dpi tiles, as it appears to produce considerable artifacts. So in presence of highdpi tiles, Linear interpolation is now always used. Change-Id: Id7d20fd5a320f3d5ef41b9fa28447a5c4f5398be Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/plugins/geoservices/osm')
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/street11
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/street-hires9
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmaposm.cpp5
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp145
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h2
-rw-r--r--src/plugins/geoservices/osm/qgeotilefetcherosm.cpp3
-rw-r--r--src/plugins/geoservices/osm/qgeotilefetcherosm.h2
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.cpp472
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.h241
9 files changed, 542 insertions, 348 deletions
diff --git a/src/plugins/geoservices/osm/providers/5.8/street b/src/plugins/geoservices/osm/providers/5.8/street
index 9819f619..b3bccf1d 100644
--- a/src/plugins/geoservices/osm/providers/5.8/street
+++ b/src/plugins/geoservices/osm/providers/5.8/street
@@ -1,9 +1,10 @@
{
- "UrlTemplate" : "https://maps.wikimedia.org/osm-intl/%z/%x/%y@2x.png",
- "ImageFormat" : "png",
+ "UrlTemplate" : "http://korona.geog.uni-heidelberg.de/tiles/roads/x=%x&y=%y&z=%z",
+ "ImageFormat" : "jpg",
"QImageFormat" : "Indexed8",
- "MaximumZoomLevel" : 18,
- "ID" : "wmf-intl-2x",
- "MapCopyRight" : "<a href='https://wikimediafoundation.org/wiki/Terms_of_Use'>WikiMedia Foundation</a>",
+ "ID" : "oms-street",
+ "MaximumZoomLevel" : 20,
+ "MapCopyRight" : "<a href='http://giscience.uni-hd.de/'>GIScience Research Group @ University of Heidelberg</a>",
+ "StyleCopyRight" : "<a href='http://www.geog.uni-heidelberg.de/personen/gis_rylov.html'>Maxim Rylov</a>",
"DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
}
diff --git a/src/plugins/geoservices/osm/providers/5.8/street-hires b/src/plugins/geoservices/osm/providers/5.8/street-hires
new file mode 100644
index 00000000..9819f619
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/street-hires
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "https://maps.wikimedia.org/osm-intl/%z/%x/%y@2x.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "MaximumZoomLevel" : 18,
+ "ID" : "wmf-intl-2x",
+ "MapCopyRight" : "<a href='https://wikimediafoundation.org/wiki/Terms_of_Use'>WikiMedia Foundation</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/qgeotiledmaposm.cpp b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
index f16e602a..d94a40a6 100644
--- a/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
+++ b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
@@ -71,10 +71,13 @@ void QGeoTiledMapOsm::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles)
return;
int providerId = tile.mapId() - 1;
- if (providerId < 0 || providerId >= m_engine->providers().size() || !m_engine->providers().at(providerId)->isValid())
+ if (providerId < 0 || providerId >= m_engine->providers().size())
return;
m_mapId = tile.mapId();
+ if (!m_engine->providers().at(providerId)->isValid())
+ return;
+
onProviderDataUpdated(m_engine->providers().at(providerId));
}
diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
index 4f25204a..152df9b6 100644
--- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
@@ -73,66 +73,93 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
domain = customAddress;
}
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "street",
- nm,
+ bool highdpi = false;
+ if (parameters.contains(QStringLiteral("osm.mapping.highdpi_tiles"))) {
+ const QString param = parameters.value(QStringLiteral("osm.mapping.highdpi_tiles")).toString().toLower();
+ if (param == "true")
+ highdpi = true;
+ }
+
+ /* TileProviders setup */
+ QVector<TileProvider *> providers_street;
+ QVector<TileProvider *> providers_satellite;
+ QVector<TileProvider *> providers_cycle;
+ QVector<TileProvider *> providers_transit;
+ QVector<TileProvider *> providers_nighttransit;
+ 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"));
+ providers_satellite.push_back(new TileProvider(domain + "satellite"));
+ providers_cycle.push_back(new TileProvider(domain + "cycle"));
+ providers_transit.push_back(new TileProvider(domain + "transit"));
+ providers_nighttransit.push_back(new TileProvider(domain + "night-transit"));
+ providers_terrain.push_back(new TileProvider(domain + "terrain"));
+ providers_hiking.push_back(new TileProvider(domain + "hiking"));
+ // Backups
+ 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_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_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_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_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_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")));
+
+
+ /* QGeoTileProviderOsms setup */
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Street map view in daylight mode"), false, false, 1),
- QGeoTileProviderOsm::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")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "satellite",
- nm,
+ providers_street ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2),
- QGeoTileProviderOsm::TileProvider()
- ));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "cycle",
- nm,
+ providers_satellite ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::CycleMap, tr("Cycle Map"), tr("Cycle map view in daylight mode"), false, false, 3),
- QGeoTileProviderOsm::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")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "transit",
- nm,
+ providers_cycle ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Public transit map view in daylight mode"), false, false, 4),
- QGeoTileProviderOsm::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")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "night-transit",
- nm,
+ providers_transit ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TransitMap, tr("Night Transit Map"), tr("Public transit map view in night mode"), false, true, 5),
- QGeoTileProviderOsm::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")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "terrain",
- nm,
+ providers_nighttransit ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view"), false, false, 6),
- QGeoTileProviderOsm::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")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "hiking",
- nm,
+ providers_terrain ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::PedestrianMap, tr("Hiking Map"), tr("Hiking map view"), false, false, 7),
- QGeoTileProviderOsm::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 ));
if (parameters.contains(QStringLiteral("osm.mapping.custom.host"))
|| parameters.contains(QStringLiteral("osm.mapping.host"))) {
@@ -154,14 +181,13 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
m_customCopyright = parameters.value(QStringLiteral("osm.mapping.copyright")).toString();
m_providers.push_back(
- new QGeoTileProviderOsm("",
- nm,
+ new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8),
- QGeoTileProviderOsm::TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"),
+ { new TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"),
QStringLiteral("png"),
mapCopyright,
- dataCopyright
- )));
+ dataCopyright) }
+ ));
m_providers.last()->disableRedirection();
}
@@ -257,9 +283,8 @@ void QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished(const QGeoTi
updateMapTypes();
}
-void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider)
{
- Q_UNUSED(error)
if (!provider->isResolved())
return;
updateMapTypes();
diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
index 7536e655..b1f0a13c 100644
--- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
+++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
@@ -65,7 +65,7 @@ public:
protected Q_SLOTS:
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
- void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider);
protected:
void updateMapTypes();
diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
index 98621411..0d7fa58e 100644
--- a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
@@ -100,9 +100,8 @@ void QGeoTileFetcherOsm::onProviderResolutionFinished(const QGeoTileProviderOsm
emit providerDataUpdated(provider);
}
-void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider)
{
- Q_UNUSED(error)
if ((m_ready = providersResolved(m_providers))) {
qWarning("QGeoTileFetcherOsm: all providers resolved");
readyUpdated();
diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.h b/src/plugins/geoservices/osm/qgeotilefetcherosm.h
index 8d69cc56..c3f33faa 100644
--- a/src/plugins/geoservices/osm/qgeotilefetcherosm.h
+++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.h
@@ -69,7 +69,7 @@ protected:
protected Q_SLOTS:
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
- void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider);
private:
QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec);
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
index 3d46a425..afa8e45f 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
@@ -44,150 +44,271 @@ QT_BEGIN_NAMESPACE
static const int maxValidZoom = 30;
-QGeoTileProviderOsm::QGeoTileProviderOsm(const QString &urlRedir,
- QNetworkAccessManager *nm,
- const QGeoMapType &mapType,
- const QGeoTileProviderOsm::TileProvider &providerFallback)
- : m_nm(nm), m_urlRedirector(urlRedir),
- m_providerFallback(providerFallback),
- m_mapType(mapType), m_status(Idle)
+QGeoTileProviderOsm::QGeoTileProviderOsm(QNetworkAccessManager *nm,
+ const QGeoMapType &mapType,
+ const QVector<TileProvider *> &providers)
+: m_nm(nm), m_provider(nullptr), m_mapType(mapType), m_status(Idle)
{
- if (!m_urlRedirector.isValid())
- disableRedirection();
+ for (int i = 0; i < providers.size(); ++i) {
+ TileProvider *p = providers[i];
+ if (!m_provider)
+ m_providerId = i;
+ addProvider(p);
+ }
+
+ if (!m_provider || m_provider->isValid())
+ m_status = Resolved;
}
QGeoTileProviderOsm::~QGeoTileProviderOsm()
{
+}
+
+QUrl QGeoTileProviderOsm::tileAddress(int x, int y, int z) const
+{
+ if (m_status != Resolved || !m_provider)
+ return QUrl();
+ return m_provider->tileAddress(x, y, z);
+}
+
+QString QGeoTileProviderOsm::mapCopyRight() const
+{
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->mapCopyRight();
+}
+
+QString QGeoTileProviderOsm::dataCopyRight() const
+{
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->dataCopyRight();
+}
+
+QString QGeoTileProviderOsm::styleCopyRight() const
+{
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->styleCopyRight();
+}
+
+QString QGeoTileProviderOsm::format() const
+{
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->format();
+}
+
+const QGeoMapType &QGeoTileProviderOsm::mapType() const
+{
+ return m_mapType;
+}
+
+bool QGeoTileProviderOsm::isValid() const
+{
+ if (m_status != Resolved || !m_provider)
+ return false;
+ return m_provider->isValid();
+}
+bool QGeoTileProviderOsm::isResolved() const
+{
+ return (m_status == Resolved);
}
void QGeoTileProviderOsm::resolveProvider()
{
- switch (m_status) {
- case Resolving:
- case Invalid:
- case Valid:
- return;
- case Idle:
- m_status = Resolving;
- break;
- }
+ if (m_status == Resolved || m_status == Resolving)
+ return;
- QNetworkRequest request;
- request.setHeader(QNetworkRequest::UserAgentHeader, QByteArrayLiteral("QGeoTileFetcherOsm"));
- request.setUrl(m_urlRedirector);
- QNetworkReply *reply = m_nm->get(request);
- connect(reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
- this, SLOT(onNetworkReplyError(QNetworkReply::NetworkError)));
+ m_status = Resolving;
+ // Provider can't be null while on Idle status.
+ connect(m_provider, &TileProvider::resolutionFinished, this, &QGeoTileProviderOsm::onResolutionFinished);
+ connect(m_provider, &TileProvider::resolutionError, this, &QGeoTileProviderOsm::onResolutionError);
+ m_provider->resolveProvider();
}
void QGeoTileProviderOsm::disableRedirection()
{
- m_status = Invalid;
- m_provider.m_valid = false;
+ if (m_provider && m_provider->isValid())
+ return;
+ bool found = false;
+ for (TileProvider *p: m_providerList) {
+ if (p->isValid() && !found) {
+ m_provider = p;
+ found = true;
+ }
+ p->disconnect(this);
+ }
}
-void QGeoTileProviderOsm::handleError(QNetworkReply::NetworkError error)
+void QGeoTileProviderOsm::onResolutionFinished(TileProvider *provider)
{
- switch (error) {
- case QNetworkReply::ConnectionRefusedError:
- case QNetworkReply::TooManyRedirectsError:
- case QNetworkReply::InsecureRedirectError:
- case QNetworkReply::ContentAccessDenied:
- case QNetworkReply::ContentOperationNotPermittedError:
- case QNetworkReply::ContentNotFoundError:
- case QNetworkReply::AuthenticationRequiredError:
- case QNetworkReply::ContentGoneError:
- case QNetworkReply::OperationNotImplementedError:
- case QNetworkReply::ServiceUnavailableError:
- // Errors we don't expect to recover from in the near future, which
- // prevent accessing the redirection info but not the actual providers.
- m_status = Invalid;
- default:
- break;
+ Q_UNUSED(provider)
+ // provider and m_provider are the same, at this point. m_status is Resolving.
+ m_status = Resolved;
+ emit resolutionFinished(this);
+}
+
+void QGeoTileProviderOsm::onResolutionError(TileProvider *provider)
+{
+ Q_UNUSED(provider)
+ // provider and m_provider are the same at this point. m_status is Resolving.
+ if (m_provider->isInvalid()) {
+ m_provider = nullptr;
+ m_status = Resolved;
+ if (m_providerId >= m_providerList.size() -1) { // no hope left
+ emit resolutionError(this);
+ return;
+ }
+ // Advance the pointer in the provider list, and possibly start resolution on the next in the list.
+ for (int i = m_providerId + 1; i < m_providerList.size(); ++i) {
+ m_providerId = i;
+ TileProvider *p = m_providerList[m_providerId];
+ if (!p->isInvalid()) {
+ m_provider = p;
+ if (!p->isValid()) {
+ m_status = Idle;
+ //m_status = Resolving;
+ //p->resolveProvider();
+ }
+ }
+ }
+ if (!m_provider)
+ emit resolutionError(this);
+ } else if (m_provider->isValid()) {
+ m_status = Resolved;
+ emit resolutionFinished(this);
+ } else { // still not resolved. But network error is recoverable.
+ m_status = Idle;
+ //m_provider->resolveProvider();
}
}
-QUrl QGeoTileProviderOsm::tileAddress(int x, int y, int z) const
+void QGeoTileProviderOsm::addProvider(TileProvider *provider)
{
- if (m_provider.isValid())
- return m_provider.tileAddress(x,y,z);
- if (m_providerFallback.isValid())
- return m_providerFallback.tileAddress(x,y,z);
- return QUrl();
+ if (!provider)
+ return;
+ QScopedPointer<TileProvider> p(provider);
+ if (provider->status() == TileProvider::Invalid)
+ return; // if the provider is already resolved and invalid, no point in adding it.
+
+ provider = p.take();
+ provider->setNetworkManager(m_nm);
+ provider->setParent(this);
+ m_providerList.append(provider);
+ if (!m_provider)
+ m_provider = provider;
}
-QString QGeoTileProviderOsm::mapCopyRight() const
+
+/*
+ QGeoTileProviderOsm::TileProvder
+*/
+
+static void sort2(int &a, int &b)
{
- if (m_provider.isValid())
- return m_provider.mapCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.mapCopyRight();
- return QString();
+ if (a > b) {
+ int temp=a;
+ a=b;
+ b=temp;
+ }
}
-QString QGeoTileProviderOsm::dataCopyRight() const
+TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr)
{
- if (m_provider.isValid())
- return m_provider.dataCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.dataCopyRight();
- return QString();
+
}
-QString QGeoTileProviderOsm::styleCopyRight() const
+TileProvider::TileProvider(const QUrl &urlRedirector) : m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr)
{
- if (m_provider.isValid())
- return m_provider.styleCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.styleCopyRight();
- return QString();
+ if (!m_urlRedirector.isValid())
+ m_status = Invalid;
}
-QString QGeoTileProviderOsm::format() const
+TileProvider::TileProvider(const QString &urlTemplate,
+ const QString &format,
+ const QString &copyRightMap,
+ const QString &copyRightData,
+ 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)
{
- if (m_provider.isValid())
- return m_provider.format();
- if (m_providerFallback.isValid())
- return m_providerFallback.format();
- return QString();
+ setupProvider();
}
-const QGeoMapType &QGeoTileProviderOsm::mapType() const
+TileProvider::~TileProvider()
{
- return m_mapType;
}
-bool QGeoTileProviderOsm::isValid() const
+void TileProvider::resolveProvider()
{
- return (m_provider.isValid() || m_providerFallback.isValid());
+ if (!m_nm)
+ return;
+
+ switch (m_status) {
+ case Resolving:
+ case Invalid:
+ case Valid:
+ return;
+ case Idle:
+ m_status = Resolving;
+ break;
+ }
+
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::UserAgentHeader, QByteArrayLiteral("QGeoTileFetcherOsm"));
+ request.setUrl(m_urlRedirector);
+ QNetworkReply *reply = m_nm->get(request);
+ connect(reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished()) );
+ connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onNetworkReplyError(QNetworkReply::NetworkError)));
}
-bool QGeoTileProviderOsm::isResolved() const
+void TileProvider::handleError(QNetworkReply::NetworkError error)
{
- return (m_status == Valid || m_status == Invalid);
+ switch (error) {
+ case QNetworkReply::ConnectionRefusedError:
+ case QNetworkReply::TooManyRedirectsError:
+ case QNetworkReply::InsecureRedirectError:
+ case QNetworkReply::ContentAccessDenied:
+ case QNetworkReply::ContentOperationNotPermittedError:
+ case QNetworkReply::ContentNotFoundError:
+ case QNetworkReply::AuthenticationRequiredError:
+ case QNetworkReply::ContentGoneError:
+ case QNetworkReply::OperationNotImplementedError:
+ case QNetworkReply::ServiceUnavailableError:
+ // Errors we don't expect to recover from in the near future, which
+ // prevent accessing the redirection info but not the actual providers.
+ qWarning() << "QGeoTileProviderOsm network error:" << error;
+ m_status = Invalid;
+ default:
+ break;
+ }
}
-void QGeoTileProviderOsm::onNetworkReplyFinished()
+void TileProvider::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
reply->deleteLater();
switch (m_status) {
- case Resolving:
- m_status = Idle;
- case Idle: // should not happen
- case Invalid: // should not happen
- break;
- case Valid: // should not happen
- return;
+ case Resolving:
+ m_status = Idle;
+ case Idle: // should not happen
+ case Invalid: // should not happen
+ break;
+ case Valid: // should not happen
+ emit resolutionFinished(this);
+ return;
}
+ QObject errorEmitter;
+ QMetaObject::Connection errorEmitterConnection = connect(&errorEmitter, &QObject::destroyed, [this](){ this->resolutionError(this); });
+
if (reply->error() != QNetworkReply::NoError) {
handleError(reply->error());
- if (m_status == Invalid)
- emit resolutionError(this, reply->error());
return;
}
m_status = Invalid;
@@ -241,12 +362,10 @@ void QGeoTileProviderOsm::onNetworkReplyFinished()
QJsonDocument d = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qWarning() << "QGeoTileProviderOsm: Error parsing redirection data: "<<error.errorString() << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
if (!d.isObject()) {
qWarning() << "QGeoTileProviderOsm: Invalid redirection data" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
const QJsonObject json = d.object();
@@ -263,56 +382,175 @@ void QGeoTileProviderOsm::onNetworkReplyFinished()
|| !copyRightMap.isString()
|| !copyRightData.isString()) {
qWarning() << "QGeoTileProviderOsm: Incomplete redirection data" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
+ m_urlTemplate = urlTemplate.toString();
+ m_format = imageFormat.toString();
+ m_copyRightMap = copyRightMap.toString();
+ m_copyRightData = copyRightData.toString();
+
const QJsonValue enabled = json.value(QLatin1String("Enabled"));
if (enabled.isBool() && ! enabled.toBool()) {
qWarning() << "QGeoTileProviderOsm: Tileserver disabled" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
- QString styleCopyRight;
const QJsonValue copyRightStyle = json.value(QLatin1String("StyleCopyRight"));
if (copyRightStyle != QJsonValue::Undefined && copyRightStyle.isString())
- styleCopyRight = copyRightStyle.toString();
+ m_copyRightStyle = copyRightStyle.toString();
- int minZL = 0;
- int maxZL = 19;
+ m_minimumZoomLevel = 0;
+ m_maximumZoomLevel = 19;
const QJsonValue minZoom = json.value(QLatin1String("MinimumZoomLevel"));
if (minZoom.isDouble())
- minZL = qBound(0, int(minZoom.toDouble()), maxValidZoom);
+ m_minimumZoomLevel = qBound(0, int(minZoom.toDouble()), maxValidZoom);
const QJsonValue maxZoom = json.value(QLatin1String("MaximumZoomLevel"));
if (maxZoom.isDouble())
- maxZL = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
-
- m_provider = TileProvider(urlTemplate.toString(),
- imageFormat.toString(),
- copyRightMap.toString(),
- copyRightData.toString(),
- minZL,
- maxZL);
- m_provider.setStyleCopyRight(styleCopyRight);
-
- if (m_provider.isValid())
- m_status = Valid;
+ m_maximumZoomLevel = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
- emit resolutionFinished(this);
+ setupProvider();
+ if (isValid()) {
+ QObject::disconnect(errorEmitterConnection);
+ emit resolutionFinished(this);
+ }
}
-void QGeoTileProviderOsm::onNetworkReplyError(QNetworkReply::NetworkError error)
+void TileProvider::onNetworkReplyError(QNetworkReply::NetworkError error)
{
if (m_status == Resolving)
m_status = Idle;
- qWarning() << "QGeoTileProviderOsm::onNetworkReplyError " << error;
handleError(error);
-
static_cast<QNetworkReply *>(sender())->deleteLater();
- if (m_status == Invalid)
- emit resolutionError(this, error);
+ emit resolutionError(this);
+}
+
+void TileProvider::setupProvider()
+{
+ if (m_urlTemplate.isEmpty())
+ return;
+
+ if (m_format.isEmpty())
+ return;
+
+ if (m_minimumZoomLevel < 0 || m_minimumZoomLevel > 30)
+ return;
+
+ if (m_maximumZoomLevel < 0 || m_maximumZoomLevel > 30 || m_maximumZoomLevel < m_minimumZoomLevel)
+ return;
+
+ // Currently supporting only %x, %y and &z
+ int offset[3];
+ offset[0] = m_urlTemplate.indexOf(QLatin1String("%x"));
+ if (offset[0] < 0)
+ return;
+
+ offset[1] = m_urlTemplate.indexOf(QLatin1String("%y"));
+ if (offset[1] < 0)
+ return;
+
+ offset[2] = m_urlTemplate.indexOf(QLatin1String("%z"));
+ if (offset[2] < 0)
+ return;
+
+ int sortedOffsets[3];
+ std::copy(offset, offset + 3, sortedOffsets);
+ sort2(sortedOffsets[0] ,sortedOffsets[1]);
+ sort2(sortedOffsets[1] ,sortedOffsets[2]);
+ sort2(sortedOffsets[0] ,sortedOffsets[1]);
+
+ int min = sortedOffsets[0];
+ int max = sortedOffsets[2];
+ int mid = sortedOffsets[1];
+
+ // Initing LUT
+ for (int i=0; i<3; i++) {
+ if (offset[0] == sortedOffsets[i])
+ paramsLUT[i] = 0;
+ else if (offset[1] == sortedOffsets[i])
+ paramsLUT[i] = 1;
+ else
+ paramsLUT[i] = 2;
+ }
+
+ m_urlPrefix = m_urlTemplate.mid(0 , min);
+ m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2);
+
+ paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2);
+ paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2);
+ m_status = Valid;
}
+bool TileProvider::isValid() const
+{
+ return m_status == Valid;
+}
+
+bool TileProvider::isInvalid() const
+{
+ return m_status == Invalid;
+}
+
+bool TileProvider::isResolved() const
+{
+ return (m_status == Valid || m_status == Invalid);
+}
+
+QString TileProvider::mapCopyRight() const
+{
+ return m_copyRightMap;
+}
+
+QString TileProvider::dataCopyRight() const
+{
+ return m_copyRightData;
+}
+
+QString TileProvider::styleCopyRight() const
+{
+ return m_copyRightStyle;
+}
+
+QString TileProvider::format() const
+{
+ return m_format;
+}
+
+void TileProvider::setStyleCopyRight(const QString &copyright)
+{
+ m_copyRightStyle = copyright;
+}
+
+QUrl TileProvider::tileAddress(int x, int y, int z) const
+{
+ if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
+ return QUrl();
+ int params[3] = { x, y, z};
+ QString url;
+ url += m_urlPrefix;
+ url += QString::number(params[paramsLUT[0]]);
+ url += paramsSep[0];
+ url += QString::number(params[paramsLUT[1]]);
+ url += paramsSep[1];
+ url += QString::number(params[paramsLUT[2]]);
+ url += m_urlSuffix;
+ return QUrl(url);
+}
+
+void TileProvider::setNetworkManager(QNetworkAccessManager *nm)
+{
+ m_nm = nm;
+}
+
+TileProvider::Status TileProvider::status() const
+{
+ return m_status;
+}
+
+
QT_END_NAMESPACE
+
+
+
+
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.h b/src/plugins/geoservices/osm/qgeotileproviderosm.h
index f396b3b5..d9f80482 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.h
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.h
@@ -40,186 +40,102 @@
#include <QtLocation/private/qgeomaptype_p.h>
#include <QtCore/QUrl>
+#include <QtCore/QVector>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QPointer>
#include <QTimer>
#include <algorithm>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
QT_BEGIN_NAMESPACE
-class QGeoTileProviderOsm: public QObject
+class TileProvider: public QObject
{
Q_OBJECT
-
- friend class QGeoTileFetcherOsm;
- friend class QGeoMapReplyOsm;
- friend class QGeoTiledMappingManagerEngineOsm;
public:
- struct TileProvider {
-
- static inline void sort2(int &a, int &b)
- {
- if (a > b) {
- int temp=a;
- a=b;
- b=temp;
- }
- }
-
- TileProvider() : m_valid(false)
- {
-
- }
-
- TileProvider(const QString &urlTemplate,
- const QString &format,
- const QString &copyRightMap,
- const QString &copyRightData,
- int minimumZoomLevel = 0,
- int maximumZoomLevel = 19) : m_valid(false)
- {
- if (urlTemplate.isEmpty())
- return;
- m_urlTemplate = urlTemplate;
-
- if (format.isEmpty())
- return;
- m_format = format;
-
- m_copyRightMap = copyRightMap;
- m_copyRightData = copyRightData;
-
- if (minimumZoomLevel < 0 || minimumZoomLevel > 30)
- return;
- m_minimumZoomLevel = minimumZoomLevel;
-
- if (maximumZoomLevel < 0 || maximumZoomLevel > 30 || maximumZoomLevel < minimumZoomLevel)
- return;
- m_maximumZoomLevel = maximumZoomLevel;
-
- // Currently supporting only %x, %y and &z
- int offset[3];
- offset[0] = m_urlTemplate.indexOf(QLatin1String("%x"));
- if (offset[0] < 0)
- return;
-
- offset[1] = m_urlTemplate.indexOf(QLatin1String("%y"));
- if (offset[1] < 0)
- return;
-
- offset[2] = m_urlTemplate.indexOf(QLatin1String("%z"));
- if (offset[2] < 0)
- return;
-
- int sortedOffsets[3];
- std::copy(offset, offset + 3, sortedOffsets);
- sort2(sortedOffsets[0] ,sortedOffsets[1]);
- sort2(sortedOffsets[1] ,sortedOffsets[2]);
- sort2(sortedOffsets[0] ,sortedOffsets[1]);
-
- int min = sortedOffsets[0];
- int max = sortedOffsets[2];
- int mid = sortedOffsets[1];
-
- // Initing LUT
- for (int i=0; i<3; i++) {
- if (offset[0] == sortedOffsets[i])
- paramsLUT[i] = 0;
- else if (offset[1] == sortedOffsets[i])
- paramsLUT[i] = 1;
- else
- paramsLUT[i] = 2;
- }
-
- m_urlPrefix = m_urlTemplate.mid(0 , min);
- m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2);
+ enum Status {Idle,
+ Resolving,
+ Valid,
+ Invalid };
- paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2);
- paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2);
- m_valid = true;
- }
+ TileProvider();
+ // "Online" constructor. Needs resolution to fetch the parameters
+ TileProvider(const QUrl &urlRedirector);
+ // Offline constructor. Doesn't need URLRedirector and networkmanager
+ TileProvider(const QString &urlTemplate,
+ const QString &format,
+ const QString &copyRightMap,
+ const QString &copyRightData,
+ int minimumZoomLevel = 0,
+ int maximumZoomLevel = 19);
- ~TileProvider()
- {
- }
+ ~TileProvider();
+ void setNetworkManager(QNetworkAccessManager *nm);
- inline bool isValid() const
- {
- return m_valid;
- }
+ void resolveProvider();
+ void handleError(QNetworkReply::NetworkError error);
+ void setupProvider();
- inline QString mapCopyRight() const
- {
- return m_copyRightMap;
- }
+ inline bool isValid() const;
+ inline bool isInvalid() const;
+ inline bool isResolved() const;
+ inline Status status() const;
- inline QString dataCopyRight() const
- {
- return m_copyRightData;
- }
+ inline QString mapCopyRight() const;
+ inline QString dataCopyRight() const;
+ inline QString styleCopyRight() const;
+ inline QString format() const;
+ QUrl tileAddress(int x, int y, int z) const;
- inline QString styleCopyRight() const
- {
- return m_copyRightStyle;
- }
+ // Optional properties, not needed to construct a provider
+ void setStyleCopyRight(const QString &copyright);
- inline QString format() const
- {
- return m_format;
- }
+ Status m_status;
+ QUrl m_urlRedirector; // The URL from where to fetch the URL template in case of a provider to resolve.
+ QNetworkAccessManager *m_nm;
+ QString m_urlTemplate;
+ QString m_format;
+ QString m_copyRightMap;
+ QString m_copyRightData;
+ QString m_copyRightStyle;
+ QString m_urlPrefix;
+ QString m_urlSuffix;
+ int m_minimumZoomLevel;
+ int m_maximumZoomLevel;
+
+ int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z
+ QString paramsSep[2]; // what goes in between %x, %y and %z
- // Optional properties, not needed to construct a provider
- void setStyleCopyRight(const QString &copyright)
- {
- m_copyRightStyle = copyright;
- }
+Q_SIGNALS:
+ void resolutionFinished(TileProvider *provider);
+ void resolutionError(TileProvider *provider);
- QUrl tileAddress(int x, int y, int z) const
- {
- if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
- return QUrl();
- int params[3] = { x, y, z};
- QString url;
- url += m_urlPrefix;
- url += QString::number(params[paramsLUT[0]]);
- url += paramsSep[0];
- url += QString::number(params[paramsLUT[1]]);
- url += paramsSep[1];
- url += QString::number(params[paramsLUT[2]]);
- url += m_urlSuffix;
- return QUrl(url);
- }
+public Q_SLOTS:
+ void onNetworkReplyFinished();
+ void onNetworkReplyError(QNetworkReply::NetworkError error);
- bool m_valid;
- QString m_urlTemplate;
- QString m_format;
- QString m_copyRightMap;
- QString m_copyRightData;
- QString m_copyRightStyle;
- QString m_urlPrefix;
- QString m_urlSuffix;
- int m_minimumZoomLevel;
- int m_maximumZoomLevel;
+friend class QGeoTileProviderOsm;
+};
- int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z
- QString paramsSep[2]; // what goes in between %x, %y and %z
- };
+class QGeoTileProviderOsm: public QObject
+{
+ Q_OBJECT
+ friend class QGeoTileFetcherOsm;
+ friend class QGeoMapReplyOsm;
+ friend class QGeoTiledMappingManagerEngineOsm;
+public:
enum Status {Idle,
Resolving,
- Valid,
- Invalid };
-
- QGeoTileProviderOsm(const QString &urlRedir,
- QNetworkAccessManager *nm,
- const QGeoMapType &mapType,
- const TileProvider &providerFallback);
+ Resolved };
+ QGeoTileProviderOsm(QNetworkAccessManager *nm,
+ const QGeoMapType &mapType,
+ const QVector<TileProvider *> &providers);
~QGeoTileProviderOsm();
-
-
QUrl tileAddress(int x, int y, int z) const;
QString mapCopyRight() const;
QString dataCopyRight() const;
@@ -231,24 +147,27 @@ public:
Q_SIGNALS:
void resolutionFinished(const QGeoTileProviderOsm *provider);
- void resolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void resolutionError(const QGeoTileProviderOsm *provider);
public Q_SLOTS:
- void onNetworkReplyFinished();
- void onNetworkReplyError(QNetworkReply::NetworkError error);
void resolveProvider();
+ void disableRedirection();
+
+protected Q_SLOTS:
+ void onResolutionFinished(TileProvider *provider);
+ void onResolutionError(TileProvider *provider);
protected:
- void disableRedirection();
- void handleError(QNetworkReply::NetworkError error);
+ void addProvider(TileProvider *provider);
+
+/* Data members */
QNetworkAccessManager *m_nm;
- QUrl m_urlRedirector; // The URL from where to fetch the URL template
- TileProvider m_provider;
- TileProvider m_providerFallback;
+ QVector<TileProvider *> m_providerList;
+ TileProvider *m_provider;
+ int m_providerId;
QGeoMapType m_mapType;
Status m_status;
- QTimer m_retryTimer;
};
QT_END_NAMESPACE