summaryrefslogtreecommitdiff
path: root/src/positioning/qgeopositioninfosource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/positioning/qgeopositioninfosource.cpp')
-rw-r--r--src/positioning/qgeopositioninfosource.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp
new file mode 100644
index 00000000..4fa7a4ca
--- /dev/null
+++ b/src/positioning/qgeopositioninfosource.cpp
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qgeopositioninfosource.h>
+#include "qgeopositioninfosource_p.h"
+#include "qgeopositioninfosourcefactory.h"
+
+#include <QFile>
+#include <QPluginLoader>
+#include <QStringList>
+#include <QJsonObject>
+#include <QCryptographicHash>
+#include <QtCore/private/qfactoryloader_p.h>
+#include <QtCore/private/qlibrary_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ ("org.qt-project.qt.position.sourcefactory/5.0",
+ QLatin1String("/position")))
+#endif
+
+/*!
+ \class QGeoPositionInfoSource
+ \inmodule QtPositioning
+ \ingroup QtPositioning-positioning
+ \since Qt Positioning 5.0
+
+ \brief The QGeoPositionInfoSource class is an abstract base class for the distribution of positional updates.
+
+ The static function QGeoPositionInfoSource::createDefaultSource() creates a default
+ position source that is appropriate for the platform, if one is available.
+ Otherwise, QGeoPositionInfoSource will check for available plugins that
+ implement the QGeoPositionInfoSourceFactory interface.
+
+ Users of a QGeoPositionInfoSource subclass can request the current position using
+ requestUpdate(), or start and stop regular position updates using
+ startUpdates() and stopUpdates(). When an update is available,
+ positionUpdated() is emitted. The last known position can be accessed with
+ lastKnownPosition().
+
+ If regular position updates are required, setUpdateInterval() can be used
+ to specify how often these updates should be emitted. If no interval is
+ specified, updates are simply provided whenever they are available.
+ For example:
+
+ \code
+ // Emit updates every 10 seconds if available
+ QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(0);
+ if (source)
+ source->setUpdateInterval(10000);
+ \endcode
+
+ To remove an update interval that was previously set, call
+ setUpdateInterval() with a value of 0.
+
+ Note that the position source may have a minimum value requirement for
+ update intervals, as returned by minimumUpdateInterval().
+
+ \warning On Windows CE it is not possible to detect if a device is GPS enabled.
+ The default position source on a Windows CE device without GPS support will never provide any position data.
+*/
+
+/*!
+ \enum QGeoPositionInfoSource::PositioningMethod
+ Defines the types of positioning methods.
+
+ \value SatellitePositioningMethods Satellite-based positioning methods such as GPS or GLONASS.
+ \value NonSatellitePositioningMethods Other positioning methods such as 3GPP cell identifier or WiFi based positioning.
+ \value AllPositioningMethods Satellite-based positioning methods as soon as available. Otherwise non-satellite based methods.
+*/
+
+void QGeoPositionInfoSourcePrivate::loadMeta()
+{
+ metaData = plugins().value(providerName);
+}
+
+void QGeoPositionInfoSourcePrivate::loadPlugin()
+{
+ int idx = int(metaData.value(QStringLiteral("index")).toDouble());
+ if (idx < 0)
+ return;
+ factory = qobject_cast<QGeoPositionInfoSourceFactory *>(loader()->instance(idx));
+}
+
+QHash<QString, QJsonObject> QGeoPositionInfoSourcePrivate::plugins(bool reload)
+{
+ static QHash<QString, QJsonObject> plugins;
+ static bool alreadyDiscovered = false;
+
+ if (reload == true)
+ alreadyDiscovered = false;
+
+ if (!alreadyDiscovered) {
+ loadPluginMetadata(plugins);
+ alreadyDiscovered = true;
+ }
+ return plugins;
+}
+
+static bool pluginComparator(const QJsonObject &p1, const QJsonObject &p2)
+{
+ const QString prio = QStringLiteral("Priority");
+ if (p1.contains(prio) && !p2.contains(prio))
+ return true;
+ if (!p1.contains(prio) && p2.contains(prio))
+ return false;
+ if (p1.value(prio).isDouble() && !p2.value(prio).isDouble())
+ return true;
+ if (!p1.value(prio).isDouble() && p2.value(prio).isDouble())
+ return false;
+ return (p1.value(prio).toDouble() > p2.value(prio).toDouble());
+}
+
+QList<QJsonObject> QGeoPositionInfoSourcePrivate::pluginsSorted()
+{
+ QList<QJsonObject> list = plugins().values();
+ qStableSort(list.begin(), list.end(), pluginComparator);
+ return list;
+}
+
+void QGeoPositionInfoSourcePrivate::loadPluginMetadata(QHash<QString, QJsonObject> &plugins)
+{
+ QFactoryLoader *l = loader();
+ QList<QJsonObject> meta = l->metaData();
+ for (int i = 0; i < meta.size(); ++i) {
+ QJsonObject obj = meta.at(i).value(QStringLiteral("MetaData")).toObject();
+ obj.insert(QStringLiteral("index"), i);
+ plugins.insertMulti(obj.value(QStringLiteral("Provider")).toString(), obj);
+ }
+}
+
+/*!
+ Creates a position source with the specified \a parent.
+*/
+
+QGeoPositionInfoSource::QGeoPositionInfoSource(QObject *parent)
+ : QObject(parent),
+ d(new QGeoPositionInfoSourcePrivate)
+{
+ d->interval = 0;
+ d->methods = 0;
+}
+
+/*!
+ Destroys the position source.
+*/
+QGeoPositionInfoSource::~QGeoPositionInfoSource()
+{
+ delete d;
+}
+
+/*!
+ \property QGeoPositionInfoSource::sourceName
+ \brief This property holds the unique name of the position source
+ implementation in use.
+
+ This is the same name that can be passed to createSource() in order to
+ create a new instance of a particular position source implementation.
+*/
+QString QGeoPositionInfoSource::sourceName() const
+{
+ return d->metaData.value(QStringLiteral("Provider")).toString();
+}
+
+/*!
+ \property QGeoPositionInfoSource::updateInterval
+ \brief This property holds the requested interval in milliseconds between each update.
+
+ If the update interval is not set (or is set to 0) the
+ source will provide updates as often as necessary.
+
+ If the update interval is set, the source will provide updates at an
+ interval as close to the requested interval as possible. If the requested
+ interval is less than the minimumUpdateInterval(),
+ the minimum interval is used instead.
+
+ Changes to the update interval will happen as soon as is practical, however the
+ time the change takes may vary between implementations. Whether or not the elapsed
+ time from the previous interval is counted as part of the new interval is also
+ implementation dependent.
+
+ The default value for this property is 0.
+
+ Note: Subclass implementations must call the base implementation of
+ setUpdateInterval() so that updateInterval() returns the correct value.
+*/
+void QGeoPositionInfoSource::setUpdateInterval(int msec)
+{
+ d->interval = msec;
+}
+
+int QGeoPositionInfoSource::updateInterval() const
+{
+ return d->interval;
+}
+
+/*!
+ Sets the preferred positioning methods for this source to \a methods.
+
+ If \a methods includes a method that is not supported by the source, the
+ unsupported method will be ignored.
+
+ If \a methods does not include any methods supported by the source, the
+ preferred methods will be set to the set of methods which the source supports.
+
+ \b {Note:} When reimplementing this method, subclasses must call the
+ base method implementation to ensure preferredPositioningMethods() returns the correct value.
+
+ \sa supportedPositioningMethods()
+*/
+void QGeoPositionInfoSource::setPreferredPositioningMethods(PositioningMethods methods)
+{
+ d->methods = methods & supportedPositioningMethods();
+ if (d->methods == 0) {
+ d->methods = supportedPositioningMethods();
+ }
+}
+
+/*!
+ Returns the positioning methods set by setPreferredPositioningMethods().
+*/
+QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSource::preferredPositioningMethods() const
+{
+ return d->methods;
+}
+
+/*!
+ Creates and returns a position source with the given \a parent that
+ reads from the system's default sources of location data, or the plugin
+ with the highest available priority.
+
+ Returns 0 if the system has no default position source, no valid plugins
+ could be found or the user does not have the permission to access the current position.
+*/
+QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(QObject *parent)
+{
+ QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted();
+ foreach (const QJsonObject &obj, plugins) {
+ if (obj.value(QStringLiteral("Position")).isBool()
+ && obj.value(QStringLiteral("Position")).toBool())
+ {
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = obj;
+ d.loadPlugin();
+ QGeoPositionInfoSource *s = 0;
+ if (d.factory)
+ s = d.factory->positionInfoSource(parent);
+ if (s) {
+ s->d->metaData = d.metaData;
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*!
+ Creates and returns a position source with the given \a parent,
+ by loading the plugin named \a sourceName.
+
+ Returns 0 if the plugin cannot be found.
+*/
+QGeoPositionInfoSource *QGeoPositionInfoSource::createSource(const QString &sourceName, QObject *parent)
+{
+ QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
+ if (plugins.contains(sourceName))
+ {
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = plugins.value(sourceName);
+ d.loadPlugin();
+ QGeoPositionInfoSource *src = 0;
+ if (d.factory)
+ src = d.factory->positionInfoSource(parent);
+ if (src)
+ {
+ src->d->metaData = d.metaData;
+ return src;
+ }
+ }
+ return 0;
+}
+
+
+/*!
+ Returns a list of available source plugins. This includes any default backend
+ plugin for the current platform.
+*/
+QStringList QGeoPositionInfoSource::availableSources()
+{
+ QStringList plugins;
+ QHash<QString, QJsonObject> meta = QGeoPositionInfoSourcePrivate::plugins();
+ foreach (const QString &name, meta.keys()) {
+ if (meta.value(name).value(QStringLiteral("Position")).isBool()
+ && meta.value(name).value(QStringLiteral("Position")).toBool()) {
+ plugins << name;
+ }
+ }
+
+ return plugins;
+}
+
+/*!
+ \fn QGeoPositionInfo QGeoPositionInfoSource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const = 0;
+
+ Returns an update containing the last known position, or a null update
+ if none is available.
+
+ If \a fromSatellitePositioningMethodsOnly is true, this returns the last
+ known position received from a satellite positioning method; if none
+ is available, a null update is returned.
+*/
+
+/*!
+ \fn virtual PositioningMethods QGeoPositionInfoSource::supportedPositioningMethods() const = 0;
+
+ Returns the positioning methods available to this source.
+
+ \sa setPreferredPositioningMethods()
+*/
+
+
+/*!
+ \property QGeoPositionInfoSource::minimumUpdateInterval
+ \brief This property holds the minimum time (in milliseconds) required to retrieve a position update.
+
+ This is the minimum value accepted by setUpdateInterval() and
+ requestUpdate().
+*/
+
+
+/*!
+ \fn virtual void QGeoPositionInfoSource::startUpdates() = 0;
+
+ Starts emitting updates at regular intervals as specified by setUpdateInterval().
+
+ If setUpdateInterval() has not been called, the source will emit updates
+ as soon as they become available.
+
+ An updateTimout() signal will be emitted if this QGeoPositionInfoSource subclass determines
+ that it will not be able to provide regular updates. This could happen if a satellite fix is
+ lost or if a hardware error is detected. Position updates will recommence if the data becomes
+ available later on. The updateTimout() signal will not be emitted again until after the
+ periodic updates resume.
+*/
+
+/*!
+ \fn virtual void QGeoPositionInfoSource::stopUpdates() = 0;
+
+ Stops emitting updates at regular intervals.
+*/
+
+/*!
+ \fn virtual void QGeoPositionInfoSource::requestUpdate(int timeout = 0);
+
+ Attempts to get the current position and emit positionUpdated() with
+ this information. If the current position cannot be found within the given \a timeout
+ (in milliseconds) or if \a timeout is less than the value returned by
+ minimumUpdateInterval(), updateTimeout() is emitted.
+
+ If the timeout is zero, the timeout defaults to a reasonable timeout
+ period as appropriate for the source.
+
+ This does nothing if another update request is in progress. However
+ it can be called even if startUpdates() has already been called and
+ regular updates are in progress.
+
+ If the source uses multiple positioning methods, it tries to get the
+ current position from the most accurate positioning method within the
+ given timeout.
+*/
+
+/*!
+ \fn virtual QGeoPositionInfoSource::Error QGeoPositionInfoSource::error() const;
+
+ Returns the type of error that last occurred.
+
+*/
+
+/*!
+ \fn void QGeoPositionInfoSource::positionUpdated(const QGeoPositionInfo &update);
+
+ If startUpdates() or requestUpdate() is called, this signal is emitted
+ when an update becomes available.
+
+ The \a update value holds the value of the new update.
+*/
+
+/*!
+ \fn void QGeoPositionInfoSource::updateTimeout();
+
+ If requestUpdate() was called, this signal will be emitted if the current position could not
+ be retrieved within the specified timeout.
+
+ If startUpdates() has been called, this signal will be emitted if this QGeoPositionInfoSource
+ subclass determines that it will not be able to provide further regular updates. This signal
+ will not be emitted again until after the regular updates resume.
+*/
+
+/*!
+ \fn void QGeoPositionInfoSource::error(QGeoPositionInfoSource::Error positioningError)
+
+ This signal is emitted after an error occurred. The \a positioningError
+ parameter describes the type of error that occurred.
+
+*/
+
+/*!
+ \enum QGeoPositionInfoSource::Error
+
+ The Error enumeration represents the errors which can occur.
+
+ \value AccessError The connection setup to the remote positioning backend failed because the
+ application lacked the required privileges.
+ \value ClosedError The remote positioning backend closed the connection, which happens for example in case
+ the user is switching location services to off. This object becomes invalid and should be deleted.
+ A call to createDefaultSource() can be used to create a new source later on.
+ \value UnknownSourceError An unidentified error occurred.
+ */
+
+#include "moc_qgeopositioninfosource.cpp"
+
+QT_END_NAMESPACE