Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qgeocodingmanagerengine_nokia.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 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
6#include "marclanguagecodes.h"
8#include "qgeouriprovider.h"
9#include "uri_constants.h"
10
11#include <QtPositioning/QGeoAddress>
12#include <QtPositioning/QGeoCoordinate>
13#include <QtPositioning/QGeoCircle>
14#include <QtPositioning/QGeoRectangle>
15#include <QtPositioning/QGeoShape>
16
17#include <QUrl>
18#include <QMap>
19#include <QStringList>
20
22
24 QGeoNetworkAccessManager *networkManager,
25 const QVariantMap &parameters,
27 QString *errorString)
28 : QGeoCodingManagerEngine(parameters)
29 , m_networkManager(networkManager)
30 , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.geocoding.host"), GEOCODING_HOST))
31 , m_reverseGeocodingUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.reversegeocoding.host"), REVERSE_GEOCODING_HOST))
32{
33 Q_ASSERT(networkManager);
34 m_networkManager->setParent(this);
35
36 if (parameters.contains(QStringLiteral("here.token")))
37 m_token = parameters.value(QStringLiteral("here.token")).toString();
38
39 if (parameters.contains(QStringLiteral("here.app_id")))
40 m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString();
41
42 if (error)
44
45 if (errorString)
46 *errorString = "";
47}
48
50
51QString QGeoCodingManagerEngineNokia::getAuthenticationString() const
52{
53 QString authenticationString;
54
55 if (!m_token.isEmpty() && !m_applicationId.isEmpty()) {
56 authenticationString += "?app_code=";
57 authenticationString += m_token;
58
59 authenticationString += "&app_id=";
60 authenticationString += m_applicationId;
61 }
62
63 return authenticationString;
64}
65
66
68 const QGeoShape &bounds)
69{
70 QString requestString = "https://";
71 requestString += m_uriProvider->getCurrentHost();
72 requestString += "/6.2/geocode.json";
73
74 requestString += getAuthenticationString();
75 requestString += "&gen=9";
76
77 requestString += "&language=";
78 requestString += languageToMarc(locale().language());
79
80 bool manualBoundsRequired = false;
81 if (bounds.type() == QGeoShape::UnknownType) {
82 manualBoundsRequired = true;
83 } else if (bounds.type() == QGeoShape::CircleType) {
84 QGeoCircle circ(bounds);
85 if (circ.isValid()) {
86 requestString += "?prox=";
87 requestString += trimDouble(circ.center().latitude());
88 requestString += ",";
89 requestString += trimDouble(circ.center().longitude());
90 requestString += ",";
91 requestString += trimDouble(circ.radius());
92 }
93 } else {
95 if (rect.isValid()) {
96 requestString += "&bbox=";
97 requestString += trimDouble(rect.topLeft().latitude());
98 requestString += ",";
99 requestString += trimDouble(rect.topLeft().longitude());
100 requestString += ";";
101 requestString += trimDouble(rect.bottomRight().latitude());
102 requestString += ",";
103 requestString += trimDouble(rect.bottomRight().longitude());
104 }
105 }
106
107 if (address.country().isEmpty()) {
108 QStringList parts;
109
110 if (!address.state().isEmpty())
111 parts << address.state();
112
113 if (!address.city().isEmpty())
114 parts << address.city();
115
116 if (!address.postalCode().isEmpty())
117 parts << address.postalCode();
118
119 if (!address.street().isEmpty())
120 parts << address.street();
121
122 requestString += "&searchtext=";
123 requestString += parts.join("+").replace(' ', '+');
124 } else {
125 requestString += "&country=";
126 requestString += address.country();
127
128 if (!address.state().isEmpty()) {
129 requestString += "&state=";
130 requestString += address.state();
131 }
132
133 if (!address.city().isEmpty()) {
134 requestString += "&city=";
135 requestString += address.city();
136 }
137
138 if (!address.postalCode().isEmpty()) {
139 requestString += "&postalcode=";
140 requestString += address.postalCode();
141 }
142
143 if (!address.street().isEmpty()) {
144 requestString += "&street=";
145 requestString += address.street();
146 }
147 }
148
149 return geocode(requestString, bounds, manualBoundsRequired);
150}
151
153 int limit,
154 int offset,
155 const QGeoShape &bounds)
156{
157 QString requestString = "https://";
158 requestString += m_uriProvider->getCurrentHost();
159 requestString += "/6.2/geocode.json";
160
161 requestString += getAuthenticationString();
162 requestString += "&gen=9";
163
164 requestString += "&language=";
165 requestString += languageToMarc(locale().language());
166
167 requestString += "&searchtext=";
168 requestString += QString(address).replace(' ', '+');
169
170 if (limit > 0) {
171 requestString += "&maxresults=";
172 requestString += QString::number(limit);
173 }
174 if (offset > 0) {
175 // We cannot do this precisely, since HERE doesn't allow
176 // precise result-set offset to be supplied; instead, it
177 // returns "pages" of results at a time.
178 // So, we tell HERE which page of results we want, and the
179 // client has to filter out duplicates if they changed
180 // the limit param since the last call.
181 requestString += "&pageinformation=";
182 requestString += QString::number(offset/limit);
183 }
184
185 bool manualBoundsRequired = false;
186 if (bounds.type() == QGeoShape::RectangleType) {
187 QGeoRectangle rect(bounds);
188 if (rect.isValid()) {
189 requestString += "&bbox=";
190 requestString += trimDouble(rect.topLeft().latitude());
191 requestString += ",";
192 requestString += trimDouble(rect.topLeft().longitude());
193 requestString += ";";
194 requestString += trimDouble(rect.bottomRight().latitude());
195 requestString += ",";
196 requestString += trimDouble(rect.bottomRight().longitude());
197 }
198 } else if (bounds.type() == QGeoShape::CircleType) {
199 QGeoCircle circ(bounds);
200 if (circ.isValid()) {
201 requestString += "?prox=";
202 requestString += trimDouble(circ.center().latitude());
203 requestString += ",";
204 requestString += trimDouble(circ.center().longitude());
205 requestString += ",";
206 requestString += trimDouble(circ.radius());
207 }
208 } else {
209 manualBoundsRequired = true;
210 }
211
212 return geocode(requestString, bounds, manualBoundsRequired, limit, offset);
213}
214
216 const QGeoShape &bounds,
217 bool manualBoundsRequired,
218 int limit,
219 int offset)
220{
222 m_networkManager->get(QNetworkRequest(QUrl(requestString))),
223 limit, offset, bounds, manualBoundsRequired, this);
224
226 this, &QGeoCodingManagerEngineNokia::placesFinished);
227
229 this, &QGeoCodingManagerEngineNokia::placesError);
230
231 return reply;
232}
233
235 const QGeoShape &bounds)
236{
237 QString requestString = "https://";
238 requestString += m_reverseGeocodingUriProvider->getCurrentHost();
239 requestString += "/6.2/reversegeocode.json";
240
241 requestString += getAuthenticationString();
242 requestString += "&gen=9";
243
244 requestString += "&mode=retrieveAddresses";
245
246 requestString += "&prox=";
247 requestString += trimDouble(coordinate.latitude());
248 requestString += ",";
249 requestString += trimDouble(coordinate.longitude());
250
251 bool manualBoundsRequired = false;
252 if (bounds.type() == QGeoShape::CircleType) {
253 QGeoCircle circ(bounds);
254 if (circ.isValid() && circ.center() == coordinate) {
255 requestString += ",";
256 requestString += trimDouble(circ.radius());
257 } else {
258 manualBoundsRequired = true;
259 }
260 } else {
261 manualBoundsRequired = true;
262 }
263
264 requestString += "&language=";
265 requestString += languageToMarc(locale().language());
266
267 return geocode(requestString, bounds, manualBoundsRequired);
268}
269
270QString QGeoCodingManagerEngineNokia::trimDouble(double degree, int decimalDigits)
271{
272 QString sDegree = QString::number(degree, 'g', decimalDigits);
273
274 int index = sDegree.indexOf('.');
275
276 if (index == -1)
277 return sDegree;
278 else
279 return QString::number(degree, 'g', decimalDigits + index);
280}
281
282void QGeoCodingManagerEngineNokia::placesFinished()
283{
284 QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender());
285
286 if (!reply)
287 return;
288
289 if (receivers(SIGNAL(finished(QGeoCodeReply*))) == 0) {
291 return;
292 }
293
295}
296
297void QGeoCodingManagerEngineNokia::placesError(QGeoCodeReply::Error error, const QString &errorString)
298{
299 QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender());
300
301 if (!reply)
302 return;
303
306 return;
307 }
308
309 emit errorOccurred(reply, error, errorString);
310}
311
312QString QGeoCodingManagerEngineNokia::languageToMarc(QLocale::Language language)
313{
314 uint offset = 3 * (uint(language));
315 if (language == QLocale::C || offset + 3 > sizeof(marc_language_code_list))
316 return QLatin1String("eng");
317
318 const unsigned char *c = marc_language_code_list + offset;
319 if (c[0] == 0)
320 return QLatin1String("eng");
321
323 code[0] = ushort(c[0]);
324 code[1] = ushort(c[1]);
325 code[2] = ushort(c[2]);
326
327 return code;
328}
329
\inmodule QtPositioning
Definition qgeoaddress.h:18
\inmodule QtPositioning
Definition qgeocircle.h:15
QGeoCoordinate center
This property holds the center coordinate for the geo circle.
Definition qgeocircle.h:17
qreal radius
This property holds the circle radius in meters.
Definition qgeocircle.h:18
\inmodule QtLocation
void finished()
This signal is emitted when this reply has finished processing.
void errorOccurred(QGeoCodeReply::Error error, const QString &errorString=QString())
This signal is emitted when an error has been detected in the processing of this reply.
Error
Describes an error which prevented the completion of the operation.
QGeoCodeReply * reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) override
Begins the reverse geocoding of coordinate.
QGeoCodingManagerEngineNokia(QGeoNetworkAccessManager *networkManager, const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString)
QGeoCodeReply * geocode(const QGeoAddress &address, const QGeoShape &bounds) override
Begins the geocoding of address.
void errorOccurred(QGeoCodeReply *reply, QGeoCodeReply::Error error, const QString &errorString=QString())
void finished(QGeoCodeReply *reply)
QLocale locale() const
Returns the locale used to hint to this geocoding manager about what language to use for the results.
\inmodule QtPositioning
double longitude
This property holds the longitude in decimal degrees.
double latitude
This property holds the latitude in decimal degrees.
virtual QNetworkReply * get(const QNetworkRequest &request)=0
\inmodule QtPositioning
Error
Describes an error related to the loading and setup of a service provider plugin.
\inmodule QtPositioning
Definition qgeoshape.h:17
bool isValid
This property holds the validity of the geo shape.
Definition qgeoshape.h:20
ShapeType type
This property holds the type of this geo shape.
Definition qgeoshape.h:19
Q_INVOKABLE QGeoRectangle boundingGeoRectangle() const
Returns a QGeoRectangle representing the geographical bounding rectangle of the geo shape,...
@ UnknownType
Definition qgeoshape.h:31
@ RectangleType
Definition qgeoshape.h:32
QString getCurrentHost() const
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
bool contains(const Key &key) const
Definition qmap.h:340
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2521
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
int receivers(const char *signal) const
Returns the number of receivers connected to the signal.
Definition qobject.cpp:2603
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3794
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
\inmodule QtCore
Definition qurl.h:94
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
#define this
Definition dialogs.cpp:9
rect
[4]
static QT_BEGIN_NAMESPACE const unsigned char marc_language_code_list[]
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
DBusConnection const char DBusError * error
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLuint index
[2]
GLenum GLuint GLintptr offset
const GLubyte * c
GLint limit
GLuint GLuint64EXT address
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
unsigned int uint
Definition qtypes.h:29
unsigned short ushort
Definition qtypes.h:28
QNetworkReply * reply
const QString REVERSE_GEOCODING_HOST
const QString GEOCODING_HOST