summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2018-05-19 21:23:48 +0300
committerVolker Krause <volker.krause@kdab.com>2018-08-16 15:40:40 +0000
commitf0472774b36c862f5fb6822f2d4d63a967d1eaec (patch)
tree3b0365e6b48637ec8f946b6e9dee5f8fb890919e
parent77556ab2fbb808a45e401e039820641e94f4fcb9 (diff)
downloadqtlocation-f0472774b36c862f5fb6822f2d4d63a967d1eaec.tar.gz
Long live for the geoclue2 position plugin
Geoclue2 requires the appropriate application's desktop id, to allow an access to the location service. This desktop id should be added to the /etc/geoclue/geoclue.conf file, e.g.: [my-app] allowed=true system=true users= Also, this desktop id should be imported to the Geoclue2 application via the QT_GEOCLUE_APP_DESKTOP_ID environment variable, e.g.: export QT_GEOCLUE_APP_DESKTOP_ID=my-app Note: Tested on stationar PC with the ArchLinux. Task-number: QTBUG-43435 Done-with: Volker Krause <vkrause@kde.org> Change-Id: I5cc204cca966cb23a59ccffbc83fd8dc7a7c4eb6 Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r--src/plugins/position/geoclue2/geoclue2.pro30
-rw-r--r--src/plugins/position/geoclue2/geocluetypes.cpp62
-rw-r--r--src/plugins/position/geoclue2/geocluetypes.h63
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml122
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml96
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml60
-rw-r--r--src/plugins/position/geoclue2/plugin.json9
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp476
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h96
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp66
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h68
-rw-r--r--src/plugins/position/position.pro1
12 files changed, 1149 insertions, 0 deletions
diff --git a/src/plugins/position/geoclue2/geoclue2.pro b/src/plugins/position/geoclue2/geoclue2.pro
new file mode 100644
index 00000000..1bd129d5
--- /dev/null
+++ b/src/plugins/position/geoclue2/geoclue2.pro
@@ -0,0 +1,30 @@
+TARGET = qtposition_geoclue2
+
+QT = core positioning dbus
+
+HEADERS += \
+ qgeopositioninfosource_geoclue2_p.h \
+ qgeopositioninfosourcefactory_geoclue2.h \
+ geocluetypes.h
+
+SOURCES += \
+ qgeopositioninfosource_geoclue2.cpp \
+ qgeopositioninfosourcefactory_geoclue2.cpp \
+ geocluetypes.cpp
+
+QDBUSXML2CPP_INTERFACE_HEADER_FLAGS += \
+ "-N -i geocluetypes.h"
+
+DBUS_INTERFACES += \
+ org.freedesktop.GeoClue2.Manager.xml \
+ org.freedesktop.GeoClue2.Client.xml \
+ org.freedesktop.GeoClue2.Location.xml
+
+INCLUDEPATH += $$QT.location.includes $$OUT_PWD
+
+OTHER_FILES += \
+ plugin.json
+
+PLUGIN_TYPE = position
+PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryGeoclue2
+load(qt_plugin)
diff --git a/src/plugins/position/geoclue2/geocluetypes.cpp b/src/plugins/position/geoclue2/geocluetypes.cpp
new file mode 100644
index 00000000..dec55d3c
--- /dev/null
+++ b/src/plugins/position/geoclue2/geocluetypes.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geocluetypes.h"
+
+QT_BEGIN_NAMESPACE
+
+QDBusArgument &operator<<(QDBusArgument &arg, const Timestamp &ts)
+{
+ arg.beginStructure();
+ arg << ts.m_seconds;
+ arg << ts.m_microseconds;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, Timestamp &ts)
+{
+ arg.beginStructure();
+ arg >> ts.m_seconds;
+ arg >> ts.m_microseconds;
+ arg.endStructure();
+ return arg;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/geocluetypes.h b/src/plugins/position/geoclue2/geocluetypes.h
new file mode 100644
index 00000000..0f3eb522
--- /dev/null
+++ b/src/plugins/position/geoclue2/geocluetypes.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOCLUETYPES_H
+#define GEOCLUETYPES_H
+
+#include <QtDBus/QDBusArgument>
+
+class Timestamp
+{
+public:
+ quint64 m_seconds = 0;
+ quint64 m_microseconds = 0;
+};
+
+Q_DECLARE_METATYPE(Timestamp)
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_TYPEINFO(Timestamp, Q_MOVABLE_TYPE);
+
+QDBusArgument &operator<<(QDBusArgument &arg, const Timestamp &ts);
+const QDBusArgument &operator>>(const QDBusArgument &arg, Timestamp &ts);
+
+QT_END_NAMESPACE
+
+#endif // GEOCLUETYPES_H
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml
new file mode 100644
index 00000000..4a9399b7
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml
@@ -0,0 +1,122 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Client:
+ @short_description: The Application-specific client API
+
+ This is the interface you use to retrieve location information and receive
+ location update signals from GeoClue service. You get the client object to
+ use this interface on from org.freedesktop.GeoClue2.Manager.GetClient()
+ method.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Client">
+ <!--
+ Location:
+
+ Current location as path to a #org.freedesktop.GeoClue2.Location object.
+ Please note that this property will be set to "/" (D-Bus equivalent of
+ null) initially, until Geoclue finds user's location. You want to delay
+ reading this property until your callback to
+ #org.freedesktop.GeoClue2.Client::LocationUpdated signal is called for
+ the first time after starting the client.
+ -->
+ <property name="Location" type="o" access="read"/>
+
+ <!--
+ DistanceThreshold:
+
+ Contains the current distance threshold in meters. This value is used
+ by the service when it gets new location info. If the distance moved is
+ below the threshold, it won't emit the LocationUpdated signal.
+ The default value is 0. When TimeThreshold is zero, it always emits
+ the signal.
+ -->
+ <property name="DistanceThreshold" type="u" access="readwrite">
+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
+ </property>
+
+ <!--
+ TimeThreshold:
+
+ Contains the current time threshold in seconds. This value is used
+ by the service when it gets new location info. If the time since the
+ last update is below the threshold, it won't emit the LocationUpdated
+ signal. The default value is 0. When TimeThreshold is zero, it always
+ emits the signal.
+ -->
+ <property name="TimeThreshold" type="u" access="readwrite">
+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
+ </property>
+
+ <!--
+ DesktopId:
+
+ The desktop file id (the basename of the desktop file). This property
+ must be set by applications for authorization to work.
+ -->
+ <property name="DesktopId" type="s" access="readwrite"/>
+
+ <!--
+ RequestedAccuracyLevel:
+
+ The level of accuracy requested by client, as
+ <link linkend="GClueAccuracyLevel">GClueAccuracyLevel</link>.
+
+ Please keep in mind that the actual accuracy of location information is
+ dependent on available hardware on your machine, external resources
+ and/or how much accuracy user agrees to be confortable with.
+ -->
+ <property name="RequestedAccuracyLevel" type="u" access="readwrite"/>
+
+ <!--
+ Active:
+
+ If client is active, i-e started successfully using
+ org.freedesktop.GeoClue2.Client.Start() and receiving location updates.
+
+ Please keep in mind that geoclue can at any time stop and start the
+ client on user (agent) request. Applications that are interested in
+ in these changes, should watch for changes in this property.
+ -->
+ <property name="Active" type="b" access="read"/>
+
+ <!--
+ Start:
+
+ Start receiving events about the current location. Applications should
+ hook-up to #org.freedesktop.GeoClue2.Client::LocationUpdated signal
+ before calling this method.
+ -->
+ <method name="Start"/>
+
+ <!--
+ Stop:
+
+ Stop receiving events about the current location.
+ -->
+ <method name="Stop"/>
+
+ <!--
+ LocationUpdated:
+ @old: old location as path to a #org.freedesktop.GeoClue2.Location object
+ @new: new location as path to a #org.freedesktop.GeoClue2.Location object
+
+ The signal is emitted every time the location changes.
+ The client should set the DistanceThreshold property to control how
+ often this signal is emitted.
+ -->
+ <signal name="LocationUpdated">
+ <arg name="oldLocation" type="o"/>
+ <arg name="newLocation" type="o"/>
+ </signal>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml
new file mode 100644
index 00000000..ebf2ea6b
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml
@@ -0,0 +1,96 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Location:
+ @short_description: The Location interface
+
+ This is the interface you use on location objects.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Location">
+
+ <!--
+ Latitude:
+
+ The latitude of the location, in degrees.
+ -->
+ <property name="Latitude" type="d" access="read"/>
+
+ <!--
+ Longitude:
+
+ The longitude of the location, in degrees.
+ -->
+ <property name="Longitude" type="d" access="read"/>
+
+ <!--
+ Accuracy:
+
+ The accuracy of the location fix, in meters.
+ -->
+ <property name="Accuracy" type="d" access="read"/>
+
+ <!--
+ Altitude:
+
+ The altitude of the location fix, in meters. When unknown, its set to
+ minimum double value, -1.7976931348623157e+308.
+ -->
+ <property name="Altitude" type="d" access="read"/>
+
+ <!--
+ Speed:
+
+ The speed in meters per second. When unknown, it's set to -1.0.
+ -->
+ <property name="Speed" type="d" access="read"/>
+
+ <!--
+ Heading:
+
+ The heading direction in degrees with respect to North direction, in
+ clockwise order. That means North becomes 0 degree, East: 90 degrees,
+ South: 180 degrees, West: 270 degrees and so on. When unknown,
+ it's set to -1.0.
+ -->
+ <property name="Heading" type="d" access="read"/>
+
+ <!--
+ Description:
+
+ A human-readable description of the location, if available.
+
+ WARNING: Applications should not rely on this property since not all
+ sources provide a description. If you really need a description (or
+ more details) about current location, use a reverse-geocoding API, e.g
+ geocode-glib.
+ -->
+ <property name="Description" type="s" access="read"/>
+
+
+ <!--
+ Timestamp:
+
+ The timestamp when the location was determined, in seconds and
+ microseconds since the Epoch. This is the time of measurement if the
+ backend provided that information, otherwise the time when GeoClue
+ received the new location.
+
+ Note that GeoClue can't guarantee that the timestamp will always
+ monotonically increase, as a backend may not respect that.
+ Also note that a timestamp can be very old, e.g. because of a cached
+ location.
+ -->
+ <property name="Timestamp" type="(tt)" access="read">
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="Timestamp"/>
+ </property>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml
new file mode 100644
index 00000000..cf9590f6
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml
@@ -0,0 +1,60 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Manager:
+ @short_description: The GeoClue service manager
+
+ This is the interface you use to talk to main GeoClue2 manager object at
+ path "/org/freedesktop/GeoClue2/Manager". The only thing you do with this
+ interface is to call org.freedesktop.GeoClue2.Manager.GetClient() on it
+ to get your application specific client object.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Manager">
+ <!--
+ InUse:
+
+ Whether service is currently is use by any application.
+ -->
+ <property name="InUse" type="b" access="read"/>
+
+ <!--
+ AvailableAccuracyLevel:
+
+ The level of available accuracy, as
+ <link linkend="GClueAccuracyLevel">GClueAccuracyLevel</link>.
+ -->
+ <property name="AvailableAccuracyLevel" type="u" access="read"/>
+
+ <!--
+ GetClient:
+ @client: The path for newly created client object
+
+ Retrieves a client object which can only be used by the calling
+ application only.
+ -->
+ <method name="GetClient">
+ <arg name="client" type="o" direction="out"/>
+ </method>
+
+ <!--
+ AddAgent:
+ @id: The Desktop ID (excluding .desktop) of the agent
+
+ An API for user authorization agents to register themselves. Each agent
+ is responsible for the user it is running as. Application developers
+ can and should simply ignore this API.
+ -->
+ <method name="AddAgent">
+ <arg name="id" type="s" direction="in"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/plugin.json b/src/plugins/position/geoclue2/plugin.json
new file mode 100644
index 00000000..c23d40e0
--- /dev/null
+++ b/src/plugins/position/geoclue2/plugin.json
@@ -0,0 +1,9 @@
+{
+ "Keys": ["geoclue2"],
+ "Provider": "geoclue2",
+ "Position": true,
+ "Satellite": false,
+ "Monitor": false,
+ "Priority": 1000,
+ "Testable": false
+}
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp
new file mode 100644
index 00000000..1e457437
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp
@@ -0,0 +1,476 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosource_geoclue2_p.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QSaveFile>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QTimer>
+#include <QtDBus/QDBusPendingCallWatcher>
+
+// Auto-generated D-Bus files.
+#include <client_interface.h>
+#include <location_interface.h>
+#include <manager_interface.h>
+
+Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue2)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+// NOTE: Copied from the /usr/include/libgeoclue-2.0/gclue-client.h
+enum GClueAccuracyLevel {
+ GCLUE_ACCURACY_LEVEL_NONE = 0,
+ GCLUE_ACCURACY_LEVEL_COUNTRY = 1,
+ GCLUE_ACCURACY_LEVEL_CITY = 4,
+ GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD = 5,
+ GCLUE_ACCURACY_LEVEL_STREET = 6,
+ GCLUE_ACCURACY_LEVEL_EXACT = 8
+};
+
+const char GEOCLUE2_SERVICE_NAME[] = "org.freedesktop.GeoClue2";
+const int MINIMUM_UPDATE_INTERVAL = 1000;
+const int UPDATE_TIMEOUT_COLD_START = 120000;
+
+static QString lastPositionFilePath()
+{
+ return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ + QStringLiteral("/qtposition-geoclue2");
+}
+
+} // namespace
+
+QGeoPositionInfoSourceGeoclue2::QGeoPositionInfoSourceGeoclue2(QObject *parent)
+ : QGeoPositionInfoSource(parent)
+ , m_requestTimer(new QTimer(this))
+{
+ qDBusRegisterMetaType<Timestamp>();
+
+ restoreLastPosition();
+
+ m_requestTimer->setSingleShot(true);
+ connect(m_requestTimer, &QTimer::timeout,
+ this, &QGeoPositionInfoSourceGeoclue2::requestUpdateTimeout);
+
+ const auto flags = QDBusServiceWatcher::WatchForRegistration;
+ const auto serviceWatcher = new QDBusServiceWatcher(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ QDBusConnection::systemBus(),
+ flags,
+ this);
+ connect(serviceWatcher, &QDBusServiceWatcher::serviceRegistered,
+ this, &QGeoPositionInfoSourceGeoclue2::createClient);
+
+ if (const auto iface = QDBusConnection::systemBus().interface()) {
+ if (iface->isServiceRegistered(QLatin1String(GEOCLUE2_SERVICE_NAME)))
+ createClient(QLatin1String(GEOCLUE2_SERVICE_NAME));
+ else
+ iface->startService(QLatin1String(GEOCLUE2_SERVICE_NAME));
+ } else {
+ qCCritical(lcPositioningGeoclue2) << "D-Bus connection interface is not exists";
+ setError(AccessError);
+ }
+}
+
+QGeoPositionInfoSourceGeoclue2::~QGeoPositionInfoSourceGeoclue2()
+{
+ saveLastPosition();
+}
+
+void QGeoPositionInfoSourceGeoclue2::setUpdateInterval(int msec)
+{
+ QGeoPositionInfoSource::setUpdateInterval(msec);
+ configureClient();
+}
+
+QGeoPositionInfo QGeoPositionInfoSourceGeoclue2::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
+{
+ if (fromSatellitePositioningMethodsOnly && !m_lastPositionFromSatellite)
+ return QGeoPositionInfo();
+ return m_lastPosition;
+}
+
+QGeoPositionInfoSourceGeoclue2::PositioningMethods QGeoPositionInfoSourceGeoclue2::supportedPositioningMethods() const
+{
+ if (m_manager) {
+ return m_manager->availableAccuracyLevel() == GCLUE_ACCURACY_LEVEL_EXACT
+ ? AllPositioningMethods : NonSatellitePositioningMethods;
+ }
+ return NoPositioningMethods;
+}
+
+void QGeoPositionInfoSourceGeoclue2::setPreferredPositioningMethods(PositioningMethods methods)
+{
+ QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
+ configureClient();
+}
+
+int QGeoPositionInfoSourceGeoclue2::minimumUpdateInterval() const
+{
+ return MINIMUM_UPDATE_INTERVAL;
+}
+
+QGeoPositionInfoSource::Error QGeoPositionInfoSourceGeoclue2::error() const
+{
+ return m_error;
+}
+
+void QGeoPositionInfoSourceGeoclue2::startUpdates()
+{
+ if (m_running) {
+ qCWarning(lcPositioningGeoclue2) << "Already running";
+ return;
+ }
+
+ qCDebug(lcPositioningGeoclue2) << "Starting updates";
+ m_running = true;
+
+ if (m_lastPosition.isValid()) {
+ QMetaObject::invokeMethod(this, "positionUpdated", Qt::QueuedConnection,
+ Q_ARG(QGeoPositionInfo, m_lastPosition));
+ }
+}
+
+void QGeoPositionInfoSourceGeoclue2::stopUpdates()
+{
+ if (!m_running) {
+ qCWarning(lcPositioningGeoclue2) << "Already stopped";
+ return;
+ }
+
+ qCDebug(lcPositioningGeoclue2) << "Stopping updates";
+ m_running = false;
+
+ // Only stop positioning if single update not requested.
+ if (!m_requestTimer->isActive() && m_client)
+ stopClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::requestUpdate(int timeout)
+{
+ if (timeout < minimumUpdateInterval() && timeout != 0) {
+ emit updateTimeout();
+ return;
+ }
+
+ if (m_requestTimer->isActive()) {
+ qCDebug(lcPositioningGeoclue2) << "Request timer was active, ignoring startUpdates";
+ return;
+ }
+
+ m_requestTimer->start(timeout ? timeout : UPDATE_TIMEOUT_COLD_START);
+ if (!m_running)
+ startClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::setError(QGeoPositionInfoSource::Error error)
+{
+ m_error = error;
+ emit QGeoPositionInfoSource::error(m_error);
+}
+
+void QGeoPositionInfoSourceGeoclue2::restoreLastPosition()
+{
+#if !defined(QT_NO_DATASTREAM)
+ const auto filePath = lastPositionFilePath();
+ QFile file(filePath);
+ if (file.open(QIODevice::ReadOnly)) {
+ QDataStream out(&file);
+ out >> m_lastPosition;
+ }
+#endif
+}
+
+void QGeoPositionInfoSourceGeoclue2::saveLastPosition()
+{
+#if !defined(QT_NO_DATASTREAM) && QT_CONFIG(temporaryfile)
+ if (!m_lastPosition.isValid())
+ return;
+
+ const auto filePath = lastPositionFilePath();
+ QSaveFile file(filePath);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ QDataStream out(&file);
+ // Only save position and timestamp.
+ out << QGeoPositionInfo(m_lastPosition.coordinate(), m_lastPosition.timestamp());
+ file.commit();
+ }
+#endif
+}
+
+void QGeoPositionInfoSourceGeoclue2::createClient(const QString &service)
+{
+ if (service != QLatin1String(GEOCLUE2_SERVICE_NAME)) {
+ qCCritical(lcPositioningGeoclue2) << "Registered unexpected service:"
+ << service << ", expected:"
+ << GEOCLUE2_SERVICE_NAME;
+ setError(UnknownSourceError);
+ return;
+ }
+
+ if (!m_manager) {
+ m_manager = new OrgFreedesktopGeoClue2ManagerInterface(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ QStringLiteral("/org/freedesktop/GeoClue2/Manager"),
+ QDBusConnection::systemBus(),
+ this);
+ }
+
+ if (!m_manager->isValid()) {
+ const auto error = m_manager->lastError();
+ qCCritical(lcPositioningGeoclue2) << "Unable to create the manager object:"
+ << error.name() << error.message();
+ setError(AccessError);
+ delete m_manager;
+ m_manager = nullptr;
+ return;
+ }
+
+ const QDBusPendingReply<QDBusObjectPath> reply = m_manager->GetClient();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<QDBusObjectPath> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCWarning(lcPositioningGeoclue2) << "Unable to obtain the client patch:"
+ << error.name() + error.message();
+ setError(AccessError);
+ } else {
+ const QString clientPath = reply.value().path();
+ qCDebug(lcPositioningGeoclue2) << "Client path is:"
+ << clientPath;
+ delete m_client;
+ m_client = new OrgFreedesktopGeoClue2ClientInterface(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ clientPath,
+ QDBusConnection::systemBus(),
+ this);
+ if (!m_client->isValid()) {
+ const auto error = m_client->lastError();
+ qCCritical(lcPositioningGeoclue2) << "Unable to create the client object:"
+ << error.name() << error.message();
+ setError(AccessError);
+ delete m_client;
+ m_client = nullptr;
+ } else {
+ connect(m_client, &OrgFreedesktopGeoClue2ClientInterface::LocationUpdated,
+ this, &QGeoPositionInfoSourceGeoclue2::handleNewLocation);
+
+ // only start the client if someone asked for it already
+ if (configureClient() && (m_running || m_requestTimer->isActive()))
+ startClient();
+ }
+ }
+ });
+}
+
+void QGeoPositionInfoSourceGeoclue2::startClient()
+{
+ if (!m_client) {
+ qCWarning(lcPositioningGeoclue2) << "Unable to start the client "
+ "due to it is not created yet";
+ return;
+ }
+
+ const QDBusPendingReply<> reply = m_client->Start();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCCritical(lcPositioningGeoclue2) << "Unable to start the client:"
+ << error.name() << error.message();
+ setError(AccessError);
+ } else {
+ qCDebug(lcPositioningGeoclue2) << "Client successfully started";
+
+ const QDBusObjectPath location = m_client->location();
+ const QString path = location.path();
+ if (path.isEmpty() || path == QLatin1String("/"))
+ return;
+
+ handleNewLocation({}, location);
+ }
+ });
+}
+
+void QGeoPositionInfoSourceGeoclue2::stopClient()
+{
+ if (!m_client) {
+ qCWarning(lcPositioningGeoclue2) << "Unable to stop the client "
+ "due to it is not created yet";
+ return;
+ }
+
+ const QDBusPendingReply<> reply = m_client->Stop();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCCritical(lcPositioningGeoclue2) << "Unable to stop the client:"
+ << error.name() << error.message();
+ setError(AccessError);
+ } else {
+ qCDebug(lcPositioningGeoclue2) << "Client successfully stopped";
+ }
+ });
+}
+
+bool QGeoPositionInfoSourceGeoclue2::configureClient()
+{
+ if (!m_client) {
+ qCWarning(lcPositioningGeoclue2) << "Unable to configure the client "
+ "due to it is not created yet";
+ return false;
+ }
+
+ auto desktopId = QString::fromUtf8(qgetenv("QT_GEOCLUE_APP_DESKTOP_ID"));
+ if (desktopId.isEmpty())
+ desktopId = QCoreApplication::applicationName();
+ if (desktopId.isEmpty()) {
+ qCCritical(lcPositioningGeoclue2) << "Unable to configure the client "
+ "due to the application desktop id "
+ "is not set via QT_GEOCLUE_APP_DESKTOP_ID "
+ "envirorment variable or QCoreApplication::applicationName";
+ setError(AccessError);
+ return false;
+ }
+
+ m_client->setDesktopId(desktopId);
+
+ const auto msecs = updateInterval();
+ const auto secs = msecs / 1000;
+ m_client->setTimeThreshold(secs);
+
+ const auto methods = preferredPositioningMethods();
+ switch (methods) {
+ case SatellitePositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_EXACT);
+ break;
+ case NonSatellitePositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_STREET);
+ break;
+ case AllPositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_EXACT);
+ break;
+ default:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_NONE);
+ break;
+ }
+
+ return true;
+}
+
+void QGeoPositionInfoSourceGeoclue2::requestUpdateTimeout()
+{
+ qCDebug(lcPositioningGeoclue2) << "Request update timeout occurred";
+
+ emit updateTimeout();
+
+ if (!m_running)
+ stopClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::handleNewLocation(const QDBusObjectPath &oldLocation,
+ const QDBusObjectPath &newLocation)
+{
+ if (m_requestTimer->isActive())
+ m_requestTimer->stop();
+
+ const auto oldPath = oldLocation.path();
+ const auto newPath = newLocation.path();
+ qCDebug(lcPositioningGeoclue2) << "Old location object path:" << oldPath;
+ qCDebug(lcPositioningGeoclue2) << "New location object path:" << newPath;
+
+ OrgFreedesktopGeoClue2LocationInterface location(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ newPath,
+ QDBusConnection::systemBus(),
+ this);
+ if (!location.isValid()) {
+ const auto error = location.lastError();
+ qCCritical(lcPositioningGeoclue2) << "Unable to create the location object:"
+ << error.name() << error.message();
+ } else {
+ QGeoCoordinate coordinate(location.latitude(),
+ location.longitude());
+ if (const auto altitude = location.altitude() > std::numeric_limits<double>::min())
+ coordinate.setAltitude(altitude);
+
+ const Timestamp ts = location.timestamp();
+ if (ts.m_seconds == 0 && ts.m_microseconds == 0) {
+ const auto dt = QDateTime::currentDateTime();
+ m_lastPosition = QGeoPositionInfo(coordinate, dt);
+ } else {
+ auto dt = QDateTime::fromSecsSinceEpoch(ts.m_seconds);
+ dt = dt.addMSecs(ts.m_microseconds / 1000);
+ m_lastPosition = QGeoPositionInfo(coordinate, dt);
+ }
+
+ const auto accuracy = location.accuracy();
+ // We assume that an accuracy as 0.0 means that it comes from a sattelite.
+ m_lastPositionFromSatellite = qFuzzyCompare(accuracy, 0.0);
+
+ m_lastPosition.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy);
+ if (const auto speed = location.speed() >= 0.0)
+ m_lastPosition.setAttribute(QGeoPositionInfo::GroundSpeed, speed);
+ if (const auto heading = location.heading() >= 0.0)
+ m_lastPosition.setAttribute(QGeoPositionInfo::Direction, heading);
+
+ emit positionUpdated(m_lastPosition);
+ qCDebug(lcPositioningGeoclue2) << "New position:" << m_lastPosition;
+ }
+
+ if (!m_running)
+ stopClient();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h
new file mode 100644
index 00000000..1ccd7290
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
+#define QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
+
+#include <QtPositioning/QGeoPositionInfoSource>
+
+class OrgFreedesktopGeoClue2ClientInterface;
+class OrgFreedesktopGeoClue2ManagerInterface;
+
+QT_BEGIN_NAMESPACE
+class QDBusObjectPath;
+class QTimer;
+
+class QGeoPositionInfoSourceGeoclue2 : public QGeoPositionInfoSource
+{
+ Q_OBJECT
+
+public:
+ explicit QGeoPositionInfoSourceGeoclue2(QObject *parent = nullptr);
+ ~QGeoPositionInfoSourceGeoclue2();
+
+ // From QGeoPositionInfoSource
+ void setUpdateInterval(int msec) override;
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const override;
+ PositioningMethods supportedPositioningMethods() const override;
+ void setPreferredPositioningMethods(PositioningMethods methods) override;
+ int minimumUpdateInterval() const override;
+
+ Error error() const override;
+
+ void startUpdates() override;
+ void stopUpdates() override;
+ void requestUpdate(int timeout = 5000) override;
+
+private:
+ void setError(QGeoPositionInfoSource::Error error);
+ void restoreLastPosition();
+ void saveLastPosition();
+ void createClient(const QString &service);
+ bool configureClient();
+ void startClient();
+ void stopClient();
+ void requestUpdateTimeout();
+ void handleNewLocation(const QDBusObjectPath &oldLocation,
+ const QDBusObjectPath &newLocation);
+
+ QTimer *m_requestTimer = nullptr;
+ OrgFreedesktopGeoClue2ManagerInterface *m_manager = nullptr;
+ OrgFreedesktopGeoClue2ClientInterface *m_client = nullptr;
+ bool m_running = false;
+ bool m_lastPositionFromSatellite = false;
+ QGeoPositionInfoSource::Error m_error = NoError;
+ QGeoPositionInfo m_lastPosition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp
new file mode 100644
index 00000000..a713c31f
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosource_geoclue2_p.h"
+#include "qgeopositioninfosourcefactory_geoclue2.h"
+
+#include <QtCore/QLoggingCategory>
+
+Q_LOGGING_CATEGORY(lcPositioningGeoclue2, "qt.positioning.geoclue2")
+
+QT_BEGIN_NAMESPACE
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue2::positionInfoSource(QObject *parent)
+{
+ return new QGeoPositionInfoSourceGeoclue2(parent);
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue2::satelliteInfoSource(QObject *parent)
+{
+ Q_UNUSED(parent)
+ return nullptr;
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGeoclue2::areaMonitor(QObject *parent)
+{
+ Q_UNUSED(parent)
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h
new file mode 100644
index 00000000..bfacd848
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
+#define QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
+
+#include <QtCore/QObject>
+#include <QtPositioning/QGeoPositionInfoSourceFactory>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Qt Positioning plugin for Geoclue. This plugin supports Geoclue version 2.x.
+*/
+class QGeoPositionInfoSourceFactoryGeoclue2 : public QObject, public QGeoPositionInfoSourceFactory
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
+ FILE "plugin.json")
+
+ Q_INTERFACES(QGeoPositionInfoSourceFactory)
+
+public:
+ QGeoPositionInfoSource *positionInfoSource(QObject *parent) override;
+ QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) override;
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro
index b9832ff4..4453b8a3 100644
--- a/src/plugins/position/position.pro
+++ b/src/plugins/position/position.pro
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
QT_FOR_CONFIG += positioning-private
qtHaveModule(dbus):SUBDIRS += geoclue
+qtHaveModule(dbus):SUBDIRS += geoclue2
qtConfig(gypsy):SUBDIRS += gypsy
qtConfig(winrt_geolocation):SUBDIRS += winrt
qtHaveModule(simulator):SUBDIRS += simulator