Skip to content

Commit

Permalink
Add a context variable for locator searches
Browse files Browse the repository at this point in the history
This allows encapsulation of properties relating to the context
of a search, such as a target map extent. Locator filters could
use this to prioritise results close to the current canvas extent.
  • Loading branch information
nyalldawson committed May 17, 2017
1 parent 376d6b3 commit a7d590e
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 17 deletions.
1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -212,6 +212,7 @@
%Include layertree/qgslayertreeviewdefaultactions.sip

%Include locator/qgslocator.sip
%Include locator/qgslocatorcontext.sip
%Include locator/qgslocatorfilter.sip
%Include locator/qgslocatorwidget.sip

Expand Down
5 changes: 4 additions & 1 deletion python/gui/locator/qgslocator.sip
Expand Up @@ -74,9 +74,12 @@ class QgsLocator : QObject
:rtype: list of QgsLocatorFilter
%End

void fetchResults( const QString &string, QgsFeedback *feedback = 0 );
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback = 0 );
%Docstring
Triggers the background fetching of filter results for a specified search ``string``.
The ``context`` argument encapsulates the context relating to the search (such as a map
extent to prioritize).

If specified, the ``feedback`` object must exist for the lifetime of this query.

The foundResult() signal will be emitted for each individual result encountered
Expand Down
53 changes: 53 additions & 0 deletions python/gui/locator/qgslocatorcontext.sip
@@ -0,0 +1,53 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/locator/qgslocatorcontext.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsLocatorContext
{
%Docstring
Encapsulates the properties relating to the context of a locator search.
.. versionadded:: 3.0
%End

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

QgsLocatorContext();
%Docstring
Constructor for QgsLocatorContext.
%End

QgsRectangle targetExtent;
%Docstring
Map extent to target in results. This can be used to prioritize searching
for results close to the current map extent. The CRS for the extent
is specified by targetExtentCrs.
.. seealso:: targetExtentCrs
%End

QgsCoordinateReferenceSystem targetExtentCrs;
%Docstring
Coordinate reference system for the map extent variable.
.. seealso:: targetExtent
%End

};



/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/locator/qgslocatorcontext.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
6 changes: 4 additions & 2 deletions python/gui/locator/qgslocatorfilter.sip
Expand Up @@ -71,9 +71,11 @@ class QgsLocatorFilter : QObject
Constructor for QgsLocatorFilter.
%End

virtual void fetchResults( const QString &string, QgsFeedback *feedback ) = 0;
virtual void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) = 0;
%Docstring
Retrieves the filter results for a specified search ``string``.
Retrieves the filter results for a specified search ``string``. The ``context``
argument encapsulates the context relating to the search (such as a map
extent to prioritize).

Implementations of fetchResults() should emit the resultFetched()
signal whenever they encounter a matching result.
Expand Down
4 changes: 2 additions & 2 deletions src/app/locator/qgsinbuiltlocatorfilters.cpp
Expand Up @@ -30,7 +30,7 @@ QgsLayerTreeLocatorFilter::QgsLayerTreeLocatorFilter( QObject *parent )
: QgsLocatorFilter( parent )
{}

void QgsLayerTreeLocatorFilter::fetchResults( const QString &string, QgsFeedback *feedback )
void QgsLayerTreeLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback )
{
QgsLayerTree *tree = QgsProject::instance()->layerTreeRoot();
QList<QgsLayerTreeLayer *> layers = tree->findLayers();
Expand Down Expand Up @@ -66,7 +66,7 @@ QgsLayoutLocatorFilter::QgsLayoutLocatorFilter( QObject *parent )
: QgsLocatorFilter( parent )
{}

void QgsLayoutLocatorFilter::fetchResults( const QString &string, QgsFeedback *feedback )
void QgsLayoutLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback )
{
Q_FOREACH ( QgsComposition *composition, QgsProject::instance()->layoutManager()->compositions() )
{
Expand Down
4 changes: 2 additions & 2 deletions src/app/locator/qgsinbuiltlocatorfilters.h
Expand Up @@ -27,7 +27,7 @@ class QgsLayerTreeLocatorFilter : public QgsLocatorFilter
public:

QgsLayerTreeLocatorFilter( QObject *parent = nullptr );
void fetchResults( const QString &string, QgsFeedback *feedback ) override;
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
void triggerResult( const QgsLocatorResult &result ) override;

};
Expand All @@ -39,7 +39,7 @@ class QgsLayoutLocatorFilter : public QgsLocatorFilter
public:

QgsLayoutLocatorFilter( QObject *parent = nullptr );
void fetchResults( const QString &string, QgsFeedback *feedback ) override;
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
void triggerResult( const QgsLocatorResult &result ) override;

};
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -693,6 +693,8 @@ SET(QGIS_GUI_HDRS
layertree/qgslayertreeembeddedconfigwidget.h
layertree/qgslayertreeembeddedwidgetregistry.h

locator/qgslocatorcontext.h

raster/qgsrasterrendererwidget.h

symbology-ng/qgssymbolwidgetcontext.h
Expand Down
4 changes: 2 additions & 2 deletions src/gui/locator/qgslocator.cpp
Expand Up @@ -52,7 +52,7 @@ void QgsLocator::registerFilter( QgsLocatorFilter *filter )
connect( filter, &QgsLocatorFilter::resultFetched, this, &QgsLocator::filterSentResult, Qt::QueuedConnection );
}

void QgsLocator::fetchResults( const QString &string, QgsFeedback *feedback )
void QgsLocator::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback )
{
// ideally this should not be required, as well behaved callers
// will NOT fire up a new fetchResults call while an existing one is
Expand All @@ -75,7 +75,7 @@ void QgsLocator::fetchResults( const QString &string, QgsFeedback *feedback )
auto gatherFilterResults = [string, feedback]( QgsLocatorFilter * filter )
{
if ( !feedback->isCanceled() )
filter->fetchResults( string, feedback );
filter->fetchResults( string, context, feedback );
};

mFuture = QtConcurrent::map( mFilters, gatherFilterResults );
Expand Down
6 changes: 5 additions & 1 deletion src/gui/locator/qgslocator.h
Expand Up @@ -22,6 +22,7 @@
#include "qgis_sip.h"
#include "qgslocatorfilter.h"
#include "qgsfeedback.h"
#include "qgslocatorcontext.h"
#include <QObject>
#include <QFuture>
#include <QFutureWatcher>
Expand Down Expand Up @@ -93,12 +94,15 @@ class GUI_EXPORT QgsLocator : public QObject

/**
* Triggers the background fetching of filter results for a specified search \a string.
* The \a context argument encapsulates the context relating to the search (such as a map
* extent to prioritize).
*
* If specified, the \a feedback object must exist for the lifetime of this query.
*
* The foundResult() signal will be emitted for each individual result encountered
* by the registered filters.
*/
void fetchResults( const QString &string, QgsFeedback *feedback = nullptr );
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback = nullptr );

/**
* Cancels any current running query, and blocks until query is completely canceled by
Expand Down
58 changes: 58 additions & 0 deletions src/gui/locator/qgslocatorcontext.h
@@ -0,0 +1,58 @@
/***************************************************************************
qgslocatorcontext.h
------------------
begin : May 2017
copyright : (C) 2017 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. *
* *
***************************************************************************/

#ifndef QGSLOCATORCONTEXT_H
#define QGSLOCATORCONTEXT_H

#include "qgis_gui.h"
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"

/**
* \class QgsLocatorContext
* \ingroup gui
* Encapsulates the properties relating to the context of a locator search.
* \since QGIS 3.0
*/
class GUI_EXPORT QgsLocatorContext
{
public:

/**
* Constructor for QgsLocatorContext.
*/
QgsLocatorContext() = default;

/**
* Map extent to target in results. This can be used to prioritize searching
* for results close to the current map extent. The CRS for the extent
* is specified by targetExtentCrs.
* \see targetExtentCrs
*/
QgsRectangle targetExtent;

/**
* Coordinate reference system for the map extent variable.
* \see targetExtent
*/
QgsCoordinateReferenceSystem targetExtentCrs;

};

#endif // QGSLOCATORCONTEXT_H


7 changes: 5 additions & 2 deletions src/gui/locator/qgslocatorfilter.h
Expand Up @@ -19,6 +19,7 @@
#define QGSLOCATORFILTER_H

#include "qgis_gui.h"
#include "qgslocatorcontext.h"
#include "qgslogger.h"
#include <QString>
#include <QVariant>
Expand Down Expand Up @@ -91,7 +92,9 @@ class GUI_EXPORT QgsLocatorFilter : public QObject
QgsLocatorFilter( QObject *parent = nullptr );

/**
* Retrieves the filter results for a specified search \a string.
* Retrieves the filter results for a specified search \a string. The \a context
* argument encapsulates the context relating to the search (such as a map
* extent to prioritize).
*
* Implementations of fetchResults() should emit the resultFetched()
* signal whenever they encounter a matching result.
Expand All @@ -100,7 +103,7 @@ class GUI_EXPORT QgsLocatorFilter : public QObject
* whether the query has been canceled. If so, the subclass should return
* from this method as soon as possible.
*/
virtual void fetchResults( const QString &string, QgsFeedback *feedback ) = 0;
virtual void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) = 0;

/**
* Triggers a filter \a result from this filter. This is called when
Expand Down
17 changes: 12 additions & 5 deletions tests/src/python/test_qgslocator.py
Expand Up @@ -17,6 +17,7 @@

from qgis.gui import (QgsLocator,
QgsLocatorFilter,
QgsLocatorContext,
QgsLocatorResult)
from qgis.PyQt.QtCore import QVariant, pyqtSignal, QCoreApplication
from time import sleep
Expand All @@ -31,7 +32,7 @@ def __init__(self, prefix, parent=None):
super().__init__(parent)
self.prefix = prefix

def fetchResults(self, string, feedback):
def fetchResults(self, string, context, feedback):
for i in range(3):
#if feedback.isCanceled():
# return
Expand Down Expand Up @@ -83,13 +84,15 @@ def got_hit(result):

got_hit._results_ = []

context = QgsLocatorContext()

# one filter
l = QgsLocator()
filter_a = test_filter('a')
l.registerFilter(filter_a)

l.foundResult.connect(got_hit)
l.fetchResults('a')
l.fetchResults('a', context)

for i in range(100):
sleep(0.002)
Expand All @@ -101,7 +104,7 @@ def got_hit(result):
filter_b = test_filter('b')
l.registerFilter(filter_b)
got_hit._results_ = []
l.fetchResults('a')
l.fetchResults('a', context)

for i in range(100):
sleep(0.002)
Expand All @@ -119,12 +122,14 @@ def got_hit(result):

got_hit._results_ = []

context = QgsLocatorContext()

l = QgsLocator()
filter_a = test_filter('a')
l.registerFilter(filter_a)

l.foundResult.connect(got_hit)
l.fetchResults('a')
l.fetchResults('a', context)
del l

def testCancelWhileFetchingResults(self):
Expand All @@ -137,12 +142,14 @@ def got_hit(result):

got_hit._results_ = []

context = QgsLocatorContext()

l = QgsLocator()
filter_a = test_filter('a')
l.registerFilter(filter_a)

l.foundResult.connect(got_hit)
l.fetchResults('a')
l.fetchResults('a', context)
l.cancel()


Expand Down

0 comments on commit a7d590e

Please sign in to comment.