Source code
Revision control
Copy as Markdown
// Copyright (C) 2015 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplacedetailsreplyimpl.h"
#include "jsonparserhelpers.h"
#include "../qplacemanagerengine_nokiav2.h"
#include "../qgeoerror_messages.h"
#include <QCoreApplication>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <QtNetwork/QNetworkReply>
#include <QtPositioning/QGeoAddress>
#include <QtPositioning/QGeoCoordinate>
#include <QtPositioning/QGeoLocation>
#include <QtPositioning/QGeoRectangle>
#include <QtLocation/QPlace>
#include <QtLocation/QPlaceAttribute>
#include <QtLocation/QPlaceContactDetail>
#include <QtLocation/QPlaceManager>
#include <QtLocation/QPlaceSupplier>
#include <QtLocation/QPlaceIcon>
#include <QtLocation/QPlaceRatings>
#include <QtLocation/QPlaceUser>
QT_BEGIN_NAMESPACE
// These countries format the street address as: {house number} {street name}
// All other countries format it as: {street name} {house number}
static const char COUNTRY_TABLE_string[] =
"CAN\0"
"NZL\0"
"GBR\0"
"AUS\0"
"LKA\0"
"USA\0"
"SGP\0"
"FRA\0"
"BHS\0"
"CHN\0"
"IND\0"
"IRL\0"
"ARE\0"
"\0";
static const int COUNTRY_TABLE_indices[] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, -1
};
static bool countryTableContains(const QString &countryCode)
{
for (int i = 0; COUNTRY_TABLE_indices[i] != -1; ++i) {
if (countryCode == QLatin1String(COUNTRY_TABLE_string + COUNTRY_TABLE_indices[i]))
return true;
}
return false;
}
QPlaceDetailsReplyImpl::QPlaceDetailsReplyImpl(QNetworkReply *reply,
QPlaceManagerEngineNokiaV2 *parent)
: QPlaceDetailsReply(parent), m_engine(parent)
{
if (!reply) {
setError(UnknownError, QStringLiteral("Null reply"));
return;
}
connect(reply, &QNetworkReply::finished,
this, &QPlaceDetailsReplyImpl::replyFinished);
connect(reply, &QNetworkReply::errorOccurred,
this, &QPlaceDetailsReplyImpl::replyError);
connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort);
connect(this, &QObject::destroyed, reply, &QObject::deleteLater);
}
QPlaceDetailsReplyImpl::~QPlaceDetailsReplyImpl()
{
}
void QPlaceDetailsReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString)
{
QPlaceReply::setError(error_, errorString);
emit errorOccurred(error_, errorString);
setFinished(true);
emit finished();
}
void QPlaceDetailsReplyImpl::replyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError)
return;
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
if (!document.isObject()) {
setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR));
return;
}
QJsonObject object = document.object();
QPlace place;
place.setPlaceId(object.value(QLatin1String("placeId")).toString());
//const QUrl view = object.value(QLatin1String("view")).toString();
place.setName(object.value(QLatin1String("name")).toString());
//if (object.contains(QLatin1String("distance")))
// double distance = object.value(QLatin1String("distance")).toDouble();
//if (object.contains(QLatin1String("alternativeNames"))) {
// QJsonArray alternativeNames = object.value(QLatin1String("alternativeNames")).toArray();
//}
QGeoLocation location;
QJsonObject locationObject = object.value(QLatin1String("location")).toObject();
//if (locationObject.contains(QLatin1String("locationId")))
// const QString locationId = locationObject.value(QLatin1String("locationId")).toString();
QJsonArray position = locationObject.value(QLatin1String("position")).toArray();
location.setCoordinate(QGeoCoordinate(position.at(0).toDouble(), position.at(1).toDouble()));
QGeoAddress address;
QJsonObject addressObject = locationObject.value(QLatin1String("address")).toObject();
address.setText(addressObject.value(QLatin1String("text")).toString());
address.setCountry(addressObject.value(QLatin1String("country")).toString());
address.setCountryCode(addressObject.value(QLatin1String("countryCode")).toString());
QString house;
QString street;
if (addressObject.contains(QLatin1String("house")))
house = addressObject.value(QLatin1String("house")).toString();
if (addressObject.contains(QLatin1String("street")))
street = addressObject.value(QLatin1String("street")).toString();
if (countryTableContains(address.countryCode())) {
if (!house.isEmpty() && !street.startsWith(house))
street = house + QLatin1Char(' ') + street;
} else {
if (!house.isEmpty() && !street.endsWith(house))
street += QLatin1Char(' ') + house;
}
address.setStreet(street);
if (addressObject.contains(QLatin1String("city")))
address.setCity(addressObject.value(QLatin1String("city")).toString());
if (addressObject.contains(QLatin1String("district")))
address.setDistrict(addressObject.value(QLatin1String("district")).toString());
if (addressObject.contains(QLatin1String("state")))
address.setState(addressObject.value(QLatin1String("state")).toString());
if (addressObject.contains(QLatin1String("county")))
address.setCounty(addressObject.value(QLatin1String("county")).toString());
if (addressObject.contains(QLatin1String("postalCode")))
address.setPostalCode(addressObject.value(QLatin1String("postalCode")).toString());
location.setAddress(address);
if (locationObject.contains(QLatin1String("bbox"))) {
QJsonArray bbox = locationObject.value(QLatin1String("bbox")).toArray();
QGeoRectangle box(QGeoCoordinate(bbox.at(3).toDouble(), bbox.at(0).toDouble()),
QGeoCoordinate(bbox.at(1).toDouble(), bbox.at(2).toDouble()));
location.setBoundingShape(box);
}
place.setLocation(location);
place.setCategories(parseCategories(object.value(QLatin1String("categories")).toArray(),
m_engine));
place.setIcon(m_engine->icon(object.value(QLatin1String("icon")).toString(),
place.categories()));
if (object.contains(QLatin1String("contacts"))) {
QJsonObject contactsObject = object.value(QLatin1String("contacts")).toObject();
if (contactsObject.contains(QLatin1String("phone"))) {
place.setContactDetails(QPlaceContactDetail::Phone,
parseContactDetails(contactsObject.value(QLatin1String("phone")).toArray()));
}
if (contactsObject.contains(QLatin1String("fax"))) {
place.setContactDetails(QPlaceContactDetail::Fax,
parseContactDetails(contactsObject.value(QLatin1String("fax")).toArray()));
}
if (contactsObject.contains(QLatin1String("website"))) {
place.setContactDetails(QPlaceContactDetail::Website,
parseContactDetails(contactsObject.value(QLatin1String("website")).toArray()));
}
if (contactsObject.contains(QLatin1String("email"))) {
place.setContactDetails(QPlaceContactDetail::Email,
parseContactDetails(contactsObject.value(QLatin1String("email")).toArray()));
}
}
//if (object.contains(QLatin1String("verifiedByOwner")))
// bool verifiedByOwner = object.value(QLatin1String("verifiedByOwner")).toBool();
if (object.contains(QLatin1String("attribution")))
place.setAttribution(object.value(QLatin1String("attribution")).toString());
if (object.contains(QLatin1String("supplier"))) {
place.setSupplier(parseSupplier(object.value(QLatin1String("supplier")).toObject(),
m_engine));
}
if (object.contains(QLatin1String("ratings"))) {
QJsonObject ratingsObject = object.value(QLatin1String("ratings")).toObject();
QPlaceRatings ratings;
ratings.setAverage(ratingsObject.value(QLatin1String("average")).toDouble());
ratings.setCount(ratingsObject.value(QLatin1String("count")).toDouble());
ratings.setMaximum(5.0);
place.setRatings(ratings);
}
if (object.contains(QLatin1String("extended"))) {
QJsonObject extendedObject = object.value(QLatin1String("extended")).toObject();
for (auto it = extendedObject.constBegin(), end = extendedObject.constEnd(); it != end; ++it) {
QJsonObject attributeObject = it.value().toObject();
QPlaceAttribute attribute;
attribute.setLabel(attributeObject.value(QLatin1String("label")).toString());
attribute.setText(attributeObject.value(QLatin1String("text")).toString());
QString key = it.key();
if (key == QLatin1String("payment"))
place.setExtendedAttribute(QPlaceAttribute::Payment, attribute);
else if (key == QLatin1String("openingHours"))
place.setExtendedAttribute(QPlaceAttribute::OpeningHours, attribute);
else
place.setExtendedAttribute(key, attribute);
}
}
if (object.contains(QLatin1String("media"))) {
QJsonObject mediaObject = object.value(QLatin1String("media")).toObject();
if (mediaObject.contains(QLatin1String("images"))) {
QPlaceContent::Collection collection;
int totalCount = 0;
parseCollection(QPlaceContent::ImageType,
mediaObject.value(QLatin1String("images")).toObject(),
&collection, &totalCount, 0, 0, m_engine);
place.setTotalContentCount(QPlaceContent::ImageType, totalCount);
place.setContent(QPlaceContent::ImageType, collection);
}
if (mediaObject.contains(QLatin1String("editorials"))) {
QPlaceContent::Collection collection;
int totalCount = 0;
parseCollection(QPlaceContent::EditorialType,
mediaObject.value(QLatin1String("editorials")).toObject(),
&collection, &totalCount, 0, 0, m_engine);
place.setTotalContentCount(QPlaceContent::EditorialType, totalCount);
place.setContent(QPlaceContent::EditorialType, collection);
}
if (mediaObject.contains(QLatin1String("reviews"))) {
QPlaceContent::Collection collection;
int totalCount = 0;
parseCollection(QPlaceContent::ReviewType,
mediaObject.value(QLatin1String("reviews")).toObject(),
&collection, &totalCount, 0, 0, m_engine);
place.setTotalContentCount(QPlaceContent::ReviewType, totalCount);
place.setContent(QPlaceContent::ReviewType, collection);
}
}
//if (object.contains(QLatin1String("related"))) {
// QJsonObject relatedObject = object.value(QLatin1String("related")).toObject();
//}
QPlaceAttribute provider;
provider.setText(QLatin1String("here"));
place.setExtendedAttribute(QPlaceAttribute::Provider, provider);
place.setVisibility(QLocation::PublicVisibility);
place.setDetailsFetched(true);
setPlace(place);
setFinished(true);
emit finished();
}
void QPlaceDetailsReplyImpl::replyError(QNetworkReply::NetworkError error)
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
reply->deleteLater();
if (error == QNetworkReply::OperationCanceledError) {
setError(QPlaceReply::CancelError, QStringLiteral("Request cancelled"));
} else if (error == QNetworkReply::ContentNotFoundError) {
setError(QPlaceReply::PlaceDoesNotExistError,
QString::fromLatin1("The id, %1, does not reference an existing place")
.arg(m_placeId));
} else {
setError(QPlaceReply::CommunicationError, reply->errorString());
}
}
QT_END_NAMESPACE