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
qdeclarativesatellitesource.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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
6
8
9/*!
10 \qmltype SatelliteSource
11 \inqmlmodule QtPositioning
12 \since 6.5
13 \brief The SatelliteSource class provides the satellite information.
14
15 The SatelliteSource class provides information about satellites in use and
16 satellites in view. This class is a QML representation of
17 \l QGeoSatelliteInfoSource.
18
19 Like its C++ equivalent, the class supports different plugins. Use the
20 \l name property to specify the name of the plugin to be used, and provide
21 \l {PluginParameter}s, if required. If the \l name property is not set,
22 a default plugin will be used. See \l {Qt Positioning Plugins} for more
23 information on the available plugins.
24
25 Use the \l valid property to check the SatelliteSource state.
26
27 Use the \l updateInterval property to indicate how often your application
28 wants to receive the satellite information updates. The \l start(),
29 \l stop() and \l update() methods can be used to control the operation
30 of the SatelliteSource, as well as the \l active property, which when set
31 is equivalent to calling \l start() or \l stop().
32
33 When the SatelliteSource is active, satellite information updates can
34 be retrieved using the \l satellitesInView and \l satellitesInUse
35 properties.
36
37 If an error happens during satellite information updates, use the
38 \l sourceError property to get the actual error code.
39
40 \section2 Example Usage
41
42 The following example shows a SatelliteSource which is using the
43 \l {Qt Positioning NMEA plugin}{NMEA} plugin to receive satellite
44 information updates every second and print the amount of satellites
45 in view and satellites in use to the console.
46
47 \qml
48 SatelliteSource {
49 id: source
50 name: "nmea"
51 active: true
52 updateInterval: 1000
53 PluginParameter { name: "nmea.source"; value: "serial:/dev/ttyACM0" }
54
55 onSatellitesInUseChanged: {
56 console.log("Satellites in use:", source.satellitesInUse.length)
57 }
58 onSatellitesInViewChanged: {
59 console.log("Satellites in view:", source.satellitesInView.length)
60 }
61 }
62 \endqml
63
64 \sa QGeoSatelliteInfoSource, PluginParameter, geoSatelliteInfo
65*/
66
67QDeclarativeSatelliteSource::QDeclarativeSatelliteSource()
68 : m_active(0), m_componentComplete(0), m_parametersInitialized(0),
69 m_startRequested(0), m_defaultSourceUsed(0), m_regularUpdates(0),
70 m_singleUpdate(0), m_singleUpdateRequested(0)
71{
72}
73
74QDeclarativeSatelliteSource::~QDeclarativeSatelliteSource()
75{
76 if (m_source)
77 m_source->disconnect(this);
78}
79
80/*!
81 \qmlproperty bool SatelliteSource::active
82
83 This property indicates whether the satellite source is active.
84 Setting this property to \c false equals calling \l stop, and
85 setting this property to \c true equals calling \l start.
86
87 \sa start, stop, update
88*/
89bool QDeclarativeSatelliteSource::isActive() const
90{
91 return m_active;
92}
93
94/*!
95 \qmlproperty bool SatelliteSource::valid
96 \readonly
97
98 This property is \c true if the SatelliteSource object has acquired a valid
99 backend plugin to provide data, and \c false otherwise.
100
101 Applications should check this property to determine whether providing
102 satellite information is available and enabled on the runtime platform,
103 and react accordingly.
104*/
105bool QDeclarativeSatelliteSource::isValid() const
106{
107 return m_source != nullptr;
108}
109
110/*!
111 \qmlproperty int SatelliteSource::updateInterval
112
113 This property holds the desired interval between updates in milliseconds.
114*/
115int QDeclarativeSatelliteSource::updateInterval() const
116{
117 return m_source ? m_source->updateInterval() : m_updateInterval;
118}
119
120/*!
121 \qmlproperty enumeration SatelliteSource::sourceError
122 \readonly
123
124 This property holds the error which last occurred with the backend data
125 provider.
126
127 \value SatelliteSource.AccessError
128 The connection setup to the satellite
129 backend failed because the application lacked the required
130 privileges.
131 \value SatelliteSource.ClosedError
132 The satellite backend closed the
133 connection, which happens for example in case the user is switching
134 location services to off.
135 \value SatelliteSource.NoError
136 No error has occurred.
137 \value SatelliteSource.UnknownSourceError
138 An unidentified error occurred.
139 \value SatelliteSource.UpdateTimeoutError
140 The satellite information could not be retrieved within the specified timeout.
141*/
142QDeclarativeSatelliteSource::SourceError QDeclarativeSatelliteSource::sourceError() const
143{
144 return m_error;
145}
146
147/*!
148 \qmlproperty string SatelliteSource::name
149
150 This property holds the unique internal name for the plugin currently
151 providing satellite information.
152
153 Setting the property causes the SatelliteSource to use a particular
154 backend plugin. If the SatelliteSource is active at the time that the name
155 property is changed, it will become inactive. If the specified backend
156 cannot be loaded the satellite source will become invalid.
157
158 Changing the name property may cause the \l updateInterval property
159 to change as well.
160*/
161QString QDeclarativeSatelliteSource::name() const
162{
163 return m_source ? m_source->sourceName() : m_name;
164}
165
166/*!
167 \qmlproperty list<PluginParameter> SatelliteSource::parameters
168 \readonly
169 \qmldefault
170
171 This property holds the list of plugin parameters.
172
173 \sa PluginParameter
174*/
175QQmlListProperty<QDeclarativePluginParameter> QDeclarativeSatelliteSource::parameters()
176{
177 return QQmlListProperty<QDeclarativePluginParameter>(this, nullptr,
178 parameter_append,
179 parameter_count,
180 parameter_at,
181 parameter_clear);
182}
183
184/*!
185 \qmlproperty list<geoSatelliteInfo> SatelliteSource::satellitesInUse
186 \readonly
187
188 This property holds the list of satellites that are currently in use.
189 These are the satellites that are used to get a "fix" - that
190 is, those used to determine the current position.
191*/
192QList<QGeoSatelliteInfo> QDeclarativeSatelliteSource::satellitesInUse() const
193{
194 return m_satellitesInUse;
195}
196
197/*!
198 \qmlproperty list<geoSatelliteInfo> SatelliteSource::satellitesInView
199 \readonly
200
201 This property holds the list of satellites that are currently in view.
202*/
203QList<QGeoSatelliteInfo> QDeclarativeSatelliteSource::satellitesInView() const
204{
205 return m_satellitesInView;
206}
207
208void QDeclarativeSatelliteSource::setUpdateInterval(int updateInterval)
209{
210 if (m_updateInterval == updateInterval)
211 return;
212
213 const auto oldInterval = m_updateInterval;
214
215 if (m_source) {
216 m_source->setUpdateInterval(updateInterval);
217 // The above call can set some other interval, for example if desired
218 // updateInterval is less than minimum supported update interval. So
219 // we need to read the value back explicitly.
220 m_updateInterval = m_source->updateInterval();
221 } else {
222 m_updateInterval = updateInterval;
223 }
224 if (oldInterval != m_updateInterval)
225 emit updateIntervalChanged();
226}
227
228void QDeclarativeSatelliteSource::setActive(bool active)
229{
230 if (active == m_active)
231 return;
232
233 if (active)
234 start();
235 else
236 stop();
237}
238
239void QDeclarativeSatelliteSource::setName(const QString &name)
240{
241 if ((m_name == name) || (name.isEmpty() && m_defaultSourceUsed))
242 return;
243
244 if (m_componentComplete && m_parametersInitialized) {
245 createSource(name); // it will update name and emit, if needed
246 } else {
247 m_name = name;
248 emit nameChanged();
249 }
250}
251
252void QDeclarativeSatelliteSource::componentComplete()
253{
254 m_componentComplete = true;
255 m_parametersInitialized = true;
256 for (QDeclarativePluginParameter *p: std::as_const(m_parameters)) {
257 if (!p->isInitialized()) {
258 m_parametersInitialized = false;
259 connect(p, &QDeclarativePluginParameter::initialized,
260 this, &QDeclarativeSatelliteSource::onParameterInitialized,
261 Qt::SingleShotConnection);
262 }
263 }
264
265 if (m_parametersInitialized)
266 createSource(m_name);
267}
268
269/*!
270 \qmlmethod bool SatelliteSource::setBackendProperty(string name, var value)
271
272 Sets the backend-specific property named \a name to \a value.
273 Returns true on success, false otherwise, including if called on an
274 uninitialized SatelliteSource.
275*/
276bool QDeclarativeSatelliteSource::setBackendProperty(const QString &name, const QVariant &value)
277{
278 if (m_source)
279 return m_source->setBackendProperty(name, value);
280 return false;
281}
282
283/*!
284 \qmlmethod var SatelliteSource::backendProperty(string name)
285
286 Returns the value of the backend-specific property named \a name, if
287 present. Otherwise, including if called on an uninitialized SatelliteSource,
288 the return value will be invalid.
289*/
290QVariant QDeclarativeSatelliteSource::backendProperty(const QString &name) const
291{
292 return m_source ? m_source->backendProperty(name) : QVariant{};
293}
294
295/*!
296 \qmlmethod void SatelliteSource::update(int timeout = 0)
297
298 A convenience method to request a single update from the satellite source.
299 If there is no source available, this method has no effect.
300
301 If the satellite source is not active, it will be activated for as
302 long as it takes to receive an update, or until the request times
303 out. The request timeout period is plugin-specific.
304
305 The \a timeout is specified in milliseconds. If the \a timeout is zero
306 (the default value), it defaults to a reasonable timeout period as
307 appropriate for the source.
308
309 \sa start(), stop(), active
310*/
311void QDeclarativeSatelliteSource::update(int timeout)
312{
313 if (m_componentComplete && m_parametersInitialized) {
314 executeSingleUpdate(timeout);
315 } else {
316 m_singleUpdateDesiredTimeout = timeout;
317 m_singleUpdateRequested = true;
318 }
319}
320
321/*!
322 \qmlmethod void SatelliteSource::start()
323
324 Requests updates from the satellite source. Uses \l updateInterval if set,
325 default interval otherwise. If there is no source available, this method
326 has no effect.
327
328 \sa stop(), update(), active
329*/
330void QDeclarativeSatelliteSource::start()
331{
332 if (m_componentComplete && m_parametersInitialized)
333 executeStart();
334 else
335 m_startRequested = true;
336}
337
338/*!
339 \qmlmethod void SatelliteSource::stop()
340
341 Stops updates from the satellite source. If there is no source available or
342 it is not active, this method has no effect.
343
344 \sa start(), update(), active
345*/
346void QDeclarativeSatelliteSource::stop()
347{
348 if (m_source) {
349 m_source->stopUpdates();
350 m_regularUpdates = false;
351
352 if (m_active && !m_singleUpdate) {
353 m_active = false;
354 emit activeChanged();
355 }
356 } else {
357 m_startRequested = false;
358 }
359}
360
361void QDeclarativeSatelliteSource::sourceErrorReceived(const QGeoSatelliteInfoSource::Error error)
362{
363 const auto oldError = m_error;
364 m_error = static_cast<SourceError>(error);
365 if (m_error != oldError)
366 emit sourceErrorChanged();
367
368 // if an error occurred during single update, the update is stopped, so we
369 // need to change the active state.
370 if (m_singleUpdate) {
371 m_singleUpdate = false;
372 if (m_active && !m_regularUpdates) {
373 m_active = false;
374 emit activeChanged();
375 }
376 }
377}
378
379void QDeclarativeSatelliteSource::onParameterInitialized()
380{
381 m_parametersInitialized = true;
382 for (QDeclarativePluginParameter *p: std::as_const(m_parameters)) {
383 if (!p->isInitialized()) {
384 m_parametersInitialized = false;
385 break;
386 }
387 }
388
389 // m_componentComplete == true here
390 if (m_parametersInitialized)
391 createSource(m_name);
392}
393
394void QDeclarativeSatelliteSource::satellitesInViewUpdateReceived(const QList<QGeoSatelliteInfo> &satellites)
395{
396 m_satellitesInView = satellites;
397 emit satellitesInViewChanged();
398 handleSingleUpdateReceived();
399}
400
401void QDeclarativeSatelliteSource::satellitesInUseUpdateReceived(const QList<QGeoSatelliteInfo> &satellites)
402{
403 m_satellitesInUse = satellites;
404 emit satellitesInUseChanged();
405 handleSingleUpdateReceived();
406}
407
408QVariantMap QDeclarativeSatelliteSource::parameterMap() const
409{
410 QVariantMap map;
411 for (const auto *parameter : std::as_const(m_parameters))
412 map.insert(parameter->name(), parameter->value());
413 return map;
414}
415
416void QDeclarativeSatelliteSource::createSource(const QString &newName)
417{
418 if (m_source && m_source->sourceName() == newName)
419 return;
420
421 const auto oldName = name();
422 const bool oldIsValid = isValid();
423 const bool oldActive = isActive();
424 const auto oldUpdateInterval = updateInterval();
425
426 if (m_source) {
427 m_source->disconnect(this);
428 m_source->stopUpdates();
429 m_source.reset(nullptr);
430 m_active = false;
431 }
432
433 if (!newName.isEmpty()) {
434 m_source.reset(QGeoSatelliteInfoSource::createSource(newName, parameterMap(), nullptr));
435 m_defaultSourceUsed = false;
436 } else {
437 m_source.reset(QGeoSatelliteInfoSource::createDefaultSource(parameterMap(), nullptr));
438 m_defaultSourceUsed = true;
439 }
440
441 if (m_source) {
442 connect(m_source.get(), &QGeoSatelliteInfoSource::errorOccurred,
443 this, &QDeclarativeSatelliteSource::sourceErrorReceived);
444 connect(m_source.get(), &QGeoSatelliteInfoSource::satellitesInViewUpdated,
445 this, &QDeclarativeSatelliteSource::satellitesInViewUpdateReceived);
446 connect(m_source.get(), &QGeoSatelliteInfoSource::satellitesInUseUpdated,
447 this, &QDeclarativeSatelliteSource::satellitesInUseUpdateReceived);
448
449 m_name = m_source->sourceName();
450 m_source->setUpdateInterval(m_updateInterval);
451 m_updateInterval = m_source->updateInterval();
452 } else {
453 m_name = newName;
454 m_defaultSourceUsed = false;
455 }
456
457 if (oldName != name())
458 emit nameChanged();
459
460 if (oldIsValid != isValid())
461 emit validityChanged();
462
463 if (oldActive != isActive())
464 emit activeChanged();
465
466 if (oldUpdateInterval != updateInterval())
467 emit updateIntervalChanged();
468
469 if (m_startRequested) {
470 m_startRequested = false;
471 executeStart();
472 }
473 if (m_singleUpdateRequested) {
474 m_singleUpdateRequested = false;
475 executeSingleUpdate(m_singleUpdateDesiredTimeout);
476 }
477}
478
479void QDeclarativeSatelliteSource::handleSingleUpdateReceived()
480{
481 if (m_singleUpdate) {
482 m_singleUpdate = false;
483 if (m_active && !m_regularUpdates) {
484 m_active = false;
485 emit activeChanged();
486 }
487 }
488}
489
490void QDeclarativeSatelliteSource::executeStart()
491{
492 if (m_source) {
493 m_regularUpdates = true;
494 if (!m_active) {
495 m_active = true;
496 emit activeChanged();
497 }
498 m_source->startUpdates();
499 }
500}
501
502void QDeclarativeSatelliteSource::executeSingleUpdate(int timeout)
503{
504 if (m_source) {
505 m_singleUpdate = true;
506 if (!m_active) {
507 m_active = true;
508 emit activeChanged();
509 }
510 m_source->requestUpdate(timeout);
511 }
512}
513
514void QDeclarativeSatelliteSource::parameter_append(PluginParameterProperty *prop,
515 QDeclarativePluginParameter *parameter)
516{
517 auto *src = static_cast<QDeclarativeSatelliteSource *>(prop->object);
518 src->m_parameters.append(parameter);
519}
520
521qsizetype QDeclarativeSatelliteSource::parameter_count(PluginParameterProperty *prop)
522{
523 return static_cast<QDeclarativeSatelliteSource *>(prop->object)->m_parameters.size();
524}
525
526QDeclarativePluginParameter *
527QDeclarativeSatelliteSource::parameter_at(PluginParameterProperty *prop, qsizetype index)
528{
529 return static_cast<QDeclarativeSatelliteSource *>(prop->object)->m_parameters[index];
530}
531
532void QDeclarativeSatelliteSource::parameter_clear(PluginParameterProperty *prop)
533{
534 auto *src = static_cast<QDeclarativeSatelliteSource *>(prop->object);
535 src->m_parameters.clear();
536}
537
538QT_END_NAMESPACE
Combined button and popup list for selecting options.