Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgeoroutingmanagerengine_nokia.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include "qgeouriprovider.h"
8#include "uri_constants.h"
9
10#include <QStringList>
11#include <QUrl>
12#include <QLocale>
13#include <QtPositioning/QGeoRectangle>
14
16
18 QGeoNetworkAccessManager *networkManager,
19 const QVariantMap &parameters,
21 QString *errorString)
22 : QGeoRoutingManagerEngine(parameters)
23 , m_networkManager(networkManager)
24 , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.routing.host"), ROUTING_HOST))
25
26{
27 Q_ASSERT(networkManager);
28 m_networkManager->setParent(this);
29
30 m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
31
32 QGeoRouteRequest::FeatureTypes featureTypes;
33 featureTypes |= QGeoRouteRequest::TollFeature;
35 featureTypes |= QGeoRouteRequest::FerryFeature;
36 featureTypes |= QGeoRouteRequest::TunnelFeature;
38 featureTypes |= QGeoRouteRequest::ParksFeature;
39 setSupportedFeatureTypes(featureTypes);
40
41 QGeoRouteRequest::FeatureWeights featureWeights;
45 setSupportedFeatureWeights(featureWeights);
46
47 QGeoRouteRequest::ManeuverDetails maneuverDetails;
48 maneuverDetails |= QGeoRouteRequest::BasicManeuvers;
49 setSupportedManeuverDetails(maneuverDetails);
50
51 QGeoRouteRequest::RouteOptimizations optimizations;
52 optimizations |= QGeoRouteRequest::ShortestRoute;
53 optimizations |= QGeoRouteRequest::FastestRoute;
54 setSupportedRouteOptimizations(optimizations);
55
56 QGeoRouteRequest::TravelModes travelModes;
57 travelModes |= QGeoRouteRequest::CarTravel;
61 setSupportedTravelModes(travelModes);
62
63 QGeoRouteRequest::SegmentDetails segmentDetails;
64 segmentDetails |= QGeoRouteRequest::BasicSegmentData;
65 setSupportedSegmentDetails(segmentDetails);
66
67 if (error)
69
70 if (errorString)
71 *errorString = QString();
72}
73
75
77{
78 const QStringList reqStrings = calculateRouteRequestString(request);
79
80 if (reqStrings.isEmpty()) {
81 QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this);
83 return reply;
84 }
85
86 QList<QNetworkReply*> replies;
87 for (const QString &reqString : reqStrings)
88 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
89
91
93 this, &QGeoRoutingManagerEngineNokia::routeFinished);
95 this, &QGeoRoutingManagerEngineNokia::routeError);
96
97 return reply;
98}
99
101{
102 const QStringList reqStrings = updateRouteRequestString(route, position);
103
104 if (reqStrings.isEmpty()) {
105 QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this);
107 return reply;
108 }
109
110 QList<QNetworkReply*> replies;
111 for (const QString &reqString : reqStrings)
112 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
113
114 QGeoRouteRequest updateRequest(route.request());
115 updateRequest.setTravelModes(route.travelMode());
116 QGeoRouteReplyNokia *reply = new QGeoRouteReplyNokia(updateRequest, replies, this);
117
119 this, &QGeoRoutingManagerEngineNokia::routeFinished);
121 this, &QGeoRoutingManagerEngineNokia::routeError);
122
123 return reply;
124}
125
126bool QGeoRoutingManagerEngineNokia::checkEngineSupport(const QGeoRouteRequest &request,
127 QGeoRouteRequest::TravelModes travelModes) const
128{
129 const QList<QGeoRouteRequest::FeatureType> featureTypeList = request.featureTypes();
130 QGeoRouteRequest::FeatureTypes featureTypeFlag = QGeoRouteRequest::NoFeature;
131 QGeoRouteRequest::FeatureWeights featureWeightFlag = QGeoRouteRequest::NeutralFeatureWeight;
132
133 for (const auto &featureType : featureTypeList) {
134 featureTypeFlag |= featureType;
135 featureWeightFlag |= request.featureWeight(featureType);
136 }
137
138 if ((featureTypeFlag & supportedFeatureTypes()) != featureTypeFlag)
139 return false;
140
141 if ((featureWeightFlag & supportedFeatureWeights()) != featureWeightFlag)
142 return false;
143
144
145 if ((request.maneuverDetail() & supportedManeuverDetails()) != request.maneuverDetail())
146 return false;
147
148 if ((request.segmentDetail() & supportedSegmentDetails()) != request.segmentDetail())
149 return false;
150
151 if ((request.routeOptimization() & supportedRouteOptimizations()) != request.routeOptimization())
152 return false;
153
154 if ((travelModes & supportedTravelModes()) != travelModes)
155 return false;
156
157 // Count the number of set bits (= number of travel modes) (popcount)
158 int count = 0;
159
160 for (unsigned bits = travelModes; bits; bits >>= 1)
161 count += (bits & 1);
162
163 // We only allow one travel mode at a time
164 if (count != 1)
165 return false;
166
167 return true;
168}
169
170QStringList QGeoRoutingManagerEngineNokia::calculateRouteRequestString(const QGeoRouteRequest &request) const
171{
172 bool supported = checkEngineSupport(request, request.travelModes());
173
174 if (!supported)
175 return QStringList();
177
178 QString baseRequest = QStringLiteral("https://");
179 baseRequest += m_uriProvider->getCurrentHost();
180 baseRequest += QStringLiteral("/routing/7.2/calculateroute.xml");
181
182 baseRequest += QStringLiteral("?alternatives=");
183 baseRequest += QString::number(request.numberAlternativeRoutes());
184
185 if (!m_apiKey.isEmpty()) {
186 baseRequest += QStringLiteral("&apiKey=");
187 baseRequest += m_apiKey;
188 }
189
190 const QList<QGeoCoordinate> waypoints = request.waypoints();
191 int numWaypoints = waypoints.size();
192 if (numWaypoints < 2)
193 return QStringList();
194 // Details: https://developer.here.com/documentation/routing/topics/resource-param-type-waypoint.html
195 for (int i = 0;i < numWaypoints;++i) {
196 const QGeoCoordinate &c = waypoints.at(i);
197 baseRequest += QStringLiteral("&waypoint");
198 baseRequest += QString::number(i);
199 baseRequest += QStringLiteral("=geo!");
200 baseRequest += trimDouble(c.latitude());
201 baseRequest += ',';
202 baseRequest += trimDouble(c.longitude());
203 baseRequest += QStringLiteral(";;"); // ;<TransitRadius>;<UserLabel>
204 }
205
206 QGeoRouteRequest::RouteOptimizations optimization = request.routeOptimization();
207
209 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
210 types.append("shortest");
211 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
212 types.append("fastest");
213
214 for (const QString &optimization : types) {
215 QString requestString = baseRequest;
216 requestString += modesRequestString(request, request.travelModes(), optimization);
217 requestString += routeRequestString(request);
218 requests << requestString;
219 }
220
221 return requests;
222}
223
224QStringList QGeoRoutingManagerEngineNokia::updateRouteRequestString(const QGeoRoute &route, const QGeoCoordinate &position)
225{
226 if (!checkEngineSupport(route.request(), route.travelMode()))
227 return QStringList();
229
230 QString baseRequest = "https://";
231 baseRequest += m_uriProvider->getCurrentHost();
232 baseRequest += "/routing/7.2/getroute.xml";
233
234 baseRequest += "?routeid=";
235 baseRequest += route.routeId();
236
237 baseRequest += "&pos=";
238 baseRequest += QString::number(position.latitude());
239 baseRequest += ',';
240 baseRequest += QString::number(position.longitude());
241
242 QGeoRouteRequest::RouteOptimizations optimization = route.request().routeOptimization();
243
245 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
246 types.append("shortest");
247 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
248 types.append("fastest");
249
250 for (const QString &optimization : types) {
251 QString requestString = baseRequest;
252 requestString += modesRequestString(route.request(), route.travelMode(), optimization);
253 requestString += routeRequestString(route.request());
254 requests << requestString;
255 }
256
257 return requests;
258}
259
260QString QGeoRoutingManagerEngineNokia::modesRequestString(const QGeoRouteRequest &request,
261 QGeoRouteRequest::TravelModes travelModes, const QString &optimization) const
262{
263 QString requestString;
264
265 QStringList modes;
266 if (travelModes.testFlag(QGeoRouteRequest::CarTravel))
267 modes.append("car");
268 if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel))
269 modes.append("pedestrian");
270 if (travelModes.testFlag(QGeoRouteRequest::PublicTransitTravel))
271 modes.append("publicTransport");
272
273 QStringList featureStrings;
274 QList<QGeoRouteRequest::FeatureType> featureTypes = request.featureTypes();
275 for (int i = 0; i < featureTypes.size(); ++i) {
276 QGeoRouteRequest::FeatureWeight weight = request.featureWeight(featureTypes.at(i));
277
279 continue;
280
281 QString weightString = "";
282 switch (weight) {
284 weightString = '1';
285 break;
287 weightString = "-1";
288 break;
290 weightString = "-3";
291 break;
294 break;
295 }
296
297 if (weightString.isEmpty())
298 continue;
299
300 switch (featureTypes.at(i)) {
302 featureStrings.append("tollroad:" + weightString);
303 break;
305 featureStrings.append("motorway:" + weightString);
306 break;
308 featureStrings.append("boatFerry:" + weightString);
309 featureStrings.append("railFerry:" + weightString);
310 break;
312 featureStrings.append("tunnel:" + weightString);
313 break;
315 featureStrings.append("dirtRoad:" + weightString);
316 break;
322 break;
323 }
324 }
325
326 requestString += "&mode=";
327 requestString += optimization + ';' + modes.join(',');
328 if (featureStrings.count())
329 requestString += ';' + featureStrings.join(',');
330 return requestString;
331}
332
333QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest &request) const
334{
335 QString requestString;
336
337 for (const QGeoRectangle &area : request.excludeAreas()) {
338 requestString += QLatin1String("&avoidareas=");
339 requestString += trimDouble(area.topLeft().latitude());
340 requestString += QLatin1String(",");
341 requestString += trimDouble(area.topLeft().longitude());
342 requestString += QLatin1String(";");
343 requestString += trimDouble(area.bottomRight().latitude());
344 requestString += QLatin1String(",");
345 requestString += trimDouble(area.bottomRight().longitude());
346 }
347
348 QStringList legAttributes;
349// if (request.segmentDetail() & QGeoRouteRequest::BasicSegmentData) // QTBUG-70501, this code expects to find links
350 {
351 requestString += "&linkattributes=sh,le"; //shape,length
352 legAttributes.append("links");
353 }
354
355// if (request.maneuverDetail() & QGeoRouteRequest::BasicManeuvers) // QTBUG-70501, this code expects to find maneuvers
356 {
357 legAttributes.append("maneuvers");
358 //requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction
359 requestString += "&maneuverattributes=all";
360 if (!(request.segmentDetail() & QGeoRouteRequest::NoSegmentData))
361 requestString += ",li"; //link
362 }
363
364 // Handle QTBUG-70502, when API fixes it
365 requestString += "&routeattributes=sm,sh,bb,lg"; //summary,shape,boundingBox,legs
366 if (legAttributes.count() > 0) {
367 requestString += "&legattributes=";
368 requestString += legAttributes.join(",");
369 }
370
371 // Handle QTBUG-70503, when API fixes it
372 requestString += "&departure=";
373 requestString += QDateTime::currentDateTime().toUTC().toString("yyyy-MM-ddThh:mm:ssZ");
374
375 requestString += "&instructionformat=text";
376
377 // ToDo: make this request-able
378 requestString += "&metricSystem=";
380 requestString += "metric";
381 else
382 requestString += "imperial";
383
384 const QLocale loc(locale());
385
386 // ToDo: make this request-able
387 if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) {
388 requestString += "&language=";
389 requestString += loc.name();
390 //If the first language isn't supported, english will be selected automatically
391 if (QLocale::English != loc.language())
392 requestString += ",en_US";
393 }
394
395 return requestString;
396}
397
398QString QGeoRoutingManagerEngineNokia::trimDouble(double degree, int decimalDigits)
399{
400 QString sDegree = QString::number(degree, 'g', decimalDigits);
401
402 int index = sDegree.indexOf('.');
403
404 if (index == -1)
405 return sDegree;
406 else
407 return QString::number(degree, 'g', decimalDigits + index);
408}
409
410void QGeoRoutingManagerEngineNokia::routeFinished()
411{
412 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
413
414 if (!reply)
415 return;
416
419 return;
420 }
421
423}
424
425void QGeoRoutingManagerEngineNokia::routeError(QGeoRouteReply::Error error, const QString &errorString)
426{
427 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
428
429 if (!reply)
430 return;
431
434 return;
435 }
436
437 emit errorOccurred(reply, error, errorString);
438}
439
DarwinBluetooth::RequestQueue requests
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtPositioning
virtual QNetworkReply * get(const QNetworkRequest &request)=0
\inmodule QtPositioning
\inmodule QtLocation
void finished()
This signal is emitted when this reply has finished processing.
Error
Describes an error which prevented the completion of the operation.
void errorOccurred(QGeoRouteReply::Error error, const QString &errorString=QString())
This signal is emitted when an error has been detected in the processing of this reply.
\inmodule QtLocation
FeatureWeight
Defines the weight to associate with a feature during the planning of a route.
RouteOptimizations routeOptimization() const
Returns the optimization criteria which this request specifies should be used while planning the rout...
void setTravelModes(TravelModes travelModes)
Sets the travel modes which should be considered during the planning of the route to travelModes.
\inmodule QtLocation
Definition qgeoroute.h:24
QGeoRouteRequest request() const
the route request which describes the criteria used in the calculation of this route
QGeoRouteRequest::TravelMode travelMode() const
Returns the travel mode for the this route.
QML_STRUCTURED_VALUEQString routeId
the identifier of this route
Definition qgeoroute.h:29
QGeoRoutingManagerEngineNokia(QGeoNetworkAccessManager *networkInterface, const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)
QGeoRouteReply * updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) override
Begins the process of updating route based on the current position position.
QGeoRouteReply * calculateRoute(const QGeoRouteRequest &request) override
void setSupportedSegmentDetails(QGeoRouteRequest::SegmentDetails segmentDetails)
Sets the levels of detail for routing segments which can be requested by this engine to segmentDetail...
QGeoRouteRequest::RouteOptimizations supportedRouteOptimizations() const
Returns the route optimizations supported by this engine.
QLocale::MeasurementSystem measurementSystem() const
Returns the measurement system used by this manager.
QGeoRouteRequest::FeatureWeights supportedFeatureWeights() const
Returns the weightings which this engine can apply to different features during route planning.
QLocale locale() const
Returns the locale used to hint to this routing manager about what language to use for addresses and ...
QGeoRouteRequest::FeatureTypes supportedFeatureTypes() const
Returns the types of features that this engine can take into account during route planning.
void errorOccurred(QGeoRouteReply *reply, QGeoRouteReply::Error error, const QString &errorString=QString())
This signal is emitted when an error has been detected in the processing of reply.
QGeoRouteRequest::SegmentDetails supportedSegmentDetails() const
Returns the levels of detail for routing segments which can be requested by this engine.
void setSupportedTravelModes(QGeoRouteRequest::TravelModes travelModes)
Sets the travel modes supported by this engine to travelModes.
QGeoRouteRequest::TravelModes supportedTravelModes() const
Returns the travel modes supported by this engine.
void setSupportedFeatureWeights(QGeoRouteRequest::FeatureWeights featureWeights)
Sets the weightings which this engine can apply to different features during route planning to featur...
void finished(QGeoRouteReply *reply)
This signal is emitted when reply has finished processing.
QGeoRouteRequest::ManeuverDetails supportedManeuverDetails() const
Returns the levels of detail for navigation maneuvers which can be requested by this engine.
void setSupportedFeatureTypes(QGeoRouteRequest::FeatureTypes featureTypes)
Sets the types of features that this engine can take into account during route planning to featureTyp...
void setSupportedRouteOptimizations(QGeoRouteRequest::RouteOptimizations optimizations)
Sets the route optimizations supported by this engine to optimizations.
void setSupportedManeuverDetails(QGeoRouteRequest::ManeuverDetails maneuverDetails)
Sets the levels of detail for navigation maneuvers which can be requested by this engine to maneuverD...
Error
Describes an error related to the loading and setup of a service provider plugin.
QString getCurrentHost() const
QString errorString() const
Returns a human-readable description of the last device error that occurred.
@ MetricSystem
Definition qlocale.h:868
@ AnyLanguage
Definition qlocale.h:44
@ English
Definition qlocale.h:119
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
NetworkError error() const
Returns the error that was found during the processing of this request.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
int receivers(const char *signal) const
Returns the number of receivers connected to the signal.
Definition qobject.cpp:2740
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
QString & append(QChar c)
Definition qstring.cpp:3252
\inmodule QtCore
Definition qurl.h:94
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
static int area(const QSize &s)
Definition qicon.cpp:153
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLuint index
[2]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLuint GLuint GLfloat weight
const GLubyte * c
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
QNetworkRequest request(url)
QNetworkReply * reply
QT_BEGIN_NAMESPACE const QString ROUTING_HOST