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 | |
46 | QT_USE_NAMESPACE |
47 | |
48 | |
49 | class GeocodeReplyTestPrivate : public QGeoCodeReplyPrivate |
50 | { |
51 | public: |
52 | GeocodeReplyTestPrivate() |
53 | { |
54 | } |
55 | ~GeocodeReplyTestPrivate() |
56 | { |
57 | } |
58 | QVariantMap () const override |
59 | { |
60 | return m_extraData; |
61 | } |
62 | |
63 | QVariantMap ; |
64 | }; |
65 | |
66 | class GeocodeReplyTest :public QGeoCodeReply |
67 | { |
68 | Q_OBJECT |
69 | public: |
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 | |
81 | class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine |
82 | |
83 | { |
84 | Q_OBJECT |
85 | public: |
86 | QGeoCodingManagerEngineTest(const QVariantMap ¶meters, |
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 | |
193 | public 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 | |
204 | public: |
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 | |
277 | protected: |
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 (QGeoCodeReply *reply, const QVariantMap &) |
296 | { |
297 | GeocodeReplyTestPrivate *replyPrivate |
298 | = static_cast<GeocodeReplyTestPrivate *>(QGeoCodeReplyPrivate::get(reply&: *reply)); |
299 | replyPrivate->m_extraData = extra; |
300 | } |
301 | |
302 | static void (QGeoLocation &location, const QVariantMap &) |
303 | { |
304 | location.setExtendedAttributes(extra); |
305 | } |
306 | |
307 | private: |
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 | |