Skip to content
Permalink
Browse files

[locator] Fix go to locator failing to parse google maps URLs

(cherry picked from commit ae34eba)
  • Loading branch information
nirvn authored and nyalldawson committed Dec 21, 2020
1 parent cdf03a7 commit da85fb6c0282a6542a9b41cc0533892b06be9d12
Showing with 59 additions and 14 deletions.
  1. +49 −14 src/app/locator/qgsinbuiltlocatorfilters.cpp
  2. +10 −0 tests/src/app/testqgsapplocatorfilters.cpp
@@ -38,6 +38,7 @@
#include "qgsvectorlayerfeatureiterator.h"
#include "qgsexpressioncontextutils.h"
#include "qgssettings.h"
#include "qgsunittypes.h"
#include "qgslocatorwidget.h"


@@ -1048,11 +1049,13 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator
scales[18] = 2821;
scales[19] = 1500;
scales[20] = 1000;
scales[21] = 282;

QUrl url( string );
if ( url.isValid() )
{
double scale = 0.0;
int meters = 0;
okX = false;
okY = false;
posX = 0.0;
@@ -1082,42 +1085,74 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator

if ( !okX && !okY )
{
QRegularExpression locationRx( QStringLiteral( "google.*\\/@([0-9\\-\\.\\,]*)z" ) );
QRegularExpression locationRx( QStringLiteral( "google.*\\/@([0-9\\-\\.\\,]*)(z|m|a)" ) );
match = locationRx.match( string );
if ( match.hasMatch() )
{
QStringList params = match.captured( 1 ).split( ',' );
if ( params.size() == 3 )
{
if ( scales.contains( params.at( 2 ).toInt() ) )
{
scale = scales.value( params.at( 2 ).toInt() );
}
posX = params.at( 1 ).toDouble( &okX );
posY = params.at( 0 ).toDouble( &okY );

if ( okX && okY )
{
if ( match.captured( 2 ) == QChar( 'z' ) && scales.contains( params.at( 2 ).toInt() ) )
{
scale = scales.value( params.at( 2 ).toInt() );
}
else if ( match.captured( 2 ) == QChar( 'm' ) )
{
// satellite view URL, scale to be derived from canvas height
meters = params.at( 2 ).toInt();
}
else if ( match.captured( 2 ) == QChar( 'a' ) )
{
// street view URL, use most zoomed in scale value
scale = scales.value( 21 );
}
}
}
}
}

if ( okX && okY )
{
QVariantMap data;
if ( scale > 0.0 )
{
data.insert( QStringLiteral( "scale" ), scale );
}

QgsPointXY point( posX, posY );
QgsPointXY dataPoint = point;
bool withinWgs84 = wgs84Crs.bounds().contains( point );
if ( withinWgs84 && currentCrs != wgs84Crs )
{
QgsCoordinateTransform transform( wgs84Crs, currentCrs, QgsProject::instance()->transformContext() );
QgsPointXY transformedPoint = transform.transform( point );
data.insert( QStringLiteral( "point" ), transformedPoint );
dataPoint = transform.transform( point );
}
else
data.insert( QStringLiteral( "point" ), dataPoint );

if ( meters > 0 )
{
data.insert( QStringLiteral( "point" ), point );
QSize outputSize = QgisApp::instance()->mapCanvas()->mapSettings().outputSize();
QgsDistanceArea da;
da.setSourceCrs( currentCrs, QgsProject::instance()->transformContext() );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
double height = da.measureLineProjected( dataPoint, meters );
double width = outputSize.width() * ( height / outputSize.height() );

QgsRectangle extent;
extent.setYMinimum( dataPoint.y() - height / 2.0 );
extent.setYMaximum( dataPoint.y() + height / 2.0 );
extent.setXMinimum( dataPoint.x() - width / 2.0 );
extent.setXMaximum( dataPoint.x() + width / 2.0 );

QgsScaleCalculator calculator;
calculator.setMapUnits( currentCrs.mapUnits() );
calculator.setDpi( QgisApp::instance()->mapCanvas()->mapSettings().outputDpi() );
scale = calculator.calculate( extent, outputSize.width() );
}

if ( scale > 0.0 )
{
data.insert( QStringLiteral( "scale" ), scale );
}

QgsLocatorResult result;
@@ -383,6 +383,16 @@ void TestQgsAppLocatorFilters::testGoto()
QCOMPARE( results.at( 0 ).displayString, QObject::tr( "Go to 6.4936° 44.5546° at scale 1:22569 (EPSG:4326 - WGS 84)" ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( 6.4936, 44.5546 ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "scale" )].toDouble(), 22569.0 );

results = gatherResults( &filter, QStringLiteral( "https://www.google.com/maps/@7.8750,81.0149,574195m/data=!3m1!1e3" ), QgsLocatorContext() );
QCOMPARE( results.count(), 1 );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( 81.0149, 7.8750 ) );

results = gatherResults( &filter, QStringLiteral( "https://www.google.com/maps/@27.7132,85.3288,3a,75y,278.89h,90t/data=!3m8!1e1!3m6!1sAF1QipMrXuXozGc9x9bxx5uPl_3ys4H-rNVqMLr6EYLA!2e10!3e11!6shttps:%2F%2Flh5.googleusercontent.com%2Fp%2FAF1QipMrXuXozGc9x9bxx5uPl_3ys4H-rNVqMLr6EYLA%3Dw203-h100-k-no-pi2.869903-ya293.58762-ro-1.9255565-fo100!7i3840!8i1920" ), QgsLocatorContext() );
QCOMPARE( results.count(), 1 );
QCOMPARE( results.at( 0 ).displayString, QObject::tr( "Go to 85.3288° 27.7132° at scale 1:282 (EPSG:4326 - WGS 84)" ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( 85.3288, 27.7132 ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "scale" )].toDouble(), 282.0 );
}

QGSTEST_MAIN( TestQgsAppLocatorFilters )

0 comments on commit da85fb6

Please sign in to comment.
You can’t perform that action at this time.