Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add go to coordinate feature to search bar #1181

Merged
merged 2 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk.conf
Original file line number Diff line number Diff line change
@@ -1 +1 @@
osgeo4a_version=20200705
osgeo4a_version=20200731
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ SET(QFIELD_CORE_SRCS
focusstack.cpp
geometry.cpp
geometryeditorsmodel.cpp
gotolocatorfilter.cpp
identifytool.cpp
layertreemapcanvasbridge.cpp
layertreemodel.cpp
Expand Down Expand Up @@ -75,6 +76,7 @@ SET(QFIELD_CORE_HDRS
focusstack.h
geometry.h
geometryeditorsmodel.h
gotolocatorfilter.h
identifytool.h
layertreemapcanvasbridge.h
layertreemodel.h
Expand Down
2 changes: 2 additions & 0 deletions src/core/core.pro
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ HEADERS += \
maptoscreen.h \
projectsource.h \
featureslocatorfilter.h \
gotolocatorfilter.h \
locatormodelsuperbridge.h \
linepolygonhighlight.h \
qgsgeometrywrapper.h \
Expand Down Expand Up @@ -119,6 +120,7 @@ SOURCES += \
maptoscreen.cpp \
projectsource.cpp \
featureslocatorfilter.cpp \
gotolocatorfilter.cpp \
locatormodelsuperbridge.cpp \
linepolygonhighlight.cpp \
qgsgeometrywrapper.cpp \
Expand Down
6 changes: 3 additions & 3 deletions src/core/featureslocatorfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

#include <QObject>

#include "qgslocatorfilter.h"
#include "qgsexpressioncontext.h"
#include "qgsvectorlayerfeatureiterator.h"
#include <qgslocatorfilter.h>
#include <qgsexpressioncontext.h>
#include <qgsvectorlayerfeatureiterator.h>


class LocatorModelSuperBridge;
Expand Down
153 changes: 153 additions & 0 deletions src/core/gotolocatorfilter.cpp
Original file line number Diff line number Diff line change
@@ -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 <QAction>

#include <qgscoordinateutils.h>
#include <qgsexpressioncontextutils.h>
#include <qgsfeedback.h>
#include <qgspoint.h>
#include <qgsproject.h>

#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<QgsPointXY>() ) );

mLocatorBridge->mapSettings()->setCenter( geom.vertexAt( 0 ) );

mLocatorBridge->locatorHighlightGeometry()->setProperty( "qgsGeometry", geom );
mLocatorBridge->locatorHighlightGeometry()->setProperty( "crs", mLocatorBridge->mapSettings()->mapSettings().destinationCrs() );
}
61 changes: 61 additions & 0 deletions src/core/gotolocatorfilter.h
Original file line number Diff line number Diff line change
@@ -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 <QObject>

#include <qgslocatorfilter.h>
#include <qgsexpressioncontext.h>


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
12 changes: 7 additions & 5 deletions src/core/locatormodelsuperbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@
***************************************************************************/


#include "locatormodelsuperbridge.h"

#include <QStandardItem>

#include <qgslocatormodel.h>
#include <qgslocator.h>

#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
Expand Down