diff options
author | Guillaume Belz <gbelz@esri.com> | 2016-08-17 23:49:22 +0100 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@theqtcompany.com> | 2016-08-31 08:10:57 +0000 |
commit | d999495a01cf6b6cb206a968944b889ab29e3450 (patch) | |
tree | 04c92d06b33d4a11e8fc52938ad46ab1f6542ce2 | |
parent | ee4bbb765e9a3ccfc9f5943d253290e3fc24484c (diff) |
Add geoservices plugin to support ESRI mapping servicesv5.8.0-alpha1
[ChangeLog] Add geoservices plugin to support ESRI mapping
services.
Change-Id: I96fdfd9af77dc51166a9ded268bbcf0d66016fda
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
30 files changed, 2858 insertions, 3 deletions
diff --git a/src/location/doc/src/plugins/esri.qdoc b/src/location/doc/src/plugins/esri.qdoc new file mode 100644 index 00000000..06b0c2c1 --- /dev/null +++ b/src/location/doc/src/plugins/esri.qdoc @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +/*! +\page location-plugin-esri.html +\title Qt Location Esri Plugin +\ingroup QtLocation-plugins + +\brief Uses Esri for location services. + +\section1 Overview + +This geo services plugin allows applications to access +\l {http://www.esri.com}{Esri} location based services using the Qt Location API. +The use of these services is governed by the \l {http://www.esri.com/legal/terms-use}{Esri terms of use}. + +Data is provided by \l {http://www.esri.com/data/find-data}{many different content providers}. + +The Esri geo services plugin can be loaded by using the plugin key "esri". + +\section1 Parameters + +\section2 Mandatory parameters + +\table +\header + \li Parameter + \li Description +\row + \li esri.token + \li Security token for using routing services only. Mapping and geocoding services do not require a token. +\endtable + +To use the routing services hosted on ArcGIS Online with the Esri plugin, a token is required. You can \l{https://developers.arcgis.com/authentication/accessing-arcgis-online-services/#registering-your-application}{obtain a token for testing purposes}, +or you can sign up for an \l {http://www.arcgis.com/features/plans/pricing.html}{ArcGIS Online subscription}. + +\section2 Optional parameters + +\table +\header + \li Parameter + \li Description +\row + \li esri.useragent + \li User agent string sent when making network requests +\row + \li esri.mapping.minimumZoomLevel + \li The minimum zoom level [double] at which the map is displayed +\row + \li esri.mapping.maximumZoomLevel + \li The maximum level [double] at which the map is displayed +\endtable + +\section2 Directions language + +The service supports generating directions in the following languages: + +\table +\header + \li Language + \li Description +\row + \li ar + \li Generate directions in Arabic +\row + \li cs + \li Generate directions in Czech +\row + \li de + \li Generate directions in German +\row + \li el + \li Generate directions in Greek +\row + \li en + \li (default) Generate directions in English +\row + \li es + \li Generate directions in Spanish +\row + \li et + \li Generate directions in Estonian +\row + \li fr + \li Generate directions in French +\row + \li he + \li Generate directions in Hebrew +\row + \li it + \li Generate directions in Italian +\row + \li ja + \li Generate directions in Japanese +\row + \li ko + \li Generate directions in Korean +\row + \li lt + \li Generate directions in Lithuanian +\row + \li lv + \li Generate directions in Latvian +\row + \li nl + \li Generate directions in Dutch +\row + \li pl + \li Generate directions in Polish +\row + \li pt-BR + \li Generate directions in Brazilian Portuguese +\row + \li pt-PT + \li Generate directions in Portuguese (Portugal) +\row + \li ru + \li Generate directions in Russian +\row + \li sv + \li Generate directions in Swedish +\row + \li tr + \li Generate directions in Turkish +\row + \li zh-CN + \li Simplified Chinese +\endtable + +If only unsupported language codes are specified via the \l{http://doc.qt.io/qt-5/qml-qtlocation-plugin.html#locales-prop} +{locales} property, the service returns the directions using the default language, English. + +\section2 Directions length units + +QLocale::MetricSystem (default) use meters, other values (QLocale::ImperialUSSystem, QLocale::ImperialUSSystem) use feet. + +*/ diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp index 51b0de60..8a3dc144 100644 --- a/src/location/maps/qgeoserviceprovider.cpp +++ b/src/location/maps/qgeoserviceprovider.cpp @@ -104,6 +104,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, \li "mapbox" -> \l {Qt Location Mapbox Plugin}{Mapbox service} \li "here" -> \l {Qt Location HERE Plugin}{HERE Services} \li "osm" -> \l {Qt Location Open Street Map Plugin}{OpenStreetMap Services} + \li "esri" -> \l {Qt Location Esri Plugin}{ESRI Services} \endlist Each service provider must follow a naming convention for their service specific diff --git a/src/plugins/geoservices/esri/esri.pro b/src/plugins/geoservices/esri/esri.pro new file mode 100644 index 00000000..3642ddaf --- /dev/null +++ b/src/plugins/geoservices/esri/esri.pro @@ -0,0 +1,39 @@ +TARGET = qtgeoservices_esri + +QT += location-private positioning-private network + +HEADERS += \ + geocodereply_esri.h \ + geocodingmanagerengine_esri.h \ + geomapsource.h \ + georoutejsonparser_esri.h \ + georoutereply_esri.h \ + georoutingmanagerengine_esri.h \ + geoserviceproviderfactory_esri.h \ + geotiledmap_esri.h \ + geotiledmappingmanagerengine_esri.h \ + geotiledmapreply_esri.h \ + geotilefetcher_esri.h + +SOURCES += \ + geocodereply_esri.cpp \ + geocodingmanagerengine_esri.cpp \ + geomapsource.cpp \ + georoutejsonparser_esri.cpp \ + georoutereply_esri.cpp \ + georoutingmanagerengine_esri.cpp \ + geoserviceproviderfactory_esri.cpp \ + geotiledmap_esri.cpp \ + geotiledmappingmanagerengine_esri.cpp \ + geotiledmapreply_esri.cpp \ + geotilefetcher_esri.cpp + +RESOURCES += \ + esri.qrc + +OTHER_FILES += \ + esri_plugin.json + +PLUGIN_TYPE = geoservices +PLUGIN_CLASS_NAME = GeoServiceProviderFactoryEsri +load(qt_plugin) diff --git a/src/plugins/geoservices/esri/esri.qrc b/src/plugins/geoservices/esri/esri.qrc new file mode 100644 index 00000000..43b0857f --- /dev/null +++ b/src/plugins/geoservices/esri/esri.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>maps.json</file> + </qresource> +</RCC> diff --git a/src/plugins/geoservices/esri/esri_plugin.json b/src/plugins/geoservices/esri/esri_plugin.json new file mode 100644 index 00000000..3398648e --- /dev/null +++ b/src/plugins/geoservices/esri/esri_plugin.json @@ -0,0 +1,13 @@ +{ + "Keys": ["esri"], + "Provider": "esri", + "Version": 100, + "Experimental": false, + "Features": [ + "OnlineMappingFeature", + "OnlineGeocodingFeature", + "ReverseGeocodingFeature", + "OnlineRoutingFeature" + ], + "Priority": 1000 +} diff --git a/src/plugins/geoservices/esri/geocodereply_esri.cpp b/src/plugins/geoservices/esri/geocodereply_esri.cpp new file mode 100644 index 00000000..a7ad9368 --- /dev/null +++ b/src/plugins/geoservices/esri/geocodereply_esri.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geocodereply_esri.h" + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QGeoCoordinate> +#include <QGeoAddress> +#include <QGeoLocation> +#include <QGeoRectangle> + +QT_BEGIN_NAMESPACE + +GeoCodeReplyEsri::GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType, + QObject *parent) : + QGeoCodeReply(parent), m_reply(reply), m_operationType(operationType) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + + setLimit(1); + setOffset(0); +} + +GeoCodeReplyEsri::~GeoCodeReplyEsri() +{ + if (m_reply) + m_reply->deleteLater(); +} + +void GeoCodeReplyEsri::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); + QGeoCodeReply::abort(); + + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +void GeoCodeReplyEsri::networkReplyError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + + if (!m_reply) + return; + + setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); + + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +void GeoCodeReplyEsri::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + { + setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; + return; + } + + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + + if (document.isObject()) { + QJsonObject object = document.object(); + + switch (operationType()) { + case Geocode: + { + QJsonArray candidates = object.value(QStringLiteral("candidates")).toArray(); + + QList<QGeoLocation> locations; + + for (int i = 0; i < candidates.count(); i++) { + if (!candidates.at(i).isObject()) + continue; + + QJsonObject candidate = candidates.at(i).toObject(); + + QGeoLocation location = parseCandidate(candidate); + locations.append(location); + } + + setLocations(locations); + setFinished(true); + } + break; + + case ReverseGeocode: + { + QGeoLocation location = parseAddress(object); + + QList<QGeoLocation> locations; + locations.append(location); + + setLocations(locations); + setFinished(true); + } + break; + } + + } else { + setError(QGeoCodeReply::CommunicationError, QStringLiteral("Unknown document")); + } + + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +QGeoLocation GeoCodeReplyEsri::parseAddress(const QJsonObject& object) +{ + QJsonObject addressObject = object.value(QStringLiteral("address")).toObject(); + + QGeoAddress address; + + address.setCountryCode(addressObject.value(QStringLiteral("CountryCode")).toString()); + address.setState(addressObject.value(QStringLiteral("Region")).toString()); + address.setCity(addressObject.value(QStringLiteral("City")).toString()); + address.setDistrict(addressObject.value(QStringLiteral("Subregion")).toString()); + address.setPostalCode(addressObject.value(QStringLiteral("Postal")).toString()); + address.setStreet(addressObject.value(QStringLiteral("Address")).toString()); + + QGeoCoordinate coordinate; + + QJsonObject locationObject = object.value(QStringLiteral("location")).toObject(); + + coordinate.setLongitude(locationObject.value(QStringLiteral("x")).toDouble()); + coordinate.setLatitude(locationObject.value(QStringLiteral("y")).toDouble()); + + QGeoLocation location; + + location.setCoordinate(coordinate); + location.setAddress(address); + + return location; +} + +QGeoLocation GeoCodeReplyEsri::parseCandidate(const QJsonObject& candidate) +{ + QGeoCoordinate coordinate; + + QJsonObject locationObject = candidate.value(QStringLiteral("location")).toObject(); + + coordinate.setLongitude(locationObject.value(QStringLiteral("x")).toDouble()); + coordinate.setLatitude(locationObject.value(QStringLiteral("y")).toDouble()); + + QGeoRectangle extent; + + if (candidate.contains(QStringLiteral("extent"))) { + QJsonObject extentObject = candidate.value(QStringLiteral("extent")).toObject(); + + extent.setTopLeft(QGeoCoordinate(extentObject.value(QStringLiteral("ymin")).toDouble(), + extentObject.value(QStringLiteral("xmin")).toDouble())); + + extent.setBottomRight(QGeoCoordinate(extentObject.value(QStringLiteral("ymax")).toDouble(), + extentObject.value(QStringLiteral("xmax")).toDouble())); + } + + QJsonObject attributesObject = candidate.value(QStringLiteral("attributes")).toObject(); + + QGeoAddress address; + + address.setText(candidate.value(QStringLiteral("address")).toString()); + + address.setCountry(attributesObject.value(QStringLiteral("Country")).toString()); + address.setCountryCode(attributesObject.value(QStringLiteral("Country")).toString()); + address.setState(attributesObject.value(QStringLiteral("Region")).toString()); + address.setCity(attributesObject.value(QStringLiteral("City")).toString()); + address.setDistrict(attributesObject.value(QStringLiteral("Subregion")).toString()); + address.setPostalCode(attributesObject.value(QStringLiteral("Postal")).toString()); + + QGeoLocation location; + + location.setCoordinate(coordinate); + location.setBoundingBox(extent); + location.setAddress(address); + + return location; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geocodereply_esri.h b/src/plugins/geoservices/esri/geocodereply_esri.h new file mode 100644 index 00000000..4434b7dc --- /dev/null +++ b/src/plugins/geoservices/esri/geocodereply_esri.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOCODEREPLYESRI_H +#define GEOCODEREPLYESRI_H + +#include <QNetworkReply> +#include <QGeoCodeReply> + +QT_BEGIN_NAMESPACE + +class GeoCodeReplyEsri : public QGeoCodeReply +{ + Q_OBJECT + +public: + enum OperationType + { + Geocode, + ReverseGeocode + }; + +public: + GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType, QObject *parent = Q_NULLPTR); + virtual ~GeoCodeReplyEsri(); + + void abort() Q_DECL_OVERRIDE; + + inline OperationType operationType() const; + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + + QGeoLocation parseAddress(const QJsonObject &object); + QGeoLocation parseCandidate(const QJsonObject &candidate); + +private: + QNetworkReply *m_reply; + OperationType m_operationType; +}; + +inline GeoCodeReplyEsri::OperationType GeoCodeReplyEsri::operationType() const +{ + return m_operationType; +} + +QT_END_NAMESPACE + +#endif // GEOCODEREPLYESRI_H diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp new file mode 100644 index 00000000..fcdc5962 --- /dev/null +++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geocodingmanagerengine_esri.h" +#include "geocodereply_esri.h" + +#include <QVariantMap> +#include <QUrl> +#include <QUrlQuery> +#include <QLocale> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QGeoCoordinate> +#include <QGeoAddress> +#include <QGeoShape> +#include <QGeoRectangle> + +QT_BEGIN_NAMESPACE + +// https://developers.arcgis.com/rest/geocode/api-reference/geocoding-find-address-candidates.htm +// https://developers.arcgis.com/rest/geocode/api-reference/geocoding-reverse-geocode.htm + +static const QString kPrefixEsri(QStringLiteral("esri.")); +static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent")); + +static const QString kUrlGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates")); +static const QString kUrlReverseGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode")); + +static QString addressToQuery(const QGeoAddress &address) +{ + return address.street() + QStringLiteral(", ") + + address.district() + QStringLiteral(", ") + + address.city() + QStringLiteral(", ") + + address.state() + QStringLiteral(", ") + + address.country(); +} + +static QString boundingBoxToLtrb(const QGeoRectangle &rect) +{ + return QString::number(rect.topLeft().longitude()) + QLatin1Char(',') + + QString::number(rect.topLeft().latitude()) + QLatin1Char(',') + + QString::number(rect.bottomRight().longitude()) + QLatin1Char(',') + + QString::number(rect.bottomRight().latitude()); +} + +GeoCodingManagerEngineEsri::GeoCodingManagerEngineEsri(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) +: QGeoCodingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) +{ + if (parameters.contains(kParamUserAgent)) + m_userAgent = parameters.value(kParamUserAgent).toString().toLatin1(); + else + m_userAgent = QByteArrayLiteral("Qt Location based application"); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +GeoCodingManagerEngineEsri::~GeoCodingManagerEngineEsri() +{ +} + +QGeoCodeReply *GeoCodingManagerEngineEsri::geocode(const QGeoAddress &address, + const QGeoShape &bounds) +{ + return geocode(addressToQuery(address), 1, -1, bounds); +} + +QGeoCodeReply *GeoCodingManagerEngineEsri::geocode(const QString &address, int limit, int offset, + const QGeoShape &bounds) +{ + Q_UNUSED(offset) + + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent); + + QUrl url(kUrlGeocode); + + QUrlQuery query; + query.addQueryItem(QStringLiteral("singleLine"), address); + query.addQueryItem(QStringLiteral("f"), QStringLiteral("json")); + query.addQueryItem(QStringLiteral("outFields"), "*"); + + if (bounds.type() == QGeoShape::RectangleType) + query.addQueryItem(QStringLiteral("searchExtent"), boundingBoxToLtrb(bounds)); + + if (limit != -1) + query.addQueryItem(QStringLiteral("maxLocations"), QString::number(limit)); + + url.setQuery(query); + request.setUrl(url); + + QNetworkReply *reply = m_networkManager->get(request); + GeoCodeReplyEsri *geocodeReply = new GeoCodeReplyEsri(reply, GeoCodeReplyEsri::Geocode, this); + + connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), + this, SLOT(replyError(QGeoCodeReply::Error,QString))); + + return geocodeReply; +} + +QGeoCodeReply *GeoCodingManagerEngineEsri::reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) +{ + Q_UNUSED(bounds) + + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent); + + QUrl url(kUrlReverseGeocode); + + QUrlQuery query; + + query.addQueryItem(QStringLiteral("f"), QStringLiteral("json")); + query.addQueryItem(QStringLiteral("langCode"), locale().name().left(2)); + query.addQueryItem(QStringLiteral("location"), QString::number(coordinate.longitude()) + QLatin1Char(',') + + QString::number(coordinate.latitude())); + + url.setQuery(query); + request.setUrl(url); + + QNetworkReply *reply = m_networkManager->get(request); + GeoCodeReplyEsri *geocodeReply = new GeoCodeReplyEsri(reply, GeoCodeReplyEsri::ReverseGeocode, + this); + + connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), + this, SLOT(replyError(QGeoCodeReply::Error,QString))); + + return geocodeReply; +} + +void GeoCodingManagerEngineEsri::replyFinished() +{ + QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender()); + if (reply) + emit finished(reply); +} + +void GeoCodingManagerEngineEsri::replyError(QGeoCodeReply::Error errorCode, + const QString &errorString) +{ + QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender()); + if (reply) + emit error(reply, errorCode, errorString); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h new file mode 100644 index 00000000..9ff246e0 --- /dev/null +++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOCODINGMANAGERENGINEESRI_H +#define GEOCODINGMANAGERENGINEESRI_H + +#include <QGeoServiceProvider> +#include <QGeoCodingManagerEngine> +#include <QGeoCodeReply> + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class GeoCodingManagerEngineEsri : public QGeoCodingManagerEngine +{ + Q_OBJECT + +public: + GeoCodingManagerEngineEsri(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString); + virtual ~GeoCodingManagerEngineEsri(); + + QGeoCodeReply *geocode(const QGeoAddress &address, const QGeoShape &bounds) Q_DECL_OVERRIDE; + QGeoCodeReply *geocode(const QString &address, int limit, int offset, + const QGeoShape &bounds) Q_DECL_OVERRIDE; + QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate, + const QGeoShape &bounds) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void replyFinished(); + void replyError(QGeoCodeReply::Error errorCode, const QString &errorString); + +private: + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; +}; + +QT_END_NAMESPACE + +#endif // GEOCODINGMANAGERENGINEESRI_H diff --git a/src/plugins/geoservices/esri/geomapsource.cpp b/src/plugins/geoservices/esri/geomapsource.cpp new file mode 100644 index 00000000..32fe1899 --- /dev/null +++ b/src/plugins/geoservices/esri/geomapsource.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geomapsource.h" + +#include <QUrl> + +QT_BEGIN_NAMESPACE + +static const QString kArcGISTileScheme(QStringLiteral("/tile/${z}/${y}/${x}")); + +struct MapStyleData +{ + QString name; + QGeoMapType::MapStyle style; +}; + +static const MapStyleData mapStyles[] = +{ + { QStringLiteral("StreetMap"), QGeoMapType::StreetMap }, + { QStringLiteral("SatelliteMapDay"), QGeoMapType::SatelliteMapDay }, + { QStringLiteral("SatelliteMapNight"), QGeoMapType::SatelliteMapNight }, + { QStringLiteral("TerrainMap"), QGeoMapType::TerrainMap }, + { QStringLiteral("HybridMap"), QGeoMapType::HybridMap }, + { QStringLiteral("TransitMap"), QGeoMapType::TransitMap }, + { QStringLiteral("GrayStreetMap"), QGeoMapType::GrayStreetMap }, + { QStringLiteral("PedestrianMap"), QGeoMapType::PedestrianMap }, + { QStringLiteral("CarNavigationMap"), QGeoMapType::CarNavigationMap }, + { QStringLiteral("CustomMap"), QGeoMapType::CustomMap } +}; + +GeoMapSource::GeoMapSource(QGeoMapType::MapStyle style, const QString &name, + const QString &description, bool mobile, bool night, int mapId, + const QString &url, const QString ©right) : + QGeoMapType(style, name, description, mobile, night, mapId), + m_url(url), m_copyright(copyright) +{ +} + +QString GeoMapSource::toFormat(const QString &url) +{ + QString format = url; + + if (!format.contains(QLatin1String("${"))) + format += kArcGISTileScheme; + + format.replace(QLatin1String("${z}"), QLatin1String("%1")); + format.replace(QLatin1String("${x}"), QLatin1String("%2")); + format.replace(QLatin1String("${y}"), QLatin1String("%3")); + format.replace(QLatin1String("${token}"), QLatin1String("%4")); + + return format; +} + +QGeoMapType::MapStyle GeoMapSource::mapStyle(const QString &styleString) +{ + for (unsigned int i = 0; i < sizeof(mapStyles)/sizeof(MapStyle); i++) { + const MapStyleData &mapStyle = mapStyles[i]; + + if (styleString.compare(mapStyle.name, Qt::CaseInsensitive) == 0) + return mapStyle.style; + } + + QGeoMapType::MapStyle style = static_cast<QGeoMapType::MapStyle>(styleString.toInt()); + if (style <= QGeoMapType::NoMap) + style = QGeoMapType::CustomMap; + + return style; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geomapsource.h b/src/plugins/geoservices/esri/geomapsource.h new file mode 100644 index 00000000..8660e999 --- /dev/null +++ b/src/plugins/geoservices/esri/geomapsource.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOMAPSOURCE_H +#define GEOMAPSOURCE_H + +#include <QtLocation/private/qgeomaptype_p.h> + +QT_BEGIN_NAMESPACE + +class GeoMapSource : public QGeoMapType +{ +public: + GeoMapSource(QGeoMapType::MapStyle style, const QString &name, + const QString &description, bool mobile, bool night, int mapId, + const QString &url, const QString ©right); + + inline const QString &url() const; + inline const QString ©right() const; + + static QString toFormat(const QString &url); + static QGeoMapType::MapStyle mapStyle(const QString &styleString); + +private: + QString m_url; + QString m_copyright; +}; + +inline const QString &GeoMapSource::url() const +{ + return m_url; +} + +inline const QString &GeoMapSource::copyright() const +{ + return m_copyright; +} + +QT_END_NAMESPACE + +#endif // GEOMAPSOURCE_H diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp new file mode 100644 index 00000000..30db48f0 --- /dev/null +++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "georoutejsonparser_esri.h" + +#include <QJsonArray> +#include <QGeoRectangle> +#include <QGeoManeuver> +#include <QGeoRouteSegment> + +QT_BEGIN_NAMESPACE + +// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/ + +static const QString kErrorMessage(QStringLiteral("Error %1: %2.")); +static const QString kErrorJson(QStringLiteral("Error: invalide JSON document.")); + +static const QString kErrorKey(QStringLiteral("error")); +static const QString kErrorCodeKey(QStringLiteral("code")); +static const QString kErrorMessageKey(QStringLiteral("message")); +static const QString kErrorDetailsKey(QStringLiteral("details")); +static const QString kDirectionsKey(QStringLiteral("directions")); +static const QString kRoutesKey(QStringLiteral("routes")); +static const QString kBarriersKey(QStringLiteral("barriers")); +static const QString kMessagesKey(QStringLiteral("messages")); +static const QString kDirectionsRouteIdKey(QStringLiteral("routeId")); +static const QString kDirectionsRouteNameKey(QStringLiteral("routeName")); +static const QString kDirectionsSummaryKey(QStringLiteral("summary")); +static const QString kDirectionsTotalLengthKey(QStringLiteral("totalLength")); +static const QString kDirectionsTotalTimeKey(QStringLiteral("totalTime")); +static const QString kDirectionsTotalDriveTimeKey(QStringLiteral("totalDriveTime")); +static const QString kDirectionsEnvelopeKey(QStringLiteral("envelope")); +static const QString kDirectionsEnvelopeXminKey(QStringLiteral("xmin")); +static const QString kDirectionsEnvelopeYminKey(QStringLiteral("ymin")); +static const QString kDirectionsEnvelopeXmaxKey(QStringLiteral("xmax")); +static const QString kDirectionsEnvelopeYmaxKey(QStringLiteral("ymax")); +static const QString kDirectionsFeaturesKey(QStringLiteral("features")); +static const QString kDirectionsFeaturesAttributesKey(QStringLiteral("attributes")); +static const QString kDirectionsFeaturesCompressedGeometryKey(QStringLiteral("compressedGeometry")); +static const QString kDirectionsFeaturesAttributesLengthKey(QStringLiteral("length")); +static const QString kDirectionsFeaturesAttributesTimeKey(QStringLiteral("time")); +static const QString kDirectionsFeaturesAttributesTextKey(QStringLiteral("text")); +static const QString kDirectionsFeaturesAttributesEtaKey(QStringLiteral("ETA")); +static const QString kDirectionsFeaturesAttributesManeuverTypeKey(QStringLiteral("maneuverType")); +static const QString kRoutesFeaturesKey(QStringLiteral("features")); +static const QString kRoutesFeaturesAttributesKey(QStringLiteral("attributes")); +static const QString kRoutesFeaturesObjectIdKey(QStringLiteral("ObjectID")); +static const QString kRoutesFeaturesGeometryKey(QStringLiteral("geometry")); +static const QString kRoutesFeaturesGeometryPathsKey(QStringLiteral("paths")); + +GeoRouteJsonParserEsri::GeoRouteJsonParserEsri(const QJsonDocument &document) +{ + if (!document.isObject()) + { + m_error = kErrorJson; + return; + } + + m_json = document.object(); + if (m_json.contains(kErrorKey)) + { + QJsonObject error = m_json.value(kErrorKey).toObject(); + int code = error.value(kErrorCodeKey).toInt(); + QString message = error.value(kErrorMessageKey).toString(); + + m_error = kErrorMessage.arg(code).arg(message); + return; + } + + parseDirections(); + parseRoutes(); +} + +QList<QGeoRoute> GeoRouteJsonParserEsri::routes() const +{ + return m_routes.values(); +} + +bool GeoRouteJsonParserEsri::isValid() const +{ + return (m_error.isEmpty()); +} + +QString GeoRouteJsonParserEsri::errorString() const +{ + return m_error; +} + +void GeoRouteJsonParserEsri::parseDirections() +{ + QJsonArray directions = m_json.value(kDirectionsKey).toArray(); + foreach (const QJsonValue &direction, directions) + parseDirection(direction.toObject()); +} + +void GeoRouteJsonParserEsri::parseDirection(const QJsonObject &direction) +{ + QGeoRoute &geoRoute = m_routes[direction.value(kDirectionsRouteIdKey).toInt()]; + + // parse summary + geoRoute.setRouteId(direction.value(kDirectionsRouteNameKey).toString()); + + QJsonObject summary = direction.value(kDirectionsSummaryKey).toObject(); + geoRoute.setDistance(summary.value(kDirectionsTotalLengthKey).toDouble()); + + geoRoute.setTravelTime(summary.value(kDirectionsTotalTimeKey).toDouble() * 60); + // default units is minutes, see directionsTimeAttributeName param + + geoRoute.setTravelMode(QGeoRouteRequest::CarTravel); + // default request is time for car, see directionsTimeAttributeName param + + QJsonObject enveloppe = summary.value(kDirectionsEnvelopeKey).toObject(); + + QGeoCoordinate topLeft(enveloppe.value(kDirectionsEnvelopeXminKey).toDouble(), + enveloppe.value(kDirectionsEnvelopeYmaxKey).toDouble()); + QGeoCoordinate bottomRight(enveloppe.value(kDirectionsEnvelopeXmaxKey).toDouble(), + enveloppe.value(kDirectionsEnvelopeYminKey).toDouble()); + geoRoute.setBounds(QGeoRectangle(topLeft, bottomRight)); + + // parse features + QJsonArray features = direction.value(kDirectionsFeaturesKey).toArray(); + + static const QMap<QString, QGeoManeuver::InstructionDirection> esriDirectionsManeuverTypes + { + { QStringLiteral("esriDMTUnknown"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTStop"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTStraight"), QGeoManeuver::DirectionForward }, + { QStringLiteral("esriDMTBearLeft"), QGeoManeuver::DirectionBearLeft }, + { QStringLiteral("esriDMTBearRight"), QGeoManeuver::DirectionBearRight }, + { QStringLiteral("esriDMTTurnLeft"), QGeoManeuver::DirectionLeft }, + { QStringLiteral("esriDMTTurnRight"), QGeoManeuver::DirectionRight }, + { QStringLiteral("esriDMTSharpLeft"), QGeoManeuver::DirectionLightLeft }, + { QStringLiteral("esriDMTSharpRight"), QGeoManeuver::DirectionLightRight }, + { QStringLiteral("esriDMTUTurn"), QGeoManeuver::DirectionUTurnRight }, + { QStringLiteral("esriDMTFerry"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTRoundabout"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayMerge"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayExit"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayChange"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkCenter"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkLeft"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkRight"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTDepart"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTTripItem"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTEndOfFerry"), QGeoManeuver::NoDirection } + }; + + QGeoRouteSegment firstSegment; + for (int i = features.size() - 1; i >= 0; --i) + { + QJsonObject feature = features.at(i).toObject(); + QJsonObject attributes = feature.value(kDirectionsFeaturesAttributesKey).toObject(); + + QGeoRouteSegment segment; + double length = attributes.value(kDirectionsFeaturesAttributesLengthKey).toDouble(); + segment.setDistance(length); + + double time = attributes.value(kDirectionsFeaturesAttributesTimeKey).toDouble() * 60; + // default units is minutes, see directionsTimeAttributeName param + segment.setTravelTime(time); + + QGeoManeuver maneuver; + QString type = attributes.value(kDirectionsFeaturesAttributesManeuverTypeKey).toString(); + maneuver.setDirection(esriDirectionsManeuverTypes.value(type)); + + maneuver.setInstructionText(attributes.value(kDirectionsFeaturesAttributesTextKey).toString() + "."); + maneuver.setDistanceToNextInstruction(length); + maneuver.setTimeToNextInstruction(time); + + segment.setManeuver(maneuver); + + segment.setNextRouteSegment(firstSegment); + firstSegment = segment; + } + geoRoute.setFirstRouteSegment(firstSegment); +} + +void GeoRouteJsonParserEsri::parseRoutes() +{ + QJsonObject routes = m_json.value(kRoutesKey).toObject(); + QJsonArray features = routes.value(kRoutesFeaturesKey).toArray(); + foreach (const QJsonValue &feature, features) + parseRoute(feature.toObject()); +} + +void GeoRouteJsonParserEsri::parseRoute(const QJsonObject &route) +{ + QJsonObject attributes = route.value(kRoutesFeaturesAttributesKey).toObject(); + QGeoRoute &geoRoute = m_routes[attributes.value(kRoutesFeaturesObjectIdKey).toInt()]; + + QJsonObject geometry = route.value(kRoutesFeaturesGeometryKey).toObject(); + QJsonArray paths = geometry.value(kRoutesFeaturesGeometryPathsKey).toArray(); + + if (!paths.isEmpty()) + { + QList<QGeoCoordinate> geoCoordinates; + foreach (const QJsonValue &value, paths.first().toArray()) // only first polyline? + { + QJsonArray geoCoordinate = value.toArray(); + if (geoCoordinate.size() == 2) // ignore 3rd coordinate + { + geoCoordinates.append(QGeoCoordinate(geoCoordinate[1].toDouble(), + geoCoordinate[0].toDouble())); + } + } + geoRoute.setPath(geoCoordinates); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.h b/src/plugins/geoservices/esri/georoutejsonparser_esri.h new file mode 100644 index 00000000..0511cf4d --- /dev/null +++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOROUTEJSONPARSERESRI_H +#define GEOROUTEJSONPARSERESRI_H + +#include <QJsonDocument> +#include <QJsonObject> +#include <QGeoRoute> +#include <QMap> + +QT_BEGIN_NAMESPACE + +class GeoRouteJsonParserEsri +{ +public: + GeoRouteJsonParserEsri(const QJsonDocument &document); + + QList<QGeoRoute> routes() const; + bool isValid() const; + QString errorString() const; + +private: + void parseDirections(); + void parseDirection(const QJsonObject &direction); + void parseRoutes(); + void parseRoute(const QJsonObject &route); + + QString m_error; + QMap<int, QGeoRoute> m_routes; + QJsonObject m_json; +}; + +QT_END_NAMESPACE + +#endif // GEOROUTEJSONPARSERESRI_H diff --git a/src/plugins/geoservices/esri/georoutereply_esri.cpp b/src/plugins/geoservices/esri/georoutereply_esri.cpp new file mode 100644 index 00000000..4a7d5c67 --- /dev/null +++ b/src/plugins/geoservices/esri/georoutereply_esri.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "georoutereply_esri.h" +#include "georoutejsonparser_esri.h" + +#include <QJsonDocument> + +QT_BEGIN_NAMESPACE + +// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/ + +GeoRouteReplyEsri::GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request, + QObject *parent) : + QGeoRouteReply(request, parent), m_reply(reply) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); +} + +GeoRouteReplyEsri::~GeoRouteReplyEsri() +{ + if (m_reply) + m_reply->deleteLater(); +} + +void GeoRouteReplyEsri::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +void GeoRouteReplyEsri::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + { + setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; + return; + } + + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + GeoRouteJsonParserEsri parser(document); + + if (parser.isValid()) + { + setRoutes(parser.routes()); + setFinished(true); + } else { + setError(QGeoRouteReply::ParseError, parser.errorString()); + } + + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +void GeoRouteReplyEsri::networkReplyError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + + if (!m_reply) + return; + + setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/georoutereply_esri.h b/src/plugins/geoservices/esri/georoutereply_esri.h new file mode 100644 index 00000000..6e97ee9f --- /dev/null +++ b/src/plugins/geoservices/esri/georoutereply_esri.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOROUTEREPLYESRI_H +#define GEOROUTEREPLYESRI_H + +#include <QNetworkReply> +#include <QGeoRouteReply> + +QT_BEGIN_NAMESPACE + +class GeoRouteReplyEsri : public QGeoRouteReply +{ + Q_OBJECT + +public: + GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = Q_NULLPTR); + virtual ~GeoRouteReplyEsri(); + + void abort() Q_DECL_OVERRIDE; + +private Q_SLOTS: + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // GEOROUTEREPLYESRI_H diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp new file mode 100644 index 00000000..ae722e59 --- /dev/null +++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "georoutingmanagerengine_esri.h" +#include "georoutereply_esri.h" + +#include <QUrlQuery> + +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 kUrlRouting(QStringLiteral("http://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve")); + +GeoRoutingManagerEngineEsri::GeoRoutingManagerEngineEsri(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) : + QGeoRoutingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) +{ + if (parameters.contains(kParamUserAgent)) + m_userAgent = parameters.value(kParamUserAgent).toString().toLatin1(); + else + m_userAgent = QByteArrayLiteral("Qt Location based application"); + + m_token = parameters.value(kParamToken).toString(); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +GeoRoutingManagerEngineEsri::~GeoRoutingManagerEngineEsri() +{ +} + +// REST reference: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000 + +QGeoRouteReply *GeoRoutingManagerEngineEsri::calculateRoute(const QGeoRouteRequest &request) +{ + QNetworkRequest networkRequest; + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent); + + QUrl url(kUrlRouting); + QUrlQuery query; + QString stops; + + foreach (const QGeoCoordinate &coordinate, request.waypoints()) + { + if (!stops.isEmpty()) + stops += "; "; + + stops += QString::number(coordinate.longitude()) + QLatin1Char(',') + + QString::number(coordinate.latitude()); + } + + query.addQueryItem(QStringLiteral("stops"), stops); + query.addQueryItem(QStringLiteral("f"), QStringLiteral("json")); + query.addQueryItem(QStringLiteral("directionsLanguage"), preferedDirectionLangage()); + query.addQueryItem(QStringLiteral("directionsLengthUnits"), preferedDirectionsLengthUnits()); + query.addQueryItem(QStringLiteral("token"), m_token); + + url.setQuery(query); + networkRequest.setUrl(url); + + QNetworkReply *reply = m_networkManager->get(networkRequest); + GeoRouteReplyEsri *routeReply = new GeoRouteReplyEsri(reply, request, this); + + connect(routeReply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(routeReply, SIGNAL(error(QGeoRouteReply::Error,QString)), this, SLOT(replyError(QGeoRouteReply::Error,QString))); + + return routeReply; +} + +void GeoRoutingManagerEngineEsri::replyFinished() +{ + QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender()); + if (reply) + emit finished(reply); +} + +void GeoRoutingManagerEngineEsri::replyError(QGeoRouteReply::Error errorCode, const QString &errorString) +{ + QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender()); + if (reply) + emit error(reply, errorCode, errorString); +} + +QString GeoRoutingManagerEngineEsri::preferedDirectionLangage() +{ + // list of supported langages is defined in: + // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000 + const QStringList supportedLanguages = { + "ar", // Generate directions in Arabic + "cs", // Generate directions in Czech + "de", // Generate directions in German + "el", // Generate directions in Greek + "en", // Generate directions in English (default) + "es", // Generate directions in Spanish + "et", // Generate directions in Estonian + "fr", // Generate directions in French + "he", // Generate directions in Hebrew + "it", // Generate directions in Italian + "ja", // Generate directions in Japanese + "ko", // Generate directions in Korean + "lt", // Generate directions in Lithuanian + "lv", // Generate directions in Latvian + "nl", // Generate directions in Dutch + "pl", // Generate directions in Polish + "pt-BR", // Generate directions in Brazilian Portuguese + "pt-PT", // Generate directions in Portuguese (Portugal) + "ru", // Generate directions in Russian + "sv", // Generate directions in Swedish + "tr", // Generate directions in Turkish + "zh-CN" // Simplified Chinese + }; + + for (const QString &language: locale().uiLanguages()) + { + if (language.startsWith("pt_BR")) // Portuguese (Brazilian) + return QStringLiteral("pt-BR"); + if (language.startsWith("pt")) // Portuguese (Portugal) + return QStringLiteral("pt-PT"); + if (language.startsWith("zh")) // Portuguese (Portugal) + return QStringLiteral("zh-CN"); + + const QString country = language.left(2); + if (supportedLanguages.contains(country)) + return country; + } + return QStringLiteral("en"); // default value +} + +QString GeoRoutingManagerEngineEsri::preferedDirectionsLengthUnits() +{ + switch (measurementSystem()) + { + case QLocale::MetricSystem: + return QStringLiteral("esriNAUMeters"); + break; + case QLocale::ImperialUSSystem: + return QStringLiteral( "esriNAUFeet"); + break; + case QLocale::ImperialUKSystem: + return QStringLiteral("esriNAUFeet"); + break; + default: + return QStringLiteral("esriNAUMeters"); + break; + } + return QStringLiteral("esriNAUMeters"); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h new file mode 100644 index 00000000..7387e25c --- /dev/null +++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOROUTINGMANAGERENGINEESRI_H +#define GEOROUTINGMANAGERENGINEESRI_H + +#include <QGeoServiceProvider> +#include <QGeoRoutingManagerEngine> + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; + +class GeoRoutingManagerEngineEsri : public QGeoRoutingManagerEngine +{ + Q_OBJECT + +public: + GeoRoutingManagerEngineEsri(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString); + virtual ~GeoRoutingManagerEngineEsri(); + + QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void replyFinished(); + void replyError(QGeoRouteReply::Error errorCode, const QString &errorString); + +private: + QString preferedDirectionLangage(); + QString preferedDirectionsLengthUnits(); + + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; + QString m_token; +}; + +QT_END_NAMESPACE + +#endif // GEOROUTINGMANAGERENGINEESRI_H diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp new file mode 100644 index 00000000..5277cde3 --- /dev/null +++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geoserviceproviderfactory_esri.h" +#include "geotiledmappingmanagerengine_esri.h" +#include "geocodingmanagerengine_esri.h" +#include "georoutingmanagerengine_esri.h" + +#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h> + +QT_BEGIN_NAMESPACE + +QGeoCodingManagerEngine *GeoServiceProviderFactoryEsri::createGeocodingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new GeoCodingManagerEngineEsri(parameters, error, errorString); +} + +QGeoMappingManagerEngine *GeoServiceProviderFactoryEsri::createMappingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + return new GeoTiledMappingManagerEngineEsri(parameters, error, errorString); +} + +QGeoRoutingManagerEngine *GeoServiceProviderFactoryEsri::createRoutingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + const QString token = parameters.value(QStringLiteral("esri.token")).toString(); + + if (!token.isEmpty()) { + return new GeoRoutingManagerEngineEsri(parameters, error, errorString); + } else { + *error = QGeoServiceProvider::MissingRequiredParameterError; + *errorString = tr("Esri plugin requires a 'esri.token' parameter.\n" + "Please visit https://developers.arcgis.com/authentication/accessing-arcgis-online-services/"); + return 0; + } +} + +QPlaceManagerEngine *GeoServiceProviderFactoryEsri::createPlaceManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h new file mode 100644 index 00000000..d198c75a --- /dev/null +++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOSERVICEPROVIDERFACTORYESRI_H +#define GEOSERVICEPROVIDERFACTORYESRI_H + +#include <QObject> +#include <QGeoServiceProviderFactory> + +QT_BEGIN_NAMESPACE + +class GeoServiceProviderFactoryEsri: public QObject, public QGeoServiceProviderFactory +{ + Q_OBJECT + Q_INTERFACES(QGeoServiceProviderFactory) + Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0" + FILE "esri_plugin.json") + +public: + QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const Q_DECL_OVERRIDE; + QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const Q_DECL_OVERRIDE; + QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const Q_DECL_OVERRIDE; + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif // GEOSERVICEPROVIDERFACTORYESRI_H diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.cpp b/src/plugins/geoservices/esri/geotiledmap_esri.cpp new file mode 100644 index 00000000..9171fc2b --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmap_esri.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geotiledmap_esri.h" +#include "geotiledmappingmanagerengine_esri.h" + +#include <QtLocation/private/qgeotilespec_p.h> + +QT_BEGIN_NAMESPACE + +GeoTiledMapEsri::GeoTiledMapEsri(GeoTiledMappingManagerEngineEsri *engine, QObject *parent) : + QGeoTiledMap(engine, parent), m_engine(engine), m_mapId(-1) +{ +} + +GeoTiledMapEsri::~GeoTiledMapEsri() +{ +} + +void GeoTiledMapEsri::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles) +{ + if (visibleTiles.isEmpty()) + return; + + QGeoTileSpec tile = *(visibleTiles.constBegin()); + if (tile.mapId() == m_mapId) + return; + + m_mapId = tile.mapId(); + + GeoMapSource *mapSource = engine()->mapSource(m_mapId); + + if (mapSource) + emit copyrightsChanged(mapSource->copyright()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.h b/src/plugins/geoservices/esri/geotiledmap_esri.h new file mode 100644 index 00000000..d9d9d0b7 --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmap_esri.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOTILEDMAPESRI_H +#define GEOTILEDMAPESRI_H + +#include <QtLocation/private/qgeotiledmap_p.h> + +QT_BEGIN_NAMESPACE + +class GeoTiledMappingManagerEngineEsri; + +class GeoTiledMapEsri: public QGeoTiledMap +{ + Q_OBJECT + +public: + explicit GeoTiledMapEsri(GeoTiledMappingManagerEngineEsri *engine, QObject *parent = Q_NULLPTR); + virtual ~GeoTiledMapEsri(); + +protected: + void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles) Q_DECL_OVERRIDE; + + inline GeoTiledMappingManagerEngineEsri *engine() const; + +private: + GeoTiledMappingManagerEngineEsri *m_engine; + int m_mapId; +}; + +inline GeoTiledMappingManagerEngineEsri *GeoTiledMapEsri::engine() const +{ + return m_engine; +} + +QT_END_NAMESPACE + +#endif // GEOTILEDMAPESRI_H diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp new file mode 100644 index 00000000..396d0f57 --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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> + +static void initResources() +{ + Q_INIT_RESOURCE(esri); +} + +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); + + setCameraCapabilities(cameraCaps); + + setTileSize(QSize(256, 256)); + + if (!initializeMapSources(error, errorString)) + return; + + QList<QGeoMapType> mapTypes; + + foreach (GeoMapSource *mapSource, m_mapSources) { + mapTypes << QGeoMapType( + mapSource->style(), + mapSource->name(), + mapSource->description(), + mapSource->mobile(), + mapSource->night(), + mapSource->mapId()); + } + + 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); + + *error = QGeoServiceProvider::NoError; + errorString->clear(); +} + +GeoTiledMappingManagerEngineEsri::~GeoTiledMappingManagerEngineEsri() +{ + qDeleteAll(m_mapSources); +} + +QGeoMap *GeoTiledMappingManagerEngineEsri::createMap() +{ + return new GeoTiledMapEsri(this); +} + +// ${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) +{ + initResources(); + QFile mapsFile(":/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 = mapSource[kPropMapId].toInt(); + if (mapId <= 0) + 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() + ); + } + + return true; +} + +GeoMapSource *GeoTiledMappingManagerEngineEsri::mapSource(int mapId) const +{ + foreach (GeoMapSource *mapSource, mapSources()) { + if (mapSource->mapId() == mapId) + return mapSource; + } + + return Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h new file mode 100644 index 00000000..a13ba05c --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOTILEDMAPPINGMANAGERENGINEESRI_H +#define GEOTILEDMAPPINGMANAGERENGINEESRI_H + +#include <QGeoServiceProvider> + +#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h> + +#include "geomapsource.h" + +QT_BEGIN_NAMESPACE + +class GeoTiledMappingManagerEngineEsri : public QGeoTiledMappingManagerEngine +{ + Q_OBJECT + +public: + GeoTiledMappingManagerEngineEsri(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString); + virtual ~GeoTiledMappingManagerEngineEsri(); + + QGeoMap *createMap() Q_DECL_OVERRIDE; + + inline const QList<GeoMapSource *>& mapSources() const; + GeoMapSource *mapSource(int mapId) const; + +private: + bool initializeMapSources(QGeoServiceProvider::Error *error, QString *errorString); + + QList<GeoMapSource *> m_mapSources; +}; + +inline const QList<GeoMapSource *>& GeoTiledMappingManagerEngineEsri::mapSources() const +{ + return m_mapSources; +} + +QT_END_NAMESPACE + +#endif // GEOTILEDMAPPINGMANAGERENGINEESRI_H diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp new file mode 100644 index 00000000..e0816c15 --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geotiledmapreply_esri.h" + +#include <QtLocation/private/qgeotilespec_p.h> + +QT_BEGIN_NAMESPACE + +static const unsigned char pngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00}; +static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00}; +static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00}; + +GeoTiledMapReplyEsri::GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec, + QObject *parent) : + QGeoTiledMapReply(spec, parent), m_reply(reply) +{ + connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(m_reply, SIGNAL(destroyed()), this, SLOT(replyDestroyed())); +} + +GeoTiledMapReplyEsri::~GeoTiledMapReplyEsri() +{ + if (m_reply) { + m_reply->deleteLater(); + m_reply = Q_NULLPTR; + } +} + +void GeoTiledMapReplyEsri::abort() +{ + if (!m_reply) + return; + + m_reply->abort(); + QGeoTiledMapReply::abort(); +} + +void GeoTiledMapReplyEsri::replyDestroyed() +{ + m_reply = Q_NULLPTR; +} + +void GeoTiledMapReplyEsri::networkReplyFinished() +{ + if (!m_reply) + return; + + if (m_reply->error() != QNetworkReply::NoError) + { + setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; + return; + } + + QByteArray const& imageData = m_reply->readAll(); + + bool validFormat = true; + if (imageData.startsWith(reinterpret_cast<const char*>(pngSignature))) + setMapImageFormat(QStringLiteral("png")); + else if (imageData.startsWith(reinterpret_cast<const char*>(jpegSignature))) + setMapImageFormat(QStringLiteral("jpg")); + else if (imageData.startsWith(reinterpret_cast<const char*>(gifSignature))) + setMapImageFormat(QStringLiteral("gif")); + else + validFormat = false; + + if (validFormat) + setMapImageData(imageData); + + setFinished(true); + + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +void GeoTiledMapReplyEsri::networkReplyError(QNetworkReply::NetworkError error) +{ + if (!m_reply) + return; + + if (error != QNetworkReply::OperationCanceledError) + setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); + + setFinished(true); + m_reply->deleteLater(); + m_reply = Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.h b/src/plugins/geoservices/esri/geotiledmapreply_esri.h new file mode 100644 index 00000000..32a35698 --- /dev/null +++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOTILEDMAPREPLYESRI_H +#define GEOTILEDMAPREPLYESRI_H + +#include <QNetworkReply> + +#include <QtLocation/private/qgeotiledmapreply_p.h> + +QT_BEGIN_NAMESPACE + +class GeoTiledMapReplyEsri : public QGeoTiledMapReply +{ + Q_OBJECT + +public: + GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent = Q_NULLPTR); + virtual ~GeoTiledMapReplyEsri(); + + void abort() Q_DECL_OVERRIDE; + +private Q_SLOTS: + void replyDestroyed(); + void networkReplyFinished(); + void networkReplyError(QNetworkReply::NetworkError error); + +private: + QNetworkReply *m_reply; +}; + +QT_END_NAMESPACE + +#endif // GEOTILEDMAPREPLYESRI_H diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.cpp b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp new file mode 100644 index 00000000..62484bbb --- /dev/null +++ b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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 "geotilefetcher_esri.h" +#include "geotiledmappingmanagerengine_esri.h" +#include "geotiledmapreply_esri.h" + +#include <QNetworkAccessManager> +#include <QNetworkRequest> + +#include <QtLocation/private/qgeotilespec_p.h> + +QT_BEGIN_NAMESPACE + +GeoTileFetcherEsri::GeoTileFetcherEsri(QObject *parent) : + QGeoTileFetcher(parent), m_networkManager(new QNetworkAccessManager(this)), + m_userAgent(QByteArrayLiteral("Qt Location based application")) +{ +} + +QGeoTiledMapReply *GeoTileFetcherEsri::getTileImage(const QGeoTileSpec &spec) +{ + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, userAgent()); + + GeoTiledMappingManagerEngineEsri *engine = qobject_cast<GeoTiledMappingManagerEngineEsri *>( + parent()); + + GeoMapSource *mapSource = engine->mapSource(spec.mapId()); + + if (!mapSource) + qWarning("Unknown mapId %d\n", spec.mapId()); + else + request.setUrl(mapSource->url().arg(spec.zoom()).arg(spec.x()).arg(spec.y())); + + QNetworkReply *reply = m_networkManager->get(request); + + return new GeoTiledMapReplyEsri(reply, spec); +} + +QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.h b/src/plugins/geoservices/esri/geotilefetcher_esri.h new file mode 100644 index 00000000..43dcfdfa --- /dev/null +++ b/src/plugins/geoservices/esri/geotilefetcher_esri.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 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$ +** +****************************************************************************/ + +#ifndef GEOTILEFETCHERESRI_H +#define GEOTILEFETCHERESRI_H + +#include <QtLocation/private/qgeotilefetcher_p.h> + +QT_BEGIN_NAMESPACE + +class QGeoTiledMappingManagerEngine; +class QNetworkAccessManager; + +class GeoTileFetcherEsri : public QGeoTileFetcher +{ + Q_OBJECT + +public: + explicit GeoTileFetcherEsri(QObject *parent = Q_NULLPTR); + + inline const QByteArray &userAgent() const; + inline void setUserAgent(const QByteArray &userAgent); + + inline const QString &token() const; + inline void setToken(const QString &token); + +private: + QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) Q_DECL_OVERRIDE; + + QNetworkAccessManager *m_networkManager; + QByteArray m_userAgent; + QString m_token; +}; + +inline const QByteArray &GeoTileFetcherEsri::userAgent() const +{ + return m_userAgent; +} + +inline void GeoTileFetcherEsri::setUserAgent(const QByteArray &userAgent) +{ + m_userAgent = userAgent; +} + +inline const QString &GeoTileFetcherEsri::token() const +{ + return m_token; +} + +inline void GeoTileFetcherEsri::setToken(const QString &token) +{ + m_token = token; +} + +QT_END_NAMESPACE + +#endif // GEOTILEFETCHERESRI_H diff --git a/src/plugins/geoservices/esri/maps.json b/src/plugins/geoservices/esri/maps.json new file mode 100644 index 00000000..8167ae7d --- /dev/null +++ b/src/plugins/geoservices/esri/maps.json @@ -0,0 +1,123 @@ +{ + "mapSources": [ + { + "style": "StreetMap", + "name": "World Street Map", + "description": "ArcGIS Online World Street Map", + "mobile": true, + "night": false, + "url": "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=3b93337983e9436f8db950e38a8629af'>Esri</a> contributors" + }, + + { + "style": "SatelliteMapDay", + "name": "World Imagery", + "": "ArcGIS Online World Imagery", + "mobile": true, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'>Esri</a> contributors" + }, + + { + "style": "TerrainMap", + "name": "World Terrain Base", + "description": "ArcGIS Online World Terrain Base", + "mobile": false, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=c61ad8ab017d49e1a82f580ee1298931'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "World Topography", + "description": "ArcGIS Online World Topography", + "mobile": true, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=30e5fe3149c34df1ba922e6f5bbf808f'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "USA Topo Maps", + "description": "This map presents land cover and detailed topographic maps for the United States.", + "mobile": true, + "night": false, + "url": "http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=99cd5fbd98934028802b4f797c4b1732'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "National Geographic World Map", + "description": "National Geographic World Map", + "mobile": false, + "night": false, + "url": "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=b9b1b422198944fbbd5250b3241691b6'>Esri</a> contributors" + }, + + { + "style": "GrayStreetMap", + "name": "Light Gray Canvas", + "description": "Thematic content providing a neutral background with minimal colors", + "mobile": true, + "night": false, + "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=ed712cb1db3e4bae9e85329040fb9a49'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "World Physical Map", + "description": "Natural Earth physical map for the world", + "mobile": false, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=c4ec722a1cd34cf0a23904aadf8923a0'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "World Shaded Relief", + "description": "Portrays surface elevation as shaded relief", + "mobile": false, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=9c5370d0b54f4de1b48a3792d7377ff2'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "World Ocean Base", + "description": "This map is designed to be used as a basemap by marine GIS professionals and as a reference map by anyone interested in ocean data", + "mobile": false, + "night": false, + "url": "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=1e126e7520f9466c9ca28b8f28b5e500'>Esri</a> contributors" + }, + + { + "style": "GrayStreetMap", + "name": "Dark Gray Canvas", + "description": "Thematic content providing a neutral background with minimal colors", + "mobile": false, + "night": true, + "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=a284a9b99b3446a3910d4144a50990f6'>Esri</a> contributors" + }, + + { + "style": "CustomMap", + "name": "DeLorme World Basemap", + "description": "DeLorme’s topographic basemap is a seamless global data set that portrays transportation, hydrography, jurisdiction boundaries, and major geographic features", + "mobile": false, + "night": false, + "url": "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer", + "copyrightText": "© <a href='http://www.arcgis.com/home/item.html?id=b165c3df453e4be6b5ac4fdb241effbe'>Esri</a> contributors" + } + ] +} diff --git a/src/plugins/geoservices/geoservices.pro b/src/plugins/geoservices/geoservices.pro index 3d0971f7..7a392b57 100644 --- a/src/plugins/geoservices/geoservices.pro +++ b/src/plugins/geoservices/geoservices.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = nokia osm mapbox +SUBDIRS = nokia osm mapbox esri diff --git a/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp index f6fe2d71..121253fa 100644 --- a/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp +++ b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp @@ -65,13 +65,14 @@ void tst_QGeoServiceProvider::tst_availableServiceProvider() const QStringList provider = QGeoServiceProvider::availableServiceProviders(); // Currently provided plugins - if (provider.count() != 7) + if (provider.count() != 8) qWarning() << provider; - QCOMPARE(provider.count(), 7); + QCOMPARE(provider.count(), 8); // these providers are deployed QVERIFY(provider.contains(QStringLiteral("mapbox"))); QVERIFY(provider.contains(QStringLiteral("here"))); QVERIFY(provider.contains(QStringLiteral("osm"))); + QVERIFY(provider.contains(QStringLiteral("esri"))); // these providers exist for unit tests only QVERIFY(provider.contains(QStringLiteral("geocode.test.plugin"))); QVERIFY(provider.contains(QStringLiteral("georoute.test.plugin"))); @@ -124,6 +125,13 @@ void tst_QGeoServiceProvider::tst_features_data() | QGeoServiceProvider::ReverseGeocodingFeature) << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature) << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::OnlinePlacesFeature); + + QTest::newRow("esri") << QString("esri") + << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature) + << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::OnlineGeocodingFeature + | QGeoServiceProvider::ReverseGeocodingFeature) + << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature) + << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::NoPlacesFeatures); } void tst_QGeoServiceProvider::tst_features() |