Skip to content
Permalink
Browse files

Add adapter class QgsGeocoderLocatorFilter

This class implements the required logic to bridge a
class which implements the QgsGeocoderInterface interface to a
QgsLocatorFilter. It allows easy creation of a locator filter
from a geocoder.

E.g.

    class GoogleGeocoder(QgsGeocoderInterface):
      ... class which implements QgsGeocoderInterface...

    my_google_geocoder = GoogleGeocoder(api_key)
    my_google_locator_filter = QgsGeocoderLocatorFilter('google', 'Google Maps', 'google', my_google_geocoder, iface.mapCanvas())
    iface.registerLocatorFilter(my_google_locator_filter)

Note:

There's an abstract base class QgsAbstractGeocoderLocatorFilter which
lives in core. This base class has the guts of the geocoder to filter
adapter logic, but it does NOT implement the part which actually zooms
the canvas to the geocode results (because it's in core!)

This abstract base class is in place for applications like QField,
where the GUI library and QgsMapCanvas is NOT used. Those applications
can then implement their own concrete class based on QgsAbstractGeocoderLocatorFilter
with the correct logic to zoom their interface to a region. Ultimately,
a single QgsGeocoderInterface could be usable across QGIS desktop, QField,
with almost all logic shared via the common abstract adapter class.
  • Loading branch information
nyalldawson committed Nov 2, 2020
1 parent 2f9236b commit 9935bbe05e6e8709bc3fc120c23c721e862726f5
@@ -0,0 +1,93 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/geocoding/qgsabstractgeocoderlocatorfilter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsAbstractGeocoderLocatorFilter : QgsLocatorFilter /Abstract/
{
%Docstring
An abstract base class which implements a locator filter populated from a QgsGeocoderInterface.

This base class implements the required logic to bridge a class which implements the
QgsGeocoderInterface interface to a QgsLocatorFilter. It allows easy creation of a locator
filter from a geocoder.

.. note::

This is a low-level API, designed for use by client applications which do not
utilize the QGIS gui library. Usually the concrete class QgsGeocoderLocatorFilter from
the gui library should be used instead.

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgsabstractgeocoderlocatorfilter.h"
%End
public:

QgsAbstractGeocoderLocatorFilter( const QString &name, const QString &displayName,
const QString &prefix,
QgsGeocoderInterface *geocoder );
%Docstring
Constructor for QgsAbstractGeocoderLocatorFilter.

The ``name`` argument specifies a unique name for the filter. This should be
an untranslated string identifying the filter.

The ``displayName`` argument must specify a translated, user-friendly name for the filter.

The ``prefix`` argument specifies the prefix character(s) for this filter. Prefixing a search
with these characters will restrict the locator search to only include results from this filter.
The ``prefix`` must consist of at least three characters.

The ``geocoder`` must specify an instance of a class which implements the :py:class:`QgsGeocoderInterface`
interface. Ownership of ``geocoder`` is not transferred, and the caller must ensure that ``geocoder``
exists for the lifetime of this filter.
%End

virtual QString name() const;

virtual QString displayName() const;

virtual QString prefix() const;

virtual void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback );

virtual void triggerResult( const QgsLocatorResult &result );


QgsGeocoderInterface *geocoder() const;
%Docstring
Returns the geocoder attached to the filter.
%End

QgsGeocoderResult locatorResultToGeocoderResult( const QgsLocatorResult &result ) const;
%Docstring
Converts a locator ``result`` to a geocoder result.

.. seealso:: :py:func:`geocoderResultToLocatorResult`
%End

QgsLocatorResult geocoderResultToLocatorResult( const QgsGeocoderResult &result );
%Docstring
Converts a geocoder ``result`` to a locator result.

.. seealso:: :py:func:`locatorResultToGeocoderResult`
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/geocoding/qgsabstractgeocoderlocatorfilter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -37,7 +37,7 @@ accuracy of the geocoding result.
Creates an invalid error result, with the specified ``errorMessage`` string.
%End

QgsGeocoderResult( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs );
QgsGeocoderResult( const QString &identifier, const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs );
%Docstring
Constructor for a valid QgsGeocoderResult, with the specified ``geometry`` and ``crs``.
%End
@@ -52,6 +52,11 @@ If the result is invalid, the error message can be retrieved by calling :py:func
QString error() const;
%Docstring
Returns the error string, if the result is invalid.
%End

QString identifier() const;
%Docstring
Returns the identifier string for the result.
%End

QgsGeometry geometry() const;
@@ -312,6 +312,7 @@
%Include auto_generated/fieldformatter/qgsvaluerelationfieldformatter.sip
%Include auto_generated/geocms/geonode/qgsgeonodeconnection.sip
%Include auto_generated/geocms/geonode/qgsgeonoderequest.sip
%Include auto_generated/geocoding/qgsabstractgeocoderlocatorfilter.sip
%Include auto_generated/geocoding/qgsgeocoder.sip
%Include auto_generated/geocoding/qgsgeocodercontext.sip
%Include auto_generated/geocoding/qgsgeocoderresult.sip
@@ -0,0 +1,61 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsgeocoderlocatorfilter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsGeocoderLocatorFilter : QgsAbstractGeocoderLocatorFilter
{
%Docstring
An adapter class which implements a locator filter populated from a QgsGeocoderInterface.

This class implements the required logic to bridge a class which implements the
QgsGeocoderInterface interface to a QgsLocatorFilter. It allows easy creation of a locator
filter from a geocoder.

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgsgeocoderlocatorfilter.h"
%End
public:

QgsGeocoderLocatorFilter( const QString &name, const QString &displayName,
const QString &prefix,
QgsGeocoderInterface *geocoder,
QgsMapCanvas *canvas );
%Docstring
Constructor for QgsGeocoderLocatorFilter.

The ``name`` argument specifies a unique name for the filter. This should be
an untranslated string identifying the filter.

The ``displayName`` argument must specify a translated, user-friendly name for the filter.

The ``prefix`` argument specifies the prefix character(s) for this filter. Prefixing a search
with these characters will restrict the locator search to only include results from this filter.
The ``prefix`` must consist of at least three characters.

The ``geocoder`` must specify an instance of a class which implements the :py:class:`QgsGeocoderInterface`
interface. Ownership of ``geocoder`` is not transferred, and the caller must ensure that ``geocoder``
exists for the lifetime of this filter.
%End

virtual QgsLocatorFilter *clone() const /Factory/;


};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsgeocoderlocatorfilter.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -84,6 +84,7 @@
%Include auto_generated/qgsfocuswatcher.sip
%Include auto_generated/qgsfontbutton.sip
%Include auto_generated/qgsformannotation.sip
%Include auto_generated/qgsgeocoderlocatorfilter.sip
%Include auto_generated/qgsgeometryrubberband.sip
%Include auto_generated/qgsgradientcolorrampdialog.sip
%Include auto_generated/qgsgradientstopeditor.sip
@@ -31,6 +31,7 @@ SET(QGIS_CORE_SRCS
classification/qgsclassificationstandarddeviation.cpp
classification/qgsclassificationlogarithmic.cpp

geocoding/qgsabstractgeocoderlocatorfilter.cpp
geocoding/qgsgeocoder.cpp
geocoding/qgsgeocodercontext.cpp
geocoding/qgsgeocoderresult.cpp
@@ -1153,6 +1154,7 @@ SET(QGIS_CORE_HDRS
geocms/geonode/qgsgeonodeconnection.h
geocms/geonode/qgsgeonoderequest.h

geocoding/qgsabstractgeocoderlocatorfilter.h
geocoding/qgsgeocoder.h
geocoding/qgsgeocodercontext.h
geocoding/qgsgeocoderresult.h
@@ -0,0 +1,91 @@
/***************************************************************************
qgsabstractgeocoderlocatorfilter.cpp
---------------
Date : August 2020
Copyright : (C) 2020 by Nyall Dawson
Email : nyall dot dawson 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 "qgsabstractgeocoderlocatorfilter.h"
#include "qgsgeocoder.h"
#include "qgsgeocodercontext.h"

QgsAbstractGeocoderLocatorFilter::QgsAbstractGeocoderLocatorFilter( const QString &name, const QString &displayName, const QString &prefix, QgsGeocoderInterface *geocoder )
: mName( name )
, mDisplayName( displayName )
, mPrefix( prefix )
, mGeocoder( geocoder )
{

}

QString QgsAbstractGeocoderLocatorFilter::name() const
{
return mName;
}

QString QgsAbstractGeocoderLocatorFilter::displayName() const
{
return mDisplayName;
}

QString QgsAbstractGeocoderLocatorFilter::prefix() const
{
return mPrefix;
}

void QgsAbstractGeocoderLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback )
{
QgsGeocoderContext geocodeContext( context.transformContext );
geocodeContext.setAreaOfInterest( QgsGeometry::fromRect( context.targetExtent ) );
geocodeContext.setAreaOfInterestCrs( context.targetExtentCrs );

const QList< QgsGeocoderResult > results = mGeocoder->geocodeString( string, geocodeContext, feedback );
for ( const QgsGeocoderResult &result : results )
{
if ( result.isValid() )
{
const QgsLocatorResult locatorRes = geocoderResultToLocatorResult( result );
emit resultFetched( locatorRes );
}
}
}

void QgsAbstractGeocoderLocatorFilter::triggerResult( const QgsLocatorResult &result )
{
const QgsGeocoderResult geocodeResult = locatorResultToGeocoderResult( result );
handleGeocodeResult( geocodeResult );
}

QgsGeocoderInterface *QgsAbstractGeocoderLocatorFilter::geocoder() const
{
return mGeocoder;
}

QgsGeocoderResult QgsAbstractGeocoderLocatorFilter::locatorResultToGeocoderResult( const QgsLocatorResult &result ) const
{
const QVariantMap attrs = result.userData.toMap();
QgsGeocoderResult geocodeResult( attrs.value( QStringLiteral( "identifier" ) ).toString(),
attrs.value( QStringLiteral( "geom" ) ).value< QgsGeometry >(),
attrs.value( QStringLiteral( "crs" ) ).value< QgsCoordinateReferenceSystem >() );
geocodeResult.setAdditionalAttributes( attrs.value( QStringLiteral( "attributes" ) ).toMap() );
return geocodeResult;
}

QgsLocatorResult QgsAbstractGeocoderLocatorFilter::geocoderResultToLocatorResult( const QgsGeocoderResult &result )
{
QVariantMap attrs;
attrs.insert( QStringLiteral( "identifier" ), result.identifier() );
attrs.insert( QStringLiteral( "geom" ), result.geometry() );
attrs.insert( QStringLiteral( "crs" ), result.crs() );
attrs.insert( QStringLiteral( "attributes" ), result.additionalAttributes() );
return QgsLocatorResult( this, result.identifier(), attrs );
}

0 comments on commit 9935bbe

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