| /**************************************************************************** |
| ** |
| ** Copyright (C) 2013-2018 Esri <contracts@esri.com> |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtLocation module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "geotiledmappingmanagerengine_esri.h" |
| #include "geotiledmap_esri.h" |
| #include "geotilefetcher_esri.h" |
| |
| #include <QtLocation/private/qgeocameracapabilities_p.h> |
| #include <QtLocation/private/qgeomaptype_p.h> |
| #include <QtLocation/private/qgeotiledmap_p.h> |
| #include <QtLocation/private/qgeofiletilecache_p.h> |
| |
| #include <QFileInfo> |
| #include <QDir> |
| #include <QUrl> |
| #include <QFile> |
| #include <QJsonDocument> |
| #include <QJsonObject> |
| |
| QT_BEGIN_NAMESPACE |
| |
| static const QString kPrefixEsri(QStringLiteral("esri.")); |
| static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent")); |
| static const QString kParamToken(kPrefixEsri + QStringLiteral("token")); |
| static const QString kPrefixMapping(kPrefixEsri + QStringLiteral("mapping.")); |
| static const QString kParamMinimumZoomLevel(kPrefixMapping + QStringLiteral("minimumZoomLevel")); |
| static const QString kParamMaximumZoomLevel(kPrefixMapping + QStringLiteral("maximumZoomLevel")); |
| |
| static const QString kPropMapSources(QStringLiteral("mapSources")); |
| static const QString kPropStyle(QStringLiteral("style")); |
| static const QString kPropName(QStringLiteral("name")); |
| static const QString kPropDescription(QStringLiteral("description")); |
| static const QString kPropMobile(QStringLiteral("mobile")); |
| static const QString kPropNight(QStringLiteral("night")); |
| static const QString kPropUrl(QStringLiteral("url")); |
| static const QString kPropMapId(QStringLiteral("mapId")); |
| static const QString kPropCopyright(QStringLiteral("copyrightText")); |
| |
| GeoTiledMappingManagerEngineEsri::GeoTiledMappingManagerEngineEsri(const QVariantMap ¶meters, |
| QGeoServiceProvider::Error *error, |
| QString *errorString) : |
| QGeoTiledMappingManagerEngine() |
| { |
| QGeoCameraCapabilities cameraCaps; |
| |
| double minimumZoomLevel = 0; |
| double maximumZoomLevel = 19; |
| |
| if (parameters.contains(kParamMinimumZoomLevel)) |
| minimumZoomLevel = parameters[kParamMinimumZoomLevel].toDouble(); |
| |
| if (parameters.contains(kParamMaximumZoomLevel)) |
| maximumZoomLevel = parameters[kParamMaximumZoomLevel].toDouble(); |
| |
| cameraCaps.setMinimumZoomLevel(minimumZoomLevel); |
| cameraCaps.setMaximumZoomLevel(maximumZoomLevel); |
| cameraCaps.setSupportsBearing(true); |
| cameraCaps.setSupportsTilting(true); |
| cameraCaps.setMinimumTilt(0); |
| cameraCaps.setMaximumTilt(80); |
| cameraCaps.setMinimumFieldOfView(20.0); |
| cameraCaps.setMaximumFieldOfView(120.0); |
| cameraCaps.setOverzoomEnabled(true); |
| setCameraCapabilities(cameraCaps); |
| |
| setTileSize(QSize(256, 256)); |
| |
| if (!initializeMapSources(error, errorString, cameraCaps)) |
| return; |
| |
| QList<QGeoMapType> mapTypes; |
| |
| foreach (GeoMapSource *mapSource, m_mapSources) { |
| mapTypes << QGeoMapType( |
| mapSource->style(), |
| mapSource->name(), |
| mapSource->description(), |
| mapSource->mobile(), |
| mapSource->night(), |
| mapSource->mapId(), |
| "esri", |
| cameraCaps); |
| } |
| |
| setSupportedMapTypes(mapTypes); |
| |
| GeoTileFetcherEsri *tileFetcher = new GeoTileFetcherEsri(this); |
| |
| if (parameters.contains(kParamUserAgent)) |
| tileFetcher->setUserAgent(parameters.value(kParamUserAgent).toString().toLatin1()); |
| |
| if (parameters.contains(kParamToken)) |
| tileFetcher->setToken(parameters.value(kParamToken).toString()); |
| |
| setTileFetcher(tileFetcher); |
| |
| /* TILE CACHE */ |
| QString cacheDirectory; |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.directory"))) { |
| cacheDirectory = parameters.value(QStringLiteral("esri.mapping.cache.directory")).toString(); |
| } else { |
| // managerName() is not yet set, we have to hardcode the plugin name below |
| cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + QLatin1String("esri"); |
| } |
| QGeoFileTileCache *tileCache = new QGeoFileTileCache(cacheDirectory); |
| |
| /* |
| * Disk cache setup -- defaults to ByteSize (old behavior) |
| */ |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.disk.cost_strategy"))) { |
| QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.disk.cost_strategy")).toString().toLower(); |
| if (cacheStrategy == QLatin1String("bytesize")) |
| tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize); |
| else |
| tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary); |
| } else { |
| tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize); |
| } |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.disk.size"))) { |
| bool ok = false; |
| int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.disk.size")).toString().toInt(&ok); |
| if (ok) |
| tileCache->setMaxDiskUsage(cacheSize); |
| } |
| |
| /* |
| * Memory cache setup -- defaults to ByteSize (old behavior) |
| */ |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.memory.cost_strategy"))) { |
| QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.memory.cost_strategy")).toString().toLower(); |
| if (cacheStrategy == QLatin1String("bytesize")) |
| tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize); |
| else |
| tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary); |
| } else { |
| tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize); |
| } |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.memory.size"))) { |
| bool ok = false; |
| int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.memory.size")).toString().toInt(&ok); |
| if (ok) |
| tileCache->setMaxMemoryUsage(cacheSize); |
| } |
| |
| /* |
| * Texture cache setup -- defaults to ByteSize (old behavior) |
| */ |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.texture.cost_strategy"))) { |
| QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.texture.cost_strategy")).toString().toLower(); |
| if (cacheStrategy == QLatin1String("bytesize")) |
| tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize); |
| else |
| tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary); |
| } else { |
| tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize); |
| } |
| if (parameters.contains(QStringLiteral("esri.mapping.cache.texture.size"))) { |
| bool ok = false; |
| int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.texture.size")).toString().toInt(&ok); |
| if (ok) |
| tileCache->setExtraTextureUsage(cacheSize); |
| } |
| |
| /* PREFETCHING */ |
| if (parameters.contains(QStringLiteral("esri.mapping.prefetching_style"))) { |
| const QString prefetchingMode = parameters.value(QStringLiteral("esri.mapping.prefetching_style")).toString(); |
| if (prefetchingMode == QStringLiteral("TwoNeighbourLayers")) |
| m_prefetchStyle = QGeoTiledMap::PrefetchTwoNeighbourLayers; |
| else if (prefetchingMode == QStringLiteral("OneNeighbourLayer")) |
| m_prefetchStyle = QGeoTiledMap::PrefetchNeighbourLayer; |
| else if (prefetchingMode == QStringLiteral("NoPrefetching")) |
| m_prefetchStyle = QGeoTiledMap::NoPrefetching; |
| } |
| |
| setTileCache(tileCache); |
| *error = QGeoServiceProvider::NoError; |
| errorString->clear(); |
| } |
| |
| GeoTiledMappingManagerEngineEsri::~GeoTiledMappingManagerEngineEsri() |
| { |
| qDeleteAll(m_mapSources); |
| } |
| |
| QGeoMap *GeoTiledMappingManagerEngineEsri::createMap() |
| { |
| QGeoTiledMap *map = new GeoTiledMapEsri(this); |
| map->setPrefetchStyle(m_prefetchStyle); |
| return map; |
| } |
| |
| // ${z} = Zoom |
| // ${x} = X |
| // ${y} = Y |
| // ${token} = Token |
| |
| // template = 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png' |
| |
| bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider::Error *error, |
| QString *errorString, |
| const QGeoCameraCapabilities &cameraCaps) |
| { |
| QFile mapsFile(":/esri/maps.json"); |
| |
| if (!mapsFile.open(QIODevice::ReadOnly)) { |
| *error = QGeoServiceProvider::NotSupportedError; |
| *errorString = Q_FUNC_INFO + QStringLiteral("Unable to open: ") + mapsFile.fileName(); |
| |
| return false; |
| } |
| |
| QByteArray mapsData = mapsFile.readAll(); |
| mapsFile.close(); |
| |
| QJsonParseError parseError; |
| |
| QJsonDocument mapsDocument = QJsonDocument::fromJson(mapsData, &parseError); |
| |
| if (!mapsDocument.isObject()) { |
| *error = QGeoServiceProvider::NotSupportedError; |
| *errorString = Q_FUNC_INFO + QStringLiteral("JSON error: ") + (int)parseError.error |
| + ", offset: " + parseError.offset |
| + ", details: " + parseError.errorString(); |
| return false; |
| } |
| |
| QVariantMap maps = mapsDocument.object().toVariantMap(); |
| |
| QVariantList mapSources = maps["mapSources"].toList(); |
| |
| foreach (QVariant mapSourceElement, mapSources) { |
| QVariantMap mapSource = mapSourceElement.toMap(); |
| |
| int mapId = m_mapSources.count() + 1; |
| |
| m_mapSources << new GeoMapSource( |
| GeoMapSource::mapStyle(mapSource[kPropStyle].toString()), |
| mapSource[kPropName].toString(), |
| mapSource[kPropDescription].toString(), |
| mapSource[kPropMobile].toBool(), |
| mapSource[kPropMapId].toBool(), |
| mapId, |
| GeoMapSource::toFormat(mapSource[kPropUrl].toString()), |
| mapSource[kPropCopyright].toString(), |
| cameraCaps |
| ); |
| } |
| |
| return true; |
| } |
| |
| GeoMapSource *GeoTiledMappingManagerEngineEsri::mapSource(int mapId) const |
| { |
| foreach (GeoMapSource *mapSource, mapSources()) { |
| if (mapSource->mapId() == mapId) |
| return mapSource; |
| } |
| |
| return nullptr; |
| } |
| |
| QT_END_NAMESPACE |