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 "qgeotilefetcher_nokia.h"
38 #include "qgeomapreply_nokia.h"
39 #include "qgeotiledmap_nokia.h"
40 #include "qgeotiledmappingmanagerengine_nokia.h"
41 #include "qgeonetworkaccessmanager.h"
42 #include "qgeouriprovider.h"
43 #include "uri_constants.h"
44
45 #include <QtLocation/private/qgeotilespec_p.h>
46
47 #include <QDebug>
48 #include <QSize>
49 #include <QDir>
50 #include <QUrl>
51 #include <QTime>
52
53 #include <map>
54
55 QT_BEGIN_NAMESPACE
56
57 namespace
58 {
sizeToStr(int size)59 QString sizeToStr(int size)
60 {
61 if (size > 256)
62 return QStringLiteral("512");
63 else if (size > 128)
64 return QStringLiteral("256");
65 else
66 return QStringLiteral("128"); // 128 pixel tiles are deprecated.
67 }
68
isAerialType(const QString mapScheme)69 bool isAerialType(const QString mapScheme)
70 {
71 return mapScheme.startsWith("satellite") || mapScheme.startsWith("hybrid") || mapScheme.startsWith("terrain");
72 }
73 }
QGeoTileFetcherNokia(const QVariantMap & parameters,QGeoNetworkAccessManager * networkManager,QGeoTiledMappingManagerEngineNokia * engine,const QSize & tileSize,int ppi)74 QGeoTileFetcherNokia::QGeoTileFetcherNokia(const QVariantMap ¶meters,
75 QGeoNetworkAccessManager *networkManager,
76 QGeoTiledMappingManagerEngineNokia *engine,
77 const QSize &tileSize,
78 int ppi)
79 : QGeoTileFetcher(engine), m_engineNokia(engine), m_networkManager(networkManager), m_ppi(ppi), m_copyrightsReply(0),
80 m_baseUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host"), MAP_TILES_HOST)),
81 m_aerialUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host.aerial"), MAP_TILES_HOST_AERIAL))
82 {
83 Q_ASSERT(networkManager);
84 m_tileSize = qMax(tileSize.width(), tileSize.height());
85 m_networkManager->setParent(this);
86
87 m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString();
88 m_token = parameters.value(QStringLiteral("here.token")).toString();
89 }
90
~QGeoTileFetcherNokia()91 QGeoTileFetcherNokia::~QGeoTileFetcherNokia()
92 {
93 }
94
getTileImage(const QGeoTileSpec & spec)95 QGeoTiledMapReply *QGeoTileFetcherNokia::getTileImage(const QGeoTileSpec &spec)
96 {
97 // TODO add error detection for if request.connectivityMode() != QGraphicsGeoMap::OnlineMode
98 int ppi = m_ppi;
99 if ((spec.mapId() == 2) || (spec.mapId() == 12) || (spec.mapId() == 21)) {
100 ppi = 72; // HiDpi apparently not supported for these maps
101 } else if ((spec.mapId() >= 7 && spec.mapId() <= 11)
102 || (spec.mapId() == 14)
103 || (spec.mapId() == 16)
104 || (spec.mapId() == 18)
105 || (spec.mapId() == 20)) {
106 ppi = 250; // LoDpi apparently not supported for these maps
107 }
108
109 QString rawRequest = getRequestString(spec, ppi);
110 if (rawRequest.isEmpty()) {
111 return new QGeoTiledMapReply(QGeoTiledMapReply::UnknownError,
112 tr("Mapping manager no longer exists"), this);
113 }
114
115 QNetworkRequest netRequest((QUrl(rawRequest))); // The extra pair of parens disambiguates this from a function declaration
116 netRequest.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
117
118 QNetworkReply *netReply = m_networkManager->get(netRequest);
119
120 QGeoTiledMapReply *mapReply = new QGeoMapReplyNokia(netReply, spec);
121
122 return mapReply;
123 }
124
getRequestString(const QGeoTileSpec & spec,int ppi)125 QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec, int ppi)
126 {
127 if (!m_engineNokia)
128 return QString();
129
130 static const QString http("http://");
131 static const QString path("/maptile/2.1/maptile/newest/");
132 static const QChar slash('/');
133
134 QString requestString = http;
135
136 const QString mapScheme = m_engineNokia->getScheme(spec.mapId());
137 if (isAerialType(mapScheme))
138 requestString += m_aerialUriProvider->getCurrentHost();
139 else
140 requestString += m_baseUriProvider->getCurrentHost();
141
142 requestString += path;
143 requestString += mapScheme;
144 requestString += slash;
145 requestString += QString::number(spec.zoom());
146 requestString += slash;
147 requestString += QString::number(spec.x());
148 requestString += slash;
149 requestString += QString::number(spec.y());
150 requestString += slash;
151 requestString += ((ppi > 72)) ? sizeToStr(m_tileSize * 2) : sizeToStr(m_tileSize);
152 static const QString slashpng("/png8");
153 requestString += slashpng;
154
155 if (!m_token.isEmpty() && !m_applicationId.isEmpty()) { // TODO: remove the if
156 requestString += "?token=";
157 requestString += m_token;
158
159 requestString += "&app_id=";
160 requestString += m_applicationId;
161 }
162
163 requestString += "&ppi=" + QString::number(ppi);
164
165 requestString += "&lg=";
166 requestString += getLanguageString();
167 return requestString;
168 }
169
getLanguageString() const170 QString QGeoTileFetcherNokia::getLanguageString() const
171 {
172 if (!m_engineNokia)
173 return QStringLiteral("ENG");
174
175 QLocale locale = m_engineNokia.data()->locale();
176
177 // English is the default, where no ln is specified. We hardcode the languages
178 // here even though the entire list is updated automagically from the server.
179 // The current languages are Arabic, Chinese, Simplified Chinese, English
180 // French, German, Italian, Polish, Russian and Spanish. The default is English.
181 // These are actually available from the same host under the URL: /maptiler/v2/info
182
183 switch (locale.language()) {
184 case QLocale::Arabic:
185 return QStringLiteral("ARA");
186 case QLocale::Chinese:
187 if (locale.script() == QLocale::TraditionalChineseScript)
188 return QStringLiteral("CHI");
189 else
190 return QStringLiteral("CHT");
191 case QLocale::Dutch:
192 return QStringLiteral("DUT");
193 case QLocale::French:
194 return QStringLiteral("FRE");
195 case QLocale::German:
196 return QStringLiteral("GER");
197 case QLocale::Gaelic:
198 return QStringLiteral("GLE");
199 case QLocale::Greek:
200 return QStringLiteral("GRE");
201 case QLocale::Hebrew:
202 return QStringLiteral("HEB");
203 case QLocale::Hindi:
204 return QStringLiteral("HIN");
205 case QLocale::Indonesian:
206 return QStringLiteral("IND");
207 case QLocale::Italian:
208 return QStringLiteral("ITA");
209 case QLocale::Persian:
210 return QStringLiteral("PER");
211 case QLocale::Polish:
212 return QStringLiteral("POL");
213 case QLocale::Portuguese:
214 return QStringLiteral("POR");
215 case QLocale::Russian:
216 return QStringLiteral("RUS");
217 case QLocale::Sinhala:
218 return QStringLiteral("SIN");
219 case QLocale::Spanish:
220 return QStringLiteral("SPA");
221 case QLocale::Thai:
222 return QStringLiteral("THA");
223 case QLocale::Turkish:
224 return QStringLiteral("TUR");
225 case QLocale::Ukrainian:
226 return QStringLiteral("UKR");
227 case QLocale::Urdu:
228 return QStringLiteral("URD");
229 case QLocale::Vietnamese:
230 return QStringLiteral("VIE");
231
232 default:
233 return QStringLiteral("ENG");
234 }
235 // No "lg" param means that we want English.
236 }
237
token() const238 QString QGeoTileFetcherNokia::token() const
239 {
240 return m_token;
241 }
242
applicationId() const243 QString QGeoTileFetcherNokia::applicationId() const
244 {
245 return m_applicationId;
246 }
247
copyrightsFetched()248 void QGeoTileFetcherNokia::copyrightsFetched()
249 {
250 if (m_engineNokia && m_copyrightsReply->error() == QNetworkReply::NoError) {
251 QMetaObject::invokeMethod(m_engineNokia.data(),
252 "loadCopyrightsDescriptorsFromJson",
253 Qt::QueuedConnection,
254 Q_ARG(QByteArray, m_copyrightsReply->readAll()));
255 }
256
257 m_copyrightsReply->deleteLater();
258 }
259
versionFetched()260 void QGeoTileFetcherNokia::versionFetched()
261 {
262 if (m_engineNokia && m_versionReply->error() == QNetworkReply::NoError) {
263 QMetaObject::invokeMethod(m_engineNokia.data(),
264 "parseNewVersionInfo",
265 Qt::QueuedConnection,
266 Q_ARG(QByteArray, m_versionReply->readAll()));
267 }
268
269 m_versionReply->deleteLater();
270 }
271
fetchCopyrightsData()272 void QGeoTileFetcherNokia::fetchCopyrightsData()
273 {
274 QString copyrightUrl = QStringLiteral("http://");
275
276 copyrightUrl += m_baseUriProvider->getCurrentHost();
277 copyrightUrl += QStringLiteral("/maptile/2.1/copyright/newest?output=json");
278
279 if (!token().isEmpty()) {
280 copyrightUrl += QStringLiteral("&token=");
281 copyrightUrl += token();
282 }
283
284 if (!applicationId().isEmpty()) {
285 copyrightUrl += QStringLiteral("&app_id=");
286 copyrightUrl += applicationId();
287 }
288
289 QNetworkRequest netRequest((QUrl(copyrightUrl)));
290 m_copyrightsReply = m_networkManager->get(netRequest);
291 if (m_copyrightsReply->error() != QNetworkReply::NoError) {
292 qWarning() << __FUNCTION__ << m_copyrightsReply->errorString();
293 m_copyrightsReply->deleteLater();
294 return;
295 }
296
297 if (m_copyrightsReply->isFinished()) {
298 copyrightsFetched();
299 } else {
300 connect(m_copyrightsReply, SIGNAL(finished()), this, SLOT(copyrightsFetched()));
301 }
302 }
303
fetchVersionData()304 void QGeoTileFetcherNokia::fetchVersionData()
305 {
306 QString versionUrl = QStringLiteral("http://");
307
308 versionUrl += m_baseUriProvider->getCurrentHost();
309 versionUrl += QStringLiteral("/maptile/2.1/version");
310
311 if (!token().isEmpty()) {
312 versionUrl += QStringLiteral("?token=");
313 versionUrl += token();
314 }
315
316 if (!applicationId().isEmpty()) {
317 versionUrl += QStringLiteral("&app_id=");
318 versionUrl += applicationId();
319 }
320
321 QNetworkRequest netRequest((QUrl(versionUrl)));
322 m_versionReply = m_networkManager->get(netRequest);
323
324 if (m_versionReply->error() != QNetworkReply::NoError) {
325 qWarning() << __FUNCTION__ << m_versionReply->errorString();
326 m_versionReply->deleteLater();
327 return;
328 }
329
330 if (m_versionReply->isFinished())
331 versionFetched();
332 else
333 connect(m_versionReply, SIGNAL(finished()), this, SLOT(versionFetched()));
334 }
335
336 QT_END_NAMESPACE
337