Skip to content

Commit f0fcdb8

Browse files
committed
[FEATURE][locator] Add quick calculator (expression evaluator) to
locator bar Allows evaluation of simple expressions (well, actually ANY QGIS expression... so you could use aggregates and the like if you wanted!) by entering "= " followed by an expression into the locator bar. If a valid expression is entered, the user is given an option to copy the result to the clipboard E.g. entering "= 10/3" gives an entry "Copy '3.3333333' to clipboard". Inspired by the same feature in Qt Creator 4.6
1 parent f3af22e commit f0fcdb8

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

src/app/locator/qgsinbuiltlocatorfilters.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "qgslayoutmanager.h"
2727
#include "qgsmapcanvas.h"
2828
#include <QToolButton>
29+
#include <QClipboard>
2930

3031
QgsLayerTreeLocatorFilter::QgsLayerTreeLocatorFilter( QObject *parent )
3132
: QgsLocatorFilter( parent )
@@ -277,3 +278,40 @@ void QgsActiveLayerFeaturesLocatorFilter::triggerResult( const QgsLocatorResult
277278

278279
QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << id );
279280
}
281+
282+
//
283+
// QgsExpressionCalculatorLocatorFilter
284+
//
285+
QgsExpressionCalculatorLocatorFilter::QgsExpressionCalculatorLocatorFilter( QObject *parent )
286+
: QgsLocatorFilter( parent )
287+
{
288+
setUseWithoutPrefix( false );
289+
}
290+
291+
void QgsExpressionCalculatorLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback * )
292+
{
293+
QgsExpressionContext context;
294+
context << QgsExpressionContextUtils::globalScope()
295+
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() );
296+
297+
QString error;
298+
if ( QgsExpression::checkExpression( string, &context, error ) )
299+
{
300+
QgsExpression exp( string );
301+
QString resultString = exp.evaluate( &context ).toString();
302+
if ( !resultString.isEmpty() )
303+
{
304+
QgsLocatorResult result;
305+
result.filter = this;
306+
result.displayString = tr( "Copy “%1” to clipboard" ).arg( resultString );
307+
result.userData = resultString;
308+
result.score = 1;
309+
emit resultFetched( result );
310+
}
311+
}
312+
}
313+
314+
void QgsExpressionCalculatorLocatorFilter::triggerResult( const QgsLocatorResult &result )
315+
{
316+
QApplication::clipboard()->setText( result.userData.toString() );
317+
}

src/app/locator/qgsinbuiltlocatorfilters.h

+16
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ class QgsActiveLayerFeaturesLocatorFilter : public QgsLocatorFilter
112112
QIcon mLayerIcon;
113113
};
114114

115+
class QgsExpressionCalculatorLocatorFilter : public QgsLocatorFilter
116+
{
117+
Q_OBJECT
118+
119+
public:
120+
121+
QgsExpressionCalculatorLocatorFilter( QObject *parent = nullptr );
122+
QString name() const override { return QStringLiteral( "calculator" ); }
123+
QString displayName() const override { return tr( "Calculator" ); }
124+
Priority priority() const override { return Highest; }
125+
QString prefix() const override { return QStringLiteral( "=" ); }
126+
127+
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
128+
void triggerResult( const QgsLocatorResult &result ) override;
129+
};
130+
115131

116132
#endif // QGSINBUILTLOCATORFILTERS_H
117133

src/app/qgisapp.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,7 @@ void QgisApp::createStatusBar()
29362936

29372937
mLocatorWidget->locator()->registerFilter( new QgsActionLocatorFilter( actionObjects ) );
29382938
mLocatorWidget->locator()->registerFilter( new QgsActiveLayerFeaturesLocatorFilter() );
2939+
mLocatorWidget->locator()->registerFilter( new QgsExpressionCalculatorLocatorFilter() );
29392940
}
29402941

29412942
void QgisApp::setIconSizes( int size )

src/core/locator/qgslocator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void QgsLocator::registerFilter( QgsLocatorFilter *filter )
6161
{
6262
if ( filter->name() == QStringLiteral( "actions" ) || filter->name() == QStringLiteral( "processing_alg" )
6363
|| filter->name() == QStringLiteral( "layertree" ) || filter->name() == QStringLiteral( "layouts" )
64-
|| filter->name() == QStringLiteral( "features" ) )
64+
|| filter->name() == QStringLiteral( "features" ) || filter->name() == QStringLiteral( "calculator" ) )
6565
{
6666
//inbuilt filter, no prefix check
6767
mPrefixedFilters.insert( filter->prefix(), filter );

0 commit comments

Comments
 (0)