Skip to content
Permalink
Browse files

[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
  • Loading branch information
nyalldawson committed Feb 24, 2018
1 parent f3af22e commit f0fcdb851751e43bd32812079c6d562d52fba7f1
@@ -26,6 +26,7 @@
#include "qgslayoutmanager.h"
#include "qgsmapcanvas.h"
#include <QToolButton>
#include <QClipboard>

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

QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << id );
}

//
// QgsExpressionCalculatorLocatorFilter
//
QgsExpressionCalculatorLocatorFilter::QgsExpressionCalculatorLocatorFilter( QObject *parent )
: QgsLocatorFilter( parent )
{
setUseWithoutPrefix( false );
}

void QgsExpressionCalculatorLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback * )
{
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() );

QString error;
if ( QgsExpression::checkExpression( string, &context, error ) )
{
QgsExpression exp( string );
QString resultString = exp.evaluate( &context ).toString();
if ( !resultString.isEmpty() )
{
QgsLocatorResult result;
result.filter = this;
result.displayString = tr( "Copy “%1” to clipboard" ).arg( resultString );
result.userData = resultString;
result.score = 1;
emit resultFetched( result );
}
}
}

void QgsExpressionCalculatorLocatorFilter::triggerResult( const QgsLocatorResult &result )
{
QApplication::clipboard()->setText( result.userData.toString() );
}
@@ -112,6 +112,22 @@ class QgsActiveLayerFeaturesLocatorFilter : public QgsLocatorFilter
QIcon mLayerIcon;
};

class QgsExpressionCalculatorLocatorFilter : public QgsLocatorFilter
{
Q_OBJECT

public:

QgsExpressionCalculatorLocatorFilter( QObject *parent = nullptr );
QString name() const override { return QStringLiteral( "calculator" ); }
QString displayName() const override { return tr( "Calculator" ); }
Priority priority() const override { return Highest; }
QString prefix() const override { return QStringLiteral( "=" ); }

void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
void triggerResult( const QgsLocatorResult &result ) override;
};


#endif // QGSINBUILTLOCATORFILTERS_H

@@ -2936,6 +2936,7 @@ void QgisApp::createStatusBar()

mLocatorWidget->locator()->registerFilter( new QgsActionLocatorFilter( actionObjects ) );
mLocatorWidget->locator()->registerFilter( new QgsActiveLayerFeaturesLocatorFilter() );
mLocatorWidget->locator()->registerFilter( new QgsExpressionCalculatorLocatorFilter() );
}

void QgisApp::setIconSizes( int size )
@@ -61,7 +61,7 @@ void QgsLocator::registerFilter( QgsLocatorFilter *filter )
{
if ( filter->name() == QStringLiteral( "actions" ) || filter->name() == QStringLiteral( "processing_alg" )
|| filter->name() == QStringLiteral( "layertree" ) || filter->name() == QStringLiteral( "layouts" )
|| filter->name() == QStringLiteral( "features" ) )
|| filter->name() == QStringLiteral( "features" ) || filter->name() == QStringLiteral( "calculator" ) )
{
//inbuilt filter, no prefix check
mPrefixedFilters.insert( filter->prefix(), filter );

0 comments on commit f0fcdb8

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