From f60373d64055e99610946697a53ab2e505324639 Mon Sep 17 00:00:00 2001 From: nirvn Date: Sat, 1 Aug 2020 11:50:45 +0700 Subject: [PATCH 1/2] Update SDK --- sdk.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk.conf b/sdk.conf index 236f02cc9e..106376dcbd 100644 --- a/sdk.conf +++ b/sdk.conf @@ -1 +1 @@ -osgeo4a_version=20200705 +osgeo4a_version=20200731 From 5b02e4d4a51b6790dbc9dfdd3336bfff82a44784 Mon Sep 17 00:00:00 2001 From: nirvn Date: Sat, 1 Aug 2020 12:51:00 +0700 Subject: [PATCH 2/2] Add go to coordinate feature to search bar --- src/core/CMakeLists.txt | 2 + src/core/core.pro | 2 + src/core/featureslocatorfilter.h | 6 +- src/core/gotolocatorfilter.cpp | 153 +++++++++++++++++++++++++++ src/core/gotolocatorfilter.h | 61 +++++++++++ src/core/locatormodelsuperbridge.cpp | 12 ++- 6 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 src/core/gotolocatorfilter.cpp create mode 100644 src/core/gotolocatorfilter.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a095872974..f8078e9d2a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -15,6 +15,7 @@ SET(QFIELD_CORE_SRCS focusstack.cpp geometry.cpp geometryeditorsmodel.cpp + gotolocatorfilter.cpp identifytool.cpp layertreemapcanvasbridge.cpp layertreemodel.cpp @@ -75,6 +76,7 @@ SET(QFIELD_CORE_HDRS focusstack.h geometry.h geometryeditorsmodel.h + gotolocatorfilter.h identifytool.h layertreemapcanvasbridge.h layertreemodel.h diff --git a/src/core/core.pro b/src/core/core.pro index 2d24a2110a..62be2c3138 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -61,6 +61,7 @@ HEADERS += \ maptoscreen.h \ projectsource.h \ featureslocatorfilter.h \ + gotolocatorfilter.h \ locatormodelsuperbridge.h \ linepolygonhighlight.h \ qgsgeometrywrapper.h \ @@ -119,6 +120,7 @@ SOURCES += \ maptoscreen.cpp \ projectsource.cpp \ featureslocatorfilter.cpp \ + gotolocatorfilter.cpp \ locatormodelsuperbridge.cpp \ linepolygonhighlight.cpp \ qgsgeometrywrapper.cpp \ diff --git a/src/core/featureslocatorfilter.h b/src/core/featureslocatorfilter.h index 141d131776..5a257f6d34 100644 --- a/src/core/featureslocatorfilter.h +++ b/src/core/featureslocatorfilter.h @@ -20,9 +20,9 @@ #include -#include "qgslocatorfilter.h" -#include "qgsexpressioncontext.h" -#include "qgsvectorlayerfeatureiterator.h" +#include +#include +#include class LocatorModelSuperBridge; diff --git a/src/core/gotolocatorfilter.cpp b/src/core/gotolocatorfilter.cpp new file mode 100644 index 0000000000..bbe61fa470 --- /dev/null +++ b/src/core/gotolocatorfilter.cpp @@ -0,0 +1,153 @@ +/*************************************************************************** + gotolocatorfilter.cpp + + --------------------- + begin : 01.08.2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "gotolocatorfilter.h" + +#include + +#include +#include +#include +#include +#include + +#include "locatormodelsuperbridge.h" +#include "qgsquickmapsettings.h" + + +GotoLocatorFilter::GotoLocatorFilter( LocatorModelSuperBridge *locatorBridge, QObject *parent ) + : QgsLocatorFilter( parent ) + , mLocatorBridge( locatorBridge ) +{ + setUseWithoutPrefix( true ); +} + +GotoLocatorFilter *GotoLocatorFilter::clone() const +{ + return new GotoLocatorFilter( mLocatorBridge ); +} + +void GotoLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback ) +{ + Q_UNUSED( feedback ) + const QgsCoordinateReferenceSystem currentCrs = mLocatorBridge->mapSettings()->mapSettings().destinationCrs(); + const QgsCoordinateReferenceSystem wgs84Crs( QStringLiteral( "EPSG:4326" ) ); + + bool okX = false; + bool okY = false; + double posX = 0.0; + double posY = 0.0; + bool posIsDms = false; + QLocale locale; + + // Coordinates such as 106.8468,-6.3804 + QRegularExpression separatorRx( QStringLiteral( "^([0-9\\-\\%1\\%2]*)[\\s%3]*([0-9\\-\\%1\\%2]*)$" ).arg( locale.decimalPoint(), + locale.groupSeparator(), + locale.decimalPoint() != ',' && locale.groupSeparator() != ',' ? QStringLiteral( "\\," ) : QString() ) ); + QRegularExpressionMatch match = separatorRx.match( string.trimmed() ); + if ( match.hasMatch() ) + { + posX = locale.toDouble( match.captured( 1 ), &okX ); + posY = locale.toDouble( match.captured( 2 ), &okY ); + } + + if ( !match.hasMatch() || !okX || !okY ) + { + // Digit detection using user locale failed, use default C decimal separators + separatorRx = QRegularExpression( QStringLiteral( "^([0-9\\-\\.]*)[\\s\\,]*([0-9\\-\\.]*)$" ) ); + match = separatorRx.match( string.trimmed() ); + if ( match.hasMatch() ) + { + posX = match.captured( 1 ).toDouble( &okX ); + posY = match.captured( 2 ).toDouble( &okY ); + } + } + + if ( !match.hasMatch() ) + { + // Check if the string is a pair of degree minute second + separatorRx = QRegularExpression( QStringLiteral( "^((?:([-+nsew])\\s*)?\\d{1,3}(?:[^0-9.]+[0-5]?\\d)?[^0-9.]+[0-5]?\\d(?:\\.\\d+)?[^0-9.]*[-+nsew]?)\\s+((?:([-+nsew])\\s*)?\\d{1,3}(?:[^0-9.]+[0-5]?\\d)?[^0-9.]+[0-5]?\\d(?:\\.\\d+)?[^0-9.]*[-+nsew]?)$" ) ); + match = separatorRx.match( string.trimmed() ); + if ( match.hasMatch() ) + { + posIsDms = true; + posX = QgsCoordinateUtils::dmsToDecimal( match.captured( 1 ), &okX ); + posY = QgsCoordinateUtils::dmsToDecimal( match.captured( 3 ), &okY ); + } + } + + if ( okX && okY ) + { + QVariantMap data; + QgsPointXY point( posX, posY ); + data.insert( QStringLiteral( "point" ), point ); + + bool withinWgs84 = wgs84Crs.bounds().contains( point ); + if ( !posIsDms && currentCrs != wgs84Crs ) + { + QgsLocatorResult result; + result.filter = this; + result.displayString = tr( "Go to %1 %2 (Map CRS)" ).arg( locale.toString( point.x(), 'g', 10 ), locale.toString( point.y(), 'g', 10 ) ); + result.userData = data; + result.score = 0.9; + emit resultFetched( result ); + } + + if ( withinWgs84 ) + { + if ( currentCrs != wgs84Crs ) + { + QgsCoordinateTransform transform( wgs84Crs, currentCrs, QgsProject::instance()->transformContext() ); + QgsPointXY transformedPoint; + try + { + transformedPoint = transform.transform( point ); + } + catch ( const QgsException &e ) + { + Q_UNUSED( e ) + return; + } + data[QStringLiteral( "point" )] = transformedPoint; + } + + QgsLocatorResult result; + result.filter = this; + result.displayString = tr( "Go to %1° %2° (WGS84)" ).arg( locale.toString( point.x(), 'g', 10 ), locale.toString( point.y(), 'g', 10 ) ); + result.userData = data; + result.score = 1.0; + emit resultFetched( result ); + } + } + return; +} + +void GotoLocatorFilter::triggerResult( const QgsLocatorResult &result ) +{ + triggerResultFromAction( result, Normal ); +} + +void GotoLocatorFilter::triggerResultFromAction( const QgsLocatorResult &result, const int actionId ) +{ + QVariantMap data = result.userData.toMap(); + + QgsGeometry geom( QgsGeometry::fromPointXY( data[QStringLiteral( "point" )].value() ) ); + + mLocatorBridge->mapSettings()->setCenter( geom.vertexAt( 0 ) ); + + mLocatorBridge->locatorHighlightGeometry()->setProperty( "qgsGeometry", geom ); + mLocatorBridge->locatorHighlightGeometry()->setProperty( "crs", mLocatorBridge->mapSettings()->mapSettings().destinationCrs() ); +} diff --git a/src/core/gotolocatorfilter.h b/src/core/gotolocatorfilter.h new file mode 100644 index 0000000000..c92db84b41 --- /dev/null +++ b/src/core/gotolocatorfilter.h @@ -0,0 +1,61 @@ +/*************************************************************************** + gotolocatorfilter.h + + --------------------- + begin : 01.08.2020 + copyright : (C) 2020 by Mathieu Pellerin + email : nirvn dot asia at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef GOTOLOCATORFILTER_H +#define GOTOLOCATORFILTER_H + +#include + +#include +#include + + +class LocatorModelSuperBridge; + +/** + * GotoLocatorFilter is a locator filter to search + * for and display coordinates. + */ +class GotoLocatorFilter : public QgsLocatorFilter +{ + Q_OBJECT + + public: + + //! Origin of the action which triggers the result + enum ActionOrigin + { + Normal, + AddFeature + }; + + explicit GotoLocatorFilter( LocatorModelSuperBridge *locatorBridge, QObject *parent = nullptr ); + GotoLocatorFilter *clone() const override; + QString name() const override { return QStringLiteral( "goto" ); } + QString displayName() const override { return tr( "Goto Coordinate" ); } + Priority priority() const override { return Medium; } + QString prefix() const override { return QStringLiteral( "goto" ); } + + void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override; + void triggerResult( const QgsLocatorResult &result ) override; + void triggerResultFromAction( const QgsLocatorResult &result, const int actionId ) override; + + private: + LocatorModelSuperBridge *mLocatorBridge = nullptr; +}; + +#endif // GOTOLOCATORFILTER_H diff --git a/src/core/locatormodelsuperbridge.cpp b/src/core/locatormodelsuperbridge.cpp index ada797edd8..d6312f2b5b 100644 --- a/src/core/locatormodelsuperbridge.cpp +++ b/src/core/locatormodelsuperbridge.cpp @@ -15,21 +15,23 @@ ***************************************************************************/ +#include "locatormodelsuperbridge.h" + #include #include +#include -#include "locatormodelsuperbridge.h" #include "qgsquickmapsettings.h" -#include "featureslocatorfilter.h" -#include "qgslocator.h" #include "featurelistextentcontroller.h" +#include "featureslocatorfilter.h" +#include "gotolocatorfilter.h" LocatorModelSuperBridge::LocatorModelSuperBridge( QObject *parent ) : QgsLocatorModelBridge( parent ) { - FeaturesLocatorFilter *filter = new FeaturesLocatorFilter( this ); - locator()->registerFilter( filter ); + locator()->registerFilter( new FeaturesLocatorFilter( this ) ); + locator()->registerFilter( new GotoLocatorFilter( this ) ); } QgsQuickMapSettings *LocatorModelSuperBridge::mapSettings() const