1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtPositioning module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
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 https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | #include <qgeosatelliteinfosource.h> |
40 | #include <qgeosatelliteinfosource_p.h> |
41 | #include "qgeopositioninfosourcefactory.h" |
42 | #include "qgeopositioninfosource_p.h" |
43 | #include <QPluginLoader> |
44 | #include <QStringList> |
45 | #include <QCryptographicHash> |
46 | #include <QtCore/private/qfactoryloader_p.h> |
47 | #include <QFile> |
48 | |
49 | QT_BEGIN_NAMESPACE |
50 | |
51 | /*! |
52 | \class QGeoSatelliteInfoSource |
53 | \inmodule QtPositioning |
54 | \ingroup QtPositioning-positioning |
55 | \since 5.2 |
56 | |
57 | \brief The QGeoSatelliteInfoSource class is an abstract base class for the distribution of satellite information updates. |
58 | |
59 | The static function QGeoSatelliteInfoSource::createDefaultSource() creates a default |
60 | satellite data source that is appropriate for the platform, if one is |
61 | available. Otherwise, available QGeoPositionInfoSourceFactory plugins will |
62 | be checked for one that has a satellite data source available. |
63 | |
64 | Call startUpdates() and stopUpdates() to start and stop regular updates, |
65 | or requestUpdate() to request a single update. |
66 | When an update is available, satellitesInViewUpdated() and/or |
67 | satellitesInUseUpdated() will be emitted. |
68 | |
69 | If regular satellite updates are required, setUpdateInterval() can be used |
70 | to specify how often these updates should be emitted. If no interval is |
71 | specified, updates are simply provided whenever they are available. |
72 | For example: |
73 | |
74 | \code |
75 | // Emit updates every 10 seconds if available |
76 | QGeoSatelliteInfoSource *source = QGeoSatelliteInfoSource::createDefaultSource(0); |
77 | if (source) |
78 | source->setUpdateInterval(10000); |
79 | \endcode |
80 | |
81 | To remove an update interval that was previously set, call |
82 | setUpdateInterval() with a value of 0. |
83 | |
84 | Note that the satellite source may have a minimum value requirement for |
85 | update intervals, as returned by minimumUpdateInterval(). |
86 | */ |
87 | |
88 | /*! |
89 | Creates a satellite source with the specified \a parent. |
90 | */ |
91 | |
92 | QGeoSatelliteInfoSourcePrivate::~QGeoSatelliteInfoSourcePrivate() |
93 | { |
94 | |
95 | } |
96 | |
97 | QGeoSatelliteInfoSourcePrivate *QGeoSatelliteInfoSourcePrivate::get(QGeoSatelliteInfoSource &source) |
98 | { |
99 | return source.d; |
100 | } |
101 | |
102 | QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QObject *parent) |
103 | : QObject(parent), |
104 | d(new QGeoSatelliteInfoSourcePrivate) |
105 | { |
106 | d->interval = 0; |
107 | } |
108 | |
109 | QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QGeoSatelliteInfoSourcePrivate &dd, QObject *parent) |
110 | : QObject(parent), |
111 | d(&dd) |
112 | { |
113 | |
114 | } |
115 | |
116 | /*! |
117 | Destroys the satellite source. |
118 | */ |
119 | QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource() |
120 | { |
121 | delete d; |
122 | } |
123 | |
124 | /*! |
125 | Returns the unique name of the satellite source implementation in use. |
126 | |
127 | This is the same name that can be passed to createSource() in order to |
128 | create a new instance of a particular satellite source implementation. |
129 | */ |
130 | QString QGeoSatelliteInfoSource::sourceName() const |
131 | { |
132 | return d->providerName; |
133 | } |
134 | |
135 | |
136 | /*! |
137 | \property QGeoSatelliteInfoSource::updateInterval |
138 | \brief This property holds the requested interval in milliseconds between each update. |
139 | |
140 | If the update interval is not set (or is set to 0) the |
141 | source will provide updates as often as necessary. |
142 | |
143 | If the update interval is set, the source will provide updates at an |
144 | interval as close to the requested interval as possible. If the requested |
145 | interval is less than the minimumUpdateInterval(), |
146 | the minimum interval is used instead. |
147 | |
148 | Changes to the update interval will happen as soon as is practical, however the |
149 | time the change takes may vary between implementations. Whether or not the elapsed |
150 | time from the previous interval is counted as part of the new interval is also |
151 | implementation dependent. |
152 | |
153 | The default value for this property is 0. |
154 | |
155 | Note: Subclass implementations must call the base implementation of |
156 | setUpdateInterval() so that updateInterval() returns the correct value. |
157 | */ |
158 | void QGeoSatelliteInfoSource::setUpdateInterval(int msec) |
159 | { |
160 | d->interval = msec; |
161 | } |
162 | |
163 | int QGeoSatelliteInfoSource::updateInterval() const |
164 | { |
165 | return d->interval; |
166 | } |
167 | |
168 | static QGeoSatelliteInfoSource* createSource_real(const QJsonObject &meta, const QVariantMap ¶meters, QObject *parent) |
169 | { |
170 | QGeoPositionInfoSourcePrivate d; |
171 | d.metaData = meta; |
172 | d.loadPlugin(); |
173 | QGeoSatelliteInfoSource *s = nullptr; |
174 | if (!parameters.isEmpty() && d.factoryV2) |
175 | s = d.factoryV2->satelliteInfoSourceWithParameters(parent, parameters); |
176 | else if (d.factory) |
177 | s = d.factory->satelliteInfoSource(parent); |
178 | if (s) |
179 | QGeoSatelliteInfoSourcePrivate::get(source&: *s)->providerName = d.metaData.value(QStringLiteral("Provider" )).toString(); |
180 | |
181 | return s; |
182 | } |
183 | |
184 | /*! |
185 | Creates and returns a source with the specified \a parent that reads |
186 | from the system's default source of satellite update information, or the |
187 | highest priority available plugin. |
188 | |
189 | Returns 0 if the system has no default satellite source, no valid plugins |
190 | could be found or the user does not have the permission to access the satellite data. |
191 | */ |
192 | QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *parent) |
193 | { |
194 | return createDefaultSource(parameters: QVariantMap(), parent); |
195 | } |
196 | |
197 | /*! |
198 | Creates and returns a source with the given \a parent, |
199 | by loading the plugin named \a sourceName. |
200 | |
201 | Returns 0 if the plugin cannot be found. |
202 | */ |
203 | QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, QObject *parent) |
204 | { |
205 | return createSource(sourceName, parameters: QVariantMap(), parent); |
206 | } |
207 | |
208 | /*! |
209 | Creates and returns a satellite source with the given \a parent that |
210 | reads from the system's default sources of satellite data, or the plugin |
211 | with the highest available priority. |
212 | |
213 | Returns nullptr if the system has no default satellite source, no valid plugins |
214 | could be found or the user does not have the permission to access the satellite information. |
215 | |
216 | This method passes \a parameters to the factory to configure the source. |
217 | |
218 | \since Qt 5.14 |
219 | */ |
220 | QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(const QVariantMap ¶meters, QObject *parent) |
221 | { |
222 | QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted(); |
223 | foreach (const QJsonObject &obj, plugins) { |
224 | if (obj.value(QStringLiteral("Satellite" )).isBool() |
225 | && obj.value(QStringLiteral("Satellite" )).toBool()) |
226 | { |
227 | const QString testableKey = QStringLiteral("Testable" ); |
228 | if (obj.contains(key: testableKey) && !obj.value(key: testableKey).toBool()) { |
229 | static bool inTest = qEnvironmentVariableIsSet(varName: "QT_QTESTLIB_RUNNING" ); |
230 | if (inTest) |
231 | continue; |
232 | } |
233 | return createSource_real(meta: obj, parameters, parent); |
234 | } |
235 | } |
236 | |
237 | return nullptr; |
238 | } |
239 | |
240 | /*! |
241 | Creates and returns a satellite source with the given \a parent, |
242 | by loading the plugin named \a sourceName. |
243 | |
244 | Returns nullptr if the plugin cannot be found. |
245 | |
246 | This method passes \a parameters to the factory to configure the source. |
247 | |
248 | \since Qt 5.14 |
249 | */ |
250 | QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, const QVariantMap ¶meters, QObject *parent) |
251 | { |
252 | QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins(); |
253 | if (plugins.contains(akey: sourceName)) |
254 | return createSource_real(meta: plugins.value(akey: sourceName), parameters, parent); |
255 | return nullptr; |
256 | } |
257 | |
258 | /*! |
259 | Returns a list of available source plugins, including the default system |
260 | backend if one is available. |
261 | */ |
262 | QStringList QGeoSatelliteInfoSource::availableSources() |
263 | { |
264 | QStringList plugins; |
265 | const QHash<QString, QJsonObject> meta = QGeoPositionInfoSourcePrivate::plugins(); |
266 | for (auto it = meta.cbegin(), end = meta.cend(); it != end; ++it) { |
267 | if (it.value().value(QStringLiteral("Satellite" )).isBool() |
268 | && it.value().value(QStringLiteral("Satellite" )).toBool()) { |
269 | plugins << it.key(); |
270 | } |
271 | } |
272 | |
273 | return plugins; |
274 | } |
275 | |
276 | /*! |
277 | \fn void QGeoSatelliteInfoSource::satellitesInViewUpdated(const QList<QGeoSatelliteInfo> &satellites); |
278 | |
279 | If startUpdates() or requestUpdate() is called, this signal is emitted |
280 | when an update is available on the satellites that are |
281 | currently in view. |
282 | |
283 | The \a satellites parameter holds the satellites currently in view. |
284 | */ |
285 | |
286 | /*! |
287 | \fn void QGeoSatelliteInfoSource::satellitesInUseUpdated(const QList<QGeoSatelliteInfo> &satellites); |
288 | |
289 | If startUpdates() or requestUpdate() is called, this signal is emitted |
290 | when an update is available on the number of satellites that are |
291 | currently in use. |
292 | |
293 | These are the satellites that are used to get a "fix" - that |
294 | is, those used to determine the current position. |
295 | |
296 | The \a satellites parameter holds the satellites currently in use. |
297 | */ |
298 | |
299 | /*! |
300 | \property QGeoSatelliteInfoSource::minimumUpdateInterval |
301 | \brief This property holds the minimum time (in milliseconds) required to retrieve a satellite update. |
302 | |
303 | This is the minimum value accepted by setUpdateInterval() and |
304 | requestUpdate(). |
305 | */ |
306 | |
307 | |
308 | /*! |
309 | \fn virtual void QGeoSatelliteInfoSource::startUpdates() = 0; |
310 | |
311 | Starts emitting updates at regular intervals. The updates will be |
312 | provided whenever new satellite information becomes available. |
313 | |
314 | If satellite information cannot be retrieved or some other |
315 | form of timeout has occurred the satellitesInViewUpdated() |
316 | and satellitesInUseUpdated() signals may be emitted with |
317 | empty parameter lists. |
318 | |
319 | \sa satellitesInViewUpdated(), satellitesInUseUpdated() |
320 | */ |
321 | |
322 | /*! |
323 | \fn virtual void QGeoSatelliteInfoSource::stopUpdates() = 0; |
324 | |
325 | Stops emitting updates at regular intervals. |
326 | */ |
327 | |
328 | /*! |
329 | \fn virtual void QGeoSatelliteInfoSource::requestUpdate(int timeout = 0); |
330 | |
331 | Attempts to get the current satellite information and emit |
332 | satellitesInViewUpdated() and satellitesInUseUpdated() with this |
333 | information. If the current satellite information cannot be found |
334 | within the given \a timeout (in milliseconds) or if \a timeout is less than the value returned by |
335 | minimumUpdateInterval(), requestTimeout() is |
336 | emitted. |
337 | |
338 | If the timeout is zero, the timeout defaults to a reasonable timeout |
339 | period as appropriate for the source. |
340 | |
341 | This does nothing if another update request is in progress. However |
342 | it can be called even if startUpdates() has already been called and |
343 | regular updates are in progress. |
344 | */ |
345 | |
346 | /*! |
347 | \fn void QGeoSatelliteInfoSource::requestTimeout(); |
348 | |
349 | Emitted if requestUpdate() was called and the current satellite |
350 | information could not be retrieved within the specified timeout. |
351 | |
352 | While the triggering of this signal may be considered an error condition, |
353 | it does not imply the emission of the \c error() signal. Only the emission of |
354 | \c requestTimeout() is required to indicate a timeout. |
355 | */ |
356 | |
357 | /*! |
358 | \fn QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSource::error() const = 0 |
359 | |
360 | Returns the last error that occurred. |
361 | |
362 | This signal is not emitted when a requestTimeout() has occurred. |
363 | */ |
364 | |
365 | /*! |
366 | \fn void QGeoSatelliteInfoSource::error(QGeoSatelliteInfoSource::Error satelliteError) |
367 | |
368 | This signal is emitted after an error occurred. The \a satelliteError |
369 | parameter describes the type of error that occurred. |
370 | |
371 | */ |
372 | |
373 | /*! |
374 | \enum QGeoSatelliteInfoSource::Error |
375 | |
376 | The Error enumeration represents the errors which can occur. |
377 | |
378 | \value AccessError The connection setup to the satellite backend failed because the |
379 | application lacked the required privileges. |
380 | \value ClosedError The satellite backend closed the connection, which happens for example in case |
381 | the user is switching location services to off. This object becomes invalid and should be deleted. |
382 | A new satellite source can be created by calling createDefaultSource() later on. |
383 | \value NoError No error has occurred. |
384 | \value UnknownSourceError An unidentified error occurred. |
385 | */ |
386 | |
387 | |
388 | QT_END_NAMESPACE |
389 | |