Skip to content
Permalink
Browse files

Made qgsexpression be DA-aware

  • Loading branch information
homann committed Sep 4, 2012
1 parent a441282 commit 6b26c4a9f894dffaa1a6c9e5033ffb03b90197b0
Showing with 41 additions and 78 deletions.
  1. +4 −0 python/core/qgsexpression.sip
  2. +15 −0 src/app/qgsfieldcalculator.cpp
  3. +13 −72 src/core/qgsexpression.cpp
  4. +9 −6 src/core/qgsexpression.h
@@ -50,6 +50,10 @@ public:
//! (used by internal functions)
QgsDistanceArea* geomCalculator();

//! Sets the geometry calculator used in evaluation of expressions,
// instead of the default.
void setGeomCalculator( QgsDistanceArea& calc );

/** This function currently replaces each expression between [% and %]
in the string with the result of its evaluation on the feature
passed as argument.
@@ -13,12 +13,16 @@
* *
***************************************************************************/

#include "qgisapp.h"
#include "qgsfieldcalculator.h"
#include "qgsdistancearea.h"
#include "qgsexpression.h"
#include "qgsmapcanvas.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

#include <QMessageBox>
#include <QSettings>

QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer* vl )
: QDialog()
@@ -78,6 +82,16 @@ QgsFieldCalculator::~QgsFieldCalculator()

void QgsFieldCalculator::accept()
{

// Set up QgsDistanceArea each time we (re-)calculate
QgsDistanceArea myDa;
QSettings settings;

myDa.setSourceCrs( mVectorLayer->crs().srsid() );
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
myDa.setEllipsoid( settings.value( "/qgis/measure/ellipsoid", GEO_NONE ).toString() );


QString calcString = builder->expressionText();
QgsExpression exp( calcString );

@@ -163,6 +177,7 @@ void QgsFieldCalculator::accept()
}

exp.setCurrentRowNumber( rownum );
exp.setGeomCalculator( myDa );

QVariant value = exp.evaluate( &feature );
if ( exp.hasEvalError() )
@@ -787,18 +787,6 @@ static QVariant fcnRound( const QVariantList& values , QgsFeature *f, QgsExpress
return QVariant();
}

static QVariant fcnScale( const QVariantList&, QgsFeature*, QgsExpression* parent )
{
return QVariant( parent->scale() );
}

static QVariant fcnFormatNumber( const QVariantList& values, QgsFeature*, QgsExpression* parent )
{
double value = getDoubleValue( values.at(0), parent );
int places = getIntValue( values.at(1), parent );
return QString( "%L1" ).arg( value, 0, 'f', places );
}

QList<QgsExpression::FunctionDef> QgsExpression::gmBuiltinFunctions;

const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
@@ -854,7 +842,6 @@ const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
<< FunctionDef( "right", 2, fcnRight, QObject::tr( "String" ) )
<< FunctionDef( "rpad", 3, fcnRPad, QObject::tr( "String" ) )
<< FunctionDef( "lpad", 3, fcnLPad, QObject::tr( "String" ) )
<< FunctionDef( "format_number", 2, fcnFormatNumber, QObject::tr( "String" ) )

// geometry accessors
<< FunctionDef( "xat", 1, fcnXat, QObject::tr( "Geometry" ), "", true )
@@ -867,7 +854,6 @@ const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
// special columns
<< FunctionDef( "$rownum", 0, fcnRowNumber, QObject::tr( "Record" ) )
<< FunctionDef( "$id", 0, fcnFeatureId, QObject::tr( "Record" ) )
<< FunctionDef( "$scale", 0, fcnScale, QObject::tr( "Record" ) )
;
}

@@ -901,8 +887,10 @@ QgsExpression::QgsExpression( const QString& expr )
: mExpression( expr )
, mRowNumber( 0 )
, mScale( 0 )
, mCalc( NULL )

{
initGeomCalculator();

mRootNode = ::parseExpression( mExpression, mParserErrorString );

if ( mParserErrorString.isNull() )
@@ -949,11 +937,16 @@ bool QgsExpression::needsGeometry()

void QgsExpression::initGeomCalculator()
{
mCalc = new QgsDistanceArea;
QSettings settings;
QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", GEO_NONE ).toString();
mCalc->setEllipsoid( ellipsoid );
mCalc->setEllipsoidalMode( false );
// Use planimetric as default
mCalc.setEllipsoidalMode( false );
}

void QgsExpression::setGeomCalculator( QgsDistanceArea& calc )
{
// Copy from supplied calculator
mCalc.setEllipsoid( calc.ellipsoid() );
mCalc.setEllipsoidalMode( calc.ellipsoidalEnabled() );
mCalc.setSourceCrs( calc.sourceCrs() );
}

bool QgsExpression::prepare( const QgsFieldMap& fields )
@@ -999,7 +992,6 @@ QString QgsExpression::dump() const
return mRootNode->dump();
}


void QgsExpression::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
if ( !mRootNode )
@@ -1049,57 +1041,6 @@ void QgsExpression::acceptVisitor( QgsExpression::Visitor& v )
mRootNode->accept( v );
}

QString QgsExpression::replaceExpressionText( QString action, QgsFeature &feat,
QgsVectorLayer* layer,
const QMap<QString, QVariant> *substitutionMap )
{
QString expr_action;

int index = 0;
while ( index < action.size() )
{
QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );

int pos = rx.indexIn( action, index );
if ( pos < 0 )
break;

int start = index;
index = pos + rx.matchedLength();

QString to_replace = rx.cap( 1 ).trimmed();
QgsDebugMsg( "Found expression: " + to_replace );

if ( substitutionMap && substitutionMap->contains( to_replace ) )
{
expr_action += action.mid( start, pos - start ) + substitutionMap->value( to_replace ).toString();
continue;
}

QgsExpression exp( to_replace );
if ( exp.hasParserError() )
{
QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
expr_action += action.mid( start, index - start );
continue;
}

QVariant result = exp.evaluate( &feat, layer->pendingFields() );
if ( exp.hasEvalError() )
{
QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
expr_action += action.mid( start, index - start );
continue;
}

QgsDebugMsg( "Expression result is: " + result.toString() );
expr_action += action.mid( start, pos - start ) + result.toString();
}

expr_action += action.mid( index );
return expr_action;
}


QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &element, QString &errorMessage )
{
@@ -24,8 +24,8 @@

#include "qgsfield.h"
#include "qgsvectorlayer.h"
#include "qgsdistancearea.h"

class QgsDistanceArea;
class QgsFeature;
class QDomElement;

@@ -131,7 +131,11 @@ class CORE_EXPORT QgsExpression

//! Return calculator used for distance and area calculations
//! (used by internal functions)
QgsDistanceArea* geomCalculator() { if ( !mCalc ) initGeomCalculator(); return mCalc; }
QgsDistanceArea* geomCalculator() { return & mCalc; }

//! Sets the geometry calculator used in evaluation of expressions,
// instead of the default.
void setGeomCalculator( QgsDistanceArea& calc );

/** This function currently replaces each expression between [% and %]
in the string with the result of its evaluation on the feature
@@ -144,8 +148,6 @@ class CORE_EXPORT QgsExpression
QgsVectorLayer* layer,
const QMap<QString, QVariant> *substitutionMap = 0 );

//

enum UnaryOperator
{
uoNot,
@@ -517,7 +519,7 @@ class CORE_EXPORT QgsExpression

protected:
// internally used to create an empty expression
QgsExpression() : mRootNode( NULL ), mRowNumber( 0 ), mCalc( NULL ) {}
QgsExpression() : mRootNode( NULL ), mRowNumber( 0 ) {}

void initGeomCalculator();

@@ -530,7 +532,8 @@ class CORE_EXPORT QgsExpression
int mRowNumber;
double mScale;

QgsDistanceArea* mCalc;
void initGeomCalculator();
QgsDistanceArea mCalc;
};

Q_DECLARE_METATYPE( QgsExpression::Interval )

0 comments on commit 6b26c4a

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