6#include <QXmlStreamReader>
9#include <QtCore/QThreadPool>
12#include <QtPositioning/QGeoRectangle>
13#include <QtPositioning/QGeoPath>
14#include <QtLocation/QGeoRoute>
15#include <QtLocation/private/qgeoroutesegment_p.h>
19QGeoDynamicSpeedInfoContainer::QGeoDynamicSpeedInfoContainer()
42 QThreadPool::globalInstance()->start(
this);
47 m_reader =
new QXmlStreamReader(m_data);
49 if (!parseRootElement())
50 emit errorOccurred(m_reader->errorString());
52 emit results(m_results);
60 if (!m_reader->readNextStartElement()) {
61 m_reader->raiseError(QStringLiteral(
"Expected a root element named \"CalculateRoute\" "
62 "(no root element found)."));
66 if (m_reader->name() == QLatin1String(
"Error")) {
67 QXmlStreamAttributes attributes = m_reader->attributes();
68 if (attributes.value(QStringLiteral(
"type")) == QLatin1String(
"ApplicationError")
69 && attributes.value(
"subtype") == QLatin1String(
"NoRouteFound"))
73 bool updateroute =
false;
74 if (m_reader->name() != QLatin1String(
"CalculateRoute")
75 && m_reader->name() != QLatin1String(
"GetRoute")) {
76 m_reader->raiseError(QStringLiteral(
"The root element is expected to have the name "
77 "\"CalculateRoute\" or \"GetRoute\" (root element "
78 "was named \"%1\").").arg(m_reader->name().toString()));
80 }
else if (m_reader->name() == QLatin1String(
"GetRoute")) {
84 if (m_reader->readNextStartElement()) {
85 if (m_reader->name() != QLatin1String(
"Response")) {
86 m_reader->raiseError(QStringLiteral(
"Expected a element named \"Response\" (element "
87 "was named \"%1\").").arg(m_reader->name().toString()));
92 while (m_reader->readNextStartElement() && !m_reader->hasError()) {
93 if (m_reader->name() == QLatin1String(
"Route")) {
95 route.setRequest(m_request);
97 route.setTravelMode(QGeoRouteRequest::TravelMode(
int(m_request.travelModes())));
98 if (!parseRoute(&route))
100 m_results.append(route);
101 }
else if (m_reader->name() == QLatin1String(
"Progress")) {
103 m_reader->skipCurrentElement();
105 m_reader->skipCurrentElement();
109 return !m_reader->hasError();
114 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Route"));
119 m_reader->readNext();
120 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
121 && m_reader->name() == QLatin1String(
"Route")) && !m_reader->hasError()) {
122 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
123 if (m_reader->name() == QLatin1String(
"RouteId")) {
124 route->setRouteId(m_reader->readElementText());
129 else if (m_reader->name() == QLatin1String(
"Mode")) {
130 if (!parseMode(route))
132 }
else if (m_reader->name() == QLatin1String(
"Shape")) {
133 QString elementName = m_reader->name().toString();
134 QList<QGeoCoordinate> path;
135 if (!parseGeoPoints(m_reader->readElementText(), &path, elementName))
137 route->setPath(path);
138 }
else if (m_reader->name() == QLatin1String(
"BoundingBox")) {
139 QGeoRectangle bounds;
140 if (!parseBoundingBox(bounds))
142 route->setBounds(bounds);
143 }
else if (m_reader->name() == QLatin1String(
"Leg")) {
144 if (!parseLeg(legIndex++))
146 }
else if (m_reader->name() == QLatin1String(
"Summary")) {
147 if (!parseSummary(route))
150 m_reader->skipCurrentElement();
153 m_reader->readNext();
156 if (m_reader->hasError())
159 return postProcessRoute(route);
164 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral(
"Leg"));
166 leg.setLegIndex(legIndex);
167 m_reader->readNext();
168 QList<QGeoManeuverContainer> maneuvers;
169 QList<QGeoRouteSegmentContainer> links;
170 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
171 && m_reader->name() == QStringLiteral(
"Leg")) &&
172 !m_reader->hasError()) {
173 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
174 if (m_reader->name() == QStringLiteral(
"Maneuver")) {
175 if (!parseManeuver(maneuvers))
184 else if (m_reader->name() == QLatin1String(
"TravelTime")) {
185 leg.setTravelTime(qRound(m_reader->readElementText().toDouble()));
186 }
else if (m_reader->name() == QLatin1String(
"Length")) {
187 leg.setDistance(m_reader->readElementText().toDouble());
189 m_reader->skipCurrentElement();
192 m_reader->readNext();
195 if (m_reader->hasError())
200 m_maneuvers << maneuvers;
211 QList<QList<QGeoRouteSegment>> legSegments;
212 Q_ASSERT(m_maneuvers.size());
216 for (qsizetype i = 0; i < m_maneuvers.size(); i++) {
217 legSegments << QList<QGeoRouteSegment>();
218 QList<QGeoRouteSegment> &segments = legSegments[i];
219 QList<QGeoManeuverContainer> &maneuvers = m_maneuvers[i];
220 for (qsizetype j = 0; j < m_maneuvers.at(i).size(); j++) {
222 QGeoRouteSegment segment;
224 QVariantMap extendedAttributes;
225 extendedAttributes[
"first"] = maneuver
.first;
226 extendedAttributes[
"last"] = maneuver
.last;
227 extendedAttributes[
"legIndex"] = i;
228 extendedAttributes[
"id"] = maneuver.id;
229 extendedAttributes[
"toLink"] = maneuver.toLink;
230 extendedAttributes[
"index"] = j;
231 maneuver.maneuver.setExtendedAttributes(extendedAttributes);
233 segment.setDistance(maneuver.maneuver.distanceToNextInstruction());
234 segment.setTravelTime(maneuver.maneuver.timeToNextInstruction());
235 segment.setPath(maneuver.path);
236 segment.setManeuver(maneuver.maneuver);
242 QGeoRouteSegment segment;
243 QGeoRouteSegment firstSegment;
244 for (
auto &segments: legSegments) {
245 for (qsizetype j = 0; j < segments.size(); j++) {
246 if (segment.isValid()) {
247 segment.setNextRouteSegment(segments[j]);
249 firstSegment = segments[j];
251 segment = segments[j];
252 if (j == segments.size() - 1) {
253 QGeoRouteSegmentPrivate *sp = QGeoRouteSegmentPrivate::get(segment);
254 sp->setLegLastSegment(
true);
259 if (firstSegment.isValid())
260 route->setFirstRouteSegment(firstSegment);
263 for (qsizetype i = 0; i < m_legs.size(); i++) {
264 auto &leg = m_legs[i];
265 leg.setTravelMode(route->travelMode());
266 leg.setRequest(route->request());
267 leg.setOverallRoute(*route);
270 leg.setFirstRouteSegment(legSegments[i].first());
273 QList<QGeoCoordinate> path;
274 QGeoRouteSegment s = leg.firstRouteSegment();
275 while (s.isValid()) {
276 path.append(s.path());
277 if (s.isLegLastSegment())
279 s = s.nextRouteSegment();
282 leg.setBounds(QGeoPath(path).boundingGeoRectangle());
284 route->setRouteLegs(m_legs);
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
319 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Mode"));
320 m_reader->readNext();
322 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
323 && m_reader->name() == QLatin1String(
"Mode")) && !m_reader->hasError()) {
324 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
325 if (m_reader->name() == QLatin1String(
"TransportModes")) {
326 QString value = m_reader->readElementText();
328 route->setTravelMode(QGeoRouteRequest::CarTravel);
329 else if (value ==
"pedestrian")
330 route->setTravelMode(QGeoRouteRequest::PedestrianTravel);
331 else if (value ==
"publicTransport")
332 route->setTravelMode(QGeoRouteRequest::PublicTransitTravel);
333 else if (value ==
"bicycle")
334 route->setTravelMode(QGeoRouteRequest::BicycleTravel);
335 else if (value ==
"truck")
336 route->setTravelMode(QGeoRouteRequest::TruckTravel);
339 m_reader->raiseError(QString(
"Unsupported travel mode '\"%1\"'").arg(value));
343 m_reader->skipCurrentElement();
346 m_reader->readNext();
348 return !m_reader->hasError();
354 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Summary"));
355 m_reader->readNext();
357 double baseTime = -1, trafficTime = -1;
359 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
360 && m_reader->name() == QLatin1String(
"Summary")) && !m_reader->hasError()) {
361 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
362 if (m_reader->name() == QLatin1String(
"Distance")) {
363 route->setDistance(m_reader->readElementText().toDouble());
364 }
else if (m_reader->name() == QLatin1String(
"TrafficTime")) {
365 trafficTime = m_reader->readElementText().toDouble();
366 }
else if (m_reader->name() == QLatin1String(
"BaseTime")) {
367 baseTime = m_reader->readElementText().toDouble();
369 m_reader->skipCurrentElement();
372 m_reader->readNext();
375 if (m_reader->hasError())
378 if (trafficTime >= 0)
379 route->setTravelTime(trafficTime);
380 else if (baseTime >= 0)
381 route->setTravelTime(baseTime);
388 QString currentElement = m_reader->name().toString();
389 m_reader->readNext();
391 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
392 && m_reader->name() == currentElement) && !m_reader->hasError()) {
393 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
394 QString name = m_reader->name().toString();
395 QString value = m_reader->readElementText();
396 if (name ==
"Latitude")
397 coord.setLatitude(value.toDouble());
398 else if (name ==
"Longitude")
399 coord.setLongitude(value.toDouble());
401 m_reader->readNext();
404 return !m_reader->hasError();
409 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Maneuver"));
411 if (!m_reader->attributes().hasAttribute(
"id")) {
412 m_reader->raiseError(
"The element \"Maneuver\" did not have the required attribute \"id\".");
416 maneuverContainter.id = m_reader->attributes().value(
"id").toString();
418 m_reader->readNext();
419 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
420 && m_reader->name() == QLatin1String(
"Maneuver")) && !m_reader->hasError()) {
421 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
422 if (m_reader->name() == QLatin1String(
"Position")) {
423 QGeoCoordinate coordinates;
424 if (parseCoordinates(coordinates))
425 maneuverContainter.maneuver.setPosition(coordinates);
426 }
else if (m_reader->name() == QLatin1String(
"Instruction")) {
427 maneuverContainter.maneuver.setInstructionText(m_reader->readElementText());
428 }
else if (m_reader->name() == QLatin1String(
"Shape")) {
429 QString elementName = m_reader->name().toString();
430 QList<QGeoCoordinate> path;
431 if (!parseGeoPoints(m_reader->readElementText(), &path, elementName))
433 maneuverContainter.path = path;
434 }
else if (m_reader->name() == QLatin1String(
"ToLink")) {
435 maneuverContainter.toLink = m_reader->readElementText();
436 }
else if (m_reader->name() == QLatin1String(
"TravelTime")) {
437 maneuverContainter.maneuver.setTimeToNextInstruction(qRound(m_reader->readElementText().toDouble()));
438 }
else if (m_reader->name() == QLatin1String(
"Length")) {
439 maneuverContainter.maneuver.setDistanceToNextInstruction(m_reader->readElementText().toDouble());
440 }
else if (m_reader->name() == QLatin1String(
"Direction")) {
441 QString value = m_reader->readElementText();
442 if (value ==
"forward")
443 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionForward);
444 else if (value ==
"bearRight")
445 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearRight);
446 else if (value ==
"lightRight")
447 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightRight);
448 else if (value ==
"right")
449 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionRight);
450 else if (value ==
"hardRight")
451 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardRight);
452 else if (value ==
"uTurnRight")
453 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnRight);
454 else if (value ==
"uTurnLeft")
455 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnLeft);
456 else if (value ==
"hardLeft")
457 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardLeft);
458 else if (value ==
"left")
459 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLeft);
460 else if (value ==
"lightLeft")
461 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightLeft);
462 else if (value ==
"bearLeft")
463 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearLeft);
465 maneuverContainter.maneuver.setDirection(QGeoManeuver::NoDirection);
467 m_reader->skipCurrentElement();
470 m_reader->readNext();
473 if (m_reader->hasError())
476 maneuvers.append(maneuverContainter);
482 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral(
"Link"));
483 m_reader->readNext();
487 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
488 && m_reader->name() == QStringLiteral(
"Link")) && !m_reader->hasError()) {
489 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
490 if (m_reader->name() == QStringLiteral(
"LinkId")) {
491 segmentContainer.id = m_reader->readElementText();
492 }
else if (m_reader->name() == QStringLiteral(
"Shape")) {
493 QString elementName = m_reader->name().toString();
494 QList<QGeoCoordinate> path;
495 parseGeoPoints(m_reader->readElementText(), &path, elementName);
496 segmentContainer.segment.setPath(path);
497 }
else if (m_reader->name() == QStringLiteral(
"Length")) {
498 segmentContainer.segment.setDistance(m_reader->readElementText().toDouble());
499 }
else if (m_reader->name() == QStringLiteral(
"Maneuver")) {
500 segmentContainer.maneuverId = m_reader->readElementText();
501 }
else if (m_reader->name() == QStringLiteral(
"DynamicSpeedInfo")) {
503 if (!parseDynamicSpeedInfo(speedInfo))
508 segmentContainer.segment.setTravelTime(time);
510 m_reader->skipCurrentElement();
513 m_reader->readNext();
516 if (m_reader->hasError())
518 links.append(segmentContainer);
522bool QGeoRouteXmlParser::parseGeoPoints(
const QString &strPoints, QList<QGeoCoordinate> *geoPoints,
523 const QString &elementName)
525 const QStringList rawPoints = strPoints.split(
' ');
527 for (
const auto &rawPoint : rawPoints) {
528 const QStringList coords = rawPoint.split(
',');
530 if (coords.length() != 2) {
531 m_reader->raiseError(QStringLiteral(
"Each of the space separated values of \"%1\" "
532 "is expected to be a comma separated pair of "
533 "coordinates (value was \"%2\")")
534 .arg(elementName).arg(rawPoint));
539 const QString latString = coords[0];
540 double lat = latString.toDouble(&ok);
543 m_reader->raiseError(QStringLiteral(
"The latitude portions of \"%1\" are expected to "
544 "have a value convertable to a double (value was "
545 "\"%2\")").arg(elementName).arg(latString));
549 const QString lngString = coords[1];
550 double lng = lngString.toDouble(&ok);
553 m_reader->raiseError(QStringLiteral(
"The longitude portions of \"%1\" are expected to "
554 "have a value convertable to a double (value was "
555 "\"%2\")").arg(elementName).arg(lngString));
559 QGeoCoordinate geoPoint(lat, lng);
560 geoPoints->append(geoPoint);
568 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"BoundingBox"));
573 m_reader->readNext();
574 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
575 && m_reader->name() == QLatin1String(
"BoundingBox")) && !m_reader->hasError()) {
576 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
577 if (m_reader->name() == QLatin1String(
"TopLeft")) {
578 QGeoCoordinate coordinates;
579 if (parseCoordinates(coordinates))
581 }
else if (m_reader->name() == QLatin1String(
"BottomRight")) {
582 QGeoCoordinate coordinates;
583 if (parseCoordinates(coordinates))
586 m_reader->skipCurrentElement();
589 m_reader->readNext();
592 if (m_reader->hasError())
595 if (tl.isValid() && br.isValid()) {
596 bounds = QGeoRectangle(tl, br);
605 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral(
"DynamicSpeedInfo"));
607 m_reader->readNext();
608 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral(
"DynamicSpeedInfo")) &&
609 !m_reader->hasError()) {
610 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
611 if (m_reader->name() == QStringLiteral(
"TrafficSpeed")) {
612 speedInfo
.trafficSpeed = m_reader->readElementText().toDouble();
613 }
else if (m_reader->name() == QStringLiteral(
"TrafficTime")) {
614 speedInfo
.trafficTime = qRound(m_reader->readElementText().toDouble());
615 }
else if (m_reader->name() == QStringLiteral(
"BaseSpeed")) {
616 speedInfo
.baseSpeed = m_reader->readElementText().toDouble();
617 }
else if (m_reader->name() == QStringLiteral(
"BaseTime")) {
618 speedInfo
.baseTime = qRound(m_reader->readElementText().toDouble());
620 m_reader->skipCurrentElement();
623 m_reader->readNext();
626 return !m_reader->hasError();
void parse(const QByteArray &data)
void run() override
Implement this pure virtual function in your subclass.