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 test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include <QtPositioning/qgeopositioninfosource.h>
30 #include <QtPositioning/private/qgeopositioninfosource_p.h>
31 #include <QtPositioning/qgeopositioninfosourcefactory.h>
32 #include <QObject>
33 #include <QtPlugin>
34 #include <QTimer>
35 
36 QT_USE_NAMESPACE
37 
38 class DummySource : public QGeoPositionInfoSource
39 {
40     Q_OBJECT
41 
42 public:
43     DummySource(const QVariantMap &parameters, QObject *parent=0);
44     ~DummySource();
45 
46     void startUpdates();
47     void stopUpdates();
48     void requestUpdate(int timeout=5000);
49 
50     QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const;
51     PositioningMethods supportedPositioningMethods() const;
52 
53     void setUpdateInterval(int msec);
54     int minimumUpdateInterval() const;
55     Error error() const;
56 
57 private:
58     QTimer *timer;
59     QTimer *timeoutTimer;
60     QTimer *singleTimer;
61     QGeoPositionInfo lastPosition;
62     QDateTime lastUpdateTime;
63 
64 private slots:
65     void updatePosition();
66     void doTimeout();
67 };
68 
69 class DummySourcePrivate : public QGeoPositionInfoSourcePrivate
70 {
71 public:
setBackendProperty(const QString & name,const QVariant & value)72     bool setBackendProperty(const QString &name, const QVariant &value) override
73     {
74         if (name == QStringLiteral("altitude")) {
75             m_altitude = value.toReal();
76             return true;
77         }
78         return false;
79     }
backendProperty(const QString & name) const80     QVariant backendProperty(const QString &name) const override
81     {
82         if (name == QStringLiteral("altitude"))
83             return m_altitude;
84         return QVariant();
85     }
86 
87     qreal m_altitude = 0.0;
88 };
89 
DummySource(const QVariantMap & parameters,QObject * parent)90 DummySource::DummySource(const QVariantMap &parameters, QObject *parent) :
91     QGeoPositionInfoSource(*new DummySourcePrivate, parent),
92     timer(new QTimer(this)),
93     timeoutTimer(new QTimer(this)),
94     singleTimer(new QTimer(this)),
95     lastPosition(QGeoCoordinate(0,0), QDateTime::currentDateTime())
96 {
97     DummySourcePrivate *dd = static_cast<DummySourcePrivate *>(QGeoPositionInfoSourcePrivate::get(*this));
98     if (parameters.contains(QStringLiteral("test.source.altitude"))) {
99         const qreal alti = parameters.value(QStringLiteral("test.source.altitude")).toReal();
100         dd->m_altitude = alti;
101         QGeoCoordinate crd = lastPosition.coordinate();
102         crd.setAltitude(alti);
103         lastPosition.setCoordinate(crd);
104     }
105     timer->setInterval(1000);
106     connect(timer, SIGNAL(timeout()),
107             this, SLOT(updatePosition()));
108     connect(singleTimer, SIGNAL(timeout()),
109             this, SLOT(updatePosition()));
110     connect(timeoutTimer, SIGNAL(timeout()),
111             this, SLOT(doTimeout()));
112 }
113 
error() const114 QGeoPositionInfoSource::Error DummySource::error() const
115 {
116     return QGeoPositionInfoSource::NoError;
117 }
118 
119 
setUpdateInterval(int msec)120 void DummySource::setUpdateInterval(int msec)
121 {
122     if (msec == 0) {
123         timer->setInterval(1000);
124     } else if (msec < 1000) {
125         msec = 1000;
126         timer->setInterval(msec);
127     } else {
128         timer->setInterval(msec);
129     }
130 
131     QGeoPositionInfoSource::setUpdateInterval(msec);
132 }
133 
minimumUpdateInterval() const134 int DummySource::minimumUpdateInterval() const
135 {
136     return 1000;
137 }
138 
lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const139 QGeoPositionInfo DummySource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
140 {
141     Q_UNUSED(fromSatellitePositioningMethodsOnly);
142     return lastPosition;
143 }
144 
supportedPositioningMethods() const145 QGeoPositionInfoSource::PositioningMethods DummySource::supportedPositioningMethods() const
146 {
147     return QGeoPositionInfoSource::AllPositioningMethods;
148 }
149 
startUpdates()150 void DummySource::startUpdates()
151 {
152     timer->start();
153 }
154 
stopUpdates()155 void DummySource::stopUpdates()
156 {
157     timer->stop();
158 }
159 
requestUpdate(int timeout)160 void DummySource::requestUpdate(int timeout)
161 {
162     if (timeout == 0)
163         timeout = 5000;
164     if (timeout < 0)
165         timeout = 0;
166 
167     timeoutTimer->setInterval(timeout);
168     timeoutTimer->start();
169 
170     if (timer->isActive()) {
171         timer->stop();
172         timer->start();
173     }
174 
175     singleTimer->setInterval(1000);
176     singleTimer->start();
177 }
178 
~DummySource()179 DummySource::~DummySource()
180 {}
181 
updatePosition()182 void DummySource::updatePosition()
183 {
184     DummySourcePrivate *dd = static_cast<DummySourcePrivate *>(QGeoPositionInfoSourcePrivate::get(*this));
185     timeoutTimer->stop();
186     singleTimer->stop();
187 
188     const QDateTime now = QDateTime::currentDateTime();
189 
190     QGeoCoordinate coord(lastPosition.coordinate().latitude() + 0.1,
191                          lastPosition.coordinate().longitude() + 0.1,
192                          dd->m_altitude);
193 
194     QGeoPositionInfo info(coord, now);
195     info.setAttribute(QGeoPositionInfo::Direction, lastPosition.coordinate().azimuthTo(coord));
196     if (lastUpdateTime.isValid()) {
197         double speed = lastPosition.coordinate().distanceTo(coord) / lastUpdateTime.msecsTo(now);
198         info.setAttribute(QGeoPositionInfo::GroundSpeed, 1000 * speed);
199     }
200 
201     lastUpdateTime = now;
202     lastPosition = info;
203     emit positionUpdated(info);
204 }
205 
doTimeout()206 void DummySource::doTimeout()
207 {
208     timeoutTimer->stop();
209     singleTimer->stop();
210     emit updateTimeout();
211 }
212 
213 
214 class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactoryV2
215 {
216     Q_OBJECT
217     Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
218                       FILE "plugin.json")
219     Q_INTERFACES(QGeoPositionInfoSourceFactoryV2)
220 
221 public:
222     QGeoPositionInfoSource *positionInfoSource(QObject *parent);
223     QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
224     QGeoAreaMonitorSource *areaMonitor(QObject *parent);
225 
226     QGeoPositionInfoSource *positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
227     QGeoSatelliteInfoSource *satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
228     QGeoAreaMonitorSource *areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters);
229 };
230 
positionInfoSource(QObject * parent)231 QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent)
232 {
233     return new DummySource(QVariantMap(), parent);
234 }
235 
satelliteInfoSource(QObject * parent)236 QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *parent)
237 {
238     return satelliteInfoSourceWithParameters(parent, QVariantMap());
239 }
240 
areaMonitor(QObject * parent)241 QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* parent)
242 {
243     return areaMonitorWithParameters(parent, QVariantMap());
244 }
245 
positionInfoSourceWithParameters(QObject * parent,const QVariantMap & parameters)246 QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
247 {
248     return new DummySource(parameters, parent);
249 }
250 
satelliteInfoSourceWithParameters(QObject * parent,const QVariantMap & parameters)251 QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
252 {
253     Q_UNUSED(parent);
254     Q_UNUSED(parameters)
255     return nullptr;
256 }
257 
areaMonitorWithParameters(QObject * parent,const QVariantMap & parameters)258 QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters)
259 {
260     Q_UNUSED(parent);
261     Q_UNUSED(parameters)
262     return nullptr;
263 }
264 
265 #include "plugin.moc"
266