1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtLocation module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qgeoroutexmlparser.h"
38
39#include <QXmlStreamReader>
40#include <QStringList>
41#include <QString>
42#include <QtCore/QThreadPool>
43#include <QDebug>
44
45#include <QtPositioning/QGeoRectangle>
46#include <QtPositioning/QGeoPath>
47#include <QtLocation/QGeoRoute>
48#include <QtLocation/private/qgeoroutesegment_p.h>
49
50QT_BEGIN_NAMESPACE
51
52QGeoDynamicSpeedInfoContainer::QGeoDynamicSpeedInfoContainer()
53: trafficSpeed(0)
54, baseSpeed(0)
55, trafficTime(0)
56, baseTime(0)
57{}
58
59QGeoRouteXmlParser::QGeoRouteXmlParser(const QGeoRouteRequest &request)
60 : m_request(request)
61{
62}
63
64QGeoRouteXmlParser::~QGeoRouteXmlParser()
65{
66}
67
68void QGeoRouteXmlParser::parse(const QByteArray &data)
69{
70 m_data = data;
71// QFile file("/tmp/here.xml");
72// file.open(QIODevice::WriteOnly);
73// file.write(data);
74// file.close();
75 QThreadPool::globalInstance()->start(runnable: this);
76}
77
78void QGeoRouteXmlParser::run()
79{
80 m_reader = new QXmlStreamReader(m_data);
81
82 if (!parseRootElement())
83 emit error(errorString: m_reader->errorString());
84 else
85 emit results(routes: m_results);
86
87 delete m_reader;
88 m_reader = 0;
89}
90
91bool QGeoRouteXmlParser::parseRootElement()
92{
93 if (!m_reader->readNextStartElement()) {
94 m_reader->raiseError(message: "Expected a root element named \"CalculateRoute\" (no root element found).");
95 return false;
96 }
97
98 if (m_reader->name() == QLatin1String("Error")) {
99 QXmlStreamAttributes attributes = m_reader->attributes();
100 if (attributes.value(QStringLiteral("type")) == QLatin1String("ApplicationError")
101 && attributes.value(qualifiedName: "subtype") == QLatin1String("NoRouteFound"))
102 return true;
103 }
104
105 bool updateroute = false;
106 if (m_reader->name() != "CalculateRoute" && m_reader->name() != "GetRoute") {
107 m_reader->raiseError(message: QString("The root element is expected to have the name \"CalculateRoute\" or \"GetRoute\" (root element was named \"%1\").").arg(a: m_reader->name().toString()));
108 return false;
109 } else if (m_reader->name() == "GetRoute") {
110 updateroute = true;
111 }
112
113 if (m_reader->readNextStartElement()) {
114 if (m_reader->name() != "Response") {
115 m_reader->raiseError(message: QString("Expected a element named \"Response\" (element was named \"%1\").").arg(a: m_reader->name().toString()));
116 return false;
117 }
118 }
119
120 while (m_reader->readNextStartElement() && !m_reader->hasError()) {
121 if (m_reader->name() == "Route") {
122 QGeoRoute route;
123 route.setRequest(m_request);
124 if (updateroute)
125 route.setTravelMode(QGeoRouteRequest::TravelMode(int(m_request.travelModes())));
126 if (!parseRoute(route: &route))
127 continue; //route parsing failed move on to the next
128 m_results.append(t: route);
129 } else if (m_reader->name() == "Progress") {
130 //TODO: updated route progress
131 m_reader->skipCurrentElement();
132 } else {
133 m_reader->skipCurrentElement();
134 }
135 }
136
137 return !m_reader->hasError();
138}
139
140bool QGeoRouteXmlParser::parseRoute(QGeoRoute *route)
141{
142 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Route");
143 m_maneuvers.clear();
144// m_segments.clear();
145 m_legs.clear();
146 int legIndex = 0;
147 m_reader->readNext();
148 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Route") &&
149 !m_reader->hasError()) {
150 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
151 if (m_reader->name() == "RouteId") {
152 route->setRouteId(m_reader->readElementText());
153 }
154 //else if (m_reader->name() == "Waypoint") {
155 // succeeded = parseWaypoint(route);
156 //}
157 else if (m_reader->name() == "Mode") {
158 if (!parseMode(route))
159 return false;
160 } else if (m_reader->name() == "Shape") {
161 QString elementName = m_reader->name().toString();
162 QList<QGeoCoordinate> path;
163 if (!parseGeoPoints(strPoints: m_reader->readElementText(), geoPoints: &path, elementName))
164 return false;
165 route->setPath(path);
166 } else if (m_reader->name() == "BoundingBox") {
167 QGeoRectangle bounds;
168 if (!parseBoundingBox(bounds))
169 return false;
170 route->setBounds(bounds);
171 } else if (m_reader->name() == "Leg") {
172 if (!parseLeg(legIndex: legIndex++))
173 return false;
174 } else if (m_reader->name() == "Summary") {
175 if (!parseSummary(route))
176 return false;
177 } else {
178 m_reader->skipCurrentElement();
179 }
180 }
181 m_reader->readNext();
182 }
183
184 if (m_reader->hasError())
185 return false;
186
187 return postProcessRoute(route);
188}
189
190bool QGeoRouteXmlParser::parseLeg(int legIndex)
191{
192 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("Leg"));
193 QGeoRouteLeg leg;
194 leg.setLegIndex(legIndex);
195 m_reader->readNext();
196 QList<QGeoManeuverContainer> maneuvers;
197 QList<QGeoRouteSegmentContainer> links;
198 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
199 && m_reader->name() == QStringLiteral("Leg")) &&
200 !m_reader->hasError()) {
201 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
202 if (m_reader->name() == QStringLiteral("Maneuver")) {
203 if (!parseManeuver(maneuvers))
204 return false;
205 }
206// Currently unused, after requesting shape attribute in maneuvers.
207// Links, however, contain additional info, such as speed limits, and might become needed in the future.
208// else if (m_reader->name() == QStringLiteral("Link")) {
209// if (!parseLink(links))
210// return false;
211// }
212 else if (m_reader->name() == "TravelTime") {
213 leg.setTravelTime(qRound(d: m_reader->readElementText().toDouble()));
214 } else if (m_reader->name() == "Length") {
215 leg.setDistance(m_reader->readElementText().toDouble());
216 } else {
217 m_reader->skipCurrentElement();
218 }
219 }
220 m_reader->readNext();
221 }
222
223 if (m_reader->hasError())
224 return false;
225
226 m_legs << leg;
227// m_segments << links;
228 m_maneuvers << maneuvers;
229 return true;
230}
231
232//static bool fuzzyCompare(const QGeoCoordinate &a, const QGeoCoordinate& b)
233//{
234// return qFuzzyCompare(a.latitude(), b.latitude()) && qFuzzyCompare(a.longitude(), b.longitude());
235//}
236
237bool QGeoRouteXmlParser::postProcessRoute(QGeoRoute *route)
238{
239 QList<QList<QGeoRouteSegment>> legSegments;
240 Q_ASSERT(m_maneuvers.size());
241
242
243 // Step 3: populate the linkMap, linkId -> linkContainer
244 for (int i = 0; i < m_maneuvers.size(); i++) {
245 legSegments << QList<QGeoRouteSegment>();
246 QList<QGeoRouteSegment> &segments = legSegments[i];
247 QList<QGeoManeuverContainer> &maneuvers = m_maneuvers[i];
248 for (int j = 0; j < m_maneuvers.at(i).size(); j++) {
249 QGeoManeuverContainer &maneuver = maneuvers[j];
250 QGeoRouteSegment segment;
251
252 QVariantMap extendedAttributes;
253 extendedAttributes["first"] = maneuver.first;
254 extendedAttributes["last"] = maneuver.last;
255 extendedAttributes["legIndex"] = i;
256 extendedAttributes["id"] = maneuver.id;
257 extendedAttributes["toLink"] = maneuver.toLink;
258 extendedAttributes["index"] = j;
259 maneuver.maneuver.setExtendedAttributes(extendedAttributes);
260
261 segment.setDistance(maneuver.maneuver.distanceToNextInstruction());
262 segment.setTravelTime(maneuver.maneuver.timeToNextInstruction());
263 segment.setPath(maneuver.path);
264 segment.setManeuver(maneuver.maneuver);
265 segments << segment;
266 }
267 }
268
269 // Step 7: connect all segments.
270 QGeoRouteSegment segment;
271 QGeoRouteSegment firstSegment;
272 for (auto &segments: legSegments) {
273 for (int j = 0; j < segments.size(); j++) {
274 if (segment.isValid()) {
275 segment.setNextRouteSegment(segments[j]);
276 } else {
277 firstSegment = segments[j];
278 }
279 segment = segments[j];
280 if (j == segments.size() - 1) {
281 QGeoRouteSegmentPrivate *sp = QGeoRouteSegmentPrivate::get(segment);
282 sp->setLegLastSegment(true);
283 }
284 }
285 }
286
287 if (firstSegment.isValid())
288 route->setFirstRouteSegment(firstSegment);
289
290 // Step 8: fill route legs.
291 for (int i = 0; i < m_legs.size(); i++) {
292 m_legs[i].setTravelMode(route->travelMode());
293 m_legs[i].setRequest(route->request());
294 m_legs[i].setOverallRoute(*route);
295 m_legs[i].setLegIndex(i);
296
297 m_legs[i].setFirstRouteSegment(legSegments[i].first());
298
299 // handle path
300 QList<QGeoCoordinate> path;
301 QGeoRouteSegment s = m_legs[i].firstRouteSegment();
302 while (s.isValid()) {
303 path.append(t: s.path());
304 if (s.isLegLastSegment())
305 break;
306 s = s.nextRouteSegment();
307 }
308 m_legs[i].setPath(path);
309 m_legs[i].setBounds(QGeoPath(path).boundingGeoRectangle());
310 }
311 route->setRouteLegs(m_legs);
312 m_legs.clear();
313// m_segments.clear();
314 m_maneuvers.clear();
315 return true;
316}
317
318/*
319bool QGeoRouteXmlParser::parseWaypoint(QGeoRoute *route)
320{
321 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Waypoint");
322 m_reader->readNext();
323 QList<QGeoCoordinate> path(route->pathSummary());
324
325 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Waypoint")) {
326 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
327 if (m_reader->name() == "MappedPosition") {
328 QGeoCoordinate coordinates;
329 if(!parseCoordinates(coordinates))
330 return false;
331 path.append(coordinates);
332 }
333 else {
334 m_reader->skipCurrentElement();
335 }
336 }
337 m_reader->readNext();
338 }
339 route->setPathSummary(path);
340 return true;
341}
342*/
343
344bool QGeoRouteXmlParser::parseMode(QGeoRoute *route)
345{
346 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Mode");
347 m_reader->readNext();
348
349 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Mode") &&
350 !m_reader->hasError()) {
351 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
352 if (m_reader->name() == "TransportModes") {
353 QString value = m_reader->readElementText();
354 if (value == "car")
355 route->setTravelMode(QGeoRouteRequest::CarTravel);
356 else if (value == "pedestrian")
357 route->setTravelMode(QGeoRouteRequest::PedestrianTravel);
358 else if (value == "publicTransport")
359 route->setTravelMode(QGeoRouteRequest::PublicTransitTravel);
360 else if (value == "bicycle")
361 route->setTravelMode(QGeoRouteRequest::BicycleTravel);
362 else if (value == "truck")
363 route->setTravelMode(QGeoRouteRequest::TruckTravel);
364 else {
365 // unsupported mode
366 m_reader->raiseError(message: QString("Unsupported travel mode '\"%1\"'").arg(a: value));
367 return false;
368 }
369 } else {
370 m_reader->skipCurrentElement();
371 }
372 }
373 m_reader->readNext();
374 }
375 return !m_reader->hasError();
376}
377
378bool QGeoRouteXmlParser::parseSummary(QGeoRoute *route)
379{
380 Q_ASSERT(route);
381 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Summary");
382 m_reader->readNext();
383
384 double baseTime = -1, trafficTime = -1;
385
386 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Summary") &&
387 !m_reader->hasError()) {
388 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
389 if (m_reader->name() == "Distance") {
390 route->setDistance(m_reader->readElementText().toDouble());
391 } else if (m_reader->name() == "TrafficTime") {
392 trafficTime = m_reader->readElementText().toDouble();
393 } else if (m_reader->name() == "BaseTime") {
394 baseTime = m_reader->readElementText().toDouble();
395 } else {
396 m_reader->skipCurrentElement();
397 }
398 }
399 m_reader->readNext();
400 }
401
402 if (m_reader->hasError())
403 return false;
404
405 if (trafficTime >= 0)
406 route->setTravelTime(trafficTime);
407 else if (baseTime >= 0)
408 route->setTravelTime(baseTime);
409
410 return true;
411}
412
413bool QGeoRouteXmlParser::parseCoordinates(QGeoCoordinate &coord)
414{
415 QString currentElement = m_reader->name().toString();
416 m_reader->readNext();
417
418 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == currentElement) &&
419 !m_reader->hasError()) {
420 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
421 QString name = m_reader->name().toString();
422 QString value = m_reader->readElementText();
423 if (name == "Latitude")
424 coord.setLatitude(value.toDouble());
425 else if (name == "Longitude")
426 coord.setLongitude(value.toDouble());
427 }
428 m_reader->readNext();
429 }
430
431 return !m_reader->hasError();
432}
433
434bool QGeoRouteXmlParser::parseManeuver(QList<QGeoManeuverContainer> &maneuvers)
435{
436 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Maneuver");
437
438 if (!m_reader->attributes().hasAttribute(qualifiedName: "id")) {
439 m_reader->raiseError(message: "The element \"Maneuver\" did not have the required attribute \"id\".");
440 return false;
441 }
442 QGeoManeuverContainer maneuverContainter;
443 maneuverContainter.id = m_reader->attributes().value(qualifiedName: "id").toString();
444
445 m_reader->readNext();
446 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Maneuver") &&
447 !m_reader->hasError()) {
448 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
449 if (m_reader->name() == "Position") {
450 QGeoCoordinate coordinates;
451 if (parseCoordinates(coord&: coordinates))
452 maneuverContainter.maneuver.setPosition(coordinates);
453 } else if (m_reader->name() == "Instruction") {
454 maneuverContainter.maneuver.setInstructionText(m_reader->readElementText());
455 } else if (m_reader->name() == "Shape") {
456 QString elementName = m_reader->name().toString();
457 QList<QGeoCoordinate> path;
458 if (!parseGeoPoints(strPoints: m_reader->readElementText(), geoPoints: &path, elementName))
459 return false;
460 maneuverContainter.path = path;
461 } else if (m_reader->name() == "ToLink") {
462 maneuverContainter.toLink = m_reader->readElementText();
463 } else if (m_reader->name() == "TravelTime") {
464 maneuverContainter.maneuver.setTimeToNextInstruction(qRound(d: m_reader->readElementText().toDouble()));
465 } else if (m_reader->name() == "Length") {
466 maneuverContainter.maneuver.setDistanceToNextInstruction(m_reader->readElementText().toDouble());
467 } else if (m_reader->name() == "Direction") {
468 QString value = m_reader->readElementText();
469 if (value == "forward")
470 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionForward);
471 else if (value == "bearRight")
472 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearRight);
473 else if (value == "lightRight")
474 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightRight);
475 else if (value == "right")
476 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionRight);
477 else if (value == "hardRight")
478 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardRight);
479 else if (value == "uTurnRight")
480 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnRight);
481 else if (value == "uTurnLeft")
482 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionUTurnLeft);
483 else if (value == "hardLeft")
484 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionHardLeft);
485 else if (value == "left")
486 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLeft);
487 else if (value == "lightLeft")
488 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionLightLeft);
489 else if (value == "bearLeft")
490 maneuverContainter.maneuver.setDirection(QGeoManeuver::DirectionBearLeft);
491 else
492 maneuverContainter.maneuver.setDirection(QGeoManeuver::NoDirection);
493 } else {
494 m_reader->skipCurrentElement();
495 }
496 }
497 m_reader->readNext();
498 }
499
500 if (m_reader->hasError())
501 return false;
502
503 maneuvers.append(t: maneuverContainter);
504 return true;
505}
506
507bool QGeoRouteXmlParser::parseLink(QList<QGeoRouteSegmentContainer> &links)
508{
509 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("Link"));
510 m_reader->readNext();
511
512 QGeoRouteSegmentContainer segmentContainer;
513
514 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral("Link")) &&
515 !m_reader->hasError()) {
516 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
517 if (m_reader->name() == QStringLiteral("LinkId")) {
518 segmentContainer.id = m_reader->readElementText();
519 } else if (m_reader->name() == QStringLiteral("Shape")) {
520 QString elementName = m_reader->name().toString();
521 QList<QGeoCoordinate> path;
522 parseGeoPoints(strPoints: m_reader->readElementText(), geoPoints: &path, elementName);
523 segmentContainer.segment.setPath(path);
524 } else if (m_reader->name() == QStringLiteral("Length")) {
525 segmentContainer.segment.setDistance(m_reader->readElementText().toDouble());
526 } else if (m_reader->name() == QStringLiteral("Maneuver")) {
527 segmentContainer.maneuverId = m_reader->readElementText();
528 } else if (m_reader->name() == QStringLiteral("DynamicSpeedInfo")) {
529 QGeoDynamicSpeedInfoContainer speedInfo;
530 if (!parseDynamicSpeedInfo(speedInfo))
531 return false;
532 const double time = speedInfo.trafficTime >= 0 ? speedInfo.trafficTime : speedInfo.baseTime;
533 if (time >= 0)
534 segmentContainer.segment.setTravelTime(time);
535 } else {
536 m_reader->skipCurrentElement();
537 }
538 }
539 m_reader->readNext();
540 }
541
542 if (m_reader->hasError())
543 return false;
544 links.append(t: segmentContainer);
545 return true;
546}
547
548bool QGeoRouteXmlParser::parseGeoPoints(const QString &strPoints, QList<QGeoCoordinate> *geoPoints, const QString &elementName)
549{
550 QStringList rawPoints = strPoints.split(sep: ' ');
551
552 for (int i = 0; i < rawPoints.length(); ++i) {
553 QStringList coords = rawPoints[i].split(sep: ',');
554
555 if (coords.length() != 2) {
556 m_reader->raiseError(message: QString("Each of the space separated values of \"%1\" is expected to be a comma separated pair of coordinates (value was \"%2\")").arg(a: elementName).arg(a: rawPoints[i]));
557 return false;
558 }
559
560 bool ok = false;
561 QString latString = coords[0];
562 double lat = latString.toDouble(ok: &ok);
563
564 if (!ok) {
565 m_reader->raiseError(message: QString("The latitude portions of \"%1\" are expected to have a value convertable to a double (value was \"%2\")").arg(a: elementName).arg(a: latString));
566 return false;
567 }
568
569 QString lngString = coords[1];
570 double lng = lngString.toDouble(ok: &ok);
571
572 if (!ok) {
573 m_reader->raiseError(message: QString("The longitude portions of \"%1\" are expected to have a value convertable to a double (value was \"%2\")").arg(a: elementName).arg(a: lngString));
574 return false;
575 }
576
577 QGeoCoordinate geoPoint(lat, lng);
578 geoPoints->append(t: geoPoint);
579 }
580
581 return true;
582}
583
584bool QGeoRouteXmlParser::parseBoundingBox(QGeoRectangle &bounds)
585{
586 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "BoundingBox");
587
588 QGeoCoordinate tl;
589 QGeoCoordinate br;
590
591 m_reader->readNext();
592 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "BoundingBox") &&
593 !m_reader->hasError()) {
594 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
595 if (m_reader->name() == "TopLeft") {
596 QGeoCoordinate coordinates;
597 if (parseCoordinates(coord&: coordinates))
598 tl = coordinates;
599 } else if (m_reader->name() == "BottomRight") {
600 QGeoCoordinate coordinates;
601 if (parseCoordinates(coord&: coordinates))
602 br = coordinates;
603 } else {
604 m_reader->skipCurrentElement();
605 }
606 }
607 m_reader->readNext();
608 }
609
610 if (m_reader->hasError())
611 return false;
612
613 if (tl.isValid() && br.isValid()) {
614 bounds = QGeoRectangle(tl, br);
615 return true;
616 }
617
618 return false;
619}
620
621bool QGeoRouteXmlParser::parseDynamicSpeedInfo(QGeoDynamicSpeedInfoContainer &speedInfo)
622{
623 Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("DynamicSpeedInfo"));
624
625 m_reader->readNext();
626 while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == QStringLiteral("DynamicSpeedInfo")) &&
627 !m_reader->hasError()) {
628 if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
629 if (m_reader->name() == QStringLiteral("TrafficSpeed")) {
630 speedInfo.trafficSpeed = m_reader->readElementText().toDouble();
631 } else if (m_reader->name() == QStringLiteral("TrafficTime")) {
632 speedInfo.trafficTime = qRound(d: m_reader->readElementText().toDouble());
633 } else if (m_reader->name() == QStringLiteral("BaseSpeed")) {
634 speedInfo.baseSpeed = m_reader->readElementText().toDouble();
635 } else if (m_reader->name() == QStringLiteral("BaseTime")) {
636 speedInfo.baseTime = qRound(d: m_reader->readElementText().toDouble());
637 } else {
638 m_reader->skipCurrentElement();
639 }
640 }
641 m_reader->readNext();
642 }
643
644 return !m_reader->hasError();
645}
646
647QT_END_NAMESPACE
648

source code of qtlocation/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp