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 
~QGeoSatelliteInfoSourcePrivate()92 QGeoSatelliteInfoSourcePrivate::~QGeoSatelliteInfoSourcePrivate()
93 {
94 
95 }
96 
get(QGeoSatelliteInfoSource & source)97 QGeoSatelliteInfoSourcePrivate *QGeoSatelliteInfoSourcePrivate::get(QGeoSatelliteInfoSource &source)
98 {
99     return source.d;
100 }
101 
QGeoSatelliteInfoSource(QObject * parent)102 QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QObject *parent)
103         : QObject(parent),
104         d(new QGeoSatelliteInfoSourcePrivate)
105 {
106     d->interval = 0;
107 }
108 
QGeoSatelliteInfoSource(QGeoSatelliteInfoSourcePrivate & dd,QObject * parent)109 QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QGeoSatelliteInfoSourcePrivate &dd, QObject *parent)
110 :   QObject(parent),
111     d(&dd)
112 {
113 
114 }
115 
116 /*!
117     Destroys the satellite source.
118 */
~QGeoSatelliteInfoSource()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 */
sourceName() const130 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 */
setUpdateInterval(int msec)158 void QGeoSatelliteInfoSource::setUpdateInterval(int msec)
159 {
160     d->interval = msec;
161 }
162 
updateInterval() const163 int QGeoSatelliteInfoSource::updateInterval() const
164 {
165     return d->interval;
166 }
167 
createSource_real(const QJsonObject & meta,const QVariantMap & parameters,QObject * parent)168 static QGeoSatelliteInfoSource* createSource_real(const QJsonObject &meta, const QVariantMap &parameters, 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(*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 */
createDefaultSource(QObject * parent)192 QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *parent)
193 {
194     return createDefaultSource(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 */
createSource(const QString & sourceName,QObject * parent)203 QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, QObject *parent)
204 {
205     return createSource(sourceName, 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 */
createDefaultSource(const QVariantMap & parameters,QObject * parent)220 QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(const QVariantMap &parameters, 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(testableKey) && !obj.value(testableKey).toBool()) {
229                 static bool inTest = qEnvironmentVariableIsSet("QT_QTESTLIB_RUNNING");
230                 if (inTest)
231                     continue;
232             }
233             return createSource_real(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 */
createSource(const QString & sourceName,const QVariantMap & parameters,QObject * parent)250 QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, const QVariantMap &parameters, QObject *parent)
251 {
252     QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
253     if (plugins.contains(sourceName))
254         return createSource_real(plugins.value(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 */
availableSources()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