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;
206 QList<QList<QGeoRouteSegment>> legSegments;
207 Q_ASSERT(m_maneuvers.size());
211 for (qsizetype i = 0; i < m_maneuvers.size(); i++) {
212 legSegments << QList<QGeoRouteSegment>();
213 QList<QGeoRouteSegment> &segments = legSegments[i];
214 QList<QGeoManeuverContainer> &maneuvers = m_maneuvers[i];
215 for (qsizetype j = 0; j < m_maneuvers.at(i).size(); j++) {
217 QGeoRouteSegment segment;
219 QVariantMap extendedAttributes;
220 extendedAttributes[
"first"] = maneuver
.first;
221 extendedAttributes[
"last"] = maneuver
.last;
222 extendedAttributes[
"legIndex"] = i;
223 extendedAttributes[
"id"] = maneuver.id;
224 extendedAttributes[
"toLink"] = maneuver.toLink;
225 extendedAttributes[
"index"] = j;
226 maneuver.maneuver.setExtendedAttributes(extendedAttributes);
228 segment.setDistance(maneuver.maneuver.distanceToNextInstruction());
229 segment.setTravelTime(maneuver.maneuver.timeToNextInstruction());
230 segment.setPath(maneuver.path);
231 segment.setManeuver(maneuver.maneuver);
237 QGeoRouteSegment segment;
238 QGeoRouteSegment firstSegment;
239 for (
auto &segments: legSegments) {
240 for (qsizetype j = 0; j < segments.size(); j++) {
241 if (segment.isValid()) {
242 segment.setNextRouteSegment(segments[j]);
244 firstSegment = segments[j];
246 segment = segments[j];
247 if (j == segments.size() - 1) {
248 QGeoRouteSegmentPrivate *sp = QGeoRouteSegmentPrivate::get(segment);
249 sp->setLegLastSegment(
true);
254 if (firstSegment.isValid())
255 route->setFirstRouteSegment(firstSegment);
258 for (qsizetype i = 0; i < m_legs.size(); i++) {
259 auto &leg = m_legs[i];
260 leg.setTravelMode(route->travelMode());
261 leg.setRequest(route->request());
262 leg.setOverallRoute(*route);
265 leg.setFirstRouteSegment(legSegments[i].first());
268 QList<QGeoCoordinate> path;
269 QGeoRouteSegment s = leg.firstRouteSegment();
270 while (s.isValid()) {
271 path.append(s.path());
272 if (s.isLegLastSegment())
274 s = s.nextRouteSegment();
277 leg.setBounds(QGeoPath(path).boundingGeoRectangle());
279 route->setRouteLegs(m_legs);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
314 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Mode"));
315 m_reader->readNext();
317 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
318 && m_reader->name() == QLatin1String(
"Mode")) && !m_reader->hasError()) {
319 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
320 if (m_reader->name() == QLatin1String(
"TransportModes")) {
321 QString value = m_reader->readElementText();
323 route->setTravelMode(QGeoRouteRequest::CarTravel);
324 else if (value ==
"pedestrian")
325 route->setTravelMode(QGeoRouteRequest::PedestrianTravel);
326 else if (value ==
"publicTransport")
327 route->setTravelMode(QGeoRouteRequest::PublicTransitTravel);
328 else if (value ==
"bicycle")
329 route->setTravelMode(QGeoRouteRequest::BicycleTravel);
330 else if (value ==
"truck")
331 route->setTravelMode(QGeoRouteRequest::TruckTravel);
334 m_reader->raiseError(QString(
"Unsupported travel mode '\"%1\"'").arg(value));
338 m_reader->skipCurrentElement();
341 m_reader->readNext();
343 return !m_reader->hasError();
349 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Summary"));
350 m_reader->readNext();
352 double baseTime = -1, trafficTime = -1;
354 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
355 && m_reader->name() == QLatin1String(
"Summary")) && !m_reader->hasError()) {
356 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
357 if (m_reader->name() == QLatin1String(
"Distance")) {
358 route->setDistance(m_reader->readElementText().toDouble());
359 }
else if (m_reader->name() == QLatin1String(
"TrafficTime")) {
360 trafficTime = m_reader->readElementText().toDouble();
361 }
else if (m_reader->name() == QLatin1String(
"BaseTime")) {
362 baseTime = m_reader->readElementText().toDouble();
364 m_reader->skipCurrentElement();
367 m_reader->readNext();
370 if (m_reader->hasError())
373 if (trafficTime >= 0)
374 route->setTravelTime(trafficTime);
375 else if (baseTime >= 0)
376 route->setTravelTime(baseTime);
383 QString currentElement = m_reader->name().toString();
384 m_reader->readNext();
386 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
387 && m_reader->name() == currentElement) && !m_reader->hasError()) {
388 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
389 QString name = m_reader->name().toString();
390 QString value = m_reader->readElementText();
391 if (name ==
"Latitude")
392 coord.setLatitude(value.toDouble());
393 else if (name ==
"Longitude")
394 coord.setLongitude(value.toDouble());
396 m_reader->readNext();
399 return !m_reader->hasError();
404 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"Maneuver"));
406 if (!m_reader->attributes().hasAttribute(
"id")) {
407 m_reader->raiseError(
"The element \"Maneuver\" did not have the required attribute \"id\".");
411 maneuverContainter.id = m_reader->attributes().value(
"id").toString();
413 m_reader->readNext();
414 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
415 && m_reader->name() == QLatin1String(
"Maneuver")) && !m_reader->hasError()) {
416 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
417 if (m_reader->name() == QLatin1String(
"Position")) {
418 QGeoCoordinate coordinates;
419 if (parseCoordinates(coordinates))
420 maneuverContainter.maneuver.setPosition(coordinates);
421 }
else if (m_reader->name() == QLatin1String(
"Instruction")) {
422 maneuverContainter.maneuver.setInstructionText(m_reader->readElementText());
423 }
else if (m_reader->name() == QLatin1String(
"Shape")) {
424 QString elementName = m_reader->name().toString();
425 QList<QGeoCoordinate> path;
426 if (!parseGeoPoints(m_reader->readElementText(), &path, elementName))
428 maneuverContainter.path = path;
429 }
else if (m_reader->name() == QLatin1String(
"ToLink")) {
430 maneuverContainter.toLink = m_reader->readElementText();
431 }
else if (m_reader->name() == QLatin1String(
"TravelTime")) {
432 maneuverContainter.maneuver.setTimeToNextInstruction(qRound(m_reader->readElementText().toDouble()));
433 }
else if (m_reader->name() == QLatin1String(
"Length")) {
434 maneuverContainter.maneuver.setDistanceToNextInstruction(m_reader->readElementText().toDouble());
435 }
else if (m_reader->name() == QLatin1String(
"Direction")) {
436 QString value = m_reader->readElementText();
437 if (value ==
"forward")
438 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionForward);
439 else if (value ==
"bearRight")
440 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearRight);
441 else if (value ==
"lightRight")
442 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightRight);
443 else if (value ==
"right")
444 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionRight);
445 else if (value ==
"hardRight")
446 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardRight);
447 else if (value ==
"uTurnRight")
448 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnRight);
449 else if (value ==
"uTurnLeft")
450 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnLeft);
451 else if (value ==
"hardLeft")
452 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardLeft);
453 else if (value ==
"left")
454 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLeft);
455 else if (value ==
"lightLeft")
456 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightLeft);
457 else if (value ==
"bearLeft")
458 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearLeft);
460 maneuverContainter.maneuver.setDirection(QGeoManeuver::NoDirection);
462 m_reader->skipCurrentElement();
465 m_reader->readNext();
468 if (m_reader->hasError())
471 maneuvers.append(maneuverContainter);
477 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral(
"Link"));
478 m_reader->readNext();
482 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
483 && m_reader->name() == QStringLiteral(
"Link")) && !m_reader->hasError()) {
484 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
485 if (m_reader->name() == QStringLiteral(
"LinkId")) {
486 segmentContainer.id = m_reader->readElementText();
487 }
else if (m_reader->name() == QStringLiteral(
"Shape")) {
488 QString elementName = m_reader->name().toString();
489 QList<QGeoCoordinate> path;
490 parseGeoPoints(m_reader->readElementText(), &path, elementName);
491 segmentContainer.segment.setPath(path);
492 }
else if (m_reader->name() == QStringLiteral(
"Length")) {
493 segmentContainer.segment.setDistance(m_reader->readElementText().toDouble());
494 }
else if (m_reader->name() == QStringLiteral(
"Maneuver")) {
495 segmentContainer.maneuverId = m_reader->readElementText();
496 }
else if (m_reader->name() == QStringLiteral(
"DynamicSpeedInfo")) {
498 if (!parseDynamicSpeedInfo(speedInfo))
503 segmentContainer.segment.setTravelTime(time);
505 m_reader->skipCurrentElement();
508 m_reader->readNext();
511 if (m_reader->hasError())
513 links.append(segmentContainer);
517bool QGeoRouteXmlParser::parseGeoPoints(
const QString &strPoints, QList<QGeoCoordinate> *geoPoints,
518 const QString &elementName)
520 const QStringList rawPoints = strPoints.split(
' ');
522 for (
const auto &rawPoint : rawPoints) {
523 const QStringList coords = rawPoint.split(
',');
525 if (coords.length() != 2) {
526 m_reader->raiseError(QStringLiteral(
"Each of the space separated values of \"%1\" "
527 "is expected to be a comma separated pair of "
528 "coordinates (value was \"%2\")")
529 .arg(elementName).arg(rawPoint));
534 const QString latString = coords[0];
535 double lat = latString.toDouble(&ok);
538 m_reader->raiseError(QStringLiteral(
"The latitude portions of \"%1\" are expected to "
539 "have a value convertable to a double (value was "
540 "\"%2\")").arg(elementName).arg(latString));
544 const QString lngString = coords[1];
545 double lng = lngString.toDouble(&ok);
548 m_reader->raiseError(QStringLiteral(
"The longitude portions of \"%1\" are expected to "
549 "have a value convertable to a double (value was "
550 "\"%2\")").arg(elementName).arg(lngString));
554 QGeoCoordinate geoPoint(lat, lng);
555 geoPoints->append(geoPoint);
563 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QLatin1String(
"BoundingBox"));
568 m_reader->readNext();
569 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
570 && m_reader->name() == QLatin1String(
"BoundingBox")) && !m_reader->hasError()) {
571 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
572 if (m_reader->name() == QLatin1String(
"TopLeft")) {
573 QGeoCoordinate coordinates;
574 if (parseCoordinates(coordinates))
576 }
else if (m_reader->name() == QLatin1String(
"BottomRight")) {
577 QGeoCoordinate coordinates;
578 if (parseCoordinates(coordinates))
581 m_reader->skipCurrentElement();
584 m_reader->readNext();
587 if (m_reader->hasError())
590 if (tl.isValid() && br.isValid()) {
591 bounds = QGeoRectangle(tl, br);
600 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral(
"DynamicSpeedInfo"));
602 m_reader->readNext();
603 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral(
"DynamicSpeedInfo")) &&
604 !m_reader->hasError()) {
605 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
606 if (m_reader->name() == QStringLiteral(
"TrafficSpeed")) {
607 speedInfo
.trafficSpeed = m_reader->readElementText().toDouble();
608 }
else if (m_reader->name() == QStringLiteral(
"TrafficTime")) {
609 speedInfo
.trafficTime = qRound(m_reader->readElementText().toDouble());
610 }
else if (m_reader->name() == QStringLiteral(
"BaseSpeed")) {
611 speedInfo
.baseSpeed = m_reader->readElementText().toDouble();
612 }
else if (m_reader->name() == QStringLiteral(
"BaseTime")) {
613 speedInfo
.baseTime = qRound(m_reader->readElementText().toDouble());
615 m_reader->skipCurrentElement();
618 m_reader->readNext();
621 return !m_reader->hasError();
void parse(const QByteArray &data)
void run() override
Implement this pure virtual function in your subclass.
Combined button and popup list for selecting options.