1 /*************************************************************************** 2 qgslocator.h 3 ------------ 4 begin : May 2017 5 copyright : (C) 2017 by Nyall Dawson 6 email : nyall dot dawson at gmail dot com 7 ***************************************************************************/ 8 9 /*************************************************************************** 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 ***************************************************************************/ 17 18 #ifndef QGSLOCATOR_H 19 #define QGSLOCATOR_H 20 21 #include <QObject> 22 #include <QFuture> 23 #include <QFutureWatcher> 24 #include <QMap> 25 #include <memory> 26 27 #include "qgis_core.h" 28 #include "qgis_sip.h" 29 #include "qgslocatorfilter.h" 30 #include "qgsfeedback.h" 31 #include "qgslocatorcontext.h" 32 33 34 /** 35 * \class QgsLocator 36 * \ingroup core 37 * \brief Handles the management of QgsLocatorFilter objects and async collection of search results from them. 38 * 39 * QgsLocator acts as both a registry for QgsLocatorFilter objects and a means of firing up 40 * asynchronous queries against these filter objects. 41 * 42 * Filters are first registered to the locator by calling registerFilter(). Registering filters 43 * transfers their ownership to the locator object. Plugins which register filters to the locator 44 * must take care to correctly call deregisterFilter() and deregister their filter upon plugin 45 * unload to avoid crashes. 46 * 47 * In order to trigger a search across registered filters, the fetchResults() method is called. 48 * This triggers threaded calls to QgsLocatorFilter::fetchResults() for all registered filters. 49 * As individual filters find matching results, the foundResult() signal will be triggered 50 * for each result. Callers should connect this signal to an appropriate slot designed 51 * to collect and handle these results. Since foundResult() is triggered whenever a filter 52 * encounters an individual result, it will usually be triggered many times for a single 53 * call to fetchResults(). 54 * 55 * \since QGIS 3.0 56 */ 57 class CORE_EXPORT QgsLocator : public QObject 58 { 59 Q_OBJECT 60 61 public: 62 63 //! List of core filters (i.e. not plugin filters) 64 static const QList<QString> CORE_FILTERS; 65 66 /** 67 * Constructor for QgsLocator. 68 */ 69 QgsLocator( QObject *parent SIP_TRANSFERTHIS = nullptr ); 70 71 /** 72 * Destructor for QgsLocator. Destruction will block while any currently running query is terminated. 73 */ 74 ~QgsLocator() override; 75 76 /** 77 * Registers a \a filter within the locator. Ownership of the filter is transferred to the 78 * locator. 79 * \warning Plugins which register filters to the locator must take care to correctly call 80 * deregisterFilter() and deregister their filters upon plugin unload to avoid crashes. 81 * \see deregisterFilter() 82 */ 83 void registerFilter( QgsLocatorFilter *filter SIP_TRANSFER ); 84 85 /** 86 * Deregisters a \a filter from the locator and deletes it. Calling this will block whilst 87 * any currently running query is terminated. 88 * 89 * Plugins which register filters to the locator must take care to correctly call 90 * deregisterFilter() to deregister their filters upon plugin unload to avoid crashes. 91 * 92 * \see registerFilter() 93 */ 94 void deregisterFilter( QgsLocatorFilter *filter ); 95 96 /** 97 * Returns the list of filters registered in the locator. 98 * \param prefix If prefix is not empty, the list returned corresponds to the filter with the given active prefix 99 * \see prefixedFilters() 100 */ 101 QList< QgsLocatorFilter *> filters( const QString &prefix = QString() ); 102 103 /** 104 * Returns a map of prefix to filter, for all registered filters 105 * with valid prefixes. 106 * \see filters() 107 * \deprecated since QGIS 3.2 use filters() instead 108 */ 109 Q_DECL_DEPRECATED QMap<QString, QgsLocatorFilter *> prefixedFilters() const; 110 111 /** 112 * Triggers the background fetching of filter results for a specified search \a string. 113 * The \a context argument encapsulates the context relating to the search (such as a map 114 * extent to prioritize). 115 * 116 * If specified, the \a feedback object must exist for the lifetime of this query. 117 * 118 * The foundResult() signal will be emitted for each individual result encountered 119 * by the registered filters. 120 */ 121 void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback = nullptr ); 122 123 /** 124 * Cancels any current running query, and blocks until query is completely canceled by 125 * all filters. 126 * \see cancelWithoutBlocking() 127 */ 128 void cancel(); 129 130 /** 131 * Triggers cancellation of any current running query without blocking. The query may 132 * take some time to cancel after calling this. 133 * \see cancel() 134 */ 135 void cancelWithoutBlocking(); 136 137 /** 138 * Returns TRUE if a query is currently being executed by the locator. 139 */ 140 bool isRunning() const; 141 142 /** 143 * Will call clearPreviousResults on all filters 144 * \since QGIS 3.2 145 */ 146 void clearPreviousResults(); 147 148 /** 149 * Returns the list for auto completion 150 * This list is updated when preparing the search 151 * \since QGIS 3.16 152 */ completionList()153 QStringList completionList() const {return mAutocompletionList;} 154 155 signals: 156 157 /** 158 * Emitted whenever a filter encounters a matching \a result after the fetchResults() method 159 * is called. 160 */ 161 void foundResult( const QgsLocatorResult &result ); 162 163 /** 164 * Emitted when locator has prepared the search (\see QgsLocatorFilter::prepare) 165 * before the search is actually performed 166 * \since QGIS 3.16 167 */ 168 void searchPrepared(); 169 170 /** 171 * Emitted when locator has finished a query, either as a result 172 * of successful completion or early cancellation. 173 */ 174 void finished(); 175 176 private slots: 177 178 void filterSentResult( QgsLocatorResult result ); 179 180 private: 181 182 QgsFeedback *mFeedback = nullptr; 183 std::unique_ptr< QgsFeedback > mOwnedFeedback; 184 185 QList< QgsLocatorFilter * > mFilters; 186 QList< QThread * > mActiveThreads; 187 188 QStringList mAutocompletionList; 189 190 void cancelRunningQuery(); 191 192 }; 193 194 #endif // QGSLOCATOR_H 195 196 197