File indexing completed on 2025-02-02 05:02:32
0001 /* 0002 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "navigationcontroller.h" 0008 #include "logging.h" 0009 0010 #include <KItinerary/LocationUtil> 0011 #include <KItinerary/Place> 0012 0013 #include <QCoreApplication> 0014 #include <QDebug> 0015 #include <QDesktopServices> 0016 #include <QUrl> 0017 #include <QUrlQuery> 0018 0019 #ifdef Q_OS_ANDROID 0020 #include "kandroidextras/activity.h" 0021 #include "kandroidextras/intent.h" 0022 #else 0023 #include <QGeoPositionInfo> 0024 #include <QGeoPositionInfoSource> 0025 #endif 0026 0027 using namespace KItinerary; 0028 0029 #ifdef Q_OS_ANDROID 0030 static bool startActivity(const QUrl &url) 0031 { 0032 using namespace KAndroidExtras; 0033 0034 Intent intent; 0035 intent.setAction(Intent::ACTION_VIEW); 0036 intent.setData(url); 0037 return Activity::startActivity(intent, 0); 0038 } 0039 #endif 0040 0041 void NavigationController::showOnMap(const QVariant &place) 0042 { 0043 if (place.isNull()) { 0044 return; 0045 } 0046 0047 const auto geo = LocationUtil::geo(place); 0048 if (geo.isValid()) { 0049 // zoom out further from airports, they are larger and you usually want to go further away from them 0050 showOnMap(geo.latitude(), geo.longitude(), place.userType() == qMetaTypeId<Airport>() ? 12 : 17); 0051 return; 0052 } 0053 0054 const auto addr = LocationUtil::address(place); 0055 if (!addr.isEmpty()) { 0056 QDesktopServices::openUrl(LocationUtil::geoUri(place)); 0057 } 0058 } 0059 0060 void NavigationController::showOnMap(float latitude, float longitude, int zoom) 0061 { 0062 QUrl url; 0063 url.setScheme(QStringLiteral("geo")); 0064 url.setPath(QString::number(latitude) + QLatin1Char(',') + QString::number(longitude)); 0065 QUrlQuery query; 0066 query.addQueryItem(QStringLiteral("z"), QString::number(zoom)); 0067 url.setQuery(query); 0068 QDesktopServices::openUrl(url); 0069 } 0070 0071 void NavigationController::showOnWheelmap(float latitude, float longitude) 0072 { 0073 QUrl url; 0074 url.setScheme(QStringLiteral("https")); 0075 url.setHost(QStringLiteral("wheelmap.org")); 0076 QUrlQuery query; 0077 query.addQueryItem(QStringLiteral("lat"), QString::number(latitude)); 0078 query.addQueryItem(QStringLiteral("lon"), QString::number(longitude)); 0079 url.setQuery(query); 0080 QDesktopServices::openUrl(url); 0081 } 0082 0083 bool NavigationController::canNavigateTo(const QVariant& place) 0084 { 0085 if (place.isNull()) { 0086 return false; 0087 } 0088 0089 if (LocationUtil::geo(place).isValid()) { 0090 return true; 0091 } 0092 0093 #ifdef Q_OS_ANDROID 0094 return !LocationUtil::address(place).isEmpty(); 0095 #else 0096 return false; 0097 #endif 0098 } 0099 0100 void NavigationController::navigateTo(const QVariant& place) 0101 { 0102 if (place.isNull()) { 0103 return; 0104 } 0105 0106 #ifdef Q_OS_ANDROID 0107 const auto geo = LocationUtil::geo(place);; 0108 const auto addr = LocationUtil::address(place); 0109 0110 QUrl url; 0111 url.setScheme(QStringLiteral("google.navigation")); 0112 if (geo.isValid()) { 0113 url.setPath(QLatin1StringView("q=") + QString::number(geo.latitude())+ QLatin1Char(',') + QString::number(geo.longitude())); 0114 } else if (!addr.isEmpty()) { 0115 url.setPath(QLatin1StringView("q=") + addr.streetAddress() + QLatin1StringView(", ") 0116 + addr.postalCode() + QLatin1Char(' ') 0117 + addr.addressLocality() + QLatin1StringView(", ") 0118 + addr.addressCountry()); 0119 } else { 0120 return; 0121 } 0122 startActivity(url); 0123 0124 #else 0125 if (m_pendingNavigation) { 0126 return; 0127 } 0128 0129 if (!m_positionSource) { 0130 m_positionSource = QGeoPositionInfoSource::createDefaultSource(QCoreApplication::instance()); 0131 if (!m_positionSource) { 0132 qWarning() << "no geo position info source available"; 0133 return; 0134 } 0135 } 0136 0137 if (m_positionSource->lastKnownPosition().isValid()) { 0138 navigateTo(m_positionSource->lastKnownPosition(), place); 0139 } else { 0140 m_pendingNavigation = QObject::connect(m_positionSource, &QGeoPositionInfoSource::positionUpdated, [this, place](const QGeoPositionInfo &pos) { 0141 navigateTo(pos, place); 0142 }); 0143 m_positionSource->requestUpdate(); 0144 } 0145 #endif 0146 } 0147 0148 #ifndef Q_OS_ANDROID 0149 void NavigationController::navigateTo(const QGeoPositionInfo &from, const QVariant &to) 0150 { 0151 qCDebug(Log) << from.coordinate() << from.isValid(); 0152 QObject::disconnect(m_pendingNavigation); 0153 if (!from.isValid()) { 0154 return; 0155 } 0156 0157 const auto geo = LocationUtil::geo(to); 0158 if (geo.isValid()) { 0159 QUrl url; 0160 url.setScheme(QStringLiteral("https")); 0161 url.setHost(QStringLiteral("www.openstreetmap.org")); 0162 url.setPath(QStringLiteral("/directions")); 0163 QUrlQuery query; 0164 query.addQueryItem(QLatin1StringView("route"), 0165 QString::number(from.coordinate().latitude()) + QLatin1Char(',') + QString::number(from.coordinate().longitude()) 0166 + QLatin1Char(';') + QString::number(geo.latitude()) + QLatin1Char(',') + QString::number(geo.longitude())); 0167 url.setQuery(query); 0168 QDesktopServices::openUrl(url); 0169 return; 0170 } 0171 } 0172 #endif 0173 0174 void NavigationController::navigateTo(const QVariant& from, const QVariant& to) 0175 { 0176 const auto fromGeo = LocationUtil::geo(from); 0177 const auto toGeo = LocationUtil::geo(to); 0178 if (!fromGeo.isValid() || !toGeo.isValid()) { 0179 navigateTo(to); 0180 return; 0181 } 0182 0183 #ifdef Q_OS_ANDROID 0184 QUrlQuery query; 0185 query.addQueryItem(QStringLiteral("start_lat"), QString::number(fromGeo.latitude())); 0186 query.addQueryItem(QStringLiteral("start_lon"), QString::number(fromGeo.longitude())); 0187 query.addQueryItem(QStringLiteral("dest_lat"), QString::number(toGeo.latitude())); 0188 query.addQueryItem(QStringLiteral("dest_lon"), QString::number(toGeo.longitude())); 0189 query.addQueryItem(QStringLiteral("start_name"), LocationUtil::name(from)); 0190 query.addQueryItem(QStringLiteral("dest_name"), LocationUtil::name(to)); 0191 QUrl url; 0192 url.setScheme(QStringLiteral("osmand.api")); 0193 url.setHost(QStringLiteral("navigate")); 0194 url.setQuery(query); 0195 if (!startActivity(url)) { 0196 navigateTo(to); 0197 } 0198 0199 #else 0200 QUrl url; 0201 url.setScheme(QStringLiteral("https")); 0202 url.setHost(QStringLiteral("www.openstreetmap.org")); 0203 url.setPath(QStringLiteral("/directions")); 0204 QUrlQuery query; 0205 query.addQueryItem(QLatin1StringView("route"), 0206 QString::number(fromGeo.latitude()) + QLatin1Char(',') + QString::number(fromGeo.longitude()) 0207 + QLatin1Char(';') + QString::number(toGeo.latitude()) + QLatin1Char(',') + QString::number(toGeo.longitude())); 0208 url.setQuery(query); 0209 QDesktopServices::openUrl(url); 0210 #endif 0211 } 0212 0213 #include "moc_navigationcontroller.cpp"