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