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: GeocodeReplyTestPrivate()52 GeocodeReplyTestPrivate() 53 { 54 } ~GeocodeReplyTestPrivate()55 ~GeocodeReplyTestPrivate() 56 { 57 } extraData()58 QVariantMap extraData() const override 59 { 60 return m_extraData; 61 } 62 63 QVariantMap m_extraData; 64 }; 65 66 class GeocodeReplyTest :public QGeoCodeReply 67 { 68 Q_OBJECT 69 public: 70 GeocodeReplyTest(QObject *parent = 0) : QGeoCodeReply (*new GeocodeReplyTestPrivate, parent) {} 71 callAddLocation(const QGeoLocation & location)72 void callAddLocation ( const QGeoLocation & location ) {addLocation(location);} callSetError(Error error,const QString & errorString)73 void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} callSetFinished(bool finished)74 void callSetFinished ( bool finished ) {setFinished(finished);} callSetLimit(int limit)75 void callSetLimit ( int limit ) {setLimit(limit);} callSetOffset(int offset)76 void callSetOffset ( int offset ) {setOffset(offset);} callSetLocations(const QList<QGeoLocation> & locations)77 void callSetLocations ( const QList<QGeoLocation> & locations ) {setLocations(locations);} callSetViewport(const QGeoShape & viewport)78 void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);} 79 }; 80 81 class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine 82 83 { 84 Q_OBJECT 85 public: QGeoCodingManagerEngineTest(const QVariantMap & parameters,QGeoServiceProvider::Error * error,QString * errorString)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("supported")) 99 supported_ = qvariant_cast<bool>(parameters.value("supported")); 100 if (parameters.contains("finishRequestImmediately")) 101 finishRequestImmediately_ = qvariant_cast<bool>(parameters.value("finishRequestImmediately")); 102 if (parameters.contains("validateWellKnownValues")) 103 validateWellKnownValues_ = qvariant_cast<bool>(parameters.value("validateWellKnownValues")); 104 if (parameters.contains("includeExtendedData")) { 105 includeExtendedData_ = qvariant_cast<bool>(parameters.value("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(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); 120 geocodeReply_->callSetViewport(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(geocodeReply_, searchString, limit, offset); 132 if (includeExtendedData_) 133 injectExtra(geocodeReply_, extendedReplyData_); 134 135 if (finishRequestImmediately_) { 136 // check if we should finish with error 137 if (errorCode_) { 138 geocodeReply_->callSetError(errorCode_, errorString_); 139 } else { 140 geocodeReply_->callSetFinished(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(200); 146 } 147 return static_cast<QGeoCodeReply*>(geocodeReply_); 148 } 149 geocode(const QGeoAddress & address,const QGeoShape & bounds)150 QGeoCodeReply* geocode(const QGeoAddress & address, const QGeoShape &bounds) 151 { 152 geocodeReply_ = new GeocodeReplyTest(); 153 connect(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); 154 geocodeReply_->callSetViewport(bounds); 155 if (includeExtendedData_) 156 injectExtra(geocodeReply_, extendedReplyData_); 157 158 if (address.street().startsWith("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(QGeoCodeReply::EngineNotSetError, address.street()); 169 } else { 170 geocodeReply_->callSetError(QGeoCodeReply::NoError,address.street()); 171 } 172 } 173 174 // 2. Set the locations into the reply 175 setLocations(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(errorCode_, errorString_); 182 } else { 183 geocodeReply_->callSetFinished(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(200); 189 } 190 return static_cast<QGeoCodeReply*>(geocodeReply_); 191 } 192 193 public Q_SLOTS: requestAborted()194 void requestAborted() 195 { 196 if (timerId_) { 197 killTimer(timerId_); 198 timerId_ = 0; 199 } 200 errorString_ = ""; 201 errorCode_ = QGeoCodeReply::NoError; 202 } 203 204 public: setLocations(GeocodeReplyTest * reply,const QString searchString,int limit,int offset)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, extendedLocationData_); 217 reply->callAddLocation(location); 218 } 219 } 220 setLocations(GeocodeReplyTest * reply,const QGeoAddress & address)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, extendedLocationData_); 230 reply->callAddLocation(location); 231 } 232 } 233 setLocations(GeocodeReplyTest * reply,const QGeoCoordinate & coordinate)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, extendedLocationData_); 241 reply->callAddLocation(location); 242 } 243 } 244 reverseGeocode(const QGeoCoordinate & coordinate,const QGeoShape & bounds)245 QGeoCodeReply* reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) 246 { 247 geocodeReply_ = new GeocodeReplyTest(); 248 connect(geocodeReply_, SIGNAL(aborted()), this, SLOT(requestAborted())); 249 250 setLocations(geocodeReply_, coordinate); 251 geocodeReply_->callSetViewport(bounds); 252 if (includeExtendedData_) 253 injectExtra(geocodeReply_, extendedReplyData_); 254 255 if (coordinate.latitude() > 70) { 256 errorString_ = "error"; 257 errorCode_ = (QGeoCodeReply::Error) (qRound(coordinate.latitude() - 70)); 258 } else { 259 errorString_ = ""; 260 errorCode_ = QGeoCodeReply::NoError; 261 } 262 if (finishRequestImmediately_) { 263 if (errorCode_) { 264 geocodeReply_->callSetError(errorCode_, errorString_); 265 } else { 266 geocodeReply_->callSetError(QGeoCodeReply::NoError,coordinate.toString()); 267 geocodeReply_->callSetFinished(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(200); 273 } 274 return static_cast<QGeoCodeReply*>(geocodeReply_); 275 } 276 277 protected: timerEvent(QTimerEvent * event)278 void timerEvent(QTimerEvent *event) 279 { 280 Q_UNUSED(event); 281 Q_ASSERT(timerId_ == event->timerId()); 282 Q_ASSERT(geocodeReply_); 283 killTimer(timerId_); 284 timerId_ = 0; 285 if (errorCode_) { 286 geocodeReply_->callSetError(errorCode_, errorString_); 287 emit error(geocodeReply_, errorCode_, errorString_); 288 } else { 289 geocodeReply_->callSetError(QGeoCodeReply::NoError, "no error"); 290 geocodeReply_->callSetFinished(true); 291 } 292 emit finished(geocodeReply_); 293 } 294 injectExtra(QGeoCodeReply * reply,const QVariantMap & extra)295 static void injectExtra(QGeoCodeReply *reply, const QVariantMap &extra) 296 { 297 GeocodeReplyTestPrivate *replyPrivate 298 = static_cast<GeocodeReplyTestPrivate *>(QGeoCodeReplyPrivate::get(*reply)); 299 replyPrivate->m_extraData = extra; 300 } 301 injectExtra(QGeoLocation & location,const QVariantMap & extra)302 static void injectExtra(QGeoLocation &location, const QVariantMap &extra) 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