diff options
author | Aaron McCarthy <aaron.mccarthy@jollamobile.com> | 2013-09-06 15:46:27 +1000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-21 11:13:34 +0100 |
commit | f8323499944e5f6a44516d96cea5f824f5a7a4b9 (patch) | |
tree | cb552e8c135b9c325ed82a139a6705d355d91763 | |
parent | 7d3d2498ae79b96f53fd960532ae81bfedf088c1 (diff) | |
download | qtlocation-f8323499944e5f6a44516d96cea5f824f5a7a4b9.tar.gz |
Don't require a position fix before reporting Geoclue satellite info.
The Geoclue plugin uses the Geoclue master provider to select the most
appropriate position provider. However, it doesn't select a provider
unless it is in the available state. For satellite information a
position fix is not required.
If the Geoclue master provider doesn't return a valid provider the
plugin will now listen for all SatelliteChanged signals from any
org.freedesktop.Geoclue.Satellite interface. This means that if
multiple satellite based providers are active at the same time
QGeoSatelliteInfoSource will include satellite information from
both providers.
Change-Id: I257b56dc03fed51a5c4ba0023862708b9618be05
Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
3 files changed, 111 insertions, 7 deletions
diff --git a/src/plugins/position/geoclue/geoclue.pro b/src/plugins/position/geoclue/geoclue.pro index 81e39d8a..5c318645 100644 --- a/src/plugins/position/geoclue/geoclue.pro +++ b/src/plugins/position/geoclue/geoclue.pro @@ -14,9 +14,11 @@ SOURCES += \ qgeopositioninfosourcefactory_geoclue.cpp \ qgeocluemaster.cpp -config_geoclue-satellite { +qtHaveModule(dbus):config_geoclue-satellite { DEFINES += HAS_SATELLITE + QT *= dbus + HEADERS += qgeosatelliteinfosource_geocluemaster.h SOURCES += qgeosatelliteinfosource_geocluemaster.cpp } diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp index 35901d10..6dcedeec 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp @@ -41,6 +41,10 @@ #include "qgeosatelliteinfosource_geocluemaster.h" +#include <QtDBus/QDBusConnection> +#include <QtDBus/QDBusMessage> +#include <QtDBus/QDBusArgument> + #define MINIMUM_UPDATE_INTERVAL 1000 QT_BEGIN_NAMESPACE @@ -117,8 +121,41 @@ void satellite_callback(GeoclueSatellite *satellite, int timestamp, int satellit } +const QDBusArgument &operator>>(const QDBusArgument &argument, QGeoSatelliteInfo &si) +{ + int a; + + argument.beginStructure(); + argument >> a; + si.setSatelliteIdentifier(a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Elevation, a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Azimuth, a); + argument >> a; + si.setSignalStrength(a); + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QList<QGeoSatelliteInfo> &sis) +{ + sis.clear(); + + argument.beginArray(); + while (!argument.atEnd()) { + QGeoSatelliteInfo si; + argument >> si; + sis.append(si); + } + argument.endArray(); + + return argument; +} + QGeoSatelliteInfoSourceGeoclueMaster::QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent) -: QGeoSatelliteInfoSource(parent), QGeoclueMaster(this), m_sat(0) +: QGeoSatelliteInfoSource(parent), QGeoclueMaster(this), m_sat(0), m_error(NoError), + m_satellitesChangedConnected(false) { m_requestTimer.setSingleShot(true); connect(&m_requestTimer, SIGNAL(timeout()), this, SIGNAL(requestTimeout())); @@ -143,7 +180,7 @@ int QGeoSatelliteInfoSourceGeoclueMaster::minimumUpdateInterval() const QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGeoclueMaster::error() const { - return NoError; + return m_error; } void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() @@ -220,11 +257,71 @@ void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteAr if (m_sat) cleanupSatelliteSource(); - m_sat = geoclue_satellite_new(service.constData(), path.constData()); - if (m_sat) { - g_signal_connect(G_OBJECT(m_sat), "satellite-changed", - G_CALLBACK(satellite_changed), this); + QByteArray providerService; + QByteArray providerPath; + + if (service.isEmpty() || path.isEmpty()) { + // No valid position provider has been selected. This probably means that the GPS provider + // has not yet obtained a position fix. It can still provide satellite information though. + if (!m_satellitesChangedConnected) { + QDBusConnection conn = QDBusConnection::sessionBus(); + conn.connect(QString(), QString(), QStringLiteral("org.freedesktop.Geoclue.Satellite"), + QStringLiteral("SatelliteChanged"), this, + SLOT(satellitesChanged(QDBusMessage))); + m_satellitesChangedConnected = true; + return; + } + } else { + if (m_satellitesChangedConnected) { + QDBusConnection conn = QDBusConnection::sessionBus(); + conn.disconnect(QString(), QString(), + QStringLiteral("org.freedesktop.Geoclue.Satellite"), + QStringLiteral("SatelliteChanged"), this, + SLOT(satellitesChanged(QDBusMessage))); + m_satellitesChangedConnected = false; + } + + providerService = service; + providerPath = path; } + + if (providerService.isEmpty() || providerPath.isEmpty()) { + m_error = AccessError; + emit QGeoSatelliteInfoSource::error(m_error); + return; + } + + m_sat = geoclue_satellite_new(providerService.constData(), providerPath.constData()); + if (!m_sat) { + m_error = AccessError; + emit QGeoSatelliteInfoSource::error(m_error); + return; + } + + g_signal_connect(G_OBJECT(m_sat), "satellite-changed", G_CALLBACK(satellite_changed), this); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::satellitesChanged(const QDBusMessage &message) +{ + QVariantList arguments = message.arguments(); + if (arguments.length() != 5) + return; + + int timestamp = arguments.at(0).toInt(); + int usedSatellites = arguments.at(1).toInt(); + int visibleSatellites = arguments.at(2).toInt(); + + QDBusArgument dbusArgument = arguments.at(3).value<QDBusArgument>(); + + QList<int> usedPrn; + dbusArgument >> usedPrn; + + dbusArgument = arguments.at(4).value<QDBusArgument>(); + + QList<QGeoSatelliteInfo> satelliteInfos; + dbusArgument >> satelliteInfos; + + satelliteChanged(timestamp, usedSatellites, visibleSatellites, usedPrn, satelliteInfos); } bool QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h index 1448f827..52cbb316 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +class QDBusMessage; + class QGeoSatelliteInfoSourceGeoclueMaster : public QGeoSatelliteInfoSource, public QGeoclueMaster { Q_OBJECT @@ -77,6 +79,7 @@ public: private slots: void positionProviderChanged(const QByteArray &service, const QByteArray &path); + void satellitesChanged(const QDBusMessage &message); private: bool configureSatelliteSource(); @@ -86,6 +89,8 @@ private: QTimer m_requestTimer; QList<QGeoSatelliteInfo> m_inView; QList<QGeoSatelliteInfo> m_inUse; + Error m_error; + bool m_satellitesChangedConnected; }; QT_END_NAMESPACE |