| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. | 
| 4 | ** Contact: http://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the QtLocation module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL3$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at http://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or later as published by the Free | 
| 28 | ** Software Foundation and appearing in the file LICENSE.GPL included in | 
| 29 | ** the packaging of this file. Please review the following information to | 
| 30 | ** ensure the GNU General Public License version 2.0 requirements will be | 
| 31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. | 
| 32 | ** | 
| 33 | ** $QT_END_LICENSE$ | 
| 34 | ** | 
| 35 | ****************************************************************************/ | 
| 36 |  | 
| 37 | #include "qdeclarativegeoserviceprovider_p.h" | 
| 38 | #include <QtQml/QQmlInfo> | 
| 39 | #include <QtQml/QQmlEngine> | 
| 40 |  | 
| 41 | QT_BEGIN_NAMESPACE | 
| 42 |  | 
| 43 | /*! | 
| 44 |     \qmltype Plugin | 
| 45 |     //! \instantiates QDeclarativeGeoServiceProvider | 
| 46 |     \inqmlmodule QtLocation | 
| 47 |     \ingroup qml-QtLocation5-common | 
| 48 |     \since QtLocation 5.5 | 
| 49 |  | 
| 50 |     \brief The Plugin type describes a Location based services plugin. | 
| 51 |  | 
| 52 |     The Plugin type is used to declaratively specify which available | 
| 53 |     GeoServices plugin should be used for various tasks in the Location API. | 
| 54 |     Plugins are used by \l Map, \l RouteModel, and \l GeocodeModel | 
| 55 |     types, as well as a variety of others. | 
| 56 |  | 
| 57 |     Plugins recognized by the system have a \l name property, a simple string | 
| 58 |     normally indicating the name of the service that the Plugin retrieves | 
| 59 |     data from. They also have a variety of features, which can be test for using the | 
| 60 |     \l {supportsRouting()}, \l {supportsGeocoding()}, \l {supportsMapping()}, | 
| 61 |     \l {supportsPlaces()} and \l {supportsNavigation()} methods. | 
| 62 |  | 
| 63 |     When a Plugin object is created, it is "detached" and not associated with | 
| 64 |     any actual service plugin. Once it has received information via setting | 
| 65 |     its \l name, \l preferred, or \l required properties, it will choose an | 
| 66 |     appropriate service plugin to attach to. Plugin objects can only be | 
| 67 |     attached once; to use multiple plugins, create multiple Plugin objects. | 
| 68 |  | 
| 69 |     \section2 Example Usage | 
| 70 |  | 
| 71 |     The following snippet shows a Plugin object being created with the | 
| 72 |     \l required and \l preferred properties set. This Plugin will attach to the | 
| 73 |     first found plugin that supports both mapping and geocoding, and will | 
| 74 |     prefer plugins named "here" or "osm" to any others. | 
| 75 |  | 
| 76 |     \code | 
| 77 |     Plugin { | 
| 78 |         id: plugin | 
| 79 |         preferred: ["here", "osm"] | 
| 80 |         required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures | 
| 81 |     } | 
| 82 |     \endcode | 
| 83 | */ | 
| 84 |  | 
| 85 | QDeclarativeGeoServiceProvider::QDeclarativeGeoServiceProvider(QObject *parent) | 
| 86 | :   QObject(parent), | 
| 87 |     sharedProvider_(0), | 
| 88 |     required_(new QDeclarativeGeoServiceProviderRequirements), | 
| 89 |     complete_(false), | 
| 90 |     experimental_(false) | 
| 91 | { | 
| 92 |     locales_.append(t: QLocale().name()); | 
| 93 | } | 
| 94 |  | 
| 95 | QDeclarativeGeoServiceProvider::~QDeclarativeGeoServiceProvider() | 
| 96 | { | 
| 97 |     delete required_; | 
| 98 |     delete sharedProvider_; | 
| 99 | } | 
| 100 |  | 
| 101 |  | 
| 102 |  | 
| 103 | /*! | 
| 104 |     \qmlproperty string Plugin::name | 
| 105 |  | 
| 106 |     This property holds the name of the plugin. Setting this property | 
| 107 |     will cause the Plugin to only attach to a plugin with exactly this | 
| 108 |     name. The value of \l required will be ignored. | 
| 109 | */ | 
| 110 | void QDeclarativeGeoServiceProvider::setName(const QString &name) | 
| 111 | { | 
| 112 |     if (name_ == name) | 
| 113 |         return; | 
| 114 |  | 
| 115 |     name_ = name; | 
| 116 |  | 
| 117 |     if (complete_) | 
| 118 |         tryAttach(); | 
| 119 |  | 
| 120 |     emit nameChanged(name: name_); | 
| 121 | } | 
| 122 |  | 
| 123 | /*! | 
| 124 |     \internal | 
| 125 | */ | 
| 126 | bool QDeclarativeGeoServiceProvider::parametersReady() { | 
| 127 |     for (const QDeclarativePluginParameter *p: qAsConst(t&: parameters_)) { | 
| 128 |         if (!p->isInitialized()) | 
| 129 |             return false; | 
| 130 |     } | 
| 131 |     return true; | 
| 132 | } | 
| 133 |  | 
| 134 | /*! | 
| 135 |     \internal | 
| 136 | */ | 
| 137 | void QDeclarativeGeoServiceProvider::tryAttach() | 
| 138 | { | 
| 139 |     if (!parametersReady()) | 
| 140 |         return; | 
| 141 |  | 
| 142 |     delete sharedProvider_; | 
| 143 |     sharedProvider_ = nullptr; | 
| 144 |  | 
| 145 |     if (name_.isEmpty()) | 
| 146 |         return; | 
| 147 |  | 
| 148 |     sharedProvider_ = new QGeoServiceProvider(name_, parameterMap()); | 
| 149 |     sharedProvider_->setQmlEngine(qmlEngine(this)); | 
| 150 |     sharedProvider_->setLocale(locales_.at(i: 0)); | 
| 151 |     sharedProvider_->setAllowExperimental(experimental_); | 
| 152 |  | 
| 153 |     emit attached(); | 
| 154 | } | 
| 155 |  | 
| 156 | QString QDeclarativeGeoServiceProvider::name() const | 
| 157 | { | 
| 158 |     return name_; | 
| 159 | } | 
| 160 |  | 
| 161 |  | 
| 162 | /*! | 
| 163 |     \qmlproperty stringlist Plugin::availableServiceProviders | 
| 164 |  | 
| 165 |     This property holds a list of all available service plugins' names. This | 
| 166 |     can be used to manually enumerate the available plugins if the | 
| 167 |     control provided by \l name and \l required is not sufficient for your | 
| 168 |     needs. | 
| 169 | */ | 
| 170 | QStringList QDeclarativeGeoServiceProvider::availableServiceProviders() | 
| 171 | { | 
| 172 |     return QGeoServiceProvider::availableServiceProviders(); | 
| 173 | } | 
| 174 |  | 
| 175 | /*! | 
| 176 |     \internal | 
| 177 | */ | 
| 178 | void QDeclarativeGeoServiceProvider::componentComplete() | 
| 179 | { | 
| 180 |     complete_ = true; | 
| 181 |  | 
| 182 |     for (QDeclarativePluginParameter *p: qAsConst(t&: parameters_)) { | 
| 183 |         if (!p->isInitialized()) { | 
| 184 |             connect(sender: p, signal: &QDeclarativePluginParameter::initialized, | 
| 185 |                     receiver: this, slot: &QDeclarativeGeoServiceProvider::tryAttach); | 
| 186 |         } | 
| 187 |     } | 
| 188 |  | 
| 189 |     if (!name_.isEmpty()) { | 
| 190 |         tryAttach(); | 
| 191 |     } else if (!prefer_.isEmpty() | 
| 192 |             || required_->mappingRequirements() != NoMappingFeatures | 
| 193 |             || required_->routingRequirements() != NoRoutingFeatures | 
| 194 |             || required_->geocodingRequirements() != NoGeocodingFeatures | 
| 195 |             || required_->placesRequirements() != NoPlacesFeatures | 
| 196 |             || required_->navigationRequirements() != NoNavigationFeatures) { | 
| 197 |  | 
| 198 |         QStringList providers = QGeoServiceProvider::availableServiceProviders(); | 
| 199 |  | 
| 200 |         /* first check any preferred plugins */ | 
| 201 |         foreach (const QString &name, prefer_) { | 
| 202 |             if (providers.contains(str: name)) { | 
| 203 |                 // so we don't try it again later | 
| 204 |                 providers.removeAll(t: name); | 
| 205 |  | 
| 206 |                 QGeoServiceProvider sp(name, parameterMap(), experimental_); | 
| 207 |                 if (required_->matches(provider: &sp)) { | 
| 208 |                     setName(name); | 
| 209 |                     return; | 
| 210 |                 } | 
| 211 |             } | 
| 212 |         } | 
| 213 |  | 
| 214 |         /* then try the rest */ | 
| 215 |         foreach (const QString &name, providers) { | 
| 216 |             QGeoServiceProvider sp(name, parameterMap(), experimental_); | 
| 217 |             if (required_->matches(provider: &sp)) { | 
| 218 |                 setName(name); | 
| 219 |                 return; | 
| 220 |             } | 
| 221 |         } | 
| 222 |  | 
| 223 |         qmlWarning(me: this) << "Could not find a plugin with the required features to attach to" ; | 
| 224 |     } | 
| 225 | } | 
| 226 |  | 
| 227 | /*! | 
| 228 |     \qmlmethod bool Plugin::supportsGeocoding(GeocodingFeatures features) | 
| 229 |  | 
| 230 |     This method returns a boolean indicating whether the specified set of \a features are supported | 
| 231 |     by the geo service provider plugin. \c True is returned if all specified \a features are | 
| 232 |     supported; otherwise \c false is returned. | 
| 233 |  | 
| 234 |     The \a features parameter can be any flag combination of: | 
| 235 |     \table | 
| 236 |         \header | 
| 237 |             \li Feature | 
| 238 |             \li Description | 
| 239 |         \row | 
| 240 |             \li Plugin.NoGeocodingFeatures | 
| 241 |             \li No geocoding features are supported. | 
| 242 |         \row | 
| 243 |             \li Plugin.OnlineGeocodingFeature | 
| 244 |             \li Online geocoding is supported. | 
| 245 |         \row | 
| 246 |             \li Plugin.OfflineGeocodingFeature | 
| 247 |             \li Offline geocoding is supported. | 
| 248 |         \row | 
| 249 |             \li Plugin.ReverseGeocodingFeature | 
| 250 |             \li Reverse geocoding is supported. | 
| 251 |         \row | 
| 252 |             \li Plugin.LocalizedGeocodingFeature | 
| 253 |             \li Supports returning geocoding results with localized addresses. | 
| 254 |         \row | 
| 255 |             \li Plugin.AnyGeocodingFeatures | 
| 256 |             \li Matches a geo service provider that provides any geocoding features. | 
| 257 |     \endtable | 
| 258 | */ | 
| 259 | bool QDeclarativeGeoServiceProvider::supportsGeocoding(const GeocodingFeatures &feature) const | 
| 260 | { | 
| 261 |     QGeoServiceProvider *sp = sharedGeoServiceProvider(); | 
| 262 |     QGeoServiceProvider::GeocodingFeatures f = | 
| 263 |             static_cast<QGeoServiceProvider::GeocodingFeature>(int(feature)); | 
| 264 |     if (f == QGeoServiceProvider::AnyGeocodingFeatures) | 
| 265 |         return (sp && (sp->geocodingFeatures() != QGeoServiceProvider::NoGeocodingFeatures)); | 
| 266 |     else | 
| 267 |         return (sp && (sp->geocodingFeatures() & f) == f); | 
| 268 | } | 
| 269 |  | 
| 270 | /*! | 
| 271 |     \qmlmethod bool Plugin::supportsMapping(MappingFeatures features) | 
| 272 |  | 
| 273 |     This method returns a boolean indicating whether the specified set of \a features are supported | 
| 274 |     by the geo service provider plugin.  True is returned if all specified \a features are | 
| 275 |     supported; otherwise false is returned. | 
| 276 |  | 
| 277 |     The \a features parameter can be any flag combination of: | 
| 278 |     \table | 
| 279 |         \header | 
| 280 |             \li Feature | 
| 281 |             \li Description | 
| 282 |         \row | 
| 283 |             \li Plugin.NoMappingFeatures | 
| 284 |             \li No mapping features are supported. | 
| 285 |         \row | 
| 286 |             \li Plugin.OnlineMappingFeature | 
| 287 |             \li Online mapping is supported. | 
| 288 |         \row | 
| 289 |             \li Plugin.OfflineMappingFeature | 
| 290 |             \li Offline mapping is supported. | 
| 291 |         \row | 
| 292 |             \li Plugin.LocalizedMappingFeature | 
| 293 |             \li Supports returning localized map data. | 
| 294 |         \row | 
| 295 |             \li Plugin.AnyMappingFeatures | 
| 296 |             \li Matches a geo service provider that provides any mapping features. | 
| 297 |     \endtable | 
| 298 | */ | 
| 299 | bool QDeclarativeGeoServiceProvider::supportsMapping(const MappingFeatures &feature) const | 
| 300 | { | 
| 301 |     QGeoServiceProvider *sp = sharedGeoServiceProvider(); | 
| 302 |     QGeoServiceProvider::MappingFeatures f = | 
| 303 |             static_cast<QGeoServiceProvider::MappingFeature>(int(feature)); | 
| 304 |     if (f == QGeoServiceProvider::AnyMappingFeatures) | 
| 305 |         return (sp && (sp->mappingFeatures() != QGeoServiceProvider::NoMappingFeatures)); | 
| 306 |     else | 
| 307 |         return (sp && (sp->mappingFeatures() & f) == f); | 
| 308 | } | 
| 309 |  | 
| 310 | /*! | 
| 311 |     \qmlmethod bool Plugin::supportsRouting(RoutingFeatures features) | 
| 312 |  | 
| 313 |     This method returns a boolean indicating whether the specified set of \a features are supported | 
| 314 |     by the geo service provider plugin.  True is returned if all specified \a features are | 
| 315 |     supported; otherwise false is returned. | 
| 316 |  | 
| 317 |     The \a features parameter can be any flag combination of: | 
| 318 |     \table | 
| 319 |         \header | 
| 320 |             \li Feature | 
| 321 |             \li Description | 
| 322 |         \row | 
| 323 |             \li Plugin.NoRoutingFeatures | 
| 324 |             \li No routing features are supported. | 
| 325 |         \row | 
| 326 |             \li Plugin.OnlineRoutingFeature | 
| 327 |             \li Online routing is supported. | 
| 328 |         \row | 
| 329 |             \li Plugin.OfflineRoutingFeature | 
| 330 |             \li Offline routing is supported. | 
| 331 |         \row | 
| 332 |             \li Plugin.LocalizedRoutingFeature | 
| 333 |             \li Supports returning routes with localized addresses and instructions. | 
| 334 |         \row | 
| 335 |             \li Plugin.RouteUpdatesFeature | 
| 336 |             \li Updating an existing route based on the current position is supported. | 
| 337 |         \row | 
| 338 |             \li Plugin.AlternativeRoutesFeature | 
| 339 |             \li Supports returning alternative routes. | 
| 340 |         \row | 
| 341 |             \li Plugin.ExcludeAreasRoutingFeature | 
| 342 |             \li Supports specifying a areas which the returned route must not cross. | 
| 343 |         \row | 
| 344 |             \li Plugin.AnyRoutingFeatures | 
| 345 |             \li Matches a geo service provider that provides any routing features. | 
| 346 |     \endtable | 
| 347 | */ | 
| 348 | bool QDeclarativeGeoServiceProvider::supportsRouting(const RoutingFeatures &feature) const | 
| 349 | { | 
| 350 |     QGeoServiceProvider *sp = sharedGeoServiceProvider(); | 
| 351 |     QGeoServiceProvider::RoutingFeatures f = | 
| 352 |             static_cast<QGeoServiceProvider::RoutingFeature>(int(feature)); | 
| 353 |     if (f == QGeoServiceProvider::AnyRoutingFeatures) | 
| 354 |         return (sp && (sp->routingFeatures() != QGeoServiceProvider::NoRoutingFeatures)); | 
| 355 |     else | 
| 356 |         return (sp && (sp->routingFeatures() & f) == f); | 
| 357 | } | 
| 358 |  | 
| 359 | /*! | 
| 360 |     \qmlmethod bool Plugin::supportsPlaces(PlacesFeatures features) | 
| 361 |  | 
| 362 |     This method returns a boolean indicating whether the specified set of \a features are supported | 
| 363 |     by the geo service provider plugin.  True is returned if all specified \a features are | 
| 364 |     supported; otherwise false is returned. | 
| 365 |  | 
| 366 |     The \a features parameter can be any flag combination of: | 
| 367 |     \table | 
| 368 |         \header | 
| 369 |             \li Feature | 
| 370 |             \li Description | 
| 371 |         \row | 
| 372 |             \li Plugin.NoPlacesFeatures | 
| 373 |             \li No places features are supported. | 
| 374 |         \row | 
| 375 |             \li Plugin.OnlinePlacesFeature | 
| 376 |             \li Online places is supported. | 
| 377 |         \row | 
| 378 |             \li Plugin.OfflinePlacesFeature | 
| 379 |             \li Offline places is supported. | 
| 380 |         \row | 
| 381 |             \li Plugin.SavePlaceFeature | 
| 382 |             \li Saving categories is supported. | 
| 383 |         \row | 
| 384 |             \li Plugin.RemovePlaceFeature | 
| 385 |             \li Removing or deleting places is supported. | 
| 386 |         \row | 
| 387 |             \li Plugin.PlaceRecommendationsFeature | 
| 388 |             \li Searching for recommended places similar to another place is supported. | 
| 389 |         \row | 
| 390 |             \li Plugin.SearchSuggestionsFeature | 
| 391 |             \li Search suggestions is supported. | 
| 392 |         \row | 
| 393 |             \li Plugin.LocalizedPlacesFeature | 
| 394 |             \li Supports returning localized place data. | 
| 395 |         \row | 
| 396 |             \li Plugin.NotificationsFeature | 
| 397 |             \li Notifications of place and category changes is supported. | 
| 398 |         \row | 
| 399 |             \li Plugin.PlaceMatchingFeature | 
| 400 |             \li Supports matching places from two different geo service providers. | 
| 401 |         \row | 
| 402 |             \li Plugin.AnyPlacesFeatures | 
| 403 |             \li Matches a geo service provider that provides any places features. | 
| 404 |     \endtable | 
| 405 | */ | 
| 406 | bool QDeclarativeGeoServiceProvider::supportsPlaces(const PlacesFeatures &feature) const | 
| 407 | { | 
| 408 |     QGeoServiceProvider *sp = sharedGeoServiceProvider(); | 
| 409 |     QGeoServiceProvider::PlacesFeatures f = | 
| 410 |             static_cast<QGeoServiceProvider::PlacesFeature>(int(feature)); | 
| 411 |     if (f == QGeoServiceProvider::AnyPlacesFeatures) | 
| 412 |         return (sp && (sp->placesFeatures() != QGeoServiceProvider::NoPlacesFeatures)); | 
| 413 |     else | 
| 414 |         return (sp && (sp->placesFeatures() & f) == f); | 
| 415 | } | 
| 416 |  | 
| 417 | /*! | 
| 418 |     \qmlmethod bool Plugin::supportsNavigation(NavigationFeatures features) | 
| 419 |  | 
| 420 |     This method returns a boolean indicating whether the specified set of \a features are supported | 
| 421 |     by the geo service provider plugin.  True is returned if all specified \a features are | 
| 422 |     supported; otherwise false is returned. | 
| 423 |  | 
| 424 |     The \a features parameter can be any flag combination of: | 
| 425 |     \table | 
| 426 |         \header | 
| 427 |             \li Feature | 
| 428 |             \li Description | 
| 429 |         \row | 
| 430 |             \li Plugin.NoNavigationFeatures | 
| 431 |             \li No navigation features are supported. | 
| 432 |         \row | 
| 433 |             \li Plugin.OnlineNavigationFeature | 
| 434 |             \li Online navigation is supported. | 
| 435 |         \row | 
| 436 |             \li Plugin.OfflineNavigationFeature | 
| 437 |             \li Offline navigation is supported. | 
| 438 |         \row | 
| 439 |             \li Plugin.AnyNavigationFeatures | 
| 440 |             \li Matches a geo service provider that provides any navigation features. | 
| 441 |     \endtable | 
| 442 | */ | 
| 443 | bool QDeclarativeGeoServiceProvider::supportsNavigation(const QDeclarativeGeoServiceProvider::NavigationFeature &feature) const | 
| 444 | { | 
| 445 |     QGeoServiceProvider *sp = sharedGeoServiceProvider(); | 
| 446 |     QGeoServiceProvider::NavigationFeatures f = | 
| 447 |             static_cast<QGeoServiceProvider::NavigationFeature>(int(feature)); | 
| 448 |     if (f == QGeoServiceProvider::AnyNavigationFeatures) | 
| 449 |         return (sp && (sp->navigationFeatures() != QGeoServiceProvider::NoNavigationFeatures)); | 
| 450 |     else | 
| 451 |         return (sp && (sp->navigationFeatures() & f) == f); | 
| 452 | } | 
| 453 |  | 
| 454 | /*! | 
| 455 |     \qmlproperty enumeration Plugin::required | 
| 456 |  | 
| 457 |     This property contains the set of features that will be required by the | 
| 458 |     Plugin object when choosing which service plugin to attach to. If the | 
| 459 |     \l name property is set, this has no effect. | 
| 460 |  | 
| 461 |     Any of the following values or a bitwise combination of multiple values | 
| 462 |     may be set: | 
| 463 |  | 
| 464 |     \list | 
| 465 |     \li Plugin.NoFeatures | 
| 466 |     \li Plugin.GeocodingFeature | 
| 467 |     \li Plugin.ReverseGeocodingFeature | 
| 468 |     \li Plugin.RoutingFeature | 
| 469 |     \li Plugin.MappingFeature | 
| 470 |     \li Plugin.AnyPlacesFeature | 
| 471 |     \endlist | 
| 472 | */ | 
| 473 | QDeclarativeGeoServiceProviderRequirements *QDeclarativeGeoServiceProvider::requirements() const | 
| 474 | { | 
| 475 |     return required_; | 
| 476 | } | 
| 477 |  | 
| 478 | void QDeclarativeGeoServiceProvider::setRequirements(QDeclarativeGeoServiceProviderRequirements *req) | 
| 479 | { | 
| 480 |     if (!name().isEmpty() || !req) | 
| 481 |         return; | 
| 482 |  | 
| 483 |     if (required_ && *required_ == *req) | 
| 484 |         return; | 
| 485 |  | 
| 486 |     delete required_; | 
| 487 |     required_ = req; | 
| 488 |     QQmlEngine::setObjectOwnership(req, QQmlEngine::CppOwnership); // To prevent the engine from making this object disappear | 
| 489 | } | 
| 490 |  | 
| 491 | /*! | 
| 492 |     \qmlproperty stringlist Plugin::preferred | 
| 493 |  | 
| 494 |     This property contains an ordered list of preferred plugin names, which | 
| 495 |     will be checked for the required features set in \l{Plugin::required}{required} | 
| 496 |     before any other available plugins are checked. | 
| 497 | */ | 
| 498 | QStringList QDeclarativeGeoServiceProvider::preferred() const | 
| 499 | { | 
| 500 |     return prefer_; | 
| 501 | } | 
| 502 |  | 
| 503 | void QDeclarativeGeoServiceProvider::setPreferred(const QStringList &val) | 
| 504 | { | 
| 505 |     prefer_ = val; | 
| 506 |     emit preferredChanged(preferences: prefer_); | 
| 507 | } | 
| 508 |  | 
| 509 | /*! | 
| 510 |     \qmlproperty bool Plugin::isAttached | 
| 511 |  | 
| 512 |     This property indicates if the Plugin item is attached to a geoservice provider plugin. | 
| 513 | */ | 
| 514 | bool QDeclarativeGeoServiceProvider::isAttached() const | 
| 515 | { | 
| 516 |     return (sharedProvider_ != 0); | 
| 517 | } | 
| 518 |  | 
| 519 | /*! | 
| 520 |     \qmlproperty bool Plugin::allowExperimental | 
| 521 |  | 
| 522 |     This property indicates if experimental plugins can be used. | 
| 523 | */ | 
| 524 | bool QDeclarativeGeoServiceProvider::allowExperimental() const | 
| 525 | { | 
| 526 |     return experimental_; | 
| 527 | } | 
| 528 |  | 
| 529 | void QDeclarativeGeoServiceProvider::setAllowExperimental(bool allow) | 
| 530 | { | 
| 531 |     if (experimental_ == allow) | 
| 532 |         return; | 
| 533 |  | 
| 534 |     experimental_ = allow; | 
| 535 |     if (sharedProvider_) | 
| 536 |         sharedProvider_->setAllowExperimental(allow); | 
| 537 |  | 
| 538 |     emit allowExperimentalChanged(allow); | 
| 539 | } | 
| 540 |  | 
| 541 | /*! | 
| 542 |     \internal | 
| 543 | */ | 
| 544 | QGeoServiceProvider *QDeclarativeGeoServiceProvider::sharedGeoServiceProvider() const | 
| 545 | { | 
| 546 |     return sharedProvider_; | 
| 547 | } | 
| 548 |  | 
| 549 | /*! | 
| 550 |     \qmlproperty stringlist Plugin::locales | 
| 551 |  | 
| 552 |     This property contains an ordered list of preferred plugin locales.  If the first locale cannot be accommodated, then | 
| 553 |     the backend falls back to using the second, and so on.  By default the locales property contains the system locale. | 
| 554 |  | 
| 555 |     The locales are specified as strings which have the format | 
| 556 |     "language[_script][_country]" or "C", where: | 
| 557 |  | 
| 558 |     \list | 
| 559 |     \li language is a lowercase, two-letter, ISO 639 language code, | 
| 560 |     \li script is a titlecase, four-letter, ISO 15924 script code, | 
| 561 |     \li country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations), | 
| 562 |     \li the "C" locale is identical in behavior to English/UnitedStates as per QLocale | 
| 563 |     \endlist | 
| 564 |  | 
| 565 |     If the first specified locale cannot be accommodated, the \l {Plugin} falls back to the next and so forth. | 
| 566 |     Some \l {Plugin} backends may not support a set of locales which are rigidly defined.  An arbitrary | 
| 567 |     example is that some \l {Place}'s in France could have French and English localizations, while | 
| 568 |     certain areas in America may only have the English localization available.  In the above scenario, | 
| 569 |     the set of supported locales is context dependent on the search location. | 
| 570 |  | 
| 571 |     If the \l {Plugin} cannot accommodate any of the preferred locales, the manager falls | 
| 572 |     back to using a supported language that is backend specific. | 
| 573 |  | 
| 574 |     For \l {Plugin}'s that do not support locales, the locales list is always empty. | 
| 575 |  | 
| 576 |     The following code demonstrates how to set a single and multiple locales: | 
| 577 |     \snippet declarative/plugin.qml Plugin locale | 
| 578 | */ | 
| 579 | QStringList QDeclarativeGeoServiceProvider::locales() const | 
| 580 | { | 
| 581 |     return locales_; | 
| 582 | } | 
| 583 |  | 
| 584 | void QDeclarativeGeoServiceProvider::setLocales(const QStringList &locales) | 
| 585 | { | 
| 586 |     if (locales_ == locales) | 
| 587 |         return; | 
| 588 |  | 
| 589 |     locales_ = locales; | 
| 590 |  | 
| 591 |     if (locales_.isEmpty()) | 
| 592 |         locales_.append(t: QLocale().name()); | 
| 593 |  | 
| 594 |     if (sharedProvider_) | 
| 595 |         sharedProvider_->setLocale(locales_.at(i: 0)); | 
| 596 |  | 
| 597 |     emit localesChanged(); | 
| 598 | } | 
| 599 |  | 
| 600 | /*! | 
| 601 |     \qmlproperty list<PluginParameter> Plugin::parameters | 
| 602 |     \default | 
| 603 |  | 
| 604 |     This property holds the list of plugin parameters. | 
| 605 | */ | 
| 606 | QQmlListProperty<QDeclarativePluginParameter> QDeclarativeGeoServiceProvider::parameters() | 
| 607 | { | 
| 608 |     return QQmlListProperty<QDeclarativePluginParameter>(this, | 
| 609 |             0, | 
| 610 |             parameter_append, | 
| 611 |             parameter_count, | 
| 612 |             parameter_at, | 
| 613 |             parameter_clear); | 
| 614 | } | 
| 615 |  | 
| 616 | /*! | 
| 617 |     \internal | 
| 618 | */ | 
| 619 | void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *parameter) | 
| 620 | { | 
| 621 |     QDeclarativeGeoServiceProvider *p = static_cast<QDeclarativeGeoServiceProvider *>(prop->object); | 
| 622 |     p->parameters_.append(t: parameter); | 
| 623 |     if (p->sharedProvider_) | 
| 624 |         p->sharedProvider_->setParameters(p->parameterMap()); | 
| 625 | } | 
| 626 |  | 
| 627 | /*! | 
| 628 |     \internal | 
| 629 | */ | 
| 630 | int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop) | 
| 631 | { | 
| 632 |     return static_cast<QDeclarativeGeoServiceProvider *>(prop->object)->parameters_.count(); | 
| 633 | } | 
| 634 |  | 
| 635 | /*! | 
| 636 |     \internal | 
| 637 | */ | 
| 638 | QDeclarativePluginParameter *QDeclarativeGeoServiceProvider::parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, int index) | 
| 639 | { | 
| 640 |     return static_cast<QDeclarativeGeoServiceProvider *>(prop->object)->parameters_[index]; | 
| 641 | } | 
| 642 |  | 
| 643 | /*! | 
| 644 |     \internal | 
| 645 | */ | 
| 646 | void QDeclarativeGeoServiceProvider::parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop) | 
| 647 | { | 
| 648 |     QDeclarativeGeoServiceProvider *p = static_cast<QDeclarativeGeoServiceProvider *>(prop->object); | 
| 649 |     p->parameters_.clear(); | 
| 650 |     if (p->sharedProvider_) | 
| 651 |         p->sharedProvider_->setParameters(p->parameterMap()); | 
| 652 | } | 
| 653 |  | 
| 654 | /*! | 
| 655 |     \internal | 
| 656 | */ | 
| 657 | QVariantMap QDeclarativeGeoServiceProvider::parameterMap() const | 
| 658 | { | 
| 659 |     QVariantMap map; | 
| 660 |  | 
| 661 |     for (int i = 0; i < parameters_.size(); ++i) { | 
| 662 |         QDeclarativePluginParameter *parameter = parameters_.at(i); | 
| 663 |         map.insert(akey: parameter->name(), avalue: parameter->value()); | 
| 664 |     } | 
| 665 |  | 
| 666 |     return map; | 
| 667 | } | 
| 668 |  | 
| 669 | /******************************************************************************* | 
| 670 | *******************************************************************************/ | 
| 671 |  | 
| 672 | QDeclarativeGeoServiceProviderRequirements::QDeclarativeGeoServiceProviderRequirements(QObject *parent) | 
| 673 |     : QObject(parent), | 
| 674 |       mapping_(QDeclarativeGeoServiceProvider::NoMappingFeatures), | 
| 675 |       routing_(QDeclarativeGeoServiceProvider::NoRoutingFeatures), | 
| 676 |       geocoding_(QDeclarativeGeoServiceProvider::NoGeocodingFeatures), | 
| 677 |       places_(QDeclarativeGeoServiceProvider::NoPlacesFeatures), | 
| 678 |       navigation_(QDeclarativeGeoServiceProvider::NoNavigationFeatures) | 
| 679 | { | 
| 680 | } | 
| 681 |  | 
| 682 | QDeclarativeGeoServiceProviderRequirements::~QDeclarativeGeoServiceProviderRequirements() | 
| 683 | { | 
| 684 | } | 
| 685 |  | 
| 686 | /*! | 
| 687 |     \internal | 
| 688 | */ | 
| 689 | QDeclarativeGeoServiceProvider::MappingFeatures QDeclarativeGeoServiceProviderRequirements::mappingRequirements() const | 
| 690 | { | 
| 691 |     return mapping_; | 
| 692 | } | 
| 693 |  | 
| 694 | /*! | 
| 695 |     \internal | 
| 696 | */ | 
| 697 | void QDeclarativeGeoServiceProviderRequirements::setMappingRequirements(const QDeclarativeGeoServiceProvider::MappingFeatures &features) | 
| 698 | { | 
| 699 |     if (mapping_ == features) | 
| 700 |         return; | 
| 701 |  | 
| 702 |     mapping_ = features; | 
| 703 |     emit mappingRequirementsChanged(features: mapping_); | 
| 704 |     emit requirementsChanged(); | 
| 705 | } | 
| 706 |  | 
| 707 | /*! | 
| 708 |     \internal | 
| 709 | */ | 
| 710 | QDeclarativeGeoServiceProvider::RoutingFeatures QDeclarativeGeoServiceProviderRequirements::routingRequirements() const | 
| 711 | { | 
| 712 |     return routing_; | 
| 713 | } | 
| 714 |  | 
| 715 | /*! | 
| 716 |     \internal | 
| 717 | */ | 
| 718 | void QDeclarativeGeoServiceProviderRequirements::setRoutingRequirements(const QDeclarativeGeoServiceProvider::RoutingFeatures &features) | 
| 719 | { | 
| 720 |     if (routing_ == features) | 
| 721 |         return; | 
| 722 |  | 
| 723 |     routing_ = features; | 
| 724 |     emit routingRequirementsChanged(features: routing_); | 
| 725 |     emit requirementsChanged(); | 
| 726 | } | 
| 727 |  | 
| 728 | /*! | 
| 729 |     \internal | 
| 730 | */ | 
| 731 | QDeclarativeGeoServiceProvider::GeocodingFeatures QDeclarativeGeoServiceProviderRequirements::geocodingRequirements() const | 
| 732 | { | 
| 733 |     return geocoding_; | 
| 734 | } | 
| 735 |  | 
| 736 | /*! | 
| 737 |     \internal | 
| 738 | */ | 
| 739 | void QDeclarativeGeoServiceProviderRequirements::setGeocodingRequirements(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features) | 
| 740 | { | 
| 741 |     if (geocoding_ == features) | 
| 742 |         return; | 
| 743 |  | 
| 744 |     geocoding_ = features; | 
| 745 |     emit geocodingRequirementsChanged(features: geocoding_); | 
| 746 |     emit requirementsChanged(); | 
| 747 | } | 
| 748 |  | 
| 749 | /*! | 
| 750 |     \internal | 
| 751 |  | 
| 752 |     */ | 
| 753 | QDeclarativeGeoServiceProvider::PlacesFeatures QDeclarativeGeoServiceProviderRequirements::placesRequirements() const | 
| 754 | { | 
| 755 |     return places_; | 
| 756 | } | 
| 757 |  | 
| 758 | /*! | 
| 759 |     \internal | 
| 760 | */ | 
| 761 | void QDeclarativeGeoServiceProviderRequirements::setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures &features) | 
| 762 | { | 
| 763 |     if (places_ == features) | 
| 764 |         return; | 
| 765 |  | 
| 766 |     places_ = features; | 
| 767 |     emit placesRequirementsChanged(features: places_); | 
| 768 |     emit requirementsChanged(); | 
| 769 | } | 
| 770 |  | 
| 771 | /*! | 
| 772 |     \internal | 
| 773 | */ | 
| 774 | QDeclarativeGeoServiceProvider::NavigationFeatures QDeclarativeGeoServiceProviderRequirements::navigationRequirements() const | 
| 775 | { | 
| 776 |     return navigation_; | 
| 777 | } | 
| 778 |  | 
| 779 | /*! | 
| 780 |     \internal | 
| 781 | */ | 
| 782 | void QDeclarativeGeoServiceProviderRequirements::setNavigationRequirements(const QDeclarativeGeoServiceProvider::NavigationFeatures &features) | 
| 783 | { | 
| 784 |     if (navigation_ == features) | 
| 785 |         return; | 
| 786 |  | 
| 787 |     navigation_ = features; | 
| 788 |     emit navigationRequirementsChanged(features: navigation_); | 
| 789 |     emit requirementsChanged(); | 
| 790 | } | 
| 791 |  | 
| 792 | /*! | 
| 793 |     \internal | 
| 794 | */ | 
| 795 | bool QDeclarativeGeoServiceProviderRequirements::matches(const QGeoServiceProvider *provider) const | 
| 796 | { | 
| 797 |     QGeoServiceProvider::MappingFeatures mapping = | 
| 798 |             static_cast<QGeoServiceProvider::MappingFeatures>(int(mapping_)); | 
| 799 |  | 
| 800 |     // extra curlies here to avoid "dangling" else, which could belong to either if | 
| 801 |     // same goes for all the rest of these blocks | 
| 802 |     if (mapping == QGeoServiceProvider::AnyMappingFeatures) { | 
| 803 |         if (provider->mappingFeatures() == QGeoServiceProvider::NoMappingFeatures) | 
| 804 |             return false; | 
| 805 |     } else { | 
| 806 |         if ((provider->mappingFeatures() & mapping) != mapping) | 
| 807 |             return false; | 
| 808 |     } | 
| 809 |  | 
| 810 |     QGeoServiceProvider::RoutingFeatures routing = | 
| 811 |             static_cast<QGeoServiceProvider::RoutingFeatures>(int(routing_)); | 
| 812 |  | 
| 813 |     if (routing == QGeoServiceProvider::AnyRoutingFeatures) { | 
| 814 |         if (provider->routingFeatures() == QGeoServiceProvider::NoRoutingFeatures) | 
| 815 |             return false; | 
| 816 |     } else { | 
| 817 |         if ((provider->routingFeatures() & routing) != routing) | 
| 818 |             return false; | 
| 819 |     } | 
| 820 |  | 
| 821 |     QGeoServiceProvider::GeocodingFeatures geocoding = | 
| 822 |             static_cast<QGeoServiceProvider::GeocodingFeatures>(int(geocoding_)); | 
| 823 |  | 
| 824 |     if (geocoding == QGeoServiceProvider::AnyGeocodingFeatures) { | 
| 825 |         if (provider->geocodingFeatures() == QGeoServiceProvider::NoGeocodingFeatures) | 
| 826 |             return false; | 
| 827 |     } else { | 
| 828 |         if ((provider->geocodingFeatures() & geocoding) != geocoding) | 
| 829 |             return false; | 
| 830 |     } | 
| 831 |  | 
| 832 |     QGeoServiceProvider::PlacesFeatures places = | 
| 833 |             static_cast<QGeoServiceProvider::PlacesFeatures>(int(places_)); | 
| 834 |  | 
| 835 |     if (places == QGeoServiceProvider::AnyPlacesFeatures) { | 
| 836 |         if (provider->placesFeatures() == QGeoServiceProvider::NoPlacesFeatures) | 
| 837 |             return false; | 
| 838 |     } else { | 
| 839 |         if ((provider->placesFeatures() & places) != places) | 
| 840 |             return false; | 
| 841 |     } | 
| 842 |  | 
| 843 |     QGeoServiceProvider::NavigationFeatures navigation = | 
| 844 |             static_cast<QGeoServiceProvider::NavigationFeatures>(int(navigation_)); | 
| 845 |  | 
| 846 |     if (navigation == QGeoServiceProvider::AnyNavigationFeatures) { | 
| 847 |         if (provider->navigationFeatures() == QGeoServiceProvider::NoNavigationFeatures) | 
| 848 |             return false; | 
| 849 |     } else { | 
| 850 |         if ((provider->navigationFeatures() & navigation) != navigation) | 
| 851 |             return false; | 
| 852 |     } | 
| 853 |  | 
| 854 |     return true; | 
| 855 | } | 
| 856 |  | 
| 857 | bool QDeclarativeGeoServiceProviderRequirements::operator == (const QDeclarativeGeoServiceProviderRequirements &rhs) const | 
| 858 | { | 
| 859 |     return (mapping_ == rhs.mapping_ && routing_ == rhs.routing_ | 
| 860 |             && geocoding_ == rhs.geocoding_ && places_ == rhs.places_ | 
| 861 |             && navigation_ == rhs.navigation_); | 
| 862 | } | 
| 863 |  | 
| 864 | /******************************************************************************* | 
| 865 | *******************************************************************************/ | 
| 866 |  | 
| 867 | /*! | 
| 868 |     \qmltype PluginParameter | 
| 869 |     //! \instantiates QDeclarativePluginParameter | 
| 870 |     \inqmlmodule QtLocation | 
| 871 |     \ingroup qml-QtLocation5-common | 
| 872 |     \since QtLocation 5.5 | 
| 873 |  | 
| 874 |     \brief The PluginParameter type describes a parameter for a plugin, either | 
| 875 |     geo service \l Plugin, or \l{Qt Positioning plugins}{position Plugin}. | 
| 876 |  | 
| 877 |     The PluginParameter object is used to provide a parameter of some kind | 
| 878 |     to a plugin. Typically these parameters contain details like an application | 
| 879 |     token for access to a service, or a proxy server to use for network access, | 
| 880 |     or the serial port to which a serial GPS receiver is connected. | 
| 881 |  | 
| 882 |     To set such a parameter, declare a PluginParameter inside an element that accepts | 
| 883 |     plugin parameters as configuration objects, such as a \l Plugin object, or a | 
| 884 |     \l PositionSource object, and give it \l{name} and \l{value} properties. A list of valid | 
| 885 |     parameter names for each plugin is available from the | 
| 886 |     \l {Qt Location#Plugin References and Parameters}{plugin reference pages} for geoservice plugins, | 
| 887 |     and \l {Qt Positioning plugins#Default plugins} for position plugins. | 
| 888 |  | 
| 889 |     \section2 Example Usage | 
| 890 |  | 
| 891 |     The following example shows an instantiation of the \l {Qt Location HERE Plugin}{HERE} plugin | 
| 892 |     with a mapping API \e app_id and \e token pair specific to the application. | 
| 893 |  | 
| 894 |     \code | 
| 895 |     Plugin { | 
| 896 |         name: "here" | 
| 897 |         PluginParameter { name: "here.app_id"; value: "EXAMPLE_API_ID" } | 
| 898 |         PluginParameter { name: "here.token"; value: "EXAMPLE_TOKEN_123" } | 
| 899 |     } | 
| 900 |     \endcode | 
| 901 | */ | 
| 902 |  | 
| 903 | /*! | 
| 904 |     \qmlproperty string PluginParameter::name | 
| 905 |  | 
| 906 |     This property holds the name of the plugin parameter as a single formatted string. | 
| 907 |     This property is a write-once property. | 
| 908 | */ | 
| 909 |  | 
| 910 | /*! | 
| 911 |     \qmlproperty QVariant PluginParameter::value | 
| 912 |  | 
| 913 |     This property holds the value of the plugin parameter which support different types of values (variant). | 
| 914 |     This property is a write-once property. | 
| 915 | */ | 
| 916 |  | 
| 917 | /******************************************************************************* | 
| 918 |  *  Implementation now in positioningquick | 
| 919 | *******************************************************************************/ | 
| 920 |  | 
| 921 | QT_END_NAMESPACE | 
| 922 |  | 
| 923 |  |