From a7d590e04176425c6b5434a87b7c4f9ed05c397b Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 8 May 2017 19:47:35 +1000 Subject: [PATCH] Add a context variable for locator searches 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. --- python/gui/gui.sip | 1 + python/gui/locator/qgslocator.sip | 5 +- python/gui/locator/qgslocatorcontext.sip | 53 ++++++++++++++++++ python/gui/locator/qgslocatorfilter.sip | 6 +- src/app/locator/qgsinbuiltlocatorfilters.cpp | 4 +- src/app/locator/qgsinbuiltlocatorfilters.h | 4 +- src/gui/CMakeLists.txt | 2 + src/gui/locator/qgslocator.cpp | 4 +- src/gui/locator/qgslocator.h | 6 +- src/gui/locator/qgslocatorcontext.h | 58 ++++++++++++++++++++ src/gui/locator/qgslocatorfilter.h | 7 ++- tests/src/python/test_qgslocator.py | 17 ++++-- 12 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 python/gui/locator/qgslocatorcontext.sip create mode 100644 src/gui/locator/qgslocatorcontext.h diff --git a/python/gui/gui.sip b/python/gui/gui.sip index ee7d754f137..e77d648b573 100644 --- a/python/gui/gui.sip +++ b/python/gui/gui.sip @@ -212,6 +212,7 @@ %Include layertree/qgslayertreeviewdefaultactions.sip %Include locator/qgslocator.sip +%Include locator/qgslocatorcontext.sip %Include locator/qgslocatorfilter.sip %Include locator/qgslocatorwidget.sip diff --git a/python/gui/locator/qgslocator.sip b/python/gui/locator/qgslocator.sip index 70b4db2ceaf..205367dab32 100644 --- a/python/gui/locator/qgslocator.sip +++ b/python/gui/locator/qgslocator.sip @@ -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 diff --git a/python/gui/locator/qgslocatorcontext.sip b/python/gui/locator/qgslocatorcontext.sip new file mode 100644 index 00000000000..c9dd0f3da51 --- /dev/null +++ b/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 * + ************************************************************************/ diff --git a/python/gui/locator/qgslocatorfilter.sip b/python/gui/locator/qgslocatorfilter.sip index 23e0ba037e9..a5e057dc4bc 100644 --- a/python/gui/locator/qgslocatorfilter.sip +++ b/python/gui/locator/qgslocatorfilter.sip @@ -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. diff --git a/src/app/locator/qgsinbuiltlocatorfilters.cpp b/src/app/locator/qgsinbuiltlocatorfilters.cpp index 0dcff4eb6c1..1676b3ad7c8 100644 --- a/src/app/locator/qgsinbuiltlocatorfilters.cpp +++ b/src/app/locator/qgsinbuiltlocatorfilters.cpp @@ -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 layers = tree->findLayers(); @@ -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() ) { diff --git a/src/app/locator/qgsinbuiltlocatorfilters.h b/src/app/locator/qgsinbuiltlocatorfilters.h index e7d5910fdfe..006d2139a5b 100644 --- a/src/app/locator/qgsinbuiltlocatorfilters.h +++ b/src/app/locator/qgsinbuiltlocatorfilters.h @@ -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; }; @@ -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; }; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 7191894e534..2b70dce84c9 100755 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -693,6 +693,8 @@ SET(QGIS_GUI_HDRS layertree/qgslayertreeembeddedconfigwidget.h layertree/qgslayertreeembeddedwidgetregistry.h + locator/qgslocatorcontext.h + raster/qgsrasterrendererwidget.h symbology-ng/qgssymbolwidgetcontext.h diff --git a/src/gui/locator/qgslocator.cpp b/src/gui/locator/qgslocator.cpp index d7a55c25142..33cb90c29f8 100644 --- a/src/gui/locator/qgslocator.cpp +++ b/src/gui/locator/qgslocator.cpp @@ -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 @@ -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 ); diff --git a/src/gui/locator/qgslocator.h b/src/gui/locator/qgslocator.h index 20e53f95e6c..2751781aa24 100644 --- a/src/gui/locator/qgslocator.h +++ b/src/gui/locator/qgslocator.h @@ -22,6 +22,7 @@ #include "qgis_sip.h" #include "qgslocatorfilter.h" #include "qgsfeedback.h" +#include "qgslocatorcontext.h" #include #include #include @@ -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 diff --git a/src/gui/locator/qgslocatorcontext.h b/src/gui/locator/qgslocatorcontext.h new file mode 100644 index 00000000000..d2816d584fc --- /dev/null +++ b/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 + + diff --git a/src/gui/locator/qgslocatorfilter.h b/src/gui/locator/qgslocatorfilter.h index b49f664202c..247e77055fc 100644 --- a/src/gui/locator/qgslocatorfilter.h +++ b/src/gui/locator/qgslocatorfilter.h @@ -19,6 +19,7 @@ #define QGSLOCATORFILTER_H #include "qgis_gui.h" +#include "qgslocatorcontext.h" #include "qgslogger.h" #include #include @@ -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. @@ -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 diff --git a/tests/src/python/test_qgslocator.py b/tests/src/python/test_qgslocator.py index 8bdf8c7e093..56d484c0d9b 100644 --- a/tests/src/python/test_qgslocator.py +++ b/tests/src/python/test_qgslocator.py @@ -17,6 +17,7 @@ import os from qgis.gui import (QgsLocator, QgsLocatorFilter, + QgsLocatorContext, QgsLocatorResult) from qgis.PyQt.QtCore import QVariant, pyqtSignal, QCoreApplication from time import sleep @@ -31,7 +32,7 @@ class test_filter(QgsLocatorFilter): 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 @@ -83,13 +84,15 @@ class TestQgsLocator(unittest.TestCase): 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) @@ -101,7 +104,7 @@ class TestQgsLocator(unittest.TestCase): 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) @@ -119,12 +122,14 @@ class TestQgsLocator(unittest.TestCase): 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): @@ -137,12 +142,14 @@ class TestQgsLocator(unittest.TestCase): 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()