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 
QDeclarativeGeoServiceProvider(QObject * parent)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(QLocale().name());
93 }
94 
~QDeclarativeGeoServiceProvider()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 */
setName(const QString & name)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_);
121 }
122 
123 /*!
124     \internal
125 */
parametersReady()126 bool QDeclarativeGeoServiceProvider::parametersReady() {
127     for (const QDeclarativePluginParameter *p: qAsConst(parameters_)) {
128         if (!p->isInitialized())
129             return false;
130     }
131     return true;
132 }
133 
134 /*!
135     \internal
136 */
tryAttach()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(0));
151     sharedProvider_->setAllowExperimental(experimental_);
152 
153     emit attached();
154 }
155 
name() const156 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 */
availableServiceProviders()170 QStringList QDeclarativeGeoServiceProvider::availableServiceProviders()
171 {
172     return QGeoServiceProvider::availableServiceProviders();
173 }
174 
175 /*!
176     \internal
177 */
componentComplete()178 void QDeclarativeGeoServiceProvider::componentComplete()
179 {
180     complete_ = true;
181 
182     for (QDeclarativePluginParameter *p: qAsConst(parameters_)) {
183         if (!p->isInitialized()) {
184             connect(p, &QDeclarativePluginParameter::initialized,
185                     this, &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(name)) {
203                 // so we don't try it again later
204                 providers.removeAll(name);
205 
206                 QGeoServiceProvider sp(name, parameterMap(), experimental_);
207                 if (required_->matches(&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(&sp)) {
218                 setName(name);
219                 return;
220             }
221         }
222 
223         qmlWarning(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 */
supportsGeocoding(const GeocodingFeatures & feature) const259 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 */
supportsMapping(const MappingFeatures & feature) const299 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 */
supportsRouting(const RoutingFeatures & feature) const348 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 */
supportsPlaces(const PlacesFeatures & feature) const406 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 */
supportsNavigation(const QDeclarativeGeoServiceProvider::NavigationFeature & feature) const443 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 */
requirements() const473 QDeclarativeGeoServiceProviderRequirements *QDeclarativeGeoServiceProvider::requirements() const
474 {
475     return required_;
476 }
477 
setRequirements(QDeclarativeGeoServiceProviderRequirements * req)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 */
preferred() const498 QStringList QDeclarativeGeoServiceProvider::preferred() const
499 {
500     return prefer_;
501 }
502 
setPreferred(const QStringList & val)503 void QDeclarativeGeoServiceProvider::setPreferred(const QStringList &val)
504 {
505     prefer_ = val;
506     emit preferredChanged(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 */
isAttached() const514 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 */
allowExperimental() const524 bool QDeclarativeGeoServiceProvider::allowExperimental() const
525 {
526     return experimental_;
527 }
528 
setAllowExperimental(bool allow)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 */
sharedGeoServiceProvider() const544 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 */
locales() const579 QStringList QDeclarativeGeoServiceProvider::locales() const
580 {
581     return locales_;
582 }
583 
setLocales(const QStringList & locales)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(QLocale().name());
593 
594     if (sharedProvider_)
595         sharedProvider_->setLocale(locales_.at(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 */
parameters()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 */
parameter_append(QQmlListProperty<QDeclarativePluginParameter> * prop,QDeclarativePluginParameter * parameter)619 void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *parameter)
620 {
621     QDeclarativeGeoServiceProvider *p = static_cast<QDeclarativeGeoServiceProvider *>(prop->object);
622     p->parameters_.append(parameter);
623     if (p->sharedProvider_)
624         p->sharedProvider_->setParameters(p->parameterMap());
625 }
626 
627 /*!
628     \internal
629 */
parameter_count(QQmlListProperty<QDeclarativePluginParameter> * prop)630 int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop)
631 {
632     return static_cast<QDeclarativeGeoServiceProvider *>(prop->object)->parameters_.count();
633 }
634 
635 /*!
636     \internal
637 */
parameter_at(QQmlListProperty<QDeclarativePluginParameter> * prop,int index)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 */
parameter_clear(QQmlListProperty<QDeclarativePluginParameter> * prop)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 */
parameterMap() const657 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(parameter->name(), parameter->value());
664     }
665 
666     return map;
667 }
668 
669 /*******************************************************************************
670 *******************************************************************************/
671 
QDeclarativeGeoServiceProviderRequirements(QObject * parent)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 
~QDeclarativeGeoServiceProviderRequirements()682 QDeclarativeGeoServiceProviderRequirements::~QDeclarativeGeoServiceProviderRequirements()
683 {
684 }
685 
686 /*!
687     \internal
688 */
mappingRequirements() const689 QDeclarativeGeoServiceProvider::MappingFeatures QDeclarativeGeoServiceProviderRequirements::mappingRequirements() const
690 {
691     return mapping_;
692 }
693 
694 /*!
695     \internal
696 */
setMappingRequirements(const QDeclarativeGeoServiceProvider::MappingFeatures & features)697 void QDeclarativeGeoServiceProviderRequirements::setMappingRequirements(const QDeclarativeGeoServiceProvider::MappingFeatures &features)
698 {
699     if (mapping_ == features)
700         return;
701 
702     mapping_ = features;
703     emit mappingRequirementsChanged(mapping_);
704     emit requirementsChanged();
705 }
706 
707 /*!
708     \internal
709 */
routingRequirements() const710 QDeclarativeGeoServiceProvider::RoutingFeatures QDeclarativeGeoServiceProviderRequirements::routingRequirements() const
711 {
712     return routing_;
713 }
714 
715 /*!
716     \internal
717 */
setRoutingRequirements(const QDeclarativeGeoServiceProvider::RoutingFeatures & features)718 void QDeclarativeGeoServiceProviderRequirements::setRoutingRequirements(const QDeclarativeGeoServiceProvider::RoutingFeatures &features)
719 {
720     if (routing_ == features)
721         return;
722 
723     routing_ = features;
724     emit routingRequirementsChanged(routing_);
725     emit requirementsChanged();
726 }
727 
728 /*!
729     \internal
730 */
geocodingRequirements() const731 QDeclarativeGeoServiceProvider::GeocodingFeatures QDeclarativeGeoServiceProviderRequirements::geocodingRequirements() const
732 {
733     return geocoding_;
734 }
735 
736 /*!
737     \internal
738 */
setGeocodingRequirements(const QDeclarativeGeoServiceProvider::GeocodingFeatures & features)739 void QDeclarativeGeoServiceProviderRequirements::setGeocodingRequirements(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features)
740 {
741     if (geocoding_ == features)
742         return;
743 
744     geocoding_ = features;
745     emit geocodingRequirementsChanged(geocoding_);
746     emit requirementsChanged();
747 }
748 
749 /*!
750     \internal
751 
752     */
placesRequirements() const753 QDeclarativeGeoServiceProvider::PlacesFeatures QDeclarativeGeoServiceProviderRequirements::placesRequirements() const
754 {
755     return places_;
756 }
757 
758 /*!
759     \internal
760 */
setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures & features)761 void QDeclarativeGeoServiceProviderRequirements::setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures &features)
762 {
763     if (places_ == features)
764         return;
765 
766     places_ = features;
767     emit placesRequirementsChanged(places_);
768     emit requirementsChanged();
769 }
770 
771 /*!
772     \internal
773 */
navigationRequirements() const774 QDeclarativeGeoServiceProvider::NavigationFeatures QDeclarativeGeoServiceProviderRequirements::navigationRequirements() const
775 {
776     return navigation_;
777 }
778 
779 /*!
780     \internal
781 */
setNavigationRequirements(const QDeclarativeGeoServiceProvider::NavigationFeatures & features)782 void QDeclarativeGeoServiceProviderRequirements::setNavigationRequirements(const QDeclarativeGeoServiceProvider::NavigationFeatures &features)
783 {
784     if (navigation_ == features)
785         return;
786 
787     navigation_ = features;
788     emit navigationRequirementsChanged(navigation_);
789     emit requirementsChanged();
790 }
791 
792 /*!
793     \internal
794 */
matches(const QGeoServiceProvider * provider) const795 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 
operator ==(const QDeclarativeGeoServiceProviderRequirements & rhs) const857 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