13#include <QtPositioning/QGeoRectangle>
18 QGeoNetworkAccessManager *networkManager,
19 const QVariantMap ¶meters,
20 QGeoServiceProvider::Error *error,
22 : QGeoRoutingManagerEngine(parameters)
23 , m_networkManager(networkManager)
24 , m_uriProvider(
new QGeoUriProvider(
this, parameters, QStringLiteral(
"here.routing.host"), ROUTING_HOST))
27 Q_ASSERT(networkManager);
28 m_networkManager->setParent(
this);
30 m_apiKey = parameters.value(QStringLiteral(
"here.apiKey")).toString();
32 QGeoRouteRequest::FeatureTypes featureTypes;
33 featureTypes |= QGeoRouteRequest::TollFeature;
34 featureTypes |= QGeoRouteRequest::HighwayFeature;
35 featureTypes |= QGeoRouteRequest::FerryFeature;
36 featureTypes |= QGeoRouteRequest::TunnelFeature;
37 featureTypes |= QGeoRouteRequest::DirtRoadFeature;
38 featureTypes |= QGeoRouteRequest::ParksFeature;
39 setSupportedFeatureTypes(featureTypes);
41 QGeoRouteRequest::FeatureWeights featureWeights;
42 featureWeights |= QGeoRouteRequest::DisallowFeatureWeight;
43 featureWeights |= QGeoRouteRequest::AvoidFeatureWeight;
44 featureWeights |= QGeoRouteRequest::PreferFeatureWeight;
45 setSupportedFeatureWeights(featureWeights);
47 QGeoRouteRequest::ManeuverDetails maneuverDetails;
48 maneuverDetails |= QGeoRouteRequest::BasicManeuvers;
49 setSupportedManeuverDetails(maneuverDetails);
51 QGeoRouteRequest::RouteOptimizations optimizations;
52 optimizations |= QGeoRouteRequest::ShortestRoute;
53 optimizations |= QGeoRouteRequest::FastestRoute;
54 setSupportedRouteOptimizations(optimizations);
56 QGeoRouteRequest::TravelModes travelModes;
57 travelModes |= QGeoRouteRequest::CarTravel;
58 travelModes |= QGeoRouteRequest::PedestrianTravel;
59 travelModes |= QGeoRouteRequest::PublicTransitTravel;
60 travelModes |= QGeoRouteRequest::BicycleTravel;
61 setSupportedTravelModes(travelModes);
63 QGeoRouteRequest::SegmentDetails segmentDetails;
64 segmentDetails |= QGeoRouteRequest::BasicSegmentData;
65 setSupportedSegmentDetails(segmentDetails);
68 *error = QGeoServiceProvider::NoError;
71 *errorString = QString();
78 const QStringList reqStrings = calculateRouteRequestString(request);
80 if (reqStrings.isEmpty()) {
81 QGeoRouteReply *reply =
new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError,
"The given route request options are not supported by this service provider.",
this);
82 emit errorOccurred(reply, reply->error(), reply->errorString());
86 QList<QNetworkReply*> replies;
87 for (
const QString &reqString : reqStrings)
88 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
92 connect(reply, &QGeoRouteReplyNokia::finished,
93 this, &QGeoRoutingManagerEngineNokia::routeFinished);
94 connect(reply, &QGeoRouteReplyNokia::errorOccurred,
95 this, &QGeoRoutingManagerEngineNokia::routeError);
102 const QStringList reqStrings = updateRouteRequestString(route, position);
104 if (reqStrings.isEmpty()) {
105 QGeoRouteReply *reply =
new QGeoRouteReply(QGeoRouteReply::UnsupportedOptionError,
"The given route request options are not supported by this service provider.",
this);
106 emit errorOccurred(reply, reply->error(), reply->errorString());
110 QList<QNetworkReply*> replies;
111 for (
const QString &reqString : reqStrings)
112 replies.append(m_networkManager->get(QNetworkRequest(QUrl(reqString))));
114 QGeoRouteRequest updateRequest(route.request());
115 updateRequest.setTravelModes(route.travelMode());
118 connect(reply, &QGeoRouteReplyNokia::finished,
119 this, &QGeoRoutingManagerEngineNokia::routeFinished);
120 connect(reply, &QGeoRouteReplyNokia::errorOccurred,
121 this, &QGeoRoutingManagerEngineNokia::routeError);
127 QGeoRouteRequest::TravelModes travelModes)
const
129 const QList<QGeoRouteRequest::FeatureType> featureTypeList = request.featureTypes();
130 QGeoRouteRequest::FeatureTypes featureTypeFlag = QGeoRouteRequest::NoFeature;
131 QGeoRouteRequest::FeatureWeights featureWeightFlag = QGeoRouteRequest::NeutralFeatureWeight;
133 for (
const auto &featureType : featureTypeList) {
134 featureTypeFlag |= featureType;
135 featureWeightFlag |= request.featureWeight(featureType);
138 if ((featureTypeFlag & supportedFeatureTypes()) != featureTypeFlag)
141 if ((featureWeightFlag & supportedFeatureWeights()) != featureWeightFlag)
145 if ((request.maneuverDetail() & supportedManeuverDetails()) != request.maneuverDetail())
148 if ((request.segmentDetail() & supportedSegmentDetails()) != request.segmentDetail())
151 if ((request.routeOptimization() & supportedRouteOptimizations()) != request.routeOptimization())
154 if ((travelModes & supportedTravelModes()) != travelModes)
160 for (
unsigned bits = travelModes; bits; bits >>= 1)
172 bool supported = checkEngineSupport(request, request.travelModes());
175 return QStringList();
176 QStringList requests;
178 QString baseRequest = QStringLiteral(
"https://");
179 baseRequest += m_uriProvider->getCurrentHost();
180 baseRequest += QStringLiteral(
"/routing/7.2/calculateroute.xml");
182 baseRequest += QStringLiteral(
"?alternatives=");
183 baseRequest += QString::number(request.numberAlternativeRoutes());
185 if (!m_apiKey.isEmpty()) {
186 baseRequest += QStringLiteral(
"&apiKey=");
187 baseRequest += m_apiKey;
190 const QList<QGeoCoordinate> waypoints = request.waypoints();
191 int numWaypoints = waypoints.size();
192 if (numWaypoints < 2)
193 return QStringList();
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());
202 baseRequest += trimDouble(c.longitude());
203 baseRequest += QStringLiteral(
";;");
206 QGeoRouteRequest::RouteOptimizations optimization = request.routeOptimization();
209 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
210 types.append(
"shortest");
211 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
212 types.append(
"fastest");
214 for (
const QString &optimization : types) {
215 QString requestString = baseRequest;
216 requestString += modesRequestString(request, request.travelModes(), optimization);
217 requestString += routeRequestString(request);
218 requests << requestString;
226 if (!checkEngineSupport(route.request(), route.travelMode()))
227 return QStringList();
228 QStringList requests;
230 QString baseRequest =
"https://";
231 baseRequest += m_uriProvider->getCurrentHost();
232 baseRequest +=
"/routing/7.2/getroute.xml";
234 baseRequest +=
"?routeid=";
235 baseRequest += route.routeId();
237 baseRequest +=
"&pos=";
238 baseRequest += QString::number(position.latitude());
240 baseRequest += QString::number(position.longitude());
242 QGeoRouteRequest::RouteOptimizations optimization = route.request().routeOptimization();
245 if (optimization.testFlag(QGeoRouteRequest::ShortestRoute))
246 types.append(
"shortest");
247 if (optimization.testFlag(QGeoRouteRequest::FastestRoute))
248 types.append(
"fastest");
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;
261 QGeoRouteRequest::TravelModes travelModes,
const QString &optimization)
const
263 QString requestString;
266 if (travelModes.testFlag(QGeoRouteRequest::CarTravel))
268 if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel))
269 modes.append(
"pedestrian");
270 if (travelModes.testFlag(QGeoRouteRequest::PublicTransitTravel))
271 modes.append(
"publicTransport");
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));
278 if (weight == QGeoRouteRequest::NeutralFeatureWeight)
281 QString weightString =
"";
283 case QGeoRouteRequest::PreferFeatureWeight:
286 case QGeoRouteRequest::AvoidFeatureWeight:
289 case QGeoRouteRequest::DisallowFeatureWeight:
292 case QGeoRouteRequest::NeutralFeatureWeight:
293 case QGeoRouteRequest::RequireFeatureWeight:
297 if (weightString.isEmpty())
300 switch (featureTypes.at(i)) {
301 case QGeoRouteRequest::TollFeature:
302 featureStrings.append(
"tollroad:" + weightString);
304 case QGeoRouteRequest::HighwayFeature:
305 featureStrings.append(
"motorway:" + weightString);
307 case QGeoRouteRequest::FerryFeature:
308 featureStrings.append(
"boatFerry:" + weightString);
309 featureStrings.append(
"railFerry:" + weightString);
311 case QGeoRouteRequest::TunnelFeature:
312 featureStrings.append(
"tunnel:" + weightString);
314 case QGeoRouteRequest::DirtRoadFeature:
315 featureStrings.append(
"dirtRoad:" + weightString);
317 case QGeoRouteRequest::PublicTransitFeature:
318 case QGeoRouteRequest::ParksFeature:
319 case QGeoRouteRequest::MotorPoolLaneFeature:
320 case QGeoRouteRequest::TrafficFeature:
321 case QGeoRouteRequest::NoFeature:
326 requestString +=
"&mode=";
327 requestString += optimization +
';' + modes.join(
',');
328 if (featureStrings.count())
329 requestString +=
';' + featureStrings.join(
',');
330 return requestString;
335 QString requestString;
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());
348 QStringList legAttributes;
351 requestString +=
"&linkattributes=sh,le";
352 legAttributes.append(
"links");
357 legAttributes.append(
"maneuvers");
359 requestString +=
"&maneuverattributes=all";
360 if (!(request.segmentDetail() & QGeoRouteRequest::NoSegmentData))
361 requestString +=
",li";
365 requestString +=
"&routeattributes=sm,sh,bb,lg";
366 if (legAttributes.count() > 0) {
367 requestString +=
"&legattributes=";
368 requestString += legAttributes.join(
",");
372 requestString +=
"&departure=";
373 requestString += QDateTime::currentDateTime().toUTC().toString(
"yyyy-MM-ddThh:mm:ssZ");
375 requestString +=
"&instructionformat=text";
378 requestString +=
"&metricSystem=";
379 if (QLocale::MetricSystem == measurementSystem())
380 requestString +=
"metric";
382 requestString +=
"imperial";
384 const QLocale loc(locale());
387 if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) {
388 requestString +=
"&language=";
389 requestString += loc.name();
391 if (QLocale::English != loc.language())
392 requestString +=
",en_US";
395 return requestString;
400 QString sDegree = QString::number(degree,
'g', decimalDigits);
402 int index = sDegree.indexOf(
'.');
407 return QString::number(degree,
'g', decimalDigits + index);
412 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
417 if (receivers(SIGNAL(finished(QGeoRouteReply*))) == 0) {
418 reply->deleteLater();
422 emit finished(reply);
427 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
432 if (receivers(SIGNAL(errorOccurred(QGeoRouteReply*,QGeoRouteReply::Error,QString))) == 0) {
433 reply->deleteLater();
437 emit errorOccurred(reply, error, errorString);
QGeoRouteReply * updateRoute(const QGeoRoute &route, const QGeoCoordinate &position) override
Begins the process of updating route based on the current position position.
~QGeoRoutingManagerEngineNokia()