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 "qgeotilefetcher_nokia.h"
#include "qgeomapreply_nokia.h"
#include "qgeotiledmap_nokia.h"
#include "qgeotiledmappingmanagerengine_nokia.h"
#include "qgeonetworkaccessmanager.h"
#include "qgeouriprovider.h"
#include "uri_constants.h"
#include <QtLocation/private/qgeotilespec_p.h>
#include <QDebug>
#include <QSize>
#include <QDir>
#include <QUrl>
#include <QTime>
#include <map>
QT_BEGIN_NAMESPACE
namespace
{
QString sizeToStr(int size)
{
if (size > 256)
return QStringLiteral("512");
else if (size > 128)
return QStringLiteral("256");
else
return QStringLiteral("128"); // 128 pixel tiles are deprecated.
}
bool isAerialType(const QString mapScheme)
{
return mapScheme.startsWith("satellite") || mapScheme.startsWith("hybrid") || mapScheme.startsWith("terrain");
}
}
QGeoTileFetcherNokia::QGeoTileFetcherNokia(const QVariantMap &parameters,
QGeoNetworkAccessManager *networkManager,
QGeoTiledMappingManagerEngineNokia *engine,
const QSize &tileSize,
int ppi)
: QGeoTileFetcher(engine), m_engineNokia(engine), m_networkManager(networkManager), m_ppi(ppi), m_copyrightsReply(nullptr),
m_baseUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host"), MAP_TILES_HOST)),
m_aerialUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host.aerial"), MAP_TILES_HOST_AERIAL))
{
Q_ASSERT(networkManager);
m_tileSize = qMax(tileSize.width(), tileSize.height());
m_networkManager->setParent(this);
m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
}
QGeoTileFetcherNokia::~QGeoTileFetcherNokia()
{
}
QGeoTiledMapReply *QGeoTileFetcherNokia::getTileImage(const QGeoTileSpec &spec)
{
// TODO add error detection for if request.connectivityMode() != QGraphicsGeoMap::OnlineMode
int ppi = m_ppi;
if ((spec.mapId() == 2) || (spec.mapId() == 12) || (spec.mapId() == 21)) {
ppi = 72; // HiDpi apparently not supported for these maps
} else if ((spec.mapId() >= 7 && spec.mapId() <= 11)
|| (spec.mapId() == 14)
|| (spec.mapId() == 16)
|| (spec.mapId() == 18)
|| (spec.mapId() == 20)) {
ppi = 250; // LoDpi apparently not supported for these maps
}
QString rawRequest = getRequestString(spec, ppi);
if (rawRequest.isEmpty()) {
return new QGeoTiledMapReply(QGeoTiledMapReply::UnknownError,
tr("Mapping manager no longer exists"), this);
}
QNetworkRequest netRequest((QUrl(rawRequest))); // The extra pair of parens disambiguates this from a function declaration
netRequest.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
QNetworkReply *netReply = m_networkManager->get(netRequest);
QGeoTiledMapReply *mapReply = new QGeoMapReplyNokia(netReply, spec);
return mapReply;
}
QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec, int ppi) const
{
if (!m_engineNokia)
return QString();
static const QString http("https://");
static const QString path("/maptile/2.1/maptile/newest/");
static const QChar slash('/');
QString requestString = http;
const QString mapScheme = m_engineNokia->getScheme(spec.mapId());
if (isAerialType(mapScheme))
requestString += m_aerialUriProvider->getCurrentHost();
else
requestString += m_baseUriProvider->getCurrentHost();
requestString += path;
requestString += mapScheme;
requestString += slash;
requestString += QString::number(spec.zoom());
requestString += slash;
requestString += QString::number(spec.x());
requestString += slash;
requestString += QString::number(spec.y());
requestString += slash;
requestString += ((ppi > 72)) ? sizeToStr(m_tileSize * 2) : sizeToStr(m_tileSize);
static const QString slashpng("/png8");
requestString += slashpng;
if (!m_apiKey.isEmpty()) { // TODO: remove the if
requestString += "?apiKey=";
requestString += m_apiKey;
}
requestString += "&ppi=" + QString::number(ppi);
requestString += "&lg=";
requestString += getLanguageString();
return requestString;
}
QString QGeoTileFetcherNokia::getLanguageString() const
{
if (!m_engineNokia)
return QStringLiteral("ENG");
QLocale locale = m_engineNokia.data()->locale();
// English is the default, where no ln is specified. We hardcode the languages
// here even though the entire list is updated automagically from the server.
// The current languages are Arabic, Chinese, Simplified Chinese, English
// French, German, Italian, Polish, Russian and Spanish. The default is English.
// These are actually available from the same host under the URL: /maptiler/v2/info
switch (locale.language()) {
case QLocale::Arabic:
return QStringLiteral("ARA");
case QLocale::Chinese:
if (locale.script() == QLocale::TraditionalChineseScript)
return QStringLiteral("CHI");
else
return QStringLiteral("CHT");
case QLocale::Dutch:
return QStringLiteral("DUT");
case QLocale::French:
return QStringLiteral("FRE");
case QLocale::German:
return QStringLiteral("GER");
case QLocale::Gaelic:
return QStringLiteral("GLE");
case QLocale::Greek:
return QStringLiteral("GRE");
case QLocale::Hebrew:
return QStringLiteral("HEB");
case QLocale::Hindi:
return QStringLiteral("HIN");
case QLocale::Indonesian:
return QStringLiteral("IND");
case QLocale::Italian:
return QStringLiteral("ITA");
case QLocale::Persian:
return QStringLiteral("PER");
case QLocale::Polish:
return QStringLiteral("POL");
case QLocale::Portuguese:
return QStringLiteral("POR");
case QLocale::Russian:
return QStringLiteral("RUS");
case QLocale::Sinhala:
return QStringLiteral("SIN");
case QLocale::Spanish:
return QStringLiteral("SPA");
case QLocale::Thai:
return QStringLiteral("THA");
case QLocale::Turkish:
return QStringLiteral("TUR");
case QLocale::Ukrainian:
return QStringLiteral("UKR");
case QLocale::Urdu:
return QStringLiteral("URD");
case QLocale::Vietnamese:
return QStringLiteral("VIE");
default:
return QStringLiteral("ENG");
}
// No "lg" param means that we want English.
}
QString QGeoTileFetcherNokia::apiKey() const
{
return m_apiKey;
}
void QGeoTileFetcherNokia::copyrightsFetched()
{
if (m_engineNokia && m_copyrightsReply->error() == QNetworkReply::NoError) {
QMetaObject::invokeMethod(m_engineNokia.data(),
"loadCopyrightsDescriptorsFromJson",
Qt::QueuedConnection,
Q_ARG(QByteArray, m_copyrightsReply->readAll()));
}
m_copyrightsReply->deleteLater();
}
void QGeoTileFetcherNokia::versionFetched()
{
if (m_engineNokia && m_versionReply->error() == QNetworkReply::NoError) {
QMetaObject::invokeMethod(m_engineNokia.data(),
"parseNewVersionInfo",
Qt::QueuedConnection,
Q_ARG(QByteArray, m_versionReply->readAll()));
}
m_versionReply->deleteLater();
}
void QGeoTileFetcherNokia::fetchCopyrightsData()
{
QString copyrightUrl = QStringLiteral("https://");
copyrightUrl += m_baseUriProvider->getCurrentHost();
copyrightUrl += QStringLiteral("/maptile/2.1/copyright/newest?output=json");
if (!apiKey().isEmpty()) {
copyrightUrl += QStringLiteral("&apiKey=");
copyrightUrl += apiKey();
}
QNetworkRequest netRequest((QUrl(copyrightUrl)));
m_copyrightsReply = m_networkManager->get(netRequest);
if (m_copyrightsReply->error() != QNetworkReply::NoError) {
qWarning() << __FUNCTION__ << m_copyrightsReply->errorString();
m_copyrightsReply->deleteLater();
return;
}
if (m_copyrightsReply->isFinished()) {
copyrightsFetched();
} else {
connect(m_copyrightsReply, &QNetworkReply::finished,
this, &QGeoTileFetcherNokia::copyrightsFetched);
}
}
void QGeoTileFetcherNokia::fetchVersionData()
{
QString versionUrl = QStringLiteral("https://");
versionUrl += m_baseUriProvider->getCurrentHost();
versionUrl += QStringLiteral("/maptile/2.1/version");
if (!apiKey().isEmpty()) {
versionUrl += QStringLiteral("?apiKey=");
versionUrl += apiKey();
}
QNetworkRequest netRequest((QUrl(versionUrl)));
m_versionReply = m_networkManager->get(netRequest);
if (m_versionReply->error() != QNetworkReply::NoError) {
qWarning() << __FUNCTION__ << m_versionReply->errorString();
m_versionReply->deleteLater();
return;
}
if (m_versionReply->isFinished())
versionFetched();
else
connect(m_versionReply, &QNetworkReply::finished,
this, &QGeoTileFetcherNokia::versionFetched);
}
QT_END_NAMESPACE