Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdeclarativepositionsource.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7
8#include <QtCore/QCoreApplication>
9#include <QtQml/qqmlinfo.h>
10#include <QtQml/qqml.h>
11#include <qdeclarativepluginparameter_p.h>
12#include <QFile>
13#include <QtNetwork/QTcpSocket>
14#include <QTimer>
15
16QT_BEGIN_NAMESPACE
17
18/*!
19 \qmltype PositionSource
20 //! \nativetype QDeclarativePositionSource
21 \inqmlmodule QtPositioning
22 \since 5.2
23
24 \brief The PositionSource type provides the device's current position.
25
26 The PositionSource type provides information about the user device's
27 current position. The position is available as a \l{Position} type, which
28 contains all the standard parameters typically available from GPS and other
29 similar systems, including longitude, latitude, speed and accuracy details.
30
31 As different position sources are available on different platforms and
32 devices, these are categorized by their basic type (Satellite, NonSatellite,
33 and AllPositioningMethods). The available methods for the current platform
34 can be enumerated in the \l{supportedPositioningMethods} property.
35
36 To indicate which methods are suitable for your application, set the
37 \l{preferredPositioningMethods} property. If the preferred methods are not
38 available, the default source of location data for the platform will be
39 chosen instead. If no default source is available (because none are installed
40 for the runtime platform, or because it is disabled), the \l{valid} property
41 will be set to false.
42
43 The \l updateInterval property can then be used to indicate how often your
44 application wishes to receive position updates. The \l{start}(),
45 \l{stop}() and \l{update}() methods can be used to control the operation
46 of the PositionSource, as well as the \l{active} property, which when set
47 is equivalent to calling \l{start}() or \l{stop}().
48
49 When the PositionSource is active, position updates can be retrieved
50 either by simply using the \l{position} property in a binding (as the
51 value of another item's property), or by providing an implementation of
52 the \c {onPositionChanged} signal-handler.
53
54 \section2 Example Usage
55
56 The following example shows a simple PositionSource used to receive
57 updates every second and print the longitude and latitude out to
58 the console.
59
60 \code
61 PositionSource {
62 id: src
63 updateInterval: 1000
64 active: true
65
66 onPositionChanged: {
67 var coord = src.position.coordinate;
68 console.log("Coordinate:", coord.longitude, coord.latitude);
69 }
70 }
71 \endcode
72
73 \section2 Controlling Operation State
74
75 As it's mentioned above, PositionSource provides two ways to control its
76 operation state:
77
78 \list
79 \li By using the \l active \l {Qt Bindable Properties}{bindable} property.
80 \li By using \l start() and \l stop() methods.
81 \endlist
82
83 \note It's very important not to mix these approaches. If a bindable
84 \l active property is used to control the PositionSource object, but later
85 \l start() or \l stop() is called from the other part of the code, the
86 binding is broken, which may result in, for example, a UI element that is
87 not connected to any underlying object anymore.
88
89 Consider the following example of \b {bad code} where the \c active property
90 is bound to the CheckBox state, and calling \l stop() in the \c onClicked
91 signal handler breaks that binding.
92
93 \qml
94 Window {
95 width: 640
96 height: 480
97 visible: true
98
99 PositionSource {
100 id: posSource
101 name: "geoclue2"
102 active: cb.checked
103 }
104
105 Column {
106 anchors.centerIn: parent
107 spacing: 20
108 CheckBox {
109 id: cb
110 }
111 Button {
112 id: btn
113 text: "Stop"
114 onClicked: {
115 posSource.stop()
116 }
117 }
118 }
119 }
120 \endqml
121
122 Once the \e Stop button is clicked, \l stop() is executed, and the binding
123 for the \l active property is broken. At this point the CheckBox UI element
124 is no longer controlling the PositionSource object.
125
126 A straightforward fix in this case is to update the CheckBox state from
127 the \c onClicked handler. As soon as the CheckBox is unchecked, the
128 \l active property will be notified, and the PositionSource object's state
129 will update accordingly. The UI will also be in a consistent state.
130
131 \qml
132 Button {
133 id: btn
134 text: "Stop"
135 onClicked: {
136 cb.checked = false
137 }
138 }
139 \endqml
140
141 \note Using \l update() to request a single position update \e {does not}
142 have any effect on the \l active property's bindings, so they can be used
143 together without any problems.
144
145 \sa {QtPositioning::Position}, {QGeoPositionInfoSource}, {PluginParameter},
146 {Qt Bindable Properties}
147
148*/
149
150QDeclarativePositionSource::QDeclarativePositionSource()
151 : m_singleUpdate(0), m_regularUpdates(0), m_componentComplete(0),
152 m_parametersInitialized(0), m_startRequested(0), m_defaultSourceUsed(0)
153{
154 m_position.setValueBypassingBindings(new QDeclarativePosition(this));
155}
156
157QDeclarativePositionSource::~QDeclarativePositionSource()
158{
159 delete m_positionSource;
160}
161
162
163/*!
164 \qmlproperty string PositionSource::name
165
166 This property holds the unique internal name for the plugin currently
167 providing position information.
168
169 Setting the property causes the PositionSource to use a particular positioning provider. If
170 the PositionSource is active at the time that the name property is changed, it will become
171 inactive. If the specified positioning provider cannot be loaded the position source will
172 become invalid.
173
174 Changing the name property may cause the \l {updateInterval}, \l {supportedPositioningMethods}
175 and \l {preferredPositioningMethods} properties to change as well.
176*/
177
178
179QString QDeclarativePositionSource::name() const
180{
181 return m_sourceName;
182}
183
184void QDeclarativePositionSource::setName(const QString &newName)
185{
186 m_sourceName.removeBindingUnlessInWrapper();
187 if (m_positionSource && m_positionSource->sourceName() == newName)
188 return;
189
190 if (newName.isEmpty() && m_defaultSourceUsed)
191 return; // previously attached to a default source, now requesting the same.
192
193 const QString previousName = m_sourceName.valueBypassingBindings();
194
195 if (!m_componentComplete || !m_parametersInitialized) {
196 if (previousName != newName) {
197 m_sourceName.setValueBypassingBindings(newName);
198 m_sourceName.notify();
199 }
200 return;
201 }
202
203 // tryAttach() will update the m_sourceName correctly
204 tryAttach(newName, false);
205}
206
207QBindable<QString> QDeclarativePositionSource::bindableName()
208{
209 return QBindable<QString>(&m_sourceName);
210}
211
212QBindable<QDeclarativePosition *> QDeclarativePositionSource::bindablePosition() const
213{
214 return QBindable<QDeclarativePosition *>(&m_position);
215}
216
217/*!
218 \internal
219*/
220void QDeclarativePositionSource::tryAttach(const QString &newName, bool useFallback)
221{
222 const QString previousName = name();
223 const bool sourceExisted = (m_positionSource != nullptr);
224
225 int previousUpdateInterval = updateInterval();
226 PositioningMethods previousPositioningMethods = supportedPositioningMethods();
227 PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
228
229 m_defaultSourceUsed = false;
230
231 if (newName.isEmpty()) {
232 setSource(QGeoPositionInfoSource::createDefaultSource(parameterMap(), this));
233 m_defaultSourceUsed = true;
234 } else {
235 setSource(QGeoPositionInfoSource::createSource(newName, parameterMap(), this));
236 if (!m_positionSource && useFallback) {
237 setSource(QGeoPositionInfoSource::createDefaultSource(parameterMap(), this));
238 m_defaultSourceUsed = true;
239 }
240 }
241
242 if (m_positionSource) {
243 m_sourceName.setValueBypassingBindings(m_positionSource->sourceName());
244
245 connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
246 this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
247 connect(m_positionSource, SIGNAL(errorOccurred(QGeoPositionInfoSource::Error)),
248 this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error)));
249
250 m_positionSource->setUpdateInterval(m_updateInterval);
251 m_positionSource->setPreferredPositioningMethods(
252 static_cast<QGeoPositionInfoSource::PositioningMethods>(int(m_preferredPositioningMethods)));
253
254 if (m_startRequested) {
255 const QGeoPositionInfo &lastKnown = m_positionSource->lastKnownPosition();
256 if (lastKnown.isValid())
257 setPosition(lastKnown);
258 }
259 } else {
260 m_sourceName.setValueBypassingBindings(newName);
261 m_defaultSourceUsed = false;
262 if (m_active) {
263 // We do not want to break the binding here, because we just want to
264 // give the user an opportunity to select another plugin and keep
265 // working.
266 m_active.setValueBypassingBindings(false);
267 m_active.notify();
268 }
269 }
270
271 if (previousUpdateInterval != updateInterval())
272 emit updateIntervalChanged();
273
274 if (previousPreferredPositioningMethods != preferredPositioningMethods())
275 emit preferredPositioningMethodsChanged();
276
277 if (previousPositioningMethods != supportedPositioningMethods())
278 notifySupportedPositioningMethodsChanged();
279
280 const bool sourceCurrentlyExists = (m_positionSource != nullptr);
281 if (sourceExisted != sourceCurrentlyExists) {
282 m_isValid.notify();
283 emit validityChanged();
284 }
285
286 if (m_active) { // implies m_positionSource
287 // If m_active is true, then the previous position source existed!
288 Q_ASSERT(sourceExisted);
289 // New source is set. It should be inactive by default.
290 // But we do not want to break the binding.
291 m_active.setValueBypassingBindings(false);
292 m_active.notify();
293 } else if (m_startRequested) {
294 m_startRequested = false;
295 executeStart();
296 }
297
298 if (previousName != m_sourceName)
299 m_sourceName.notify();
300}
301
302/*!
303 \qmlproperty bool PositionSource::valid
304
305 This property is true if the PositionSource object has acquired a valid
306 backend plugin to provide data. If false, other methods on the PositionSource
307 will have no effect.
308
309 Applications should check this property to determine whether positioning is
310 available and enabled on the runtime platform, and react accordingly.
311*/
312bool QDeclarativePositionSource::isValid() const
313{
314 return m_isValid.value();
315}
316
317QBindable<bool> QDeclarativePositionSource::bindableIsValid() const
318{
319 return QBindable<bool>(&m_isValid);
320}
321
322bool QDeclarativePositionSource::isValidActualComputation() const
323{
324 return m_positionSource != nullptr;
325}
326
327/*!
328 \internal
329*/
330void QDeclarativePositionSource::onParameterInitialized()
331{
332 m_parametersInitialized = true;
333 for (QDeclarativePluginParameter *p: std::as_const(m_parameters)) {
334 if (!p->isInitialized()) {
335 m_parametersInitialized = false;
336 break;
337 }
338 }
339
340 // If here, componentComplete has been called.
341 if (m_parametersInitialized)
342 tryAttach(m_sourceName.value());
343}
344
345void QDeclarativePositionSource::notifySupportedPositioningMethodsChanged()
346{
347 m_supportedPositioningMethods.notify();
348 emit supportedPositioningMethodsChanged();
349}
350
351void QDeclarativePositionSource::setPosition(const QGeoPositionInfo &pi)
352{
353 m_position.value()->setPosition(pi);
354 m_position.notify();
355 emit positionChanged();
356}
357
358void QDeclarativePositionSource::setSource(QGeoPositionInfoSource *source)
359{
360 if (m_positionSource)
361 delete m_positionSource;
362
363 if (!source) {
364 m_positionSource = nullptr;
365 } else {
366 m_positionSource = source;
367 connect(m_positionSource, &QGeoPositionInfoSource::supportedPositioningMethodsChanged,
368 this, &QDeclarativePositionSource::notifySupportedPositioningMethodsChanged);
369 }
370}
371
372bool QDeclarativePositionSource::parametersReady()
373{
374 for (const QDeclarativePluginParameter *p: std::as_const(m_parameters)) {
375 if (!p->isInitialized())
376 return false;
377 }
378 return true;
379}
380
381/*!
382 \internal
383*/
384QVariantMap QDeclarativePositionSource::parameterMap() const
385{
386 QVariantMap map;
387
388 for (const auto *parameter : m_parameters)
389 map.insert(parameter->name(), parameter->value());
390
391 return map;
392}
393
394/*!
395 \internal
396*/
397void QDeclarativePositionSource::setUpdateInterval(int updateInterval)
398{
399 if (m_positionSource) {
400 int previousUpdateInterval = m_positionSource->updateInterval();
401
402 m_updateInterval = updateInterval;
403
404 if (previousUpdateInterval != updateInterval) {
405 m_positionSource->setUpdateInterval(updateInterval);
406 if (previousUpdateInterval != m_positionSource->updateInterval())
407 emit updateIntervalChanged();
408 }
409 } else {
410 if (m_updateInterval != updateInterval) {
411 m_updateInterval = updateInterval;
412 emit updateIntervalChanged();
413 }
414 }
415}
416
417/*!
418 \qmlproperty int PositionSource::updateInterval
419
420 This property holds the desired interval between updates (milliseconds).
421
422 \sa {QGeoPositionInfoSource::updateInterval()}
423*/
424
425int QDeclarativePositionSource::updateInterval() const
426{
427 if (!m_positionSource)
428 return m_updateInterval;
429
430 return m_positionSource->updateInterval();
431}
432
433/*!
434 \qmlproperty enumeration PositionSource::supportedPositioningMethods
435
436 This property holds the supported positioning methods of the
437 current source.
438
439 \value PositionSource.NoPositioningMethods
440 No positioning methods supported (no source).
441 \value PositionSource.SatellitePositioningMethods
442 Satellite-based positioning methods such as GPS are supported.
443 \value PositionSource.NonSatellitePositioningMethods
444 Non-satellite-based methods are supported.
445 \value PositionSource.AllPositioningMethods
446 Both satellite-based and non-satellite positioning methods are supported.
447*/
448
449QDeclarativePositionSource::PositioningMethods
450QDeclarativePositionSource::supportedPositioningMethods() const
451{
452 return m_supportedPositioningMethods.value();
453}
454
455QDeclarativePositionSource::PositioningMethods
456QDeclarativePositionSource::supportedMethodsActualComputation() const
457{
458 if (m_positionSource) {
459 return static_cast<QDeclarativePositionSource::PositioningMethods>(
460 int(m_positionSource->supportedPositioningMethods()));
461 }
462 return QDeclarativePositionSource::NoPositioningMethods;
463}
464
465QBindable<QDeclarativePositionSource::PositioningMethods>
466QDeclarativePositionSource::bindableSupportedPositioningMethods() const
467{
468 return QBindable<PositioningMethods>(&m_supportedPositioningMethods);
469}
470
471/*!
472 \qmlproperty enumeration PositionSource::preferredPositioningMethods
473
474 This property holds the preferred positioning methods of the
475 current source.
476
477 \value PositionSource.NoPositioningMethods
478 No positioning method is preferred.
479 \value PositionSource.SatellitePositioningMethods
480 Satellite-based positioning methods such as GPS should be preferred.
481 \value PositionSource.NonSatellitePositioningMethods
482 Non-satellite-based methods should be preferred.
483 \value PositionSource.AllPositioningMethods
484 Any positioning methods are acceptable.
485*/
486
487void QDeclarativePositionSource::setPreferredPositioningMethods(PositioningMethods methods)
488{
489 if (m_positionSource) {
490 PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
491
492 m_preferredPositioningMethods = methods;
493
494 if (previousPreferredPositioningMethods != methods) {
495 m_positionSource->setPreferredPositioningMethods(
496 static_cast<QGeoPositionInfoSource::PositioningMethods>(int(methods)));
497 if (previousPreferredPositioningMethods != m_positionSource->preferredPositioningMethods())
498 emit preferredPositioningMethodsChanged();
499 }
500 } else {
501 if (m_preferredPositioningMethods != methods) {
502 m_preferredPositioningMethods = methods;
503 emit preferredPositioningMethodsChanged();
504 }
505 }
506}
507
508QDeclarativePositionSource::PositioningMethods QDeclarativePositionSource::preferredPositioningMethods() const
509{
510 if (m_positionSource) {
511 return static_cast<QDeclarativePositionSource::PositioningMethods>(
512 int(m_positionSource->preferredPositioningMethods()));
513 }
514 return m_preferredPositioningMethods;
515}
516
517/*!
518 \qmlmethod void PositionSource::start()
519
520 Requests updates from the location source.
521 Uses \l updateInterval if set, default interval otherwise.
522 If there is no source available, this method has no effect.
523
524 \note Calling this method breaks the bindings of
525 \l {PositionSource::}{active} property.
526
527 \sa stop(), update(), active
528*/
529
530void QDeclarativePositionSource::start()
531{
532 if (m_positionSource) {
533 m_active.removeBindingUnlessInWrapper();
534 executeStart();
535 }
536}
537
538/*!
539 \qmlmethod void PositionSource::update(int timeout)
540
541 A convenience method to request single update from the location source.
542 If there is no source available, this method has no effect.
543
544 If the position source is not active, it will be activated for as
545 long as it takes to receive an update, or until the request times
546 out. The request timeout period is source-specific.
547
548 The \a timeout is specified in milliseconds. If the \a timeout is zero
549 (the default value), it defaults to a reasonable timeout period as
550 appropriate for the source.
551
552 \sa start(), stop(), active
553*/
554
555void QDeclarativePositionSource::update(int timeout)
556{
557 if (m_positionSource) {
558 m_singleUpdate = true;
559 if (!m_active) {
560 // Questionable: we do not want this method to break the binding.
561 // Mostly because it can be called while the updates are already
562 // running.
563 m_active.setValueBypassingBindings(true);
564 m_active.notify();
565 }
566 // Use default timeout value. Set active before calling the
567 // update request because on some platforms there may
568 // be results immediately.
569 m_positionSource->requestUpdate(timeout);
570 }
571}
572
573/*!
574 \qmlmethod void PositionSource::stop()
575
576 Stops updates from the location source.
577 If there is no source available or it is not active,
578 this method has no effect.
579
580 \note Calling this method breaks the bindings of
581 \l {PositionSource::}{active} property.
582
583 \sa start(), update(), active
584*/
585
586void QDeclarativePositionSource::stop()
587{
588 if (m_positionSource) {
589 m_positionSource->stopUpdates();
590 m_regularUpdates = false;
591 // Try to break the binding even if we do not actually need to update
592 // the active state. The m_active can be updated later, when the
593 // single update request finishes.
594 m_active.removeBindingUnlessInWrapper();
595 if (m_active && !m_singleUpdate) {
596 m_active.setValueBypassingBindings(false);
597 m_active.notify();
598 }
599 }
600}
601
602/*!
603 \qmlproperty bool PositionSource::active
604
605 This property indicates whether the position source is active.
606 Setting this property to false equals calling \l stop, and
607 setting this property true equals calling \l start.
608
609 \sa start, stop, update
610*/
611void QDeclarativePositionSource::setActive(bool active)
612{
613 // We need to remove binding, if this method is called explicitly.
614 // Other changes to m_active are done inside start() and stop() methods.
615 m_active.removeBindingUnlessInWrapper();
616 if (active == m_active)
617 return;
618
619 if (active) {
620 // If the component is not completed yet, we need to defer the
621 // actual executeStart() call until everything is set up.
622 if (m_componentComplete && m_parametersInitialized)
623 executeStart();
624 else
625 m_startRequested = true;
626 } else {
627 stop();
628 }
629}
630
631bool QDeclarativePositionSource::isActive() const
632{
633 return m_active;
634}
635
636/*!
637 \qmlproperty Position PositionSource::position
638
639 This property holds the last known positional data.
640 It is a read-only property.
641
642 The Position type has different positional member variables,
643 whose validity can be checked with appropriate validity functions
644 (for example sometimes an update does not have speed or altitude data).
645
646 However, whenever a \c {positionChanged} signal has been received, at least
647 position::coordinate::latitude, position::coordinate::longitude, and position::timestamp can
648 be assumed to be valid.
649
650 \sa start, stop, update
651*/
652
653QDeclarativePosition *QDeclarativePositionSource::position()
654{
655 return m_position.value();
656}
657
658void QDeclarativePositionSource::positionUpdateReceived(const QGeoPositionInfo &update)
659{
660 setPosition(update);
661
662 if (m_singleUpdate && m_active) {
663 // we need to reset m_singleUpdate because we got one
664 m_singleUpdate = false;
665 if (!m_regularUpdates) {
666 // but we change the active state only if the regular updates are
667 // also stopped
668 m_active.setValueBypassingBindings(false);
669 m_active.notify();
670 }
671 }
672}
673
674
675/*!
676 \qmlproperty enumeration PositionSource::sourceError
677
678 This property holds the error which last occurred with the PositionSource.
679
680 \value PositionSource.AccessError
681 The connection setup to the remote positioning backend failed because the
682 application lacked the required privileges.
683 \value PositionSource.ClosedError
684 The positioning backend closed the connection, which happens for example in case
685 the user is switching location services to off. As soon as the location service is re-enabled
686 regular updates will resume.
687 \value PositionSource.NoError No error has occurred.
688 \value PositionSource.UnknownSourceError An unidentified error occurred.
689 \value PositionSource.UpdateTimeoutError
690 The current position could not be
691 retrieved within the specified timeout, or this PositionSource determined
692 that it will not be able to provide further regular updates.
693*/
694
695QDeclarativePositionSource::SourceError QDeclarativePositionSource::sourceError() const
696{
697 return m_sourceError;
698}
699
700QBindable<QDeclarativePositionSource::SourceError>
701QDeclarativePositionSource::bindableSourceError() const
702{
703 return QBindable<QDeclarativePositionSource::SourceError>(&m_sourceError);
704}
705
706QGeoPositionInfoSource *QDeclarativePositionSource::positionSource() const
707{
708 return m_positionSource;
709}
710
711/*!
712 \qmlproperty list<PluginParameter> PositionSource::parameters
713 \qmldefault
714
715 This property holds the list of plugin parameters.
716
717 \since QtPositioning 5.14
718*/
719QQmlListProperty<QDeclarativePluginParameter> QDeclarativePositionSource::parameters()
720{
721 return QQmlListProperty<QDeclarativePluginParameter>(this,
722 0,
723 parameter_append,
724 parameter_count,
725 parameter_at,
726 parameter_clear);
727}
728
729/*!
730 \internal
731*/
732void QDeclarativePositionSource::parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *parameter)
733{
734 QDeclarativePositionSource *p = static_cast<QDeclarativePositionSource *>(prop->object);
735 p->m_parameters.append(parameter);
736}
737
738/*!
739 \internal
740*/
741qsizetype QDeclarativePositionSource::parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop)
742{
743 return static_cast<QDeclarativePositionSource *>(prop->object)->m_parameters.size();
744}
745
746/*!
747 \internal
748*/
749QDeclarativePluginParameter *QDeclarativePositionSource::parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, qsizetype index)
750{
751 return static_cast<QDeclarativePositionSource *>(prop->object)->m_parameters[index];
752}
753
754/*!
755 \internal
756*/
757void QDeclarativePositionSource::parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop)
758{
759 QDeclarativePositionSource *p = static_cast<QDeclarativePositionSource *>(prop->object);
760 p->m_parameters.clear();
761}
762
763void QDeclarativePositionSource::executeStart()
764{
765 if (m_positionSource) {
766 m_positionSource->startUpdates();
767
768 // If this method is called directly from start(), the binding is
769 // already broken there (for the consistency with stop()).
770 // If this method is called by a timer, started in setActive(), we do
771 // not need to break the binding, because it was already done (if
772 // needed).
773
774 m_regularUpdates = true;
775 if (!m_active) {
776 m_active.setValueBypassingBindings(true);
777 m_active.notify();
778 }
779 }
780}
781
782void QDeclarativePositionSource::componentComplete()
783{
784 m_componentComplete = true;
785 m_parametersInitialized = true;
786 for (QDeclarativePluginParameter *p: std::as_const(m_parameters)) {
787 if (!p->isInitialized()) {
788 m_parametersInitialized = false;
789 connect(p, &QDeclarativePluginParameter::initialized,
790 this, &QDeclarativePositionSource::onParameterInitialized,
791 Qt::SingleShotConnection);
792 }
793 }
794
795 if (m_parametersInitialized)
796 tryAttach(m_sourceName.value());
797}
798
799/*!
800 \qmlmethod bool PositionSource::setBackendProperty(string name, var value)
801
802 Sets the backend-specific property named \a name to \a value.
803 Returns true on success, false otherwise, including if called on an uninitialized PositionSource.
804 Supported backend-specific properties are listed and described in
805 \l {Qt Positioning plugins#Default plugins}.
806
807 \since Qt Positioning 5.14
808
809 \sa backendProperty, QGeoPositionInfoSource::setBackendProperty
810*/
811bool QDeclarativePositionSource::setBackendProperty(const QString &name, const QVariant &value)
812{
813 if (m_positionSource)
814 return m_positionSource->setBackendProperty(name, value);
815 return false;
816}
817
818/*!
819 \qmlmethod var PositionSource::backendProperty(string name)
820
821 Returns the value of the backend-specific property named \a name, if present.
822 Otherwise, including if called on an uninitialized PositionSource, the return value will be invalid.
823 Supported backend-specific properties are listed and described in
824 \l {Qt Positioning plugins#Default plugins}.
825
826 \since Qt Positioning 5.14
827
828 \sa setBackendProperty, QGeoPositionInfoSource::setBackendProperty
829*/
830QVariant QDeclarativePositionSource::backendProperty(const QString &name) const
831{
832 if (m_positionSource)
833 return m_positionSource->backendProperty(name);
834 return QVariant();
835}
836
837QBindable<bool> QDeclarativePositionSource::bindableActive()
838{
839 return QBindable<bool>(&m_active);
840}
841
842/*!
843 \internal
844*/
845void QDeclarativePositionSource::sourceErrorReceived(const QGeoPositionInfoSource::Error error)
846{
847 if (error == QGeoPositionInfoSource::AccessError)
848 m_sourceError.setValueBypassingBindings(QDeclarativePositionSource::AccessError);
849 else if (error == QGeoPositionInfoSource::ClosedError)
850 m_sourceError.setValueBypassingBindings(QDeclarativePositionSource::ClosedError);
851 else if (error == QGeoPositionInfoSource::UpdateTimeoutError)
852 m_sourceError.setValueBypassingBindings(QDeclarativePositionSource::UpdateTimeoutError);
853 else if (error == QGeoPositionInfoSource::NoError)
854 return; //nothing to do
855 else
856 m_sourceError.setValueBypassingBindings(QDeclarativePositionSource::UnknownSourceError);
857
858 m_sourceError.notify();
859 emit sourceErrorChanged();
860
861 // if an error occurred during single update, the update is stopped, so we
862 // need to change the active state.
863 if (m_active && m_singleUpdate) {
864 m_singleUpdate = false;
865 if (!m_regularUpdates) {
866 m_active.setValueBypassingBindings(false);
867 m_active.notify();
868 }
869 }
870}
871
872QT_END_NAMESPACE
873
874#include "moc_qdeclarativepositionsource_p.cpp"