summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/location/doc/src/plugins/mapbox.qdoc8
-rw-r--r--src/location/maps/qgeorouteparserosrmv5.cpp29
-rw-r--r--src/location/maps/qgeorouteparserosrmv5_p.h4
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp129
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp35
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h4
6 files changed, 68 insertions, 141 deletions
diff --git a/src/location/doc/src/plugins/mapbox.qdoc b/src/location/doc/src/plugins/mapbox.qdoc
index aef0a981..14fe5f80 100644
--- a/src/location/doc/src/plugins/mapbox.qdoc
+++ b/src/location/doc/src/plugins/mapbox.qdoc
@@ -153,5 +153,13 @@ The following table lists optional parameters that can be passed to the Mapbox p
\tt{OneNeighbourLayer} only prefetches the one layer closest to the current zoom level.
Finally, \tt{NoPrefetching} allows to disable the prefetching, so only tiles that are visible will be fetched.
Note that, depending on the active map type, this hint might be ignored.
+\row
+ \li mapbox.routing.use_mapbox_text_instructions
+ \li Whether to use the instruction text that came with the response from the server (true) or the
+ text generated by the plugin. The default value is true.
+ Note that if instructions in a language that is not directly supported by Mapbox are needed (see
+ \l{https://www.mapbox.com/api-documentation/#instructions-languages}{here} for the supported languages),
+ it is possible to use the \l{Qt Linguist} to translate QtLocation to the desired language, and set this parameter to
+ false in order to use the translated built-in instructions.
\endtable
*/
diff --git a/src/location/maps/qgeorouteparserosrmv5.cpp b/src/location/maps/qgeorouteparserosrmv5.cpp
index 75daefda..38eeb243 100644
--- a/src/location/maps/qgeorouteparserosrmv5.cpp
+++ b/src/location/maps/qgeorouteparserosrmv5.cpp
@@ -793,8 +793,10 @@ static QGeoManeuver::InstructionDirection instructionDirection(const QJsonObject
return QGeoManeuver::NoDirection;
}
-static QGeoRouteSegment parseStep(const QJsonObject &step) {
- // OSRM Instructions documentation: https://github.com/Project-OSRM/osrm-text-instructions/blob/master/instructions.json
+static QGeoRouteSegment parseStep(const QJsonObject &step, bool useServerText) {
+ // OSRM Instructions documentation: https://github.com/Project-OSRM/osrm-text-instructions
+ // This goes on top of OSRM: https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md
+ // Mapbox however, includes this in the reply, under "instruction".
QGeoRouteSegment segment;
if (!step.value(QLatin1String("maneuver")).isObject())
return segment;
@@ -808,6 +810,10 @@ static QGeoRouteSegment parseStep(const QJsonObject &step) {
if (!maneuver.value(QLatin1String("location")).isArray())
return segment;
+ QString instruction_text;
+ if (maneuver.value(QLatin1String("instruction")).isString())
+ instruction_text = maneuver.value(QLatin1String("instruction")).toString();
+
double time = step.value(QLatin1String("duration")).toDouble();
double distance = step.value(QLatin1String("distance")).toDouble();
@@ -825,7 +831,7 @@ static QGeoRouteSegment parseStep(const QJsonObject &step) {
geoManeuver.setDirection(instructionDirection(maneuver));
geoManeuver.setDistanceToNextInstruction(distance);
geoManeuver.setTimeToNextInstruction(time);
- geoManeuver.setInstructionText(instructionText(step, maneuver, geoManeuver.direction()));
+ geoManeuver.setInstructionText((useServerText && !instruction_text.isEmpty()) ? instruction_text : instructionText(step, maneuver, geoManeuver.direction()));
geoManeuver.setPosition(coord);
geoManeuver.setWaypoint(coord);
@@ -845,6 +851,9 @@ public:
QGeoRouteReply::Error parseReply(QList<QGeoRoute> &routes, QString &errorString, const QByteArray &reply) const Q_DECL_OVERRIDE;
QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const Q_DECL_OVERRIDE;
+
+ bool m_useServerText = false;
+ QString m_accessToken;
};
QGeoRouteParserOsrmV5Private::QGeoRouteParserOsrmV5Private() : QGeoRouteParserPrivate()
@@ -906,7 +915,7 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList<QGeoRoute>
error = true;
break;
}
- QGeoRouteSegment segment = parseStep(s.toObject());
+ QGeoRouteSegment segment = parseStep(s.toObject(), m_useServerText);
if (segment.isValid()) {
segments.append(segment);
} else {
@@ -963,16 +972,26 @@ QUrl QGeoRouteParserOsrmV5Private::requestUrl(const QGeoRouteRequest &request, c
query.addQueryItem(QStringLiteral("steps"), QStringLiteral("true"));
query.addQueryItem(QStringLiteral("geometries"), QStringLiteral("polyline"));
query.addQueryItem(QStringLiteral("alternatives"), QStringLiteral("true"));
+ if (!m_accessToken.isEmpty())
+ query.addQueryItem(QStringLiteral("access_token"), m_accessToken);
url.setQuery(query);
return url;
}
-QGeoRouteParserOsrmV5::QGeoRouteParserOsrmV5(QObject *parent) : QGeoRouteParser(*new QGeoRouteParserOsrmV5Private(), parent)
+QGeoRouteParserOsrmV5::QGeoRouteParserOsrmV5(QObject *parent, bool useServerText) : QGeoRouteParser(*new QGeoRouteParserOsrmV5Private(), parent)
{
+ Q_D(QGeoRouteParserOsrmV5);
+ d->m_useServerText = useServerText;
}
QGeoRouteParserOsrmV5::~QGeoRouteParserOsrmV5()
{
}
+void QGeoRouteParserOsrmV5::setAccessToken(const QString &token)
+{
+ Q_D(QGeoRouteParserOsrmV5);
+ d->m_accessToken = token;
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeorouteparserosrmv5_p.h b/src/location/maps/qgeorouteparserosrmv5_p.h
index d2c59165..c6ad0367 100644
--- a/src/location/maps/qgeorouteparserosrmv5_p.h
+++ b/src/location/maps/qgeorouteparserosrmv5_p.h
@@ -60,9 +60,11 @@ class Q_LOCATION_PRIVATE_EXPORT QGeoRouteParserOsrmV5 : public QGeoRouteParser
Q_DECLARE_PRIVATE(QGeoRouteParserOsrmV5)
public:
- QGeoRouteParserOsrmV5(QObject *parent = Q_NULLPTR);
+ QGeoRouteParserOsrmV5(QObject *parent = Q_NULLPTR, bool useServerText = false);
virtual ~QGeoRouteParserOsrmV5();
+ void setAccessToken(const QString &token);
+
private:
Q_DISABLE_COPY(QGeoRouteParserOsrmV5)
};
diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
index 8fc3386a..43b18454 100644
--- a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
@@ -39,7 +39,8 @@
****************************************************************************/
#include "qgeoroutereplymapbox.h"
-
+#include "qgeoroutingmanagerenginemapbox.h"
+#include <QtLocation/private/qgeorouteparser_p.h>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
@@ -48,40 +49,6 @@
QT_BEGIN_NAMESPACE
-static QList<QGeoCoordinate> parsePolyline(const QString &line)
-{
- QList<QGeoCoordinate> path;
- QByteArray data(line.toLocal8Bit());
-
- int mode = 0, shift = 0, value = 0, coord[2] = {0, 0};
- for (int i = 0; i < data.length(); ++i) {
- int c = data.at(i) - 63;
- value |= (c & 0x1f) << shift;
- shift += 5;
- if (c & 0x20) continue;
- coord[mode] += (value & 1) ? ~(value >> 1) : (value >> 1);
- if (mode) path.append(QGeoCoordinate((double)coord[0]/1e5, (double)coord[1]/1e5));
- mode = 1 - mode;
- value = shift = 0;
- }
- return path;
-}
-
-static QList<QGeoCoordinate> parseGeometry(const QJsonValue &geometry)
-{
- QList<QGeoCoordinate> path;
- if (geometry.isString()) path = parsePolyline(geometry.toString());
- if (geometry.isObject()) {
- QJsonArray coords = geometry.toObject().value(QStringLiteral("coordinates")).toArray();
- for (int i = 0; i < coords.count(); i++) {
- QJsonArray coord = coords.at(i).toArray();
- if (coord.count() != 2) continue;
- path.append(QGeoCoordinate(coord.at(1).toDouble(), coord.at(0).toDouble()));
- }
- }
- return path;
-}
-
QGeoRouteReplyMapbox::QGeoRouteReplyMapbox(QNetworkReply *reply, const QGeoRouteRequest &request,
QObject *parent)
: QGeoRouteReply(request, parent)
@@ -101,73 +68,6 @@ QGeoRouteReplyMapbox::~QGeoRouteReplyMapbox()
{
}
-static QGeoRoute constructRoute(const QJsonObject &obj)
-{
- QGeoRoute route;
- route.setDistance(obj.value(QStringLiteral("distance")).toDouble());
- route.setTravelTime(obj.value(QStringLiteral("duration")).toDouble());
-
- QList<QGeoCoordinate> path = parseGeometry(obj.value(QStringLiteral("geometry")));
- route.setPath(path);
-
- QGeoRouteSegment firstSegment, lastSegment;
- QJsonArray legs = obj.value(QStringLiteral("legs")).toArray();
-
- for (int i = 0; i < legs.count(); i++) {
- QJsonObject leg = legs.at(i).toObject();
- QJsonArray steps = leg.value("steps").toArray();
-
- for (int j = 0; j < steps.count(); j++) {
- QJsonObject step = steps.at(j).toObject();
- QJsonObject stepManeuver = step.value("maneuver").toObject();
-
- QGeoRouteSegment segment;
- segment.setDistance(step.value("distance").toDouble());
- segment.setTravelTime(step.value(QStringLiteral("duration")).toDouble());
-
- QGeoManeuver maneuver;
- maneuver.setDistanceToNextInstruction(step.value("distance").toDouble());
- maneuver.setInstructionText(stepManeuver.value("instruction").toString());
- maneuver.setTimeToNextInstruction(step.value(QStringLiteral("duration")).toDouble());
- QJsonArray location = stepManeuver.value(QStringLiteral("location")).toArray();
- if (location.count() > 1)
- maneuver.setPosition(QGeoCoordinate(location.at(0).toDouble(), location.at(1).toDouble()));
-
- QString modifier = stepManeuver.value("modifier").toString();
- int bearing1 = stepManeuver.value("bearing_before").toInt();
- int bearing2 = stepManeuver.value("bearing_after").toInt();
-
- if (modifier == "straight")
- maneuver.setDirection(QGeoManeuver::DirectionForward);
- else if (modifier == "slight right")
- maneuver.setDirection(QGeoManeuver::DirectionLightRight);
- else if (modifier == "right")
- maneuver.setDirection(QGeoManeuver::DirectionRight);
- else if (modifier == "sharp right")
- maneuver.setDirection(QGeoManeuver::DirectionHardRight);
- else if (modifier == "uturn")
- maneuver.setDirection(bearing2 - bearing1 > 180 ? QGeoManeuver::DirectionUTurnLeft : QGeoManeuver::DirectionUTurnRight);
- else if (modifier == "sharp left")
- maneuver.setDirection(QGeoManeuver::DirectionHardLeft);
- else if (modifier == "left")
- maneuver.setDirection(QGeoManeuver::DirectionLeft);
- else if (modifier == "slight left")
- maneuver.setDirection(QGeoManeuver::DirectionLightLeft);
- else
- maneuver.setDirection(QGeoManeuver::NoDirection);
-
- segment.setManeuver(maneuver);
- segment.setPath(parseGeometry(step.value(QStringLiteral("geometry"))));
-
- if (!firstSegment.isValid()) firstSegment = segment;
- if (lastSegment.isValid()) lastSegment.setNextRouteSegment(segment);
- lastSegment = segment;
- }
- }
- route.setFirstRouteSegment(firstSegment);
- return route;
-}
-
void QGeoRouteReplyMapbox::networkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
@@ -176,26 +76,19 @@ void QGeoRouteReplyMapbox::networkReplyFinished()
if (reply->error() != QNetworkReply::NoError)
return;
- QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
- if (document.isObject()) {
- QJsonObject object = document.object();
+ QGeoRoutingManagerEngineMapbox *engine = qobject_cast<QGeoRoutingManagerEngineMapbox *>(parent());
+ const QGeoRouteParser *parser = engine->routeParser();
- QString status = object.value(QStringLiteral("code")).toString();
- if (status != QStringLiteral("Ok")) {
- setError(QGeoRouteReply::UnknownError, object.value(QStringLiteral("message")).toString());
- return;
- }
+ QList<QGeoRoute> routes;
+ QString errorString;
+ QGeoRouteReply::Error error = parser->parseReply(routes, errorString, reply->readAll());
- QList<QGeoRoute> list;
- QJsonArray routes = object.value(QStringLiteral("routes")).toArray();
- for (int i = 0; i < routes.count(); i++) {
- QGeoRoute route = constructRoute(routes.at(i).toObject());
- list.append(route);
- }
- setRoutes(list);
+ if (error == QGeoRouteReply::NoError) {
+ setRoutes(routes.mid(0, request().numberAlternativeRoutes() + 1));
+ // setError(QGeoRouteReply::NoError, status); // can't do this, or NoError is emitted and does damages
setFinished(true);
} else {
- setError(QGeoRouteReply::ParseError, QStringLiteral("Couldn't parse json."));
+ setError(error, errorString);
}
}
diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp
index 1b7cc1b3..2697114d 100644
--- a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp
@@ -41,6 +41,7 @@
#include "qgeoroutingmanagerenginemapbox.h"
#include "qgeoroutereplymapbox.h"
#include "qmapboxcommon.h"
+#include "QtLocation/private/qgeorouteparserosrmv5_p.h"
#include <QtCore/QUrlQuery>
#include <QtCore/QDebug>
@@ -62,6 +63,15 @@ QGeoRoutingManagerEngineMapbox::QGeoRoutingManagerEngineMapbox(const QVariantMap
m_accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString();
}
+ bool use_mapbox_text_instructions = true;
+ if (parameters.contains(QStringLiteral("mapbox.routing.use_mapbox_text_instructions"))) {
+ use_mapbox_text_instructions = parameters.value(QStringLiteral("mapbox.use_mapbox_text_instructions")).toBool();
+ }
+
+ QGeoRouteParserOsrmV5 *parser = new QGeoRouteParserOsrmV5(this, use_mapbox_text_instructions);
+ parser->setAccessToken(m_accessToken);
+ m_routeParser = parser;
+
*error = QGeoServiceProvider::NoError;
errorString->clear();
}
@@ -73,7 +83,7 @@ QGeoRoutingManagerEngineMapbox::~QGeoRoutingManagerEngineMapbox()
QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRequest &request)
{
QNetworkRequest networkRequest;
- networkRequest.setRawHeader("User-Agent", m_userAgent);
+ networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
QString url = mapboxDirectionsApiPath;
@@ -94,24 +104,10 @@ QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRe
}
}
- foreach (const QGeoCoordinate &c, request.waypoints()) {
- url += QString("%1,%2;").arg(c.longitude()).arg(c.latitude());
- }
- if (url.right(1) == QLatin1Char(';'))
- url.chop(1);
-
- QUrlQuery query;
- query.addQueryItem(QStringLiteral("steps"), QStringLiteral("true"));
- query.addQueryItem(QStringLiteral("alternatives"), QStringLiteral("true"));
- query.addQueryItem(QStringLiteral("overview"), QStringLiteral("full"));
- query.addQueryItem(QStringLiteral("geometries"), QStringLiteral("geojson"));
- query.addQueryItem(QStringLiteral("access_token"), m_accessToken);
-
- QUrl u(url);
- u.setQuery(query);
- networkRequest.setUrl(u);
+ networkRequest.setUrl(m_routeParser->requestUrl(request, url));
QNetworkReply *reply = m_networkManager->get(networkRequest);
+
QGeoRouteReplyMapbox *routeReply = new QGeoRouteReplyMapbox(reply, request, this);
connect(routeReply, SIGNAL(finished()), this, SLOT(replyFinished()));
@@ -121,6 +117,11 @@ QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRe
return routeReply;
}
+const QGeoRouteParser *QGeoRoutingManagerEngineMapbox::routeParser() const
+{
+ return m_routeParser;
+}
+
void QGeoRoutingManagerEngineMapbox::replyFinished()
{
QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h
index 5b440147..61ab9a4a 100644
--- a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h
+++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
class QNetworkAccessManager;
+class QGeoRouteParser;
class QGeoRoutingManagerEngineMapbox : public QGeoRoutingManagerEngine
{
@@ -59,6 +60,7 @@ public:
~QGeoRoutingManagerEngineMapbox();
QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request);
+ const QGeoRouteParser *routeParser() const;
private Q_SLOTS:
void replyFinished();
@@ -68,6 +70,8 @@ private:
QNetworkAccessManager *m_networkManager;
QByteArray m_userAgent;
QString m_accessToken;
+ bool m_useMapboxText = false;
+ QGeoRouteParser *m_routeParser = nullptr;
};
QT_END_NAMESPACE