| /**************************************************************************** |
| ** |
| ** Copyright (C) 2015 The Qt Company Ltd. |
| ** Contact: http://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtLocation module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL3$ |
| ** 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 http://www.qt.io/terms-conditions. For further |
| ** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free |
| ** Software Foundation and appearing in the file LICENSE.GPL included in |
| ** the packaging of this file. Please review the following information to |
| ** ensure the GNU General Public License version 2.0 requirements will be |
| ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qgeoserviceprovider.h" |
| #include "qgeoserviceprovider_p.h" |
| #include "qgeoserviceproviderfactory.h" |
| |
| #include "qgeocodingmanager.h" |
| #include "qgeomappingmanager_p.h" |
| #include "qgeoroutingmanager.h" |
| #include "qplacemanager.h" |
| #include "qnavigationmanager_p.h" |
| #include "qgeocodingmanagerengine.h" |
| #include "qgeomappingmanagerengine_p.h" |
| #include "qgeoroutingmanagerengine.h" |
| #include "qplacemanagerengine.h" |
| #include "qplacemanagerengine_p.h" |
| #include "qnavigationmanagerengine_p.h" |
| |
| #include <QList> |
| #include <QString> |
| #include <QVariant> |
| |
| #include <QDebug> |
| #include <QStringList> |
| #include <QCoreApplication> |
| #include <QObject> |
| #include <QMetaObject> |
| #include <QMetaEnum> |
| #include <QtCore/private/qfactoryloader_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, |
| ("org.qt-project.qt.geoservice.serviceproviderfactory/5.0", |
| QLatin1String("/geoservices"))) |
| |
| /*! |
| \class QGeoServiceProvider |
| \inmodule QtLocation |
| \ingroup QtLocation-common |
| \since 5.6 |
| |
| \brief The QGeoServiceProvider class aggregates access to services which provide |
| geographical information. |
| |
| The Maps and Navigation API allows people to access various kinds of |
| geographical information, including functionality to perform geocoding, |
| routing and the display of maps. The QGeoServiceProvider aggregates the |
| access to a set of these services that are provided by a single vendor. |
| |
| It is possible to mix and match service providers for the various domains, |
| so that a geocoding manager from one service provider can be used with |
| a geographic routing manager from another service provider. |
| |
| This is not recommended unless the client is able to verify that the |
| data provided by the different services are compatible, as differences |
| in the underlying data sets could cause serious incongruences between |
| the services. |
| |
| Subclasses of QGeoServiceProvider guarantee that the different services |
| that they provide are interoperable. |
| |
| At this point there are two GeoServices plugins packaged with Qt. They are |
| accessible using their provider names: |
| |
| \list |
| \li "mapbox" -> \l {Qt Location Mapbox Plugin}{Mapbox service} |
| \li "here" -> \l {Qt Location HERE Plugin}{HERE Services} |
| \li "osm" -> \l {Qt Location Open Street Map Plugin}{OpenStreetMap Services} |
| \li "esri" -> \l {Qt Location Esri Plugin}{ESRI Services} |
| \endlist |
| |
| Each service provider must follow a naming convention for their service specific |
| parameter names/keys. They use the provider name as prefix for all their |
| parameter names. For example, the \l {Qt Location HERE Plugin}{HERE} service provider |
| requires the \c here.app_id parameter. When a provider is loaded only those parameters are |
| passed on whose parameter names start with the provider name. This avoids the sharing |
| sensitive parameters such as confidential \c token or \c app_id parameters with other |
| plugins. |
| |
| Please check the GeoServices plugin specific documentation to |
| obtain a complete list of the available parameter names/keys and values. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::Error |
| |
| Describes an error related to the loading and setup of a service provider plugin. |
| |
| \value NoError |
| No error has occurred. |
| \value NotSupportedError |
| The plugin does not support this functionality. |
| \value UnknownParameterError |
| The plugin did not recognize one of the parameters it was given. |
| \value MissingRequiredParameterError |
| The plugin did not find one of the parameters it was expecting. |
| \value ConnectionError |
| The plugin could not connect to its backend service or database. |
| \value LoaderError |
| The plugin failed to load. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::RoutingFeature |
| |
| Describes the routing features supported by the geo service provider. |
| |
| \value NoRoutingFeatures No routing features are supported. |
| \value OnlineRoutingFeature Online routing is supported. |
| \value OfflineRoutingFeature Offline routing is supported. |
| \value LocalizedRoutingFeature Supports returning routes with localized addresses and |
| instructions. |
| \value RouteUpdatesFeature Updating an existing route based on the current position is |
| supported. |
| \value AlternativeRoutesFeature Supports returning alternative routes. |
| \value ExcludeAreasRoutingFeature Supports specifying a areas which the returned route must |
| not cross. |
| \value AnyRoutingFeatures Matches a geo service provider that provides any routing |
| features. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::GeocodingFeature |
| |
| Describes the geocoding features supported by the geo service provider. |
| |
| \value NoGeocodingFeatures No geocoding features are supported. |
| \value OnlineGeocodingFeature Online geocoding is supported. |
| \value OfflineGeocodingFeature Offline geocoding is supported. |
| \value ReverseGeocodingFeature Reverse geocoding is supported. |
| \value LocalizedGeocodingFeature Supports returning geocoding results with localized |
| addresses. |
| \value AnyGeocodingFeatures Matches a geo service provider that provides any geocoding |
| features. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::MappingFeature |
| |
| Describes the mapping features supported by the geo service provider. |
| |
| \value NoMappingFeatures No mapping features are supported. |
| \value OnlineMappingFeature Online mapping is supported. |
| \value OfflineMappingFeature Offline mapping is supported. |
| \value LocalizedMappingFeature Supports returning localized map data. |
| \value AnyMappingFeatures Matches a geo service provider that provides any mapping |
| features. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::PlacesFeature |
| |
| Describes the places features supported by the geo service provider. |
| |
| \value NoPlacesFeatures No places features are supported. |
| \value OnlinePlacesFeature Online places is supported. |
| \value OfflinePlacesFeature Offline places is supported. |
| \value SavePlaceFeature Saving places is supported. |
| \value RemovePlaceFeature Removing or deleting places is supported. |
| \value SaveCategoryFeature Saving categories is supported. |
| \value RemoveCategoryFeature Removing or deleting categories is supported. |
| \value PlaceRecommendationsFeature Searching for recommended places similar to another place |
| is supported. |
| \value SearchSuggestionsFeature Search suggestions is supported. |
| \value LocalizedPlacesFeature Supports returning localized place data. |
| \value NotificationsFeature Notifications of place and category changes is supported. |
| \value PlaceMatchingFeature Supports matching places from two different geo service |
| providers. |
| \value AnyPlacesFeatures Matches a geo service provider that provides any places |
| features. |
| */ |
| |
| /*! |
| \enum QGeoServiceProvider::NavigationFeature |
| |
| Describes the navigation features supported by the geo service provider. |
| |
| \value NoNavigationFeatures No navigation features are supported. |
| \value OnlineNavigationFeature Online navigation is supported. |
| \value OfflineNavigationFeature Offline navigation is supported. |
| \value AnyNavigationFeatures Matches a geo service provider that provides any navigation |
| features. |
| */ |
| |
| /*! |
| Returns a list of names of the available service providers, for use with |
| the QGeoServiceProvider constructors. |
| */ |
| QStringList QGeoServiceProvider::availableServiceProviders() |
| { |
| return QGeoServiceProviderPrivate::plugins().keys(); |
| } |
| |
| /*! |
| Constructs a QGeoServiceProvider whose backend has the name \a |
| providerName, using the provided \a parameters. |
| |
| If multiple plugins have the same \a providerName, the plugin with the |
| highest reported providerVersion() will be used. |
| |
| If \a allowExperimental is true then plugins marked as experimental may be used. By default |
| experimental plugins are not considered. |
| |
| If no plugin matching \a providerName was able to be loaded then error() |
| and errorString() will provide details about why this is the case. |
| |
| \note Before the list of \a parameters is passed on to the to-be-loaded |
| provider plugin, the list is filtered to avoid the sharing of plugin specific |
| parameters with unrelated provider plugins. Plugin specific parameter |
| keys must be prefixed with the provider name (e.g. \c here.app_id). |
| */ |
| QGeoServiceProvider::QGeoServiceProvider(const QString &providerName, |
| const QVariantMap ¶meters, |
| bool allowExperimental) |
| : d_ptr(new QGeoServiceProviderPrivate()) |
| { |
| d_ptr->experimental = allowExperimental; |
| d_ptr->parameterMap = parameters; |
| // TODO Qt 6 Remove silent nokia rename |
| if (providerName == QStringLiteral("nokia")) |
| d_ptr->providerName = QStringLiteral("here"); |
| else |
| d_ptr->providerName = providerName; |
| d_ptr->loadMeta(); |
| } |
| |
| /*! |
| Destroys the service provider object. |
| */ |
| QGeoServiceProvider::~QGeoServiceProvider() |
| { |
| delete d_ptr; |
| } |
| |
| /* Template for the routingFeatures(), geocodingFeatures() etc methods. |
| * Ideally, the enumName would be a template parameter, but strings |
| * are not a valid const expr. :( */ |
| template <class Flags> |
| Flags QGeoServiceProviderPrivate::features(const char *enumName) |
| { |
| const QMetaObject *mo = &QGeoServiceProvider::staticMetaObject; |
| const QMetaEnum en = mo->enumerator( |
| mo->indexOfEnumerator(enumName)); |
| |
| /* We need the typename keyword here, or Flags::enum_type will be parsed |
| * as a non-type and lead to an error */ |
| Flags ret = typename Flags::enum_type(0); |
| if (this->metaData.contains(QStringLiteral("Features")) |
| && this->metaData.value(QStringLiteral("Features")).isArray()) { |
| QJsonArray features = this->metaData.value(QStringLiteral("Features")).toArray(); |
| foreach (const QJsonValue &v, features) { |
| int val = en.keyToValue(v.toString().toLatin1().constData()); |
| if (v.isString() && val != -1) { |
| ret |= typename Flags::enum_type(val); |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| /*! |
| Returns the routing features supported by the geo service provider. |
| */ |
| QGeoServiceProvider::RoutingFeatures QGeoServiceProvider::routingFeatures() const |
| { |
| return d_ptr->features<RoutingFeatures>("RoutingFeatures"); |
| } |
| |
| /*! |
| Returns the geocoding features supported by the geo service provider. |
| */ |
| QGeoServiceProvider::GeocodingFeatures QGeoServiceProvider::geocodingFeatures() const |
| { |
| return d_ptr->features<GeocodingFeatures>("GeocodingFeatures"); |
| } |
| |
| /*! |
| Returns the mapping features supported by the geo service provider. |
| */ |
| QGeoServiceProvider::MappingFeatures QGeoServiceProvider::mappingFeatures() const |
| { |
| return d_ptr->features<MappingFeatures>("MappingFeatures"); |
| } |
| |
| /*! |
| Returns the places features supported by the geo service provider. |
| */ |
| QGeoServiceProvider::PlacesFeatures QGeoServiceProvider::placesFeatures() const |
| { |
| return d_ptr->features<PlacesFeatures>("PlacesFeatures"); |
| } |
| |
| /*! |
| Returns the navigation features supported by the geo service provider. |
| |
| \since QtLocation 5.11 |
| */ |
| QGeoServiceProvider::NavigationFeatures QGeoServiceProvider::navigationFeatures() const |
| { |
| return d_ptr->features<NavigationFeatures>("NavigationFeatures"); |
| } |
| |
| /* Sadly, these are necessary to figure out which of the factory->createX |
| * methods we need to call. Ideally it would be nice to find a way to embed |
| * these into the manager() template. */ |
| template <class Engine> |
| Engine *createEngine(QGeoServiceProviderPrivate *) |
| { |
| return 0; |
| } |
| template <> QGeoCodingManagerEngine *createEngine<QGeoCodingManagerEngine>(QGeoServiceProviderPrivate *d_ptr) |
| { |
| return d_ptr->factory->createGeocodingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->geocodeError), &(d_ptr->geocodeErrorString)); |
| } |
| template <> QGeoRoutingManagerEngine *createEngine<QGeoRoutingManagerEngine>(QGeoServiceProviderPrivate *d_ptr) |
| { |
| return d_ptr->factory->createRoutingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->routingError), &(d_ptr->routingErrorString)); |
| } |
| template <> QGeoMappingManagerEngine *createEngine<QGeoMappingManagerEngine>(QGeoServiceProviderPrivate *d_ptr) |
| { |
| return d_ptr->factory->createMappingManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->mappingError), &(d_ptr->mappingErrorString)); |
| } |
| template <> QPlaceManagerEngine *createEngine<QPlaceManagerEngine>(QGeoServiceProviderPrivate *d_ptr) |
| { |
| return d_ptr->factory->createPlaceManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->placeError), &(d_ptr->placeErrorString)); |
| } |
| template <> QNavigationManagerEngine *createEngine<QNavigationManagerEngine>(QGeoServiceProviderPrivate *d_ptr) |
| { |
| if (!d_ptr->factoryV2) |
| return nullptr; |
| return d_ptr->factoryV2->createNavigationManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->navigationError), &(d_ptr->navigationErrorString)); |
| } |
| |
| /* Template for generating the code for each of the geocodingManager(), |
| * mappingManager() etc methods */ |
| template <class Manager, class Engine> |
| Manager *QGeoServiceProviderPrivate::manager(QGeoServiceProvider::Error *_error, |
| QString *_errorString, Manager **_manager) |
| { |
| // make local references just so this method is easier to read |
| QGeoServiceProvider::Error &error = *_error; |
| QString &errorString = *_errorString; |
| Manager *&manager = *_manager; |
| |
| if (!this->factory) { |
| this->filterParameterMap(); |
| this->loadPlugin(this->parameterMap); |
| } |
| |
| if (!this->factory) { |
| error = this->error; |
| errorString = this->errorString; |
| return 0; |
| } |
| |
| if (!manager) { |
| Engine *engine = createEngine<Engine>(this); // this sets the specific error variables directly, |
| // from now on the local error, errorString refs should be set. |
| |
| if (engine) { |
| engine->setManagerName( |
| this->metaData.value(QStringLiteral("Provider")).toString()); |
| engine->setManagerVersion( |
| int(this->metaData.value(QStringLiteral("Version")).toDouble())); |
| manager = new Manager(engine); |
| } else if (error == QGeoServiceProvider::NoError) { |
| error = QGeoServiceProvider::NotSupportedError; |
| errorString = QLatin1String("The service provider does not support the "); |
| errorString.append(QLatin1String(Manager::staticMetaObject.className())); |
| errorString.append(QLatin1String(" type.")); |
| } |
| |
| if (error != QGeoServiceProvider::NoError) { |
| delete manager; |
| manager = 0; |
| this->error = error; |
| this->errorString = errorString; |
| } |
| |
| if (manager && this->localeSet) |
| manager->setLocale(this->locale); |
| } |
| |
| if (manager) { |
| this->error = QGeoServiceProvider::NoError; |
| this->errorString.clear(); |
| } |
| |
| return manager; |
| } |
| |
| /*! |
| Returns the QGeoCodingManager made available by the service |
| provider. |
| |
| This function will return 0 if the service provider does not provide |
| any geocoding services. |
| |
| This function will attempt to construct a QGeoCodingManager instance |
| when it is called for the first time. If the attempt is successful the |
| QGeoCodingManager will be cached, otherwise each call of this function |
| will attempt to construct a QGeoCodingManager instance until the |
| construction is successful. |
| |
| The QGeoCodingManager is owned by this QGeoServiceProvider and should not |
| be deleted separately. Users should assume that deleting the |
| QGeoServiceProvider renders the pointer returned by this method invalid. |
| |
| After this function has been called, error() and errorString() will |
| report any errors which occurred during the construction of the |
| QGeoCodingManager. |
| */ |
| QGeoCodingManager *QGeoServiceProvider::geocodingManager() const |
| { |
| QGeoCodingManager *mgr = d_ptr->manager<QGeoCodingManager, QGeoCodingManagerEngine>( |
| &(d_ptr->geocodeError), &(d_ptr->geocodeErrorString), |
| &(d_ptr->geocodingManager)); |
| if (!mgr) |
| qDebug() << d_ptr->error << ", " << d_ptr->errorString; |
| return mgr; |
| } |
| |
| /*! |
| Returns the QGeoMappingManager made available by the service provider. |
| |
| This function will return 0 if the service provider does not provide |
| any mapping services. |
| |
| This function will attempt to construct a QGeoMappingManager instance |
| when it is called for the first time. If the attempt is successful the |
| QGeoMappingManager will be cached, otherwise each call of this function |
| will attempt to construct a QGeoMappingManager instance until the |
| construction is successful. |
| |
| The QGeoMappingManager is owned by this QGeoServiceProvider and should not |
| be deleted separately. Users should assume that deleting the |
| QGeoServiceProvider renders the pointer returned by this method invalid. |
| |
| After this function has been called, error() and errorString() will |
| report any errors which occurred during the construction of the |
| QGeoMappingManager. |
| |
| \internal |
| */ |
| QGeoMappingManager *QGeoServiceProvider::mappingManager() const |
| { |
| QGeoMappingManager *mgr = d_ptr->manager<QGeoMappingManager, QGeoMappingManagerEngine>( |
| &(d_ptr->mappingError), &(d_ptr->mappingErrorString), |
| &(d_ptr->mappingManager)); |
| if (!mgr) |
| qDebug() << d_ptr->error << ", " << d_ptr->errorString; |
| return mgr; |
| } |
| |
| /*! |
| Returns the QGeoRoutingManager made available by the service provider. |
| |
| This function will return 0 if the service provider does not provide |
| any geographic routing services. |
| |
| This function will attempt to construct a QGeoRoutingManager instance |
| when it is called for the first time. If the attempt is successful the |
| QGeoRoutingManager will be cached, otherwise each call of this function |
| will attempt to construct a QGeoRoutingManager instance until the |
| construction is successful. |
| |
| The QGeoRoutingManager is owned by this QGeoServiceProvider and should not |
| be deleted separately. Users should assume that deleting the |
| QGeoServiceProvider renders the pointer returned by this method invalid. |
| |
| After this function has been called, error() and errorString() will |
| report any errors which occurred during the construction of the |
| QGeoRoutingManager. |
| */ |
| QGeoRoutingManager *QGeoServiceProvider::routingManager() const |
| { |
| QGeoRoutingManager *mgr = d_ptr->manager<QGeoRoutingManager, QGeoRoutingManagerEngine>( |
| &(d_ptr->routingError), &(d_ptr->routingErrorString), |
| &(d_ptr->routingManager)); |
| if (!mgr) |
| qDebug() << d_ptr->error << ", " << d_ptr->errorString; |
| return mgr; |
| } |
| |
| /*! |
| Returns the QPlaceManager made available by the service provider. |
| |
| This function will attempt to construct a QPlaceManager instance |
| when it is called for the first time. If the attempt is successful the |
| QPlaceManager will be cached, otherwise each call of this function |
| will attempt to construct a QPlace instance until the |
| construction is successful. |
| |
| The QGeoPlaceManager is owned by this QGeoServiceProvider and should not |
| be deleted separately. Users should assume that deleting the |
| QGeoServiceProvider renders the pointer returned by this method invalid. |
| |
| After this function has been called, error() and errorString() will |
| report any errors which occurred during the construction of the QPlaceManager. |
| */ |
| QPlaceManager *QGeoServiceProvider::placeManager() const |
| { |
| QPlaceManager *mgr = d_ptr->manager<QPlaceManager, QPlaceManagerEngine>( |
| &(d_ptr->placeError), &(d_ptr->placeErrorString), |
| &(d_ptr->placeManager)); |
| if (!mgr) |
| qDebug() << d_ptr->error << ", " << d_ptr->errorString; |
| return mgr; |
| } |
| |
| /*! |
| Returns a new QNavigationManager made available by the service provider. |
| |
| After this function has been called, error() and errorString() will |
| report any errors which occurred during the construction of the QNavigationManagerEngine. |
| */ |
| QNavigationManager *QGeoServiceProvider::navigationManager() const |
| { |
| QNavigationManager * mgr = d_ptr->manager<QNavigationManager, QNavigationManagerEngine>( |
| &(d_ptr->navigationError), &(d_ptr->navigationErrorString), |
| &(d_ptr->navigationManager)); |
| if (!mgr) |
| qDebug() << d_ptr->error << ", " << d_ptr->errorString; |
| return mgr; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last operation that was performed by this class. |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::error() const |
| { |
| return d_ptr->error; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last operation that was performed by this class. |
| */ |
| QString QGeoServiceProvider::errorString() const |
| { |
| return d_ptr->errorString; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last attempt to create a mapping manager. |
| |
| \since 5.13 |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::mappingError() const |
| { |
| return d_ptr->mappingError; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last attempt to create a mapping manager. |
| |
| \since 5.13 |
| */ |
| QString QGeoServiceProvider::mappingErrorString() const |
| { |
| return d_ptr->mappingErrorString; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last attempt to create a geocoding manager. |
| |
| \since 5.13 |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::geocodingError() const |
| { |
| return d_ptr->geocodeError; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last attempt to create a geocoding manager. |
| |
| \since 5.13 |
| */ |
| QString QGeoServiceProvider::geocodingErrorString() const |
| { |
| return d_ptr->geocodeErrorString; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last attempt to create a routing manager. |
| |
| \since 5.13 |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::routingError() const |
| { |
| return d_ptr->routingError; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last attempt to create a routing manager. |
| |
| \since 5.13 |
| */ |
| QString QGeoServiceProvider::routingErrorString() const |
| { |
| return d_ptr->routingErrorString; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last attempt to create a places manager. |
| |
| \since 5.13 |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::placesError() const |
| { |
| return d_ptr->placeError; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last attempt to create a places manager. |
| |
| \since 5.13 |
| */ |
| QString QGeoServiceProvider::placesErrorString() const |
| { |
| return d_ptr->placeErrorString; |
| } |
| |
| /*! |
| Returns an error code describing the error which occurred during the |
| last attempt to create a navigation manager. |
| |
| \since 5.13 |
| */ |
| QGeoServiceProvider::Error QGeoServiceProvider::navigationError() const |
| { |
| return d_ptr->navigationError; |
| } |
| |
| /*! |
| Returns a string describing the error which occurred during the |
| last attempt to create a navigation manager. |
| |
| \since 5.13 |
| */ |
| QString QGeoServiceProvider::navigationErrorString() const |
| { |
| return d_ptr->navigationErrorString; |
| } |
| |
| /*! |
| Sets whether experimental plugins are considered when locating the |
| correct plugin library for this service provider to \a allow. |
| |
| \b {Important:} this will destroy any existing managers held by this |
| service provider instance. You should be sure not to attempt to use any |
| pointers that you have previously retrieved after calling this method. |
| */ |
| void QGeoServiceProvider::setAllowExperimental(bool allow) |
| { |
| d_ptr->experimental = allow; |
| d_ptr->unload(); |
| d_ptr->loadMeta(); |
| } |
| |
| void QGeoServiceProvider::setQmlEngine(QQmlEngine *engine) |
| { |
| d_ptr->qmlEngine = engine; |
| } |
| |
| /*! |
| Sets the parameters used to construct individual manager classes for |
| this service provider to \a parameters. |
| |
| Before the list of \a parameters is passed on to the to-be-loaded |
| service provider, the list is filtered to avoid the sharing of provider specific |
| parameters with unrelated service providers. Provider specific parameter |
| keys must be prefixed with the provider name (e.g. \c here.app_id). |
| |
| \b {Important:} this will destroy any existing managers held by this |
| service provider instance. You should be sure not to attempt to use any |
| pointers that you have previously retrieved after calling this method. |
| */ |
| void QGeoServiceProvider::setParameters(const QVariantMap ¶meters) |
| { |
| d_ptr->parameterMap = parameters; |
| d_ptr->unload(); |
| d_ptr->loadMeta(); |
| } |
| |
| /*! |
| Sets the locale used by this service provider to \a locale. If the relevant features |
| (see LocalizedMappingFeature etc), this will change the languages, units |
| and other locale-specific attributes of the provider's data. |
| */ |
| void QGeoServiceProvider::setLocale(const QLocale &locale) |
| { |
| d_ptr->locale = locale; |
| d_ptr->localeSet = true; |
| |
| if (d_ptr->geocodingManager) |
| d_ptr->geocodingManager->setLocale(locale); |
| if (d_ptr->routingManager) |
| d_ptr->routingManager->setLocale(locale); |
| if (d_ptr->mappingManager) |
| d_ptr->mappingManager->setLocale(locale); |
| if (d_ptr->placeManager) |
| d_ptr->placeManager->setLocale(locale); |
| if (d_ptr->navigationManager) |
| d_ptr->navigationManager->setLocale(locale); |
| } |
| |
| /******************************************************************************* |
| *******************************************************************************/ |
| |
| QGeoServiceProviderPrivate::QGeoServiceProviderPrivate() |
| : factory(0), |
| experimental(false), |
| geocodingManager(0), |
| routingManager(0), |
| mappingManager(0), |
| placeManager(0), |
| geocodeError(QGeoServiceProvider::NoError), |
| routingError(QGeoServiceProvider::NoError), |
| mappingError(QGeoServiceProvider::NoError), |
| placeError(QGeoServiceProvider::NoError), |
| error(QGeoServiceProvider::NoError), |
| localeSet(false) |
| { |
| metaData.insert(QStringLiteral("index"), -1); |
| } |
| |
| QGeoServiceProviderPrivate::~QGeoServiceProviderPrivate() |
| { |
| delete geocodingManager; |
| delete routingManager; |
| delete mappingManager; |
| delete placeManager; |
| delete navigationManager; |
| } |
| |
| void QGeoServiceProviderPrivate::unload() |
| { |
| delete geocodingManager; |
| geocodingManager = 0; |
| |
| delete routingManager; |
| routingManager = 0; |
| |
| delete mappingManager; |
| mappingManager = 0; |
| |
| delete placeManager; |
| placeManager = 0; |
| |
| delete navigationManager; |
| navigationManager = nullptr; |
| |
| factory = factoryV2 = factoryV3 = nullptr; |
| error = QGeoServiceProvider::NoError; |
| errorString = QLatin1String(""); |
| metaData = QJsonObject(); |
| metaData.insert(QStringLiteral("index"), -1); |
| } |
| |
| /* Filter out any parameter that doesn't match any plugin */ |
| void QGeoServiceProviderPrivate::filterParameterMap() |
| { |
| const auto availablePlugins = QGeoServiceProviderPrivate::plugins(); |
| |
| cleanedParameterMap = parameterMap; |
| for (auto it = availablePlugins.keyBegin(), end = availablePlugins.keyEnd(); it != end; ++it) { |
| if (*it == providerName) // don't remove parameters for current provider |
| continue; |
| |
| QVariantMap::iterator i = cleanedParameterMap.begin(); |
| while (i != cleanedParameterMap.end()) { |
| // remove every parameter meant for other plugins |
| if (i.key().startsWith(QString(*it + QLatin1Char('.')))) |
| i = cleanedParameterMap.erase(i); |
| else |
| ++i; |
| } |
| } |
| } |
| |
| void QGeoServiceProviderPrivate::loadMeta() |
| { |
| factory = factoryV2 = factoryV3 = nullptr; |
| metaData = QJsonObject(); |
| metaData.insert(QStringLiteral("index"), -1); |
| error = QGeoServiceProvider::NotSupportedError; |
| errorString = QString(QLatin1String("The geoservices provider %1 is not supported.")).arg(providerName); |
| |
| QList<QJsonObject> candidates = QGeoServiceProviderPrivate::plugins().values(providerName); |
| |
| int versionFound = -1; |
| int idx = -1; |
| |
| // figure out which version of the plugin we want |
| // (always latest unless experimental) |
| for (int i = 0; i < candidates.size(); ++i) { |
| QJsonObject meta = candidates[i]; |
| if (meta.contains(QStringLiteral("Version")) |
| && meta.value(QStringLiteral("Version")).isDouble() |
| && meta.contains(QStringLiteral("Experimental")) |
| && meta.value(QStringLiteral("Experimental")).isBool()) { |
| int ver = int(meta.value(QStringLiteral("Version")).toDouble()); |
| if (ver > versionFound && !(!experimental && meta.value(QStringLiteral("Experimental")).toBool())) { |
| versionFound = ver; |
| idx = i; |
| } |
| } |
| } |
| |
| if (idx != -1) { |
| error = QGeoServiceProvider::NoError; |
| errorString = QStringLiteral(""); |
| metaData = candidates[idx]; |
| } |
| } |
| |
| void QGeoServiceProviderPrivate::loadPlugin(const QVariantMap ¶meters) |
| { |
| Q_UNUSED(parameters); |
| |
| if (int(metaData.value(QStringLiteral("index")).toDouble()) < 0) { |
| error = QGeoServiceProvider::NotSupportedError; |
| errorString = QString(QLatin1String("The geoservices provider is not supported.")); |
| factory = factoryV2 = factoryV3 = nullptr; |
| return; |
| } |
| |
| error = QGeoServiceProvider::NoError; |
| errorString = QLatin1String(""); |
| |
| int idx = int(metaData.value(QStringLiteral("index")).toDouble()); |
| |
| // load the actual plugin |
| QObject *instance = loader()->instance(idx); |
| if (!instance) { |
| error = QGeoServiceProvider::LoaderError; |
| errorString = QLatin1String("loader()->instance(idx) failed to return an instance. Set the environment variable QT_DEBUG_PLUGINS to see more details."); |
| return; |
| } |
| factoryV3 = qobject_cast<QGeoServiceProviderFactoryV3 *>(instance); |
| if (!factoryV3) { |
| factoryV2 = qobject_cast<QGeoServiceProviderFactoryV2 *>(instance); |
| if (!factoryV2) |
| factory = qobject_cast<QGeoServiceProviderFactory *>(instance); |
| else |
| factory = factoryV2; |
| } else { |
| factory = factoryV2 = factoryV3; |
| factoryV3->setQmlEngine(qmlEngine); |
| } |
| } |
| |
| QHash<QString, QJsonObject> QGeoServiceProviderPrivate::plugins(bool reload) |
| { |
| static QHash<QString, QJsonObject> plugins; |
| static bool alreadyDiscovered = false; |
| |
| if (reload == true) |
| alreadyDiscovered = false; |
| |
| if (!alreadyDiscovered) { |
| loadPluginMetadata(plugins); |
| alreadyDiscovered = true; |
| } |
| return plugins; |
| } |
| |
| void QGeoServiceProviderPrivate::loadPluginMetadata(QHash<QString, QJsonObject> &list) |
| { |
| QFactoryLoader *l = loader(); |
| QList<QJsonObject> meta = l->metaData(); |
| for (int i = 0; i < meta.size(); ++i) { |
| QJsonObject obj = meta.at(i).value(QStringLiteral("MetaData")).toObject(); |
| obj.insert(QStringLiteral("index"), i); |
| list.insertMulti(obj.value(QStringLiteral("Provider")).toString(), obj); |
| } |
| } |
| |
| |
| QT_END_NAMESPACE |
| |