File indexing completed on 2024-04-21 03:49:36

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Levente Kurusa <levex@linux.com>
0004 //
0005 
0006 #include "GeoUriParser.h"
0007 
0008 #include <QString>
0009 #include <QUrl>
0010 #include <QUrlQuery>
0011 
0012 #include "PlanetFactory.h"
0013 #include "MarbleDebug.h"
0014 
0015 namespace Marble {
0016 
0017 GeoUriParser::GeoUriParser( const QString& geoUri )
0018     : m_geoUri( geoUri ),
0019       m_coordinates(),
0020       m_planet(PlanetFactory::construct(QStringLiteral("earth")))
0021 {
0022 }
0023 
0024 void GeoUriParser::setGeoUri( const QString &geoUri )
0025 {
0026     m_geoUri = geoUri;
0027     m_coordinates = GeoDataCoordinates();
0028     m_planet = PlanetFactory::construct(QStringLiteral("earth"));
0029 }
0030 
0031 QString GeoUriParser::geoUri() const
0032 {
0033     return m_geoUri;
0034 }
0035 
0036 GeoDataCoordinates GeoUriParser::coordinates() const
0037 {
0038     return m_coordinates;
0039 }
0040 
0041 Planet GeoUriParser::planet() const
0042 {
0043     return m_planet;
0044 }
0045 
0046 QString GeoUriParser::queryValue(const QUrl& url, const QString& one, const QString& two)
0047 {
0048     QUrlQuery query( url );
0049     if ( query.hasQueryItem( one ) ) {
0050         return query.queryItemValue( one );
0051     } else if ( query.hasQueryItem( two )  ) {
0052         return query.queryItemValue( two );
0053     }
0054 
0055     return QString();
0056 }
0057 
0058 bool GeoUriParser::parse()
0059 {
0060     if ( m_geoUri.isEmpty() ) {
0061         return false;
0062     }
0063 
0064     QString const floatRegexp = "[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?";
0065 
0066     QRegExp geoUriRegexp( "geo:(" + floatRegexp + "),(" + floatRegexp + "),?(" + floatRegexp + ")?(?:;(crs|u)=([\\w\\d-]+))?(?:;(crs|u)=([\\w\\d-]+))?" , Qt::CaseInsensitive, QRegExp::RegExp2 );
0067 
0068 
0069     if ( geoUriRegexp.indexIn( m_geoUri ) > -1 && geoUriRegexp.captureCount() > 1 ) {
0070         double const lat = geoUriRegexp.capturedTexts()[1].toDouble();
0071         double const lon = geoUriRegexp.capturedTexts()[2].toDouble();
0072         double const alt = geoUriRegexp.captureCount() > 2 ? geoUriRegexp.capturedTexts()[3].toDouble() : 0.0;
0073 
0074         if ( geoUriRegexp.captureCount() > 3 ) {
0075             // this is not a bug! The '<=' was intended, otherwise we would skip that last Cgroups's data!
0076             for ( int i = 4; i <= geoUriRegexp.captureCount(); ++i )
0077             {
0078                 if (geoUriRegexp.capturedTexts()[i] == QLatin1String("crs")) {
0079                     for ( const QString& str: PlanetFactory::planetList()) {
0080                         if ( geoUriRegexp.captureCount() < i+1 ) {
0081                             i = geoUriRegexp.captureCount() + 1;
0082                             break;
0083                         }
0084                         if ( geoUriRegexp.capturedTexts()[i+1].contains(str, Qt::CaseInsensitive) ) {
0085                             m_planet = PlanetFactory::construct( str );
0086                             break;
0087                         }
0088                     }
0089                     ++i;
0090                 } else if (geoUriRegexp.capturedTexts()[i] == QLatin1String("u")) {
0091                     mDebug() << "Captured uncertainty parameter, but this is not supported by Marble (yet).";
0092                     ++i;
0093                 }
0094             }
0095         }
0096         GeoDataCoordinates const coordinates( lon, lat, alt, GeoDataCoordinates::Degree );
0097         if ( coordinates.isValid() ) {
0098             m_coordinates = coordinates;
0099             return true;
0100         }
0101     }
0102     if ( m_geoUri.startsWith(QLatin1String("worldwind://goto/")) ) {
0103         m_geoUri.replace(QStringLiteral("goto/"), QStringLiteral("goto/?"));
0104         QUrl worldwindUrl( m_geoUri );
0105 
0106         double lat = queryValue(worldwindUrl, "lat", "latitude").toDouble();
0107         double lon = queryValue(worldwindUrl, "lon", "longitude").toDouble();
0108         double alt = queryValue(worldwindUrl, "alt", "altitude").toDouble();
0109         //double bank = getDoubleFromParameter(worldwindUrl, "bank", "");
0110         //double dir = getDoubleFromParameter(worldwindUrl, "dir", "direction");
0111         //double tilt = getDoubleFromParameter(worldwindUrl, "tilt", "");
0112         //QString layer = worldwindUrl.queryItemValue("layer");
0113         QString world = queryValue(worldwindUrl, "world");
0114 
0115         for ( const QString& str: PlanetFactory::planetList()) {
0116             if ( world.contains(str, Qt::CaseInsensitive) ) {
0117                 m_planet = PlanetFactory::construct( str );
0118                 break;
0119             }
0120         }
0121 
0122         GeoDataCoordinates const coordinates( lon, lat, alt, GeoDataCoordinates::Degree );
0123         if ( coordinates.isValid() ) {
0124             m_coordinates = coordinates;
0125             return true;
0126         }
0127     }
0128 
0129     return false;
0130 }
0131 
0132 }