Qt 6.x
The Qt SDK
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_appId = parameters.value(QStringLiteral("here.app_id")).toString();
31 m_token = parameters.value(QStringLiteral("here.token")).toString();
32
33 QGeoRouteRequest::FeatureTypes featureTypes;
34 featureTypes |= QGeoRouteRequest::TollFeature;
36 featureTypes |= QGeoRouteRequest::FerryFeature;
37 featureTypes |= QGeoRouteRequest::TunnelFeature;
39 featureTypes |= QGeoRouteRequest::ParksFeature;
40 setSupportedFeatureTypes(featureTypes);
41
42 QGeoRouteRequest::FeatureWeights featureWeights;
46 setSupportedFeatureWeights(featureWeights);
47
48 QGeoRouteRequest::ManeuverDetails maneuverDetails;
49 maneuverDetails |= QGeoRouteRequest::BasicManeuvers;
50 setSupportedManeuverDetails(maneuverDetails);
51
52 QGeoRouteRequest::RouteOptimizations optimizations;
53 optimizations |= QGeoRouteRequest::ShortestRoute;
54 optimizations |= QGeoRouteRequest::FastestRoute;
55 setSupportedRouteOptimizations(optimizations);
56
57 QGeoRouteRequest::TravelModes travelModes;
58 travelModes |= QGeoRouteRequest::CarTravel;
62 setSupportedTravelModes(travelModes);
63
64 QGeoRouteRequest::SegmentDetails segmentDetails;
65 segmentDetails |= QGeoRouteRequest::BasicSegmentData;
66 setSupportedSegmentDetails(segmentDetails);
67
68 if (error)
70
71 if (errorString)
72 *errorString = QString();
73}
74
76
78{
79 const QStringList reqStrings = calculateRouteRequestString(request);
80
81 if (reqStrings.isEmpty()) {
82 QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this);
84 return reply;
85 }
86
88 for (const QString &reqString : reqStrings)
89 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
90
92
94 this, &QGeoRoutingManagerEngineNokia::routeFinished);
96 this, &QGeoRoutingManagerEngineNokia::routeError);
97
98 return reply;
99}
100
102{
103 const QStringList reqStrings = updateRouteRequestString(route, position);
104
105 if (reqStrings.isEmpty()) {
106 QGeoRouteReply *reply = new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError, "The given route request options are not supported by this service provider.", this);
108 return reply;
109 }
110
111 QList<QNetworkReply*> replies;
112 for (const QString &reqString : reqStrings)
113 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
114
115 QGeoRouteRequest updateRequest(route.request());
116 updateRequest.setTravelModes(route.travelMode());
117 QGeoRouteReplyNokia *reply = new QGeoRouteReplyNokia(updateRequest, replies, this);
118
120 this, &QGeoRoutingManagerEngineNokia::routeFinished);
122 this, &QGeoRoutingManagerEngineNokia::routeError);
123
124 return reply;
125}
126
127bool QGeoRoutingManagerEngineNokia::checkEngineSupport(const QGeoRouteRequest &request,
128 QGeoRouteRequest::TravelModes travelModes) const
129{
130 const QList<QGeoRouteRequest::FeatureType> featureTypeList = request.featureTypes();
131 QGeoRouteRequest::FeatureTypes featureTypeFlag = QGeoRouteRequest::NoFeature;
132 QGeoRouteRequest::FeatureWeights featureWeightFlag = QGeoRouteRequest::NeutralFeatureWeight;
133
134 for (const auto &featureType : featureTypeList) {
135 featureTypeFlag |= featureType;
136 featureWeightFlag |= request.featureWeight(featureType);
137 }
138
139 if ((featureTypeFlag & supportedFeatureTypes()) != featureTypeFlag)
140 return false;
141
142 if ((featureWeightFlag & supportedFeatureWeights()) != featureWeightFlag)
143 return false;
144
145
146 if ((request.maneuverDetail() & supportedManeuverDetails()) != request.maneuverDetail())
147 return false;
148
149 if ((request.segmentDetail() & supportedSegmentDetails()) != request.segmentDetail())
150 return false;
151
152 if ((request.routeOptimization() & supportedRouteOptimizations()) != request.routeOptimization())
153 return false;
154
155 if ((travelModes & supportedTravelModes()) != travelModes)
156 return false;
157
158 // Count the number of set bits (= number of travel modes) (popcount)
159 int count = 0;
160
161 for (unsigned bits = travelModes; bits; bits >>= 1)
162 count += (bits & 1);
163
164 // We only allow one travel mode at a time
165 if (count != 1)
166 return false;
167
168 return true;
169}
170
171QStringList QGeoRoutingManagerEngineNokia::calculateRouteRequestString(const QGeoRouteRequest &request) const
172{
173 bool supported = checkEngineSupport(request, request.travelModes());
174
175 if (!supported)
176 return QStringList();
178
179 QString baseRequest = QStringLiteral("http://");
180 baseRequest += m_uriProvider->getCurrentHost();
181 baseRequest += QStringLiteral("/routing/7.2/calculateroute.xml");
182
183 baseRequest += QStringLiteral("?alternatives=");
184 baseRequest += QString::number(request.numberAlternativeRoutes());
185
186 if (!m_appId.isEmpty() && !m_token.isEmpty()) {
187 baseRequest += QStringLiteral("&app_id=");
188 baseRequest += m_appId;
189 baseRequest += QStringLiteral("&token=");
190 baseRequest += m_token;
191 }
192
193 const QList<QGeoCoordinate> waypoints = request.waypoints();
194 int numWaypoints = waypoints.size();
195 if (numWaypoints < 2)
196 return QStringList();
197 // Details: https://developer.here.com/documentation/routing/topics/resource-param-type-waypoint.html
198 for (int i = 0;i < numWaypoints;++i) {
199 const QGeoCoordinate &c = waypoints.at(i);
200 baseRequest += QStringLiteral("&waypoint");
201 baseRequest += QString::number(i);
202 baseRequest += QStringLiteral("=geo!");
203 baseRequest += trimDouble(c.latitude());
204 baseRequest += ',';
205 baseRequest += trimDouble(c.longitude());
206 baseRequest += QStringLiteral(";;"); // ;<TransitRadius>;<UserLabel>
207 }
208
209 QGeoRouteRequest::RouteOptimizations optimization = request.routeOptimization();
210
212 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
213 types.append("shortest");
214 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
215 types.append("fastest");
216
217 for (const QString &optimization : types) {
218 QString requestString = baseRequest;
219 requestString += modesRequestString(request, request.travelModes(), optimization);
220 requestString += routeRequestString(request);
221 requests << requestString;
222 }
223
224 return requests;
225}
226
227QStringList QGeoRoutingManagerEngineNokia::updateRouteRequestString(const QGeoRoute &route, const QGeoCoordinate &position)
228{
229 if (!checkEngineSupport(route.request(), route.travelMode()))
230 return QStringList();
232
233 QString baseRequest = "http://";
234 baseRequest += m_uriProvider->getCurrentHost();
235 baseRequest += "/routing/7.2/getroute.xml";
236
237 baseRequest += "?routeid=";
238 baseRequest += route.routeId();
239
240 baseRequest += "&pos=";
241 baseRequest += QString::number(position.latitude());
242 baseRequest += ',';
243 baseRequest += QString::number(position.longitude());
244
245 QGeoRouteRequest::RouteOptimizations optimization = route.request().routeOptimization();
246
248 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
249 types.append("shortest");
250 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
251 types.append("fastest");
252
253 for (const QString &optimization : types) {
254 QString requestString = baseRequest;
255 requestString += modesRequestString(route.request(), route.travelMode(), optimization);
256 requestString += routeRequestString(route.request());
257 requests << requestString;
258 }
259
260 return requests;
261}
262
263QString QGeoRoutingManagerEngineNokia::modesRequestString(const QGeoRouteRequest &request,
264 QGeoRouteRequest::TravelModes travelModes, const QString &optimization) const
265{
266 QString requestString;
267
268 QStringList modes;
269 if (travelModes.testFlag(QGeoRouteRequest::CarTravel))
270 modes.append("car");
271 if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel))
272 modes.append("pedestrian");
273 if (travelModes.testFlag(QGeoRouteRequest::PublicTransitTravel))
274 modes.append("publicTransport");
275
276 QStringList featureStrings;
277 QList<QGeoRouteRequest::FeatureType> featureTypes = request.featureTypes();
278 for (int i = 0; i < featureTypes.size(); ++i) {
279 QGeoRouteRequest::FeatureWeight weight = request.featureWeight(featureTypes.at(i));
280
282 continue;
283
284 QString weightString = "";
285 switch (weight) {
287 weightString = '1';
288 break;
290 weightString = "-1";
291 break;
293 weightString = "-3";
294 break;
297 break;
298 }
299
300 if (weightString.isEmpty())
301 continue;
302
303 switch (featureTypes.at(i)) {
305 featureStrings.append("tollroad:" + weightString);
306 break;
308 featureStrings.append("motorway:" + weightString);
309 break;
311 featureStrings.append("boatFerry:" + weightString);
312 featureStrings.append("railFerry:" + weightString);
313 break;
315 featureStrings.append("tunnel:" + weightString);
316 break;
318 featureStrings.append("dirtRoad:" + weightString);
319 break;
325 break;
326 }
327 }
328
329 requestString += "&mode=";
330 requestString += optimization + ';' + modes.join(',');
331 if (featureStrings.count())
332 requestString += ';' + featureStrings.join(',');
333 return requestString;
334}
335
336QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest &request) const
337{
338 QString requestString;
339
340 for (const QGeoRectangle &area : request.excludeAreas()) {
341 requestString += QLatin1String("&avoidareas=");
342 requestString += trimDouble(area.topLeft().latitude());
343 requestString += QLatin1String(",");
344 requestString += trimDouble(area.topLeft().longitude());
345 requestString += QLatin1String(";");
346 requestString += trimDouble(area.bottomRight().latitude());
347 requestString += QLatin1String(",");
348 requestString += trimDouble(area.bottomRight().longitude());
349 }
350
351 QStringList legAttributes;
352// if (request.segmentDetail() & QGeoRouteRequest::BasicSegmentData) // QTBUG-70501, this code expects to find links
353 {
354 requestString += "&linkattributes=sh,le"; //shape,length
355 legAttributes.append("links");
356 }
357
358// if (request.maneuverDetail() & QGeoRouteRequest::BasicManeuvers) // QTBUG-70501, this code expects to find maneuvers
359 {
360 legAttributes.append("maneuvers");
361 //requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction
362 requestString += "&maneuverattributes=all";
363 if (!(request.segmentDetail() & QGeoRouteRequest::NoSegmentData))
364 requestString += ",li"; //link
365 }
366
367 // Handle QTBUG-70502, when API fixes it
368 requestString += "&routeattributes=sm,sh,bb,lg"; //summary,shape,boundingBox,legs
369 if (legAttributes.count() > 0) {
370 requestString += "&legattributes=";
371 requestString += legAttributes.join(",");
372 }
373
374 // Handle QTBUG-70503, when API fixes it
375 requestString += "&departure=";
376 requestString += QDateTime::currentDateTime().toUTC().toString("yyyy-MM-ddThh:mm:ssZ");
377
378 requestString += "&instructionformat=text";
379
380 // ToDo: make this request-able
381 requestString += "&metricSystem=";
383 requestString += "metric";
384 else
385 requestString += "imperial";
386
387 const QLocale loc(locale());
388
389 // ToDo: make this request-able
390 if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) {
391 requestString += "&language=";
392 requestString += loc.name();
393 //If the first language isn't supported, english will be selected automatically
394 if (QLocale::English != loc.language())
395 requestString += ",en_US";
396 }
397
398 return requestString;
399}
400
401QString QGeoRoutingManagerEngineNokia::trimDouble(double degree, int decimalDigits)
402{
403 QString sDegree = QString::number(degree, 'g', decimalDigits);
404
405 int index = sDegree.indexOf('.');
406
407 if (index == -1)
408 return sDegree;
409 else
410 return QString::number(degree, 'g', decimalDigits + index);
411}
412
413void QGeoRoutingManagerEngineNokia::routeFinished()
414{
415 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
416
417 if (!reply)
418 return;
419
422 return;
423 }
424
426}
427
428void QGeoRoutingManagerEngineNokia::routeError(QGeoRouteReply::Error error, const QString &errorString)
429{
430 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
431
432 if (!reply)
433 return;
434
437 return;
438 }
439
440 emit errorOccurred(reply, error, errorString);
441}
442
DarwinBluetooth::RequestQueue requests
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
QDateTime toUTC() const
Returns a copy of this datetime converted to UTC.
\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.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void append(parameter_type t)
Definition qlist.h:441
@ MetricSystem
Definition qlocale.h:858
@ AnyLanguage
Definition qlocale.h:42
@ English
Definition qlocale.h:117
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
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:2823
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:2521
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
int receivers(const char *signal) const
Returns the number of receivers connected to the signal.
Definition qobject.cpp:2603
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
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:7822
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
\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.
DBusConnection const char DBusError * error
static int area(const QSize &s)
Definition qicon.cpp:152
#define SIGNAL(a)
Definition qobjectdefs.h:52
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