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
qgeoroutingmanagerengineohosmapkit.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/private/qohoslogger_p.h>
5#include <QtCore/qjsonarray.h>
6#include <QtCore/qjsondocument.h>
7#include <QtCore/qjsonobject.h>
8#include <QtCore/qurl.h>
9#include <QtLocation/QGeoRouteReply>
10#include <QtLocation/QGeoRouteRequest>
11#include <QtNetwork/qnetworkaccessmanager.h>
12#include <QtNetwork/qnetworkreply.h>
13#include <QtNetwork/qnetworkrequest.h>
14#include <QtPositioning/qgeocoordinate.h>
15#include <bitset>
16#include <qgeoroutereplyohosmapkit.h>
17#include <qgeoroutingmanagerengineohosmapkit.h>
18#include <qohosmapkitcommon.h>
19
21
22namespace {
23
24const QString routingApiBasePath = QLatin1String("https://mapapi.cloud.huawei.com/mapApi/v1/routeService/");
26 {{{QGeoRouteRequest::PedestrianTravel}, QUrl(routingApiBasePath + QLatin1String("walking"))},
27 {{QGeoRouteRequest::BicycleTravel}, QUrl(routingApiBasePath + QLatin1String("bicycling"))},
28 {{QGeoRouteRequest::CarTravel}, QUrl(routingApiBasePath + QLatin1String("driving"))},
29};
30
43
44bool isSingleTravelMode(QGeoRouteRequest::TravelModes modes)
45{
46 auto modesBits = std::bitset<sizeof(unsigned)>(static_cast<unsigned>(modes));
47 return modesBits.count() == 1;
48}
49
50QJsonArray createRestApiAvoidArray(const QGeoRouteRequest &request)
51{
52 QJsonArray restApiAvoidArray;
53
54 auto features = request.featureTypes();
55 auto travelModes = request.travelModes();
56
57 for (auto feature : features) {
58 if (travelModes != QGeoRouteRequest::CarTravel && feature != QGeoRouteRequest::FerryFeature)
59 continue;
60
61 auto featureWeight = request.featureWeight(feature);
62
63 switch (feature) {
64 case QGeoRouteRequest::TollFeature:
65 if (featureWeight == QGeoRouteRequest::AvoidFeatureWeight
66 || featureWeight == QGeoRouteRequest::DisallowFeatureWeight)
67 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::AvoidToolRoads));
68 break;
69 case QGeoRouteRequest::HighwayFeature:
70 if (featureWeight == QGeoRouteRequest::AvoidFeatureWeight
71 || featureWeight == QGeoRouteRequest::DisallowFeatureWeight) {
72 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::AvoidHighways));
73 } else if (featureWeight == QGeoRouteRequest::PreferFeatureWeight
74 || featureWeight == QGeoRouteRequest::RequireFeatureWeight) {
75 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::PrioritizeHighways));
76 }
77 break;
78 case QGeoRouteRequest::FerryFeature:
79 if (featureWeight == QGeoRouteRequest::AvoidFeatureWeight
80 || featureWeight == QGeoRouteRequest::DisallowFeatureWeight)
81 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::AvoidFerries));
82 break;
83 default:
84 break;
85 }
86 }
87
88 if (travelModes == QGeoRouteRequest::CarTravel) {
89 auto routeOptimizations = request.routeOptimization();
90 if (routeOptimizations.testFlag(QGeoRouteRequest::ShortestRoute))
91 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::ShortDistance));
92 else if (routeOptimizations.testFlag(QGeoRouteRequest::FastestRoute))
93 restApiAvoidArray.push_back(static_cast<int>(RestApiRoutingPolicy::Fast));
94 }
95
96 return restApiAvoidArray;
97}
98
99QJsonArray createWaypointsJsonArray(const QList<QGeoCoordinate> &waypoints)
100{
101 QJsonArray waypointsArray;
102
103 constexpr int minNumOfWaypointsToCreateRouteMidpoints = 3;
104 if (waypoints.size() < minNumOfWaypointsToCreateRouteMidpoints)
105 return waypointsArray;
106 constexpr int secondElementIndex = 1;
107 const int penultimateElementIndex = waypoints.size() - 2;
108 for (const auto &waypoint: waypoints.mid(secondElementIndex, penultimateElementIndex))
109 waypointsArray.push_back(OhosMapKit::CoordinateJson::tryConvertFromQGeoCoordinate(waypoint));
110
111 return waypointsArray;
112}
113
114QByteArray createRouteRequestBody(const QGeoRouteRequest &request)
115{
116 constexpr int minNumOfWaypoints = 2;
117 constexpr int restApiWaypointsLimitation = 25;
118 auto waypoints = request.waypoints();
119 if (waypoints.size() < minNumOfWaypoints || waypoints.size() > restApiWaypointsLimitation) {
120 qOhosPrintfWarning(
121 "%s: Invalid number of waypoints: %d. Cannot create route request.",
122 Q_FUNC_INFO, int(waypoints.size()));
123 return {};
124 }
125
126 QJsonObject routeRequestBody;
127
128 routeRequestBody.insert(
129 QStringLiteral("origin"),
130 OhosMapKit::CoordinateJson::tryConvertFromQGeoCoordinate(waypoints.first()));
131 routeRequestBody.insert(
132 QStringLiteral("destination"),
133 OhosMapKit::CoordinateJson::tryConvertFromQGeoCoordinate(waypoints.last()));
134
135 auto restApiAvoidArray = createRestApiAvoidArray(request);
136 if (!restApiAvoidArray.isEmpty())
137 routeRequestBody.insert(QStringLiteral("avoid"), restApiAvoidArray);
138
139 if (request.travelModes() == QGeoRouteRequest::CarTravel) {
140 auto waypointsArray = createWaypointsJsonArray(waypoints);
141 if (!waypointsArray.empty())
142 routeRequestBody.insert(QStringLiteral("waypoints"), waypointsArray);
143 }
144
145 return QJsonDocument(routeRequestBody).toJson(QJsonDocument::Compact);
146}
147
149{
150public:
152 const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString);
153
154 QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request) override;
155
156private:
157 void onReplyFinished();
158 void onReplyError(QGeoRouteReply::Error errorCode, const QString &errorString);
159
160 QNetworkAccessManager m_networkManager;
161 QString m_userAgent;
162 QString m_authenticationKey;
163};
164
166 const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)
170{
171 if (error != nullptr)
172 *error = QGeoServiceProvider::NoError;
173
174 if (errorString != nullptr)
175 errorString->clear();
176}
177
179{
180 auto travelModes = request.travelModes();
181
182 if (!isSingleTravelMode(travelModes)) {
183 return new QGeoRouteReply(
184 QGeoRouteReply::UnsupportedOptionError,
185 tr("Selection of multiple travel modes is not supported by OHOS Map Kit plugin"));
186 }
187
188 if (!routingApiUrl.contains(travelModes)) {
189 return new QGeoRouteReply(
190 QGeoRouteReply::UnsupportedOptionError,
191 tr("Selected travel mode: %1 is not supported by OHOS Map Kit plugin")
192 .arg(travelModes.toInt()));
193 }
194
195 auto *reply = makeQGeoRouteReplyOhosMapKit(
196 m_networkManager.post(
197 OhosMapKit::createOhosMapKitNetworkRequestWithJsonBody(
198 routingApiUrl.value(travelModes), m_userAgent, m_authenticationKey),
199 createRouteRequestBody(request)),
200 request, this);
201
202 connect(
203 reply, &QGeoRouteReply::finished,
204 this, &QGeoRoutingManagerEngineOhosMapKit::onReplyFinished);
205 connect(
206 reply, &QGeoRouteReply::errorOccurred,
207 this, &QGeoRoutingManagerEngineOhosMapKit::onReplyError);
208
209 return reply;
210}
211
212void QGeoRoutingManagerEngineOhosMapKit::onReplyFinished()
213{
214 auto *reply = qobject_cast<QGeoRouteReply *>(sender());
215 if (reply != nullptr)
216 Q_EMIT finished(reply);
217}
218
219void QGeoRoutingManagerEngineOhosMapKit::onReplyError(
220 QGeoRouteReply::Error errorCode, const QString &errorString)
221{
222 auto *reply = qobject_cast<QGeoRouteReply *>(sender());
223 if (reply != nullptr)
224 Q_EMIT errorOccurred(reply, errorCode, errorString);
225}
226
227}
228
230 const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)
231{
232 return new QGeoRoutingManagerEngineOhosMapKit(parameters, error, errorString);
233}
234
235QT_END_NAMESPACE
QGeoRoutingManagerEngineOhosMapKit(const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)
QGeoRouteReply * calculateRoute(const QGeoRouteRequest &request) override
Begins the calculation of the route specified by request.
Combined button and popup list for selecting options.
QJsonArray createRestApiAvoidArray(const QGeoRouteRequest &request)
QJsonArray createWaypointsJsonArray(const QList< QGeoCoordinate > &waypoints)
const QHash< QGeoRouteRequest::TravelModes, QUrl > routingApiUrl
QByteArray createRouteRequestBody(const QGeoRouteRequest &request)
bool isSingleTravelMode(QGeoRouteRequest::TravelModes modes)
QGeoRoutingManagerEngine * makeQGeoRoutingManagerEngineOhosMapKit(const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)