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 "qplacedetailsreplyimpl.h"
38#include "jsonparserhelpers.h"
39#include "../qplacemanagerengine_nokiav2.h"
40#include "../qgeoerror_messages.h"
41
42#include <QCoreApplication>
43#include <QtCore/QJsonDocument>
44#include <QtCore/QJsonObject>
45#include <QtCore/QJsonArray>
46#include <QtNetwork/QNetworkReply>
47#include <QtLocation/QPlaceManager>
48#include <QtLocation/QPlaceSupplier>
49#include <QtLocation/QPlaceImage>
50#include <QtLocation/QPlaceEditorial>
51#include <QtLocation/QPlaceReview>
52#include <QtLocation/QPlaceUser>
53
54QT_BEGIN_NAMESPACE
55
56// These countries format the street address as: {house number} {street name}
57// All other countries format it as: {street name} {house number}
58static const char COUNTRY_TABLE_string[] =
59 "CAN\0"
60 "NZL\0"
61 "GBR\0"
62 "AUS\0"
63 "LKA\0"
64 "USA\0"
65 "SGP\0"
66 "FRA\0"
67 "BHS\0"
68 "CHN\0"
69 "IND\0"
70 "IRL\0"
71 "ARE\0"
72 "\0";
73
74static const int COUNTRY_TABLE_indices[] = {
75 0, 4, 8, 12, 16, 20, 24, 28,
76 32, 36, 40, 44, 48, -1
77};
78
79static bool countryTableContains(const QString &countryCode)
80{
81 for (int i = 0; COUNTRY_TABLE_indices[i] != -1; ++i) {
82 if (countryCode == QLatin1String(COUNTRY_TABLE_string + COUNTRY_TABLE_indices[i]))
83 return true;
84 }
85
86 return false;
87}
88
89QPlaceDetailsReplyImpl::QPlaceDetailsReplyImpl(QNetworkReply *reply,
90 QPlaceManagerEngineNokiaV2 *parent)
91: QPlaceDetailsReply(parent), m_engine(parent)
92{
93 if (!reply) {
94 setError(error_: UnknownError, QStringLiteral("Null reply"));
95 return;
96 }
97 connect(sender: reply, SIGNAL(finished()), receiver: this, SLOT(replyFinished()));
98 connect(sender: reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),
99 receiver: this, SLOT(replyError(QNetworkReply::NetworkError)));
100 connect(sender: this, signal: &QPlaceReply::aborted, receiver: reply, slot: &QNetworkReply::abort);
101 connect(sender: this, signal: &QObject::destroyed, receiver: reply, slot: &QObject::deleteLater);
102}
103
104QPlaceDetailsReplyImpl::~QPlaceDetailsReplyImpl()
105{
106}
107
108void QPlaceDetailsReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString)
109{
110 QPlaceReply::setError(error: error_, errorString);
111 emit error(error: error_, errorString);
112 setFinished(true);
113 emit finished();
114}
115
116void QPlaceDetailsReplyImpl::replyFinished()
117{
118 QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
119 reply->deleteLater();
120
121 if (reply->error() != QNetworkReply::NoError)
122 return;
123
124 QJsonDocument document = QJsonDocument::fromJson(json: reply->readAll());
125 if (!document.isObject()) {
126 setError(error_: ParseError, errorString: QCoreApplication::translate(context: NOKIA_PLUGIN_CONTEXT_NAME, key: PARSE_ERROR));
127 return;
128 }
129
130 QJsonObject object = document.object();
131
132 QPlace place;
133
134 place.setPlaceId(object.value(key: QLatin1String("placeId")).toString());
135
136 //const QUrl view = object.value(QLatin1String("view")).toString();
137
138 place.setName(object.value(key: QLatin1String("name")).toString());
139
140 //if (object.contains(QLatin1String("distance")))
141 // double distance = object.value(QLatin1String("distance")).toDouble();
142
143 //if (object.contains(QLatin1String("alternativeNames"))) {
144 // QJsonArray alternativeNames = object.value(QLatin1String("alternativeNames")).toArray();
145 //}
146
147 QGeoLocation location;
148
149 QJsonObject locationObject = object.value(key: QLatin1String("location")).toObject();
150
151 //if (locationObject.contains(QLatin1String("locationId")))
152 // const QString locationId = locationObject.value(QLatin1String("locationId")).toString();
153
154 QJsonArray position = locationObject.value(key: QLatin1String("position")).toArray();
155 location.setCoordinate(QGeoCoordinate(position.at(i: 0).toDouble(), position.at(i: 1).toDouble()));
156
157 QGeoAddress address;
158
159 QJsonObject addressObject = locationObject.value(key: QLatin1String("address")).toObject();
160
161 address.setText(addressObject.value(key: QLatin1String("text")).toString());
162
163 address.setCountry(addressObject.value(key: QLatin1String("country")).toString());
164 address.setCountryCode(addressObject.value(key: QLatin1String("countryCode")).toString());
165
166 QString house;
167 QString street;
168
169 if (addressObject.contains(key: QLatin1String("house")))
170 house = addressObject.value(key: QLatin1String("house")).toString();
171 if (addressObject.contains(key: QLatin1String("street")))
172 street = addressObject.value(key: QLatin1String("street")).toString();
173
174 if (countryTableContains(countryCode: address.countryCode())) {
175 if (!house.isEmpty() && !street.startsWith(s: house))
176 street = house + QLatin1Char(' ') + street;
177 } else {
178 if (!house.isEmpty() && !street.endsWith(s: house))
179 street += QLatin1Char(' ') + house;
180 }
181
182 address.setStreet(street);
183
184 if (addressObject.contains(key: QLatin1String("city")))
185 address.setCity(addressObject.value(key: QLatin1String("city")).toString());
186 if (addressObject.contains(key: QLatin1String("district")))
187 address.setDistrict(addressObject.value(key: QLatin1String("district")).toString());
188 if (addressObject.contains(key: QLatin1String("state")))
189 address.setState(addressObject.value(key: QLatin1String("state")).toString());
190 if (addressObject.contains(key: QLatin1String("county")))
191 address.setCounty(addressObject.value(key: QLatin1String("county")).toString());
192 if (addressObject.contains(key: QLatin1String("postalCode")))
193 address.setPostalCode(addressObject.value(key: QLatin1String("postalCode")).toString());
194
195 location.setAddress(address);
196
197 if (locationObject.contains(key: QLatin1String("bbox"))) {
198 QJsonArray bbox = locationObject.value(key: QLatin1String("bbox")).toArray();
199 QGeoRectangle box(QGeoCoordinate(bbox.at(i: 3).toDouble(), bbox.at(i: 0).toDouble()),
200 QGeoCoordinate(bbox.at(i: 1).toDouble(), bbox.at(i: 2).toDouble()));
201 location.setBoundingBox(box);
202 }
203
204 place.setLocation(location);
205
206 place.setCategories(parseCategories(categoryArray: object.value(key: QLatin1String("categories")).toArray(),
207 engine: m_engine));
208
209 place.setIcon(m_engine->icon(remotePath: object.value(key: QLatin1String("icon")).toString(),
210 categories: place.categories()));
211
212 if (object.contains(key: QLatin1String("contacts"))) {
213 QJsonObject contactsObject = object.value(key: QLatin1String("contacts")).toObject();
214
215 if (contactsObject.contains(key: QLatin1String("phone"))) {
216 place.setContactDetails(contactType: QPlaceContactDetail::Phone,
217 details: parseContactDetails(contacts: contactsObject.value(key: QLatin1String("phone")).toArray()));
218 }
219 if (contactsObject.contains(key: QLatin1String("fax"))) {
220 place.setContactDetails(contactType: QPlaceContactDetail::Fax,
221 details: parseContactDetails(contacts: contactsObject.value(key: QLatin1String("fax")).toArray()));
222 }
223 if (contactsObject.contains(key: QLatin1String("website"))) {
224 place.setContactDetails(contactType: QPlaceContactDetail::Website,
225 details: parseContactDetails(contacts: contactsObject.value(key: QLatin1String("website")).toArray()));
226 }
227 if (contactsObject.contains(key: QLatin1String("email"))) {
228 place.setContactDetails(contactType: QPlaceContactDetail::Email,
229 details: parseContactDetails(contacts: contactsObject.value(key: QLatin1String("email")).toArray()));
230 }
231 }
232
233 //if (object.contains(QLatin1String("verifiedByOwner")))
234 // bool verifiedByOwner = object.value(QLatin1String("verifiedByOwner")).toBool();
235
236 if (object.contains(key: QLatin1String("attribution")))
237 place.setAttribution(object.value(key: QLatin1String("attribution")).toString());
238
239 if (object.contains(key: QLatin1String("supplier"))) {
240 place.setSupplier(parseSupplier(supplierObject: object.value(key: QLatin1String("supplier")).toObject(),
241 engine: m_engine));
242 }
243
244 if (object.contains(key: QLatin1String("ratings"))) {
245 QJsonObject ratingsObject = object.value(key: QLatin1String("ratings")).toObject();
246
247 QPlaceRatings ratings;
248 ratings.setAverage(ratingsObject.value(key: QLatin1String("average")).toDouble());
249 ratings.setCount(ratingsObject.value(key: QLatin1String("count")).toDouble());
250 ratings.setMaximum(5.0);
251
252 place.setRatings(ratings);
253 }
254
255 if (object.contains(key: QLatin1String("extended"))) {
256 QJsonObject extendedObject = object.value(key: QLatin1String("extended")).toObject();
257
258 for (auto it = extendedObject.constBegin(), end = extendedObject.constEnd(); it != end; ++it) {
259 QJsonObject attributeObject = it.value().toObject();
260
261 QPlaceAttribute attribute;
262
263 attribute.setLabel(attributeObject.value(key: QLatin1String("label")).toString());
264 attribute.setText(attributeObject.value(key: QLatin1String("text")).toString());
265
266 QString key = it.key();
267 if (key == QLatin1String("payment"))
268 place.setExtendedAttribute(attributeType: QPlaceAttribute::Payment, attribute);
269 else if (key == QLatin1String("openingHours"))
270 place.setExtendedAttribute(attributeType: QPlaceAttribute::OpeningHours, attribute);
271 else
272 place.setExtendedAttribute(attributeType: key, attribute);
273 }
274 }
275
276 if (object.contains(key: QLatin1String("media"))) {
277 QJsonObject mediaObject = object.value(key: QLatin1String("media")).toObject();
278
279 if (mediaObject.contains(key: QLatin1String("images"))) {
280 QPlaceContent::Collection collection;
281 int totalCount = 0;
282
283 parseCollection(type: QPlaceContent::ImageType,
284 object: mediaObject.value(key: QLatin1String("images")).toObject(),
285 collection: &collection, totalCount: &totalCount, previous: 0, next: 0, engine: m_engine);
286
287 place.setTotalContentCount(type: QPlaceContent::ImageType, total: totalCount);
288 place.setContent(type: QPlaceContent::ImageType, content: collection);
289 }
290 if (mediaObject.contains(key: QLatin1String("editorials"))) {
291 QPlaceContent::Collection collection;
292 int totalCount = 0;
293
294 parseCollection(type: QPlaceContent::EditorialType,
295 object: mediaObject.value(key: QLatin1String("editorials")).toObject(),
296 collection: &collection, totalCount: &totalCount, previous: 0, next: 0, engine: m_engine);
297
298 place.setTotalContentCount(type: QPlaceContent::EditorialType, total: totalCount);
299 place.setContent(type: QPlaceContent::EditorialType, content: collection);
300 }
301 if (mediaObject.contains(key: QLatin1String("reviews"))) {
302 QPlaceContent::Collection collection;
303 int totalCount = 0;
304
305 parseCollection(type: QPlaceContent::ReviewType,
306 object: mediaObject.value(key: QLatin1String("reviews")).toObject(),
307 collection: &collection, totalCount: &totalCount, previous: 0, next: 0, engine: m_engine);
308
309 place.setTotalContentCount(type: QPlaceContent::ReviewType, total: totalCount);
310 place.setContent(type: QPlaceContent::ReviewType, content: collection);
311 }
312 }
313
314 //if (object.contains(QLatin1String("related"))) {
315 // QJsonObject relatedObject = object.value(QLatin1String("related")).toObject();
316 //}
317
318 QPlaceAttribute provider;
319 provider.setText(QLatin1String("here"));
320 place.setExtendedAttribute(attributeType: QPlaceAttribute::Provider, attribute: provider);
321
322 place.setVisibility(QLocation::PublicVisibility);
323 place.setDetailsFetched(true);
324 setPlace(place);
325
326 setFinished(true);
327 emit finished();
328}
329
330void QPlaceDetailsReplyImpl::replyError(QNetworkReply::NetworkError error)
331{
332 QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
333 reply->deleteLater();
334 if (error == QNetworkReply::OperationCanceledError) {
335 setError(error_: QPlaceReply::CancelError, QStringLiteral("Request cancelled"));
336 } else if (error == QNetworkReply::ContentNotFoundError) {
337 setError(error_: QPlaceReply::PlaceDoesNotExistError,
338 errorString: QString::fromLatin1(str: "The id, %1, does not reference an existing place")
339 .arg(a: m_placeId));
340 } else {
341 setError(error_: QPlaceReply::CommunicationError, errorString: reply->errorString());
342 }
343}
344
345QT_END_NAMESPACE
346

source code of qtlocation/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp