Skip to content

Commit

Permalink
[FEATURE][locator] Add quick calculator (expression evaluator) to
Browse files Browse the repository at this point in the history
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 f0fcdb8
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
38 changes: 38 additions & 0 deletions src/app/locator/qgsinbuiltlocatorfilters.cpp
Expand Up @@ -26,6 +26,7 @@
#include "qgslayoutmanager.h"
#include "qgsmapcanvas.h"
#include <QToolButton>
#include <QClipboard>

QgsLayerTreeLocatorFilter::QgsLayerTreeLocatorFilter( QObject *parent )
: QgsLocatorFilter( parent )
Expand Down Expand Up @@ -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() );
}
16 changes: 16 additions & 0 deletions src/app/locator/qgsinbuiltlocatorfilters.h
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -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 )
Expand Down
2 changes: 1 addition & 1 deletion src/core/locator/qgslocator.cpp
Expand Up @@ -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 );
Expand Down

0 comments on commit f0fcdb8

Please sign in to comment.