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
qplacesearchreplyohosmapkit.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/qjsonarray.h>
5#include <QtCore/qjsondocument.h>
6#include <QtCore/qjsonobject.h>
7#include <QtCore/qmetaobject.h>
8#include <QtLocation/qplace.h>
9#include <QtLocation/qplaceattribute.h>
10#include <QtLocation/qplacecategory.h>
11#include <QtLocation/qplacecontactdetail.h>
12#include <QtLocation/qplaceicon.h>
13#include <QtLocation/qplaceratings.h>
14#include <QtLocation/qplaceresult.h>
15#include <QtLocation/qplacesearchrequest.h>
16#include <QtLocation/qplacesearchresult.h>
17#include <QtPositioning/qgeoaddress.h>
18#include <QtPositioning/qgeolocation.h>
19#include <qohosmapkitcommon.h>
20#include <qplacesearchreplyohosmapkit.h>
21#include <qplacemanagerengineohosmapkit.h>
22
24
25namespace {
26
28{
29public:
31 const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngine *parent);
32
33private:
34 void onReplyFinished();
35 void onNetworkError(QNetworkReply::NetworkError error);
36};
37
38void populatePlaceExtendedAttributes(const QJsonObject &poiJsonObj, QPlace &place)
39{
40 const QJsonValue openingHours = poiJsonObj.value(QStringLiteral("openingHours"));
41 if (!openingHours.isUndefined() && !openingHours.isNull()) {
42 QPlaceAttribute attr;
43 attr.setLabel(QPlaceSearchReplyOhosMapKit::tr("Opening hours"));
44 attr.setText(openingHours.toVariant().toString());
45 place.setExtendedAttribute(QStringLiteral("openingHours"), attr);
46 }
47
48 const QJsonArray photos = poiJsonObj.value(QStringLiteral("photoUrls")).toArray();
49 if (!photos.isEmpty()) {
50 QPlaceAttribute attr;
51 attr.setLabel(QPlaceSearchReplyOhosMapKit::tr("Photo URLs"));
52 attr.setText(QString::fromUtf8(QJsonDocument(photos).toJson(QJsonDocument::Compact)));
53 place.setExtendedAttribute(QStringLiteral("photoUrls"), attr);
54 }
55}
56
57void populatePlaceFromPoiJson(const QJsonObject &poiJsonObj, QPlace &place)
58{
59 auto phoneData = poiJsonObj.value(QStringLiteral("phone")).toVariant().toString();
60 if (!phoneData.isEmpty()) {
61 QPlaceContactDetail phoneDetail;
62 phoneDetail.setLabel(QPlaceSearchReplyOhosMapKit::tr("Phone"));
63 phoneDetail.setValue(phoneData);
64 place.appendContactDetail(QPlaceContactDetail::Phone, phoneDetail);
65 }
66
67 auto internationalPhoneData =
68 poiJsonObj.value(QStringLiteral("internationalPhone")).toVariant().toString();
69 if (!internationalPhoneData.isEmpty()) {
70 QPlaceContactDetail intlPhoneDetail;
71 intlPhoneDetail.setLabel(QPlaceSearchReplyOhosMapKit::tr("International phone"));
72 intlPhoneDetail.setValue(internationalPhoneData);
73 place.appendContactDetail(QPlaceContactDetail::Phone, intlPhoneDetail);
74 }
75
76 auto websiteUrl = poiJsonObj.value(QStringLiteral("websiteUrl")).toVariant().toString();
77 if (!websiteUrl.isEmpty()) {
78 QPlaceContactDetail websiteDetail;
79 websiteDetail.setLabel(QPlaceSearchReplyOhosMapKit::tr("Website"));
80 websiteDetail.setValue(internationalPhoneData);
81 place.appendContactDetail(QPlaceContactDetail::Website, websiteDetail);
82 }
83
84 auto rating = poiJsonObj.value(QStringLiteral("rating")).toDouble(0.0);
85 if (rating > 0.0) {
86 QPlaceRatings ratings;
87 ratings.setAverage(rating);
88 place.setRatings(ratings);
89 }
90
91 auto iconUrl = poiJsonObj.value(QStringLiteral("icon")).toVariant().toUrl();
92 if (!iconUrl.isEmpty()) {
93 QPlaceIcon icon;
94 icon.setParameters({{QPlaceIcon::SingleUrl, iconUrl}});
95 place.setIcon(icon);
96 }
97
98 auto hwPoi = poiJsonObj.value(QStringLiteral("hwPoiTypes")).toArray();
99 if (!hwPoi.isEmpty()) {
100 auto id = hwPoi.first().toVariant().toString();
101 if (!id.isEmpty()) {
102 QPlaceCategory c;
103 c.setCategoryId(id);
104 place.setCategory(c);
105 }
106 }
107
108 populatePlaceExtendedAttributes(poiJsonObj, place);
109}
110
111QPlaceResult siteJsonObjToPlaceResult(const QJsonObject &siteJsonObj)
112{
113 QPlace place;
114
115 place.setName(siteJsonObj.value(QStringLiteral("name")).toVariant().toString());
116 place.setLocation(OhosMapKit::SiteJson::tryConvertToQGeoLocation(siteJsonObj));
117
118 const QJsonObject poiObj = siteJsonObj.value(QStringLiteral("poi")).toObject();
119 if (!poiObj.isEmpty())
120 populatePlaceFromPoiJson(poiObj, place);
121
122 QPlaceResult result;
123 result.setPlace(place);
124 result.setDistance(siteJsonObj.value(QStringLiteral("distance")).toVariant().toInt());
125 return result;
126}
127
128QList<QPlaceSearchResult> parsePlaceSearchResponse(const QJsonDocument &responseBodyJsonDoc)
129{
130 QList<QPlaceSearchResult> results;
131
132 const QJsonObject responseBodyJsonObj = responseBodyJsonDoc.object();
133 if (responseBodyJsonObj.contains(QStringLiteral("sites"))) {
134 const QJsonArray sites = responseBodyJsonObj.value(QStringLiteral("sites")).toArray();
135 for (const QJsonValue &siteValue : sites) {
136 if (siteValue.isObject())
137 results.append(siteJsonObjToPlaceResult(siteValue.toObject()));
138 }
139 }
140
141 return results;
142}
143
145 const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngine *parent)
147{
148 Q_ASSERT(parent);
149 if (!reply) {
150 setError(QPlaceReply::UnknownError, QStringLiteral("Null reply"));
151 return;
152 }
153 setRequest(request);
154
155 connect(reply, &QNetworkReply::finished, this, &QPlaceSearchReplyOhosMapKit::onReplyFinished);
156 connect(reply, &QNetworkReply::errorOccurred, this, &QPlaceSearchReplyOhosMapKit::onNetworkError);
157
158 connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort);
159 connect(this, &QObject::destroyed, reply, &QObject::deleteLater);
160}
161
162void QPlaceSearchReplyOhosMapKit::onReplyFinished()
163{
164 auto *reply = static_cast<QNetworkReply *>(sender());
165 reply->deleteLater();
166
167 auto setErrorEmitAndFinish = [&](QPlaceReply::Error errorCode, const QString &errorString) {
168 setError(errorCode, errorString);
169 Q_EMIT errorOccurred(errorCode, errorString);
170
171 setFinished(true);
172 Q_EMIT finished();
173 };
174
175 if (reply->error() != QNetworkReply::NoError) {
176 setErrorEmitAndFinish(
177 QPlaceReply::CommunicationError,
178 tr("Network reply error: %1")
179 .arg(QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(reply->error())));
180 return;
181 }
182
183 const auto responseBodyJsonDoc = QJsonDocument::fromJson(reply->readAll());
184 if (!responseBodyJsonDoc.isObject()) {
185 setErrorEmitAndFinish(QPlaceReply::ParseError, tr("Response parse error"));
186 return;
187 }
188
189 auto results = parsePlaceSearchResponse(responseBodyJsonDoc);
190
191 if (request().relevanceHint() == QPlaceSearchRequest::DistanceHint) {
192 std::sort(
193 results.begin(), results.end(),
194 [](const auto &a, const auto &b) {
195 return
196 a.type() == QPlaceSearchResult::PlaceResult
197 && b.type() == QPlaceSearchResult::PlaceResult
198 && QPlaceResult(a).distance() < QPlaceResult(b).distance();
199 });
200 } else if (request().relevanceHint() == QPlaceSearchRequest::LexicalPlaceNameHint) {
201 std::sort(
202 results.begin(), results.end(),
203 [](const auto &a, const auto &b) {
204 return
205 a.type() == QPlaceSearchResult::PlaceResult
206 && b.type() == QPlaceSearchResult::PlaceResult
207 && QPlaceResult(a).place().name() < QPlaceResult(b).place().name();
208 });
209 }
210
211 setResults(results);
212
213 setFinished(true);
214 Q_EMIT finished();
215}
216
217void QPlaceSearchReplyOhosMapKit::onNetworkError(QNetworkReply::NetworkError error)
218{
219 Q_UNUSED(error)
220 auto *reply = static_cast<QNetworkReply *>(sender());
221 reply->deleteLater();
222 setError(QPlaceReply::CommunicationError, reply->errorString());
223}
224
225}
226
228 const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngine *parent)
229{
230 return new QPlaceSearchReplyOhosMapKit(request, reply, parent);
231}
232
233QT_END_NAMESPACE
QPlaceSearchReplyOhosMapKit(const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngine *parent)
Combined button and popup list for selecting options.
QList< QPlaceSearchResult > parsePlaceSearchResponse(const QJsonDocument &responseBodyJsonDoc)
void populatePlaceExtendedAttributes(const QJsonObject &poiJsonObj, QPlace &place)
void populatePlaceFromPoiJson(const QJsonObject &poiJsonObj, QPlace &place)
QPlaceResult siteJsonObjToPlaceResult(const QJsonObject &siteJsonObj)
QPlaceSearchReply * makeQPlaceSearchReplyOhosMapKit(const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngine *parent)