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#ifndef QGEOCODINGMANAGERENGINE_TEST_H
30#define QGEOCODINGMANAGERENGINE_TEST_H
31
32#include <qgeoserviceprovider.h>
33#include <qgeocodingmanagerengine.h>
34#include <QLocale>
35#include <QtPositioning/qgeoaddress.h>
36#include <QtPositioning/qgeolocation.h>
37#include <qgeocodereply.h>
38#include <QtLocation/private/qgeocodereply_p.h>
39#include <QtPositioning/QGeoShape>
40
41#include <QTimer>
42#include <QDebug>
43#include <QTimerEvent>
44#include <QVariantMap>
45
46QT_USE_NAMESPACE
47
48
49class GeocodeReplyTestPrivate : public QGeoCodeReplyPrivate
50{
51public:
52 GeocodeReplyTestPrivate()
53 {
54 }
55 ~GeocodeReplyTestPrivate()
56 {
57 }
58 QVariantMap extraData() const override
59 {
60 return m_extraData;
61 }
62
63 QVariantMap m_extraData;
64};
65
66class GeocodeReplyTest :public QGeoCodeReply
67{
68 Q_OBJECT
69public:
70 GeocodeReplyTest(QObject *parent = 0) : QGeoCodeReply (*new GeocodeReplyTestPrivate, parent) {}
71
72 void callAddLocation ( const QGeoLocation & location ) {addLocation(location);}
73 void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);}
74 void callSetFinished ( bool finished ) {setFinished(finished);}
75 void callSetLimit ( int limit ) {setLimit(limit);}
76 void callSetOffset ( int offset ) {setOffset(offset);}
77 void callSetLocations ( const QList<QGeoLocation> & locations ) {setLocations(locations);}
78 void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);}
79};
80
81class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine
82
83{
84Q_OBJECT
85public:
86 QGeoCodingManagerEngineTest(const QVariantMap &parameters,
87 QGeoServiceProvider::Error *error, QString *errorString) :
88 QGeoCodingManagerEngine(parameters),
89 validateWellKnownValues_(false),
90 finishRequestImmediately_(true),
91 supported_(true),
92 geocodeReply_(0),
93 timerId_(0),
94 errorCode_(QGeoCodeReply::NoError)
95 {
96 Q_UNUSED(error);
97 Q_UNUSED(errorString);
98 if (parameters.contains(akey: "supported"))
99 supported_ = qvariant_cast<bool>(v: parameters.value(akey: "supported"));
100 if (parameters.contains(akey: "finishRequestImmediately"))
101 finishRequestImmediately_ = qvariant_cast<bool>(v: parameters.value(akey: "finishRequestImmediately"));
102 if (parameters.contains(akey: "validateWellKnownValues"))
103 validateWellKnownValues_ = qvariant_cast<bool>(v: parameters.value(akey: "validateWellKnownValues"));
104 if (parameters.contains(akey: "includeExtendedData")) {
105 includeExtendedData_ = qvariant_cast<bool>(v: parameters.value(akey: "includeExtendedData"));
106 extendedLocationData_["QGeoCodingManagerEngineTest_locationExtendedAttribute"] = 42;
107 extendedReplyData_["QGeoCodingManagerEngineTest_extraData"] = 43;
108 }
109
110 setLocale(QLocale (QLocale::German, QLocale::Germany));
111 }
112
113 QGeoCodeReply* geocode(const QString &searchString,
114 int limit = -1,
115 int offset = 0,
116 const QGeoShape &bounds = QGeoShape())
117 {
118 geocodeReply_ = new GeocodeReplyTest();
119 connect(sender: geocodeReply_, SIGNAL(aborted()), receiver: this, SLOT(requestAborted()));
120 geocodeReply_->callSetViewport(viewport: bounds);
121
122 if (searchString.length() == 1) {
123 errorString_ = searchString;
124 errorCode_ = (QGeoCodeReply::Error)searchString.toInt();
125 } else {
126 errorString_ = "";
127 errorCode_ = QGeoCodeReply::NoError;
128 }
129
130 if (errorCode_ == QGeoCodeReply::NoError)
131 setLocations(reply: geocodeReply_, searchString, limit, offset);
132 if (includeExtendedData_)
133 injectExtra(reply: geocodeReply_, extra: extendedReplyData_);
134
135 if (finishRequestImmediately_) {
136 // check if we should finish with error
137 if (errorCode_) {
138 geocodeReply_->callSetError(error: errorCode_, errorString: errorString_);
139 } else {
140 geocodeReply_->callSetFinished(finished: true);
141 }
142 } else {
143 // we only allow serialized requests in QML - previous must have been aborted
144 Q_ASSERT(timerId_ == 0);
145 timerId_ = startTimer(interval: 200);
146 }
147 return static_cast<QGeoCodeReply*>(geocodeReply_);
148 }
149
150 QGeoCodeReply* geocode(const QGeoAddress & address, const QGeoShape &bounds)
151 {
152 geocodeReply_ = new GeocodeReplyTest();
153 connect(sender: geocodeReply_, SIGNAL(aborted()), receiver: this, SLOT(requestAborted()));
154 geocodeReply_->callSetViewport(viewport: bounds);
155 if (includeExtendedData_)
156 injectExtra(reply: geocodeReply_, extra: extendedReplyData_);
157
158 if (address.street().startsWith(s: "error")) {
159 errorString_ = address.street();
160 errorCode_ = (QGeoCodeReply::Error)address.county().toInt();
161 } else {
162 errorString_ = "";
163 errorCode_ = QGeoCodeReply::NoError;
164 }
165 // 1. Check if we are to validate values
166 if (validateWellKnownValues_) {
167 if (address.street() != "wellknown street") {
168 geocodeReply_->callSetError(error: QGeoCodeReply::EngineNotSetError, errorString: address.street());
169 } else {
170 geocodeReply_->callSetError(error: QGeoCodeReply::NoError,errorString: address.street());
171 }
172 }
173
174 // 2. Set the locations into the reply
175 setLocations(reply: geocodeReply_, address);
176
177 // 3. Finish the request
178 if (finishRequestImmediately_) {
179 // check if we should finish with error
180 if (errorCode_) {
181 geocodeReply_->callSetError(error: errorCode_, errorString: errorString_);
182 } else {
183 geocodeReply_->callSetFinished(finished: true);
184 }
185 } else {
186 // we only allow serialized requests in QML - previous must have been aborted
187 Q_ASSERT(timerId_ == 0);
188 timerId_ = startTimer(interval: 200);
189 }
190 return static_cast<QGeoCodeReply*>(geocodeReply_);
191 }
192
193public Q_SLOTS:
194 void requestAborted()
195 {
196 if (timerId_) {
197 killTimer(id: timerId_);
198 timerId_ = 0;
199 }
200 errorString_ = "";
201 errorCode_ = QGeoCodeReply::NoError;
202 }
203
204public:
205 void setLocations(GeocodeReplyTest* reply, const QString searchString, int limit, int offset)
206 {
207 if (limit < 0)
208 limit = 0;
209 for (int i = 0; i < limit; ++i) {
210 QGeoLocation location;
211 QGeoAddress address;
212 address.setStreet(searchString);
213 address.setCounty(QString::number(offset));
214 location.setAddress(address);
215 if (includeExtendedData_)
216 injectExtra(location, extra: extendedLocationData_);
217 reply->callAddLocation(location);
218 }
219 }
220
221 void setLocations(GeocodeReplyTest* reply, const QGeoAddress& address)
222 {
223 int count = address.county().toInt();
224
225 for (int i = 0; i < count; ++i) {
226 QGeoLocation location;
227 location.setAddress(address);
228 if (includeExtendedData_)
229 injectExtra(location, extra: extendedLocationData_);
230 reply->callAddLocation(location);
231 }
232 }
233
234 void setLocations(GeocodeReplyTest* reply, const QGeoCoordinate & coordinate)
235 {
236 for (int i = 0; i < coordinate.longitude(); ++i) {
237 QGeoLocation location;
238 location.setCoordinate(coordinate);
239 if (includeExtendedData_)
240 injectExtra(location, extra: extendedLocationData_);
241 reply->callAddLocation(location);
242 }
243 }
244
245 QGeoCodeReply* reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds)
246 {
247 geocodeReply_ = new GeocodeReplyTest();
248 connect(sender: geocodeReply_, SIGNAL(aborted()), receiver: this, SLOT(requestAborted()));
249
250 setLocations(reply: geocodeReply_, coordinate);
251 geocodeReply_->callSetViewport(viewport: bounds);
252 if (includeExtendedData_)
253 injectExtra(reply: geocodeReply_, extra: extendedReplyData_);
254
255 if (coordinate.latitude() > 70) {
256 errorString_ = "error";
257 errorCode_ = (QGeoCodeReply::Error) (qRound(d: coordinate.latitude() - 70));
258 } else {
259 errorString_ = "";
260 errorCode_ = QGeoCodeReply::NoError;
261 }
262 if (finishRequestImmediately_) {
263 if (errorCode_) {
264 geocodeReply_->callSetError(error: errorCode_, errorString: errorString_);
265 } else {
266 geocodeReply_->callSetError(error: QGeoCodeReply::NoError,errorString: coordinate.toString());
267 geocodeReply_->callSetFinished(finished: true);
268 }
269 } else {
270 // we only allow serialized requests in QML - previous must have been aborted or finished
271 Q_ASSERT(timerId_ == 0);
272 timerId_ = startTimer(interval: 200);
273 }
274 return static_cast<QGeoCodeReply*>(geocodeReply_);
275 }
276
277protected:
278 void timerEvent(QTimerEvent *event)
279 {
280 Q_UNUSED(event);
281 Q_ASSERT(timerId_ == event->timerId());
282 Q_ASSERT(geocodeReply_);
283 killTimer(id: timerId_);
284 timerId_ = 0;
285 if (errorCode_) {
286 geocodeReply_->callSetError(error: errorCode_, errorString: errorString_);
287 emit error(reply: geocodeReply_, error: errorCode_, errorString: errorString_);
288 } else {
289 geocodeReply_->callSetError(error: QGeoCodeReply::NoError, errorString: "no error");
290 geocodeReply_->callSetFinished(finished: true);
291 }
292 emit finished(reply: geocodeReply_);
293 }
294
295 static void injectExtra(QGeoCodeReply *reply, const QVariantMap &extra)
296 {
297 GeocodeReplyTestPrivate *replyPrivate
298 = static_cast<GeocodeReplyTestPrivate *>(QGeoCodeReplyPrivate::get(reply&: *reply));
299 replyPrivate->m_extraData = extra;
300 }
301
302 static void injectExtra(QGeoLocation &location, const QVariantMap &extra)
303 {
304 location.setExtendedAttributes(extra);
305 }
306
307private:
308 bool includeExtendedData_ = false;
309 bool validateWellKnownValues_;
310 bool finishRequestImmediately_;
311 bool supported_;
312 GeocodeReplyTest* geocodeReply_;
313 int timerId_;
314 QGeoCodeReply::Error errorCode_;
315 QString errorString_;
316 QVariantMap extendedLocationData_;
317 QVariantMap extendedReplyData_;
318};
319
320#endif
321

source code of qtlocation/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h