From e7099f14c8faea4fb7c89877973b7cec75044cb3 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 26 Jul 2016 16:45:37 +0200 Subject: Enable dynamic addition/removal of map types by the mapping manager Map types are currently fixed in the constructor, regardless of whether they were available, or, now, whether they are enabled or not. This patch makes the geomappingmanager notify (e.g., emit a signal) when the available map types change at runtime. This is used in the OSM mappingmanagerengine, which can now disable map types if provider records turn out to be invalid or disabled after they have been fetched. Change-Id: I8e0e75504c882609f91c6d1ceb88424eee656f26 Reviewed-by: Leena Miettinen Reviewed-by: Alex Blasche --- src/imports/location/qdeclarativegeomap.cpp | 38 ++++++++++++++++++ src/imports/location/qdeclarativegeomap_p.h | 1 + src/location/doc/src/plugins/osm.qdoc | 9 ++++- src/location/maps/qgeomappingmanager.cpp | 6 +++ src/location/maps/qgeomappingmanager_p.h | 1 + src/location/maps/qgeomappingmanagerengine.cpp | 1 + src/location/maps/qgeomappingmanagerengine_p.h | 1 + .../osm/qgeotiledmappingmanagerengineosm.cpp | 46 +++++++++++++++++----- .../osm/qgeotiledmappingmanagerengineosm.h | 7 ++++ src/plugins/geoservices/osm/qgeotilefetcherosm.cpp | 5 ++- 10 files changed, 103 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp index b220c899..ad2b78da 100644 --- a/src/imports/location/qdeclarativegeomap.cpp +++ b/src/imports/location/qdeclarativegeomap.cpp @@ -249,6 +249,43 @@ void QDeclarativeGeoMap::onMapChildrenChanged() copyrights->setCopyrightsZ(maxChildZ + 1); } +static QDeclarativeGeoMapType *findMapType(const QList &types, const QGeoMapType &type) +{ + for (int i = 0; i < types.size(); ++i) + if (types[i]->mapType() == type) + return types[i]; + return Q_NULLPTR; +} + +void QDeclarativeGeoMap::onSupportedMapTypesChanged() +{ + QList supportedMapTypes; + QList types = m_mappingManager->supportedMapTypes(); + for (int i = 0; i < types.size(); ++i) { + // types that are present and get removed will be deleted at QObject destruction + QDeclarativeGeoMapType *type = findMapType(m_supportedMapTypes, types[i]); + if (!type) + type = new QDeclarativeGeoMapType(types[i], this); + supportedMapTypes.append(type); + } + m_supportedMapTypes.swap(supportedMapTypes); + if (m_supportedMapTypes.isEmpty()) { + m_map->setActiveMapType(QGeoMapType()); // no supported map types: setting an invalid one + } else { + bool hasMapType = false; + foreach (QDeclarativeGeoMapType *declarativeType, m_supportedMapTypes) { + if (declarativeType->mapType() == m_map->activeMapType()) + hasMapType = true; + } + if (!hasMapType) { + QDeclarativeGeoMapType *type = m_supportedMapTypes.at(0); + m_activeMapType = type; + m_map->setActiveMapType(type->mapType()); + } + } + + emit supportedMapTypesChanged(); +} void QDeclarativeGeoMap::setError(QGeoServiceProvider::Error error, const QString &errorString) { @@ -518,6 +555,7 @@ void QDeclarativeGeoMap::mappingManagerInitialized() m_map->prefetchData(); m_map->update(); + connect(m_mappingManager, SIGNAL(supportedMapTypesChanged()), this, SLOT(onSupportedMapTypesChanged())); emit minimumZoomLevelChanged(); emit maximumZoomLevelChanged(); emit supportedMapTypesChanged(); diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h index ca1b7a62..40693ef4 100644 --- a/src/imports/location/qdeclarativegeomap_p.h +++ b/src/imports/location/qdeclarativegeomap_p.h @@ -170,6 +170,7 @@ private Q_SLOTS: void mapCenterChanged(const QGeoCoordinate ¢er); void pluginReady(); void onMapChildrenChanged(); + void onSupportedMapTypesChanged(); private: void setupMapView(QDeclarativeGeoMapItemView *view); diff --git a/src/location/doc/src/plugins/osm.qdoc b/src/location/doc/src/plugins/osm.qdoc index 2fd9e7c4..75ac104d 100644 --- a/src/location/doc/src/plugins/osm.qdoc +++ b/src/location/doc/src/plugins/osm.qdoc @@ -37,12 +37,17 @@ This geo services plugin allows applications to access \l {http://openstreetmap.org}{Open Street Map} location based services using the Qt Location API. -Data, imagery and map information provided by \l {http://www.mapquest.com}{MapQuest}, +Data, imagery and map information provided by \l {http://korona.geog.uni-heidelberg.de/}{OpenMapSurfer}, \l {http://www.thunderforest.com/}{ThunderForest}, OpenStreetMap and contributors. The data is available under the \l {http://www.opendatacommons.org/licenses/odbl}{Open Database License}. The Open Street Map geo services plugin can be loaded by using the plugin key "osm". +\note Since Qt 5.6.2, the available map types offered by this plugin may change without notice depending on the +actual availability of each provider. To prevent these changes, either a different geo service plugin should be used, or the plugin +parameter \e osm.mapping.providersrepository.address should be set to a user-specified repository, in order to take full control over +(and accept \b responsibility for) selecting the provider that is used for each map type. + \section1 Parameters \section2 Optional parameters @@ -78,7 +83,7 @@ a prefix. \li The OpenStreetMap plugin retrieves the provider's information from a remote repository. This is done to prevent using hardcoded servers by default, which may become unavailable. By default this information is fetched from \l {http://maps-redirect.qt.io} {maps-redirect.qt.io}. Setting this parameter changes the provider repository address to a user-specified one, which must contain the files - \tt{street}, \tt{satellite}, \tt{cycle}, \tt{transit}, \tt{night-transit}, \tt{terrain} and \tt{hiking}. + \tt{street}, \tt{satellite}, \tt{cycle}, \tt{transit}, \tt{night-transit}, \tt{terrain} and \tt{hiking}, each of which must contain valid provider information. \row \li osm.mapping.providersrepository.disabled \li By default, the OpenStreetMap plugin retrieves the provider's information from a remote repository to avoid a loss of service due to unavailability of hardcoded services. diff --git a/src/location/maps/qgeomappingmanager.cpp b/src/location/maps/qgeomappingmanager.cpp index 681e68a7..8c02417d 100644 --- a/src/location/maps/qgeomappingmanager.cpp +++ b/src/location/maps/qgeomappingmanager.cpp @@ -81,6 +81,12 @@ QGeoMappingManager::QGeoMappingManager(QGeoMappingManagerEngine *engine, QObject this, SIGNAL(initialized()), Qt::QueuedConnection); + + connect(d_ptr->engine, + SIGNAL(supportedMapTypesChanged()), + this, + SIGNAL(supportedMapTypesChanged()), + Qt::QueuedConnection); } /*! diff --git a/src/location/maps/qgeomappingmanager_p.h b/src/location/maps/qgeomappingmanager_p.h index 043ebd8f..2ec1e8b5 100644 --- a/src/location/maps/qgeomappingmanager_p.h +++ b/src/location/maps/qgeomappingmanager_p.h @@ -89,6 +89,7 @@ public: Q_SIGNALS: void initialized(); + void supportedMapTypesChanged(); protected: QGeoMappingManager(QGeoMappingManagerEngine *engine, QObject *parent = 0); diff --git a/src/location/maps/qgeomappingmanagerengine.cpp b/src/location/maps/qgeomappingmanagerengine.cpp index 70b1e836..d25b4749 100644 --- a/src/location/maps/qgeomappingmanagerengine.cpp +++ b/src/location/maps/qgeomappingmanagerengine.cpp @@ -147,6 +147,7 @@ void QGeoMappingManagerEngine::setSupportedMapTypes(const QList &su { Q_D(QGeoMappingManagerEngine); d->supportedMapTypes = supportedMapTypes; + emit supportedMapTypesChanged(); } QGeoCameraCapabilities QGeoMappingManagerEngine::cameraCapabilities() diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h index 7e866d89..4eb24eac 100644 --- a/src/location/maps/qgeomappingmanagerengine_p.h +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -98,6 +98,7 @@ public: Q_SIGNALS: void initialized(); + void supportedMapTypesChanged(); protected: void setSupportedMapTypes(const QList &supportedMapTypes); diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp index 92982a1f..738bf9a9 100644 --- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp @@ -80,11 +80,8 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian new QGeoTileProviderOsm(domain + "satellite", nm, QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2), - QGeoTileProviderOsm::TileProvider(QStringLiteral("http://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/%z/%y/%x"), - QStringLiteral("jpg"), - QStringLiteral("USGS The National Map: Orthoimagery"), - QStringLiteral("USGS/NASA Landsat") - ))); + QGeoTileProviderOsm::TileProvider() + )); m_providers.push_back( new QGeoTileProviderOsm(domain + "cycle", nm, @@ -167,15 +164,17 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian if (parameters.contains(QStringLiteral("osm.mapping.providersrepository.disabled"))) disableRedirection = parameters.value(QStringLiteral("osm.mapping.providersrepository.disabled")).toBool(); - QList mapTypes; foreach (QGeoTileProviderOsm * provider, m_providers) { provider->setParent(this); if (disableRedirection) provider->disableRedirection(); - mapTypes << provider->mapType(); + + connect(provider, &QGeoTileProviderOsm::resolutionFinished, + this, &QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished); + connect(provider, &QGeoTileProviderOsm::resolutionError, + this, &QGeoTiledMappingManagerEngineOsm::onProviderResolutionError); } - // See map type implementations in QGeoTiledMapOsm and QGeoTileFetcherOsm. - setSupportedMapTypes(mapTypes); + updateMapTypes(); QGeoTileFetcherOsm *tileFetcher = new QGeoTileFetcherOsm(m_providers, nm, this); if (parameters.contains(QStringLiteral("osm.useragent"))) { @@ -214,4 +213,33 @@ QString QGeoTiledMappingManagerEngineOsm::customCopyright() const return m_customCopyright; } +void QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider) +{ + if (!provider->isResolved()) + return; + updateMapTypes(); +} + +void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + if (!provider->isResolved()) + return; + updateMapTypes(); +} + +void QGeoTiledMappingManagerEngineOsm::updateMapTypes() +{ + QList mapTypes; + foreach (QGeoTileProviderOsm * provider, m_providers) { + // assume provider are ok until they have been resolved invalid + if (!provider->isResolved() || provider->isValid()) + mapTypes << provider->mapType(); + } + const QList currentlySupportedMapTypes = supportedMapTypes(); + if (currentlySupportedMapTypes != mapTypes) + // See map type implementations in QGeoTiledMapOsm and QGeoTileFetcherOsm. + setSupportedMapTypes(mapTypes); +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h index 9755b0c2..68a7a517 100644 --- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h @@ -57,6 +57,13 @@ public: const QVector &providers(); QString customCopyright() const; +protected Q_SLOTS: + void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); + void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error); + +protected: + void updateMapTypes(); + private: QVector m_providers; QString m_customCopyright; diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp index 45da7d42..f643c66e 100644 --- a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp @@ -109,7 +109,10 @@ QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec) int id = spec.mapId(); if (id < 1 || id > m_providers.size()) { qWarning("Unknown map id %d\n", spec.mapId()); - id = 0; + if (m_providers.isEmpty()) + return Q_NULLPTR; + else + id = 1; } id -= 1; // TODO: make OSM map ids start from 0. -- cgit v1.2.1