| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.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 "qgeocodingmanagerengineosm.h" |
| |
| #include <QtCore/QVariantMap> |
| #include <QtCore/QUrl> |
| #include <QtCore/QUrlQuery> |
| #include <QtCore/QLocale> |
| #include <QtNetwork/QNetworkAccessManager> |
| #include <QtNetwork/QNetworkRequest> |
| #include <QtPositioning/QGeoCoordinate> |
| #include <QtPositioning/QGeoAddress> |
| #include <QtPositioning/QGeoShape> |
| #include <QtPositioning/QGeoRectangle> |
| #include "qgeocodereplyosm.h" |
| |
| |
| QT_BEGIN_NAMESPACE |
| |
| 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()); |
| } |
| |
| QGeoCodingManagerEngineOsm::QGeoCodingManagerEngineOsm(const QVariantMap ¶meters, |
| QGeoServiceProvider::Error *error, |
| QString *errorString) |
| : QGeoCodingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) |
| { |
| if (parameters.contains(QStringLiteral("osm.useragent"))) |
| m_userAgent = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1(); |
| else |
| m_userAgent = "Qt Location based application"; |
| |
| if (parameters.contains(QStringLiteral("osm.geocoding.host"))) |
| m_urlPrefix = parameters.value(QStringLiteral("osm.geocoding.host")).toString().toLatin1(); |
| else |
| m_urlPrefix = QStringLiteral("https://nominatim.openstreetmap.org"); |
| |
| if (parameters.contains(QStringLiteral("osm.geocoding.debug_query"))) |
| m_debugQuery = parameters.value(QStringLiteral("osm.geocoding.debug_query")).toBool(); |
| if (parameters.contains(QStringLiteral("osm.geocoding.include_extended_data"))) |
| m_includeExtraData = parameters.value(QStringLiteral("osm.geocoding.include_extended_data")).toBool(); |
| |
| *error = QGeoServiceProvider::NoError; |
| errorString->clear(); |
| } |
| |
| QGeoCodingManagerEngineOsm::~QGeoCodingManagerEngineOsm() |
| { |
| } |
| |
| QGeoCodeReply *QGeoCodingManagerEngineOsm::geocode(const QGeoAddress &address, const QGeoShape &bounds) |
| { |
| return geocode(addressToQuery(address), -1, -1, bounds); |
| } |
| |
| QGeoCodeReply *QGeoCodingManagerEngineOsm::geocode(const QString &address, int limit, int offset, const QGeoShape &bounds) |
| { |
| Q_UNUSED(offset); |
| |
| QNetworkRequest request; |
| request.setRawHeader("User-Agent", m_userAgent); |
| |
| QUrl url(QString("%1/search").arg(m_urlPrefix)); |
| QUrlQuery query; |
| query.addQueryItem(QStringLiteral("q"), address); |
| query.addQueryItem(QStringLiteral("format"), QStringLiteral("json")); |
| query.addQueryItem(QStringLiteral("accept-language"), locale().name().left(2)); |
| //query.addQueryItem(QStringLiteral("countrycodes"), QStringLiteral("au,jp")); |
| if (bounds.type() != QGeoShape::UnknownType) { |
| query.addQueryItem(QStringLiteral("viewbox"), boundingBoxToLtrb(bounds.boundingGeoRectangle())); |
| query.addQueryItem(QStringLiteral("bounded"), QStringLiteral("1")); |
| } |
| query.addQueryItem(QStringLiteral("polygon_geojson"), QStringLiteral("1")); |
| query.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1")); |
| if (limit != -1) |
| query.addQueryItem(QStringLiteral("limit"), QString::number(limit)); |
| |
| url.setQuery(query); |
| request.setUrl(url); |
| |
| QNetworkReply *reply = m_networkManager->get(request); |
| |
| QGeoCodeReplyOsm *geocodeReply = new QGeoCodeReplyOsm(reply, m_includeExtraData, this); |
| if (m_debugQuery) { |
| QGeoCodeReplyOsmPrivate *replyPrivate |
| = static_cast<QGeoCodeReplyOsmPrivate *>(QGeoCodeReplyPrivate::get(*geocodeReply)); |
| replyPrivate->m_extraData["request_url"] = url; |
| } |
| |
| connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); |
| connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), |
| this, SLOT(replyError(QGeoCodeReply::Error,QString))); |
| |
| return geocodeReply; |
| } |
| |
| QGeoCodeReply *QGeoCodingManagerEngineOsm::reverseGeocode(const QGeoCoordinate &coordinate, |
| const QGeoShape &bounds) |
| { |
| Q_UNUSED(bounds); |
| |
| QNetworkRequest request; |
| request.setRawHeader("User-Agent", m_userAgent); |
| |
| QUrl url(QString("%1/reverse").arg(m_urlPrefix)); |
| QUrlQuery query; |
| query.addQueryItem(QStringLiteral("format"), QStringLiteral("json")); |
| query.addQueryItem(QStringLiteral("accept-language"), locale().name().left(2)); |
| query.addQueryItem(QStringLiteral("lat"), QString::number(coordinate.latitude())); |
| query.addQueryItem(QStringLiteral("lon"), QString::number(coordinate.longitude())); |
| query.addQueryItem(QStringLiteral("zoom"), QStringLiteral("18")); |
| query.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1")); |
| |
| url.setQuery(query); |
| request.setUrl(url); |
| |
| QNetworkReply *reply = m_networkManager->get(request); |
| |
| QGeoCodeReplyOsm *geocodeReply = new QGeoCodeReplyOsm(reply, m_includeExtraData, this); |
| if (m_debugQuery) { |
| QGeoCodeReplyOsmPrivate *replyPrivate |
| = static_cast<QGeoCodeReplyOsmPrivate *>(QGeoCodeReplyPrivate::get(*geocodeReply)); |
| replyPrivate->m_extraData["request_url"] = url; |
| } |
| |
| connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished())); |
| connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)), |
| this, SLOT(replyError(QGeoCodeReply::Error,QString))); |
| |
| return geocodeReply; |
| } |
| |
| void QGeoCodingManagerEngineOsm::replyFinished() |
| { |
| QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender()); |
| if (reply) |
| emit finished(reply); |
| } |
| |
| void QGeoCodingManagerEngineOsm::replyError(QGeoCodeReply::Error errorCode, const QString &errorString) |
| { |
| QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender()); |
| if (reply) |
| emit error(reply, errorCode, errorString); |
| } |
| |
| QT_END_NAMESPACE |