Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeoroutingmanagerenginemapbox.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Vlad Seryakov <vseryakov@gmail.com>
2// Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
8#include <QtLocation/private/qgeorouteparserosrmv5_p.h>
9#include <QtLocation/qgeoroutesegment.h>
10#include <QtLocation/qgeomaneuver.h>
11
12#include <QtCore/QJsonDocument>
13#include <QtCore/QJsonObject>
14#include <QtCore/QJsonArray>
15#include <QtCore/QUrlQuery>
16#include <QtCore/QDebug>
17
19
21{
22public:
23 QGeoRouteParserOsrmV5ExtensionMapbox(const QString &accessToken, bool useMapboxTextInstructions);
24 void updateQuery(QUrlQuery &query) const override;
25 void updateSegment(QGeoRouteSegment &segment, const QJsonObject &step, const QJsonObject &maneuver) const override;
26
29};
30
31QGeoRouteParserOsrmV5ExtensionMapbox::QGeoRouteParserOsrmV5ExtensionMapbox(const QString &accessToken, bool useMapboxTextInstructions)
33{
34
35}
36
38{
39 if (!m_accessToken.isEmpty())
40 query.addQueryItem(QLatin1String("access_token"), m_accessToken);
41
42 query.addQueryItem(QLatin1String("annotations"), QLatin1String("duration,distance,speed,congestion"));
43
44 query.addQueryItem(QLatin1String("voice_instructions"), QLatin1String("true"));
45 query.addQueryItem(QLatin1String("banner_instructions"), QLatin1String("true"));
46 query.addQueryItem(QLatin1String("roundabout_exits"), QLatin1String("true"));
47
48 QLocale::MeasurementSystem unit = QLocale::system().measurementSystem();
49 query.addQueryItem(QLatin1String("voice_units"), unit == QLocale::MetricSystem ? QLatin1String("metric") : QLatin1String("imperial"));
50}
51
52static QVariantMap parseMapboxVoiceInstruction(const QJsonObject &voiceInstruction)
53{
54 QVariantMap map;
55
56 if (voiceInstruction.value(QLatin1String("distanceAlongGeometry")).isDouble())
57 map.insert(QLatin1String("distance_along_geometry"), voiceInstruction.value(QLatin1String("distanceAlongGeometry")).toDouble());
58
59 if (voiceInstruction.value(QLatin1String("announcement")).isString())
60 map.insert(QLatin1String("announcement"), voiceInstruction.value(QLatin1String("announcement")).toString());
61
62 if (voiceInstruction.value(QLatin1String("ssmlAnnouncement")).isString())
63 map.insert(QLatin1String("ssml_announcement"), voiceInstruction.value(QLatin1String("ssmlAnnouncement")).toString());
64
65 return map;
66}
67
68static QVariantList parseMapboxVoiceInstructions(const QJsonArray &voiceInstructions)
69{
70 QVariantList list;
71 for (const QJsonValueConstRef voiceInstructionValue : voiceInstructions) {
72 if (voiceInstructionValue.isObject())
73 list << parseMapboxVoiceInstruction(voiceInstructionValue.toObject());
74 }
75 return list;
76}
77
78static QVariantMap parseMapboxBannerComponent(const QJsonObject &bannerComponent)
79{
80 QVariantMap map;
81
82 if (bannerComponent.value(QLatin1String("type")).isString())
83 map.insert(QLatin1String("type"), bannerComponent.value(QLatin1String("type")).toString());
84
85 if (bannerComponent.value(QLatin1String("text")).isString())
86 map.insert(QLatin1String("text"), bannerComponent.value(QLatin1String("text")).toString());
87
88 if (bannerComponent.value(QLatin1String("abbr")).isString())
89 map.insert(QLatin1String("abbr"), bannerComponent.value(QLatin1String("abbr")).toString());
90
91 if (bannerComponent.value(QLatin1String("abbr_priority")).isDouble())
92 map.insert(QLatin1String("abbr_priority"), bannerComponent.value(QLatin1String("abbr_priority")).toInt());
93
94 return map;
95}
96
97static QVariantList parseMapboxBannerComponents(const QJsonArray &bannerComponents)
98{
99 QVariantList list;
100 for (const QJsonValueConstRef bannerComponentValue : bannerComponents) {
101 if (bannerComponentValue.isObject())
102 list << parseMapboxBannerComponent(bannerComponentValue.toObject());
103 }
104 return list;
105}
106
107static QVariantMap parseMapboxBanner(const QJsonObject &banner)
108{
109 QVariantMap map;
110
111 if (banner.value(QLatin1String("text")).isString())
112 map.insert(QLatin1String("text"), banner.value(QLatin1String("text")).toString());
113
114 if (banner.value(QLatin1String("components")).isArray())
115 map.insert(QLatin1String("components"), parseMapboxBannerComponents(banner.value(QLatin1String("components")).toArray()));
116
117 if (banner.value(QLatin1String("type")).isString())
118 map.insert(QLatin1String("type"), banner.value(QLatin1String("type")).toString());
119
120 if (banner.value(QLatin1String("modifier")).isString())
121 map.insert(QLatin1String("modifier"), banner.value(QLatin1String("modifier")).toString());
122
123 if (banner.value(QLatin1String("degrees")).isDouble())
124 map.insert(QLatin1String("degrees"), banner.value(QLatin1String("degrees")).toDouble());
125
126 if (banner.value(QLatin1String("driving_side")).isString())
127 map.insert(QLatin1String("driving_side"), banner.value(QLatin1String("driving_side")).toString());
128
129 return map;
130}
131
132static QVariantMap parseMapboxBannerInstruction(const QJsonObject &bannerInstruction)
133{
134 QVariantMap map;
135
136 if (bannerInstruction.value(QLatin1String("distanceAlongGeometry")).isDouble())
137 map.insert(QLatin1String("distance_along_geometry"), bannerInstruction.value(QLatin1String("distanceAlongGeometry")).toDouble());
138
139 if (bannerInstruction.value(QLatin1String("primary")).isObject())
140 map.insert(QLatin1String("primary"), parseMapboxBanner(bannerInstruction.value(QLatin1String("primary")).toObject()));
141
142 if (bannerInstruction.value(QLatin1String("secondary")).isObject())
143 map.insert(QLatin1String("secondary"), parseMapboxBanner(bannerInstruction.value(QLatin1String("secondary")).toObject()));
144
145 if (bannerInstruction.value(QLatin1String("then")).isObject())
146 map.insert(QLatin1String("then"), parseMapboxBanner(bannerInstruction.value(QLatin1String("then")).toObject()));
147
148 return map;
149}
150
151static QVariantList parseMapboxBannerInstructions(const QJsonArray &bannerInstructions)
152{
153 QVariantList list;
154 for (const QJsonValueConstRef bannerInstructionValue : bannerInstructions) {
155 if (bannerInstructionValue.isObject())
156 list << parseMapboxBannerInstruction(bannerInstructionValue.toObject());
157 }
158 return list;
159}
160
161void QGeoRouteParserOsrmV5ExtensionMapbox::updateSegment(QGeoRouteSegment &segment, const QJsonObject &step, const QJsonObject &maneuver) const
162{
163 QGeoManeuver m = segment.maneuver();
164 QVariantMap extendedAttributes = m.extendedAttributes();
165 if (m_useMapboxTextInstructions && maneuver.value(QLatin1String("instruction")).isString()) {
166 QString maneuverInstructionText = maneuver.value(QLatin1String("instruction")).toString();
167 if (!maneuverInstructionText.isEmpty())
168 m.setInstructionText(maneuverInstructionText);
169 }
170
171 if (step.value(QLatin1String("voiceInstructions")).isArray())
172 extendedAttributes.insert(QLatin1String("mapbox.voice_instructions"),
173 parseMapboxVoiceInstructions(step.value(QLatin1String("voiceInstructions")).toArray()));
174 if (step.value(QLatin1String("bannerInstructions")).isArray())
175 extendedAttributes.insert(QLatin1String("mapbox.banner_instructions"),
176 parseMapboxBannerInstructions(step.value(QLatin1String("bannerInstructions")).toArray()));
177
178 m.setExtendedAttributes(extendedAttributes);
179 segment.setManeuver(m);
180}
181
182
183QGeoRoutingManagerEngineMapbox::QGeoRoutingManagerEngineMapbox(const QVariantMap &parameters,
184 QGeoServiceProvider::Error *error,
185 QString *errorString)
186 : QGeoRoutingManagerEngine(parameters),
187 m_networkManager(new QNetworkAccessManager(this)),
188 m_userAgent(mapboxDefaultUserAgent)
189{
190 if (parameters.contains(QStringLiteral("mapbox.useragent"))) {
191 m_userAgent = parameters.value(QStringLiteral("mapbox.useragent")).toString().toLatin1();
192 }
193
194 if (parameters.contains(QStringLiteral("mapbox.access_token"))) {
195 m_accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString();
196 }
197
198 bool use_mapbox_text_instructions = true;
199 if (parameters.contains(QStringLiteral("mapbox.routing.use_mapbox_text_instructions"))) {
200 use_mapbox_text_instructions = parameters.value(QStringLiteral("mapbox.routing.use_mapbox_text_instructions")).toBool();
201 }
202
203 QGeoRouteParserOsrmV5 *parser = new QGeoRouteParserOsrmV5(this);
204 parser->setExtension(new QGeoRouteParserOsrmV5ExtensionMapbox(m_accessToken, use_mapbox_text_instructions));
205 if (parameters.contains(QStringLiteral("mapbox.routing.traffic_side"))) {
206 QString trafficSide = parameters.value(QStringLiteral("mapbox.routing.traffic_side")).toString();
207 if (trafficSide == QStringLiteral("right"))
208 parser->setTrafficSide(QGeoRouteParser::RightHandTraffic);
209 else if (trafficSide == QStringLiteral("left"))
210 parser->setTrafficSide(QGeoRouteParser::LeftHandTraffic);
211 }
212 m_routeParser = parser;
213
214 *error = QGeoServiceProvider::NoError;
215 errorString->clear();
216}
217
221
223{
224 QNetworkRequest networkRequest;
225 networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
226
227 QString url = mapboxDirectionsApiPath;
228
229 QGeoRouteRequest::TravelModes travelModes = request.travelModes();
230 if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel)) {
231 url += QStringLiteral("walking/");
232 } else if (travelModes.testFlag(QGeoRouteRequest::BicycleTravel)) {
233 url += QStringLiteral("cycling/");
234 } else if (travelModes.testFlag(QGeoRouteRequest::CarTravel)) {
235 const QList<QGeoRouteRequest::FeatureType> &featureTypes = request.featureTypes();
236 int trafficFeatureIdx = featureTypes.indexOf(QGeoRouteRequest::TrafficFeature);
237 QGeoRouteRequest::FeatureWeight trafficWeight = request.featureWeight(QGeoRouteRequest::TrafficFeature);
238 if (trafficFeatureIdx >= 0 &&
239 (trafficWeight == QGeoRouteRequest::AvoidFeatureWeight || trafficWeight == QGeoRouteRequest::DisallowFeatureWeight)) {
240 url += QStringLiteral("driving-traffic/");
241 } else {
242 url += QStringLiteral("driving/");
243 }
244 }
245
246 networkRequest.setUrl(m_routeParser->requestUrl(request, url));
247
248 QNetworkReply *reply = m_networkManager->get(networkRequest);
249
250 QGeoRouteReplyMapbox *routeReply = new QGeoRouteReplyMapbox(reply, request, this);
251
252 connect(routeReply, &QGeoRouteReplyMapbox::finished,
253 this, &QGeoRoutingManagerEngineMapbox::replyFinished);
254 connect(routeReply, &QGeoRouteReplyMapbox::errorOccurred,
255 this, &QGeoRoutingManagerEngineMapbox::replyError);
256
257 return routeReply;
258}
259
260const QGeoRouteParser *QGeoRoutingManagerEngineMapbox::routeParser() const
261{
262 return m_routeParser;
263}
264
265void QGeoRoutingManagerEngineMapbox::replyFinished()
266{
267 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
268 if (reply)
269 emit finished(reply);
270}
271
272void QGeoRoutingManagerEngineMapbox::replyError(QGeoRouteReply::Error errorCode,
273 const QString &errorString)
274{
275 QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
276 if (reply)
277 emit errorOccurred(reply, errorCode, errorString);
278}
279
280QT_END_NAMESPACE
void updateSegment(QGeoRouteSegment &segment, const QJsonObject &step, const QJsonObject &maneuver) const override
QGeoRouteParserOsrmV5ExtensionMapbox(const QString &accessToken, bool useMapboxTextInstructions)
void updateQuery(QUrlQuery &query) const override
const QGeoRouteParser * routeParser() const
QGeoRouteReply * calculateRoute(const QGeoRouteRequest &request) override
Begins the calculation of the route specified by request.
static QVariantMap parseMapboxBannerComponent(const QJsonObject &bannerComponent)
static QVariantMap parseMapboxBannerInstruction(const QJsonObject &bannerInstruction)
static QVariantList parseMapboxBannerComponents(const QJsonArray &bannerComponents)
static QVariantMap parseMapboxBanner(const QJsonObject &banner)
static QVariantList parseMapboxVoiceInstructions(const QJsonArray &voiceInstructions)
static QVariantList parseMapboxBannerInstructions(const QJsonArray &bannerInstructions)
static QVariantMap parseMapboxVoiceInstruction(const QJsonObject &voiceInstruction)