Remove deprecated methods from QgsExpression

Now all evaluate/prepare/etc methods must be called using QgsExpressionContexts

Also remove most remaining traces of special variables. This brings some
user facing changes, such that existing expressions may need to be
updated if they used these old special variables (eg $scale,
$feature). These changes are noted in doc/qgis3_user_changes.dox
so that we can include them in the release notes.
This commit is contained in:
Nyall Dawson 2016-08-06 20:47:55 +10:00
parent 56400b147b
commit 7da8110536
21 changed files with 113 additions and 930 deletions

View File

@ -243,6 +243,13 @@ be returned in place of a null pointer.</li>
<li>updateCRSCache() has been renamed to updateCrsCache</li>
</ul>
\subsection qgis_api_break_3_0_QgsDataDefined QgsDataDefined
<ul>
<li>expressionParams(), setExpressionParams() and insertExpressionParam() have been removed.
QgsExpressionContext variables should be used in their place.</li>
</ul>
\subsection qgis_api_break_3_0_QgsDataDefinedSymbolDialog QgsDataDefinedSymbolDialog
<ul>
@ -290,6 +297,23 @@ place of a null pointer.</li>
<li>The ct member has been removed. Use coordinateTransform() and setCoordinateTransform() instead.
</ul>
\subsection qgis_api_break_3_0_QgsExpression QgsExpression
<ul>
<li>prepare( const QgsFields &fields ) has been removed. Use prepare( const QgsExpressionContext *context ) instead.</li>
<li>The evaluate methods which accept feature parameters have been removed. Use the version which takes a QgsExpressionContext
argument instead.</li>
<li>isValid( const QString& text, const QgsFields& fields, QString &errorMessage ) has been removed, use the QgsExpressionContext
version instead.</li>
<li>setCurrentRowNumber, currentRowNumber, scale, setScale, setSpecialColumn, unsetSpecialColumn, specialColumn, hasSpecialColumn have been
removed. Use QgsExpressionContext variables instead.</li>
<li>The replaceExpressionText version which accepts a QgsFeature argument has been removed. Use the QgsExpressionContext
version instead.</li>
<li>QgsExpression::Function::func has been modified to use a QgsExpressionContext argument rather than a QgsFeature.</li>
<li>The QgsExpression::Node::eval and prepare versions which take a QgsFeature has been removed, use the QgsExpressionContext versions instead.</li>
<li>QgsExpression::Interval has been removed. Use QgsInterval instead.</li>
</ul>
\subsection qgis_api_break_3_0_QgsFeature QgsFeature
<ul>

View File

@ -0,0 +1,24 @@
/*! \page qgis3_user_changes QGIS 3.0 User Changes
\tableofcontents
Notes regarding user related changes for QGIS 3.0 which should be included in the release notes.
\subsection qgis3_user_changes_expressions Expressions
QGIS 3.0 brings some changes to the expression engine, which may require existing projects to
be updated so that any expressions in use have the following changes:
<ul>
<li>$rownum has been replaced by @row_number</li>
<li>$scale has been replaced by @map_scale</li>
<li>$map has been replaced by @map_id</li>
<li>$numpages has been replaced by @layout_numpages</li>
<li>$page has been replaced by @layout_page</li>
<li>$feature has been replaced by @atlas_featurenumber</li>
<li>$atlasfeatureid has been replaced by @atlas_featureid</li>
<li>$atlasfeature has been replaced by @atlas_feature</li>
<li>$atlasgeometry has been replaced by @atlas_geometry</li>
<li>$numfeatures has been replaced by @atlas_totalfeatures</li>
</ul>
*/

View File

@ -72,7 +72,10 @@ def register_function(function, arg_count, group, usesgeometry=False, referenced
self.function = func
self.expandargs = expandargs
def func(self, values, feature, parent):
def func(self, values, context, parent):
feature = None
if context:
feature = context.feature()
try:
if self.expandargs:
values.append(feature)

View File

@ -110,12 +110,6 @@ class QgsDataDefined
*/
QString expressionOrField() const;
//! @note not available in python bindings
//QMap<QString, QVariant> expressionParams() const;
//! @note not available in python bindings
//void setExpressionParams( QMap<QString, QVariant> params );
void insertExpressionParam( const QString& key, const QVariant& param );
/** Prepares the expression using a vector layer
* @param layer vector layer
* @returns true if expression was successfully prepared

View File

@ -22,10 +22,6 @@ class QgsExpression
//! Returns root node of the expression. Root node is null is parsing has failed
const QgsExpression::Node* rootNode() const;
//! Get the expression ready for evaluation - find out column indexes.
//! @deprecated use prepare( const QgsExpressionContext *context ) instead
bool prepare( const QgsFields &fields ) /Deprecated/;
/** Get the expression ready for evaluation - find out column indexes.
* @param context context for preparing expression
* @note added in QGIS 2.12
@ -47,28 +43,6 @@ class QgsExpression
// evaluation
//! Evaluate the feature and return the result
//! @note prepare() should be called before calling this method
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
QVariant evaluate( const QgsFeature* f ) /Deprecated/;
//! Evaluate the feature and return the result
//! @note prepare() should be called before calling this method
//! @note available in python bindings as evaluatePrepared
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
QVariant evaluate( const QgsFeature& f ) /PyName=evaluatePrepared,Deprecated/;
//! Evaluate the feature and return the result
//! @note this method does not expect that prepare() has been called on this instance
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
QVariant evaluate( const QgsFeature* f, const QgsFields& fields ) /Deprecated/;
//! Evaluate the feature and return the result
//! @note this method does not expect that prepare() has been called on this instance
//! @note not available in python bindings
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
// inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
/** Evaluate the feature and return the result.
* @note this method does not expect that prepare() has been called on this instance
* @note added in QGIS 2.12
@ -89,39 +63,11 @@ class QgsExpression
//! Set evaluation error (used internally by evaluation functions)
void setEvalErrorString( const QString& str );
//! Set the number for $rownum special column
//! @deprecated use QgsExpressionContext to set row number instead
void setCurrentRowNumber( int rowNumber ) /Deprecated/;
//! Return the number used for $rownum special column
//! @deprecated use QgsExpressionContext to retrieve row number instead
int currentRowNumber() /Deprecated/; //TODO QGIS 3.0: make the following methods private. They are still required for replaceExpressionText
//but should not be publicly used
/** Assign a special column
* @deprecated use global or project QgsExpressionContext variables instead
*/
static void setSpecialColumn( const QString& name, const QVariant& value ) /Deprecated/;
/** Unset a special column
* @deprecated use global or project QgsExpressionContext variables instead
*/
static void unsetSpecialColumn( const QString& name ) /Deprecated/;
/** Return the value of the given special column or a null QVariant if undefined
* @deprecated use global or project QgsExpressionContext variables instead
*/
static QVariant specialColumn( const QString& name ) /Deprecated/;
/** Check whether a special column exists
* @note added in 2.2
*/
static bool hasSpecialColumn( const QString& name );
/** Checks whether an expression consists only of a single field reference
* @note added in 2.9
*/
bool isField() const;
//! @deprecated use QgsExpressionContext variant instead
static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage ) /Deprecated/;
/** Tests whether a string is a valid expression.
* @param text string to test
* @param context optional expression context
@ -131,10 +77,6 @@ class QgsExpression
*/
static bool isValid( const QString& text, const QgsExpressionContext* context, QString &errorMessage );
void setScale( double scale );
double scale();
//! Return the original, unmodified expression string.
//! If there was none supplied because it was constructed by sole
//! API calls, dump() will be used to create one instead.
@ -192,24 +134,6 @@ class QgsExpression
*/
void setAreaUnits( QgsUnitTypes::AreaUnit unit );
/** This function currently replaces each expression between [% and %]
* in the string with the result of its evaluation on the feature
* passed as argument.
*
* Additional substitutions can be passed through the substitutionMap
* parameter
* @param action
* @param feat
* @param layer
* @param substitutionMap
* @param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance and area conversion
* @deprecated use QgsExpressionContext variant instead
*/
static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap = 0,
const QgsDistanceArea* distanceArea = 0 ) /Deprecated/;
/** This function replaces each expression between [% and %]
* in the string with the result of its evaluation with the specified context
*
@ -410,18 +334,13 @@ class QgsExpression
/** The help text for the function. */
const QString helptext() const;
//! @deprecated Use QgsExpressionContext variant instead
virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) /Deprecated/;
/** Returns result of evaluating the function.
* @param values list of values passed to the function
* @param context context expression is being evaluated against
* @param parent parent expression
* @returns result of function
* @note named funcV2 in Python bindings. Will be renamed to func to replace deprecated method in QGIS 3.0.
*/
//TODO QGIS 3.0 - rename python method
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) /PyName=funcV2/;
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) = 0;
virtual bool handlesNull() const;
};
@ -459,11 +378,6 @@ class QgsExpression
*/
static int functionCount();
/**
* Returns a list of special Column definitions
*/
static QList<QgsExpression::Function *> specialColumns();
/** Returns a quoted column reference (in double quotes)
* @see quotedString()
* @see quotedValue()
@ -534,33 +448,19 @@ class QgsExpression
*/
virtual QgsExpression::NodeType nodeType() const = 0;
/**
* Abstract virtual eval method
* Errors are reported to the parent
* @deprecated use QgsExpressionContext variant instead
*/
virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) /Deprecated/;
/**
* Abstract virtual eval method
* Errors are reported to the parent
* @note added in QGIS 2.12
*/
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context );
/**
* Abstract virtual preparation method
* Errors are reported to the parent
* @deprecated use QgsExpressionContext variant instead
*/
virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) /Deprecated/;
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) = 0;
/**
* Abstract virtual preparation method
* Errors are reported to the parent
* @note added in QGIS 2.12
*/
virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context );
virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) = 0;
/**
* Abstract virtual dump method
@ -671,37 +571,6 @@ class QgsExpression
virtual QString dump() const;
};
//TODO QGIS 3.0 - remove
//! @deprecated use QgsInterval instead
class Interval
{
public:
Interval( int seconds = 0 );
//! interval length in years
double years() const;
//! interval length in months
double months() const;
//! interval length in weeks
double weeks() const;
//! interval length in days
double days() const;
//! interval length in hours
double hours() const;
//! interval length in minutus
double minutes() const;
//! interval length in seconds
double seconds() const;
//! getter interval validity
bool isValid() const;
//! setter interval validity
void setValid( bool valid );
//! compare two intervals
bool operator==( QgsExpression::Interval other ) const;
//! convert a string to an interval
static QgsExpression::Interval fromString( const QString& string );
};
class NodeUnaryOperator : QgsExpression::Node
{
public:

View File

@ -35,7 +35,7 @@ from qgis.PyQt.QtWidgets import QComboBox, QHeaderView, QLineEdit, QMessageBox,
from qgis.PyQt.QtCore import QItemSelectionModel
from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSlot
from qgis.core import QgsExpression
from qgis.core import QgsExpression, QgsExpressionContextUtils
from qgis.gui import QgsFieldExpressionWidget
from processing.tools import dataobjects
@ -92,9 +92,10 @@ class FieldsMappingModel(QAbstractTableModel):
return
if self._layer is None:
return
dp = self._layer.dataProvider()
context = QgsExpressionContextUtils.createFeatureBasedContext(QgsFeature(), self._layer.fields())
for feature in dp.getFeatures():
expression.evaluate(feature, dp.fields())
context.setFeature(feature)
expression.evaluate(context)
if expression.hasEvalError():
self._errors[row] = expression.evalErrorString()
return

View File

@ -142,17 +142,6 @@ QString QgsDataDefined::expressionOrField() const
return d->useExpression ? d->expressionString : QString( "\"%1\"" ).arg( d->field );
}
QMap<QString, QVariant> QgsDataDefined::expressionParams() const
{
return d->expressionParams;
}
void QgsDataDefined::setExpressionParams( const QMap<QString, QVariant>& params )
{
d.detach();
d->expressionParams = params;
}
bool QgsDataDefined::prepareExpression( QgsVectorLayer* layer )
{
if ( layer )
@ -188,18 +177,6 @@ bool QgsDataDefined::prepareExpression( const QgsExpressionContext& context )
return false;
}
// setup expression parameters
QVariant scaleV = d->expressionParams.value( "scale" );
if ( scaleV.isValid() )
{
bool ok;
double scale = scaleV.toDouble( &ok );
if ( ok )
{
d->expression->setScale( scale );
}
}
d->expression->prepare( &context );
d->exprRefColumns = d->expression->referencedColumns();
@ -286,12 +263,6 @@ void QgsDataDefined::setField( const QString &field )
d->exprRefColumns.clear();
}
void QgsDataDefined::insertExpressionParam( const QString& key, const QVariant& param )
{
d.detach();
d->expressionParams.insert( key, param );
}
QgsStringMap QgsDataDefined::toMap( const QString &baseName ) const
{
QgsStringMap map;

View File

@ -136,12 +136,6 @@ class CORE_EXPORT QgsDataDefined
*/
QString expressionOrField() const;
//! @note not available in python bindings
QMap<QString, QVariant> expressionParams() const;
//! @note not available in python bindings
void setExpressionParams( const QMap<QString, QVariant>& params );
void insertExpressionParam( const QString& key, const QVariant& param );
/** Prepares the expression using a vector layer
* @param layer vector layer
* @returns true if expression was successfully prepared

View File

@ -56,7 +56,6 @@ class QgsDataDefinedPrivate : public QSharedData
, useExpression( other.useExpression )
, expressionString( other.expressionString )
, field( other.field )
, expressionParams( other.expressionParams )
, expressionPrepared( false )
, exprRefColumns( other.exprRefColumns )
{
@ -80,7 +79,6 @@ class QgsDataDefinedPrivate : public QSharedData
QString expressionString;
QString field;
QMap<QString, QVariant> expressionParams;
bool expressionPrepared;
QStringList exprRefColumns;
};

View File

@ -1242,99 +1242,6 @@ static QVariant fcnSubstr( const QVariantList& values, const QgsExpressionContex
int len = getIntValue( values.at( 2 ), parent );
return QVariant( str.mid( from -1, len ) );
}
static QVariant fcnRowNumber( const QVariantList&, const QgsExpressionContext* context, QgsExpression* parent )
{
if ( context && context->hasVariable( "row_number" ) )
return context->variable( "row_number" );
Q_NOWARN_DEPRECATED_PUSH
return QVariant( parent->currentRowNumber() );
Q_NOWARN_DEPRECATED_POP
//when above is removed - return QVariant()
}
static QVariant fcnMapId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "map_id" ) )
return context->variable( "map_id" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$map" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnComposerNumPages( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "layout_numpages" ) )
return context->variable( "layout_numpages" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$numpages" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnComposerPage( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "layout_page" ) )
return context->variable( "layout_page" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$page" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnAtlasFeature( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "atlas_featurenumber" ) )
return context->variable( "atlas_featurenumber" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$feature" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnAtlasFeatureId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "atlas_featureid" ) )
return context->variable( "atlas_featureid" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$atlasfeatureid" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnAtlasCurrentFeature( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "atlas_feature" ) )
return context->variable( "atlas_feature" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$atlasfeature" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnAtlasCurrentGeometry( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "atlas_geometry" ) )
return context->variable( "atlas_geometry" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$atlasgeometry" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnAtlasNumFeatures( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
if ( context && context->hasVariable( "atlas_totalfeatures" ) )
return context->variable( "atlas_totalfeatures" );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( "$numfeatures" );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnFeatureId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
{
FEAT_FROM_CONTEXT( context, f );
@ -2630,11 +2537,6 @@ static QVariant fcnPi( const QVariantList& values, const QgsExpressionContext *,
return M_PI;
}
static QVariant fcnScale( const QVariantList&, const QgsExpressionContext*, QgsExpression* parent )
{
return QVariant( parent->scale() );
}
static QVariant fcnFormatNumber( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
double value = getDoubleValue( values.at( 0 ), parent );
@ -2963,14 +2865,6 @@ static QVariant fncLighter( const QVariantList &values, const QgsExpressionConte
return QgsSymbolLayerUtils::encodeColor( color );
}
static QVariant fcnSpecialColumn( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QString varName = getStringValue( values.at( 0 ), parent );
Q_NOWARN_DEPRECATED_PUSH
return QgsExpression::specialColumn( varName );
Q_NOWARN_DEPRECATED_POP
}
static QVariant fcnGetGeometry( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QgsFeature feat = getFeature( values.at( 0 ), parent );
@ -3407,18 +3301,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "order_parts", 3, fcnOrderParts, "GeometryGroup", QString() )
<< new StaticFunction( "closest_point", 2, fcnClosestPoint, "GeometryGroup" )
<< new StaticFunction( "shortest_line", 2, fcnShortestLine, "GeometryGroup" )
<< new StaticFunction( "$rownum", 0, fcnRowNumber, "deprecated" )
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
<< new StaticFunction( "$scale", 0, fcnScale, "Record" )
<< new StaticFunction( "$map", 0, fcnMapId, "deprecated" )
<< new StaticFunction( "$numpages", 0, fcnComposerNumPages, "deprecated" )
<< new StaticFunction( "$page", 0, fcnComposerPage, "deprecated" )
<< new StaticFunction( "$feature", 0, fcnAtlasFeature, "deprecated" )
<< new StaticFunction( "$atlasfeatureid", 0, fcnAtlasFeatureId, "deprecated" )
<< new StaticFunction( "$atlasfeature", 0, fcnAtlasCurrentFeature, "deprecated" )
<< new StaticFunction( "$atlasgeometry", 0, fcnAtlasCurrentGeometry, "deprecated" )
<< new StaticFunction( "$numfeatures", 0, fcnAtlasNumFeatures, "deprecated" )
<< new StaticFunction( "uuid", 0, fcnUuid, "Record", QString(), false, QStringList(), false, QStringList() << "$uuid" )
<< new StaticFunction( "get_feature", 3, fcnGetFeature, "Record", QString(), false, QStringList(), false, QStringList() << "getFeature" )
<< new StaticFunction( "layer_property", 2, fcnGetLayerProperty, "General" )
@ -3429,8 +3313,6 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
// feature request
<< new StaticFunction( "eval", 1, fcnEval, "General", QString(), true, QStringList( QgsFeatureRequest::AllAttributes ) )
<< new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
<< new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
;
QgsExpressionContextUtils::registerContextFunctions();
@ -3444,58 +3326,6 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
return gmFunctions;
}
QMap<QString, QVariant> QgsExpression::gmSpecialColumns;
QMap<QString, QString> QgsExpression::gmSpecialColumnGroups;
void QgsExpression::setSpecialColumn( const QString& name, const QVariant& variant )
{
int fnIdx = functionIndex( name );
if ( fnIdx != -1 )
{
// function of the same name already exists
return;
}
gmSpecialColumns[ name ] = variant;
}
void QgsExpression::unsetSpecialColumn( const QString& name )
{
QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name );
if ( fit != gmSpecialColumns.end() )
{
gmSpecialColumns.erase( fit );
}
}
QVariant QgsExpression::specialColumn( const QString& name )
{
int fnIdx = functionIndex( name );
if ( fnIdx != -1 )
{
// function of the same name already exists
return QVariant();
}
QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.constFind( name );
if ( it == gmSpecialColumns.constEnd() )
{
return QVariant();
}
return it.value();
}
bool QgsExpression::hasSpecialColumn( const QString& name )
{
if ( functionIndex( name ) != -1 )
return false;
return gmSpecialColumns.contains( name );
}
bool QgsExpression::isValid( const QString &text, const QgsFields &fields, QString &errorMessage )
{
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( 0, fields );
return isValid( text, &context, errorMessage );
}
bool QgsExpression::isValid( const QString &text, const QgsExpressionContext *context, QString &errorMessage )
{
QgsExpression exp( text );
@ -3504,10 +3334,6 @@ bool QgsExpression::isValid( const QString &text, const QgsExpressionContext *co
return !exp.hasParserError();
}
void QgsExpression::setScale( double scale ) { d->mScale = scale; }
double QgsExpression::scale() { return d->mScale; }
QString QgsExpression::expression() const
{
if ( !d->mExp.isNull() )
@ -3516,18 +3342,6 @@ QString QgsExpression::expression() const
return dump();
}
QList<QgsExpression::Function*> QgsExpression::specialColumns()
{
QList<Function*> defs;
for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.constBegin(); it != gmSpecialColumns.constEnd(); ++it )
{
//check for special column group name
QString group = gmSpecialColumnGroups.value( it.key(), "Record" );
defs << new StaticFunction( it.key(), 0, static_cast< FcnEvalContext >( nullptr ), group );
}
return defs;
}
QString QgsExpression::quotedColumnRef( QString name )
{
return QString( "\"%1\"" ).arg( name.replace( '\"', "\"\"" ) );
@ -3691,13 +3505,6 @@ void QgsExpression::setGeomCalculator( const QgsDistanceArea &calc )
d->mCalc = QSharedPointer<QgsDistanceArea>( new QgsDistanceArea( calc ) );
}
bool QgsExpression::prepare( const QgsFields& fields )
{
detach();
QgsExpressionContext fc = QgsExpressionContextUtils::createFeatureBasedContext( 0, fields );
return prepare( &fc );
}
bool QgsExpression::prepare( const QgsExpressionContext *context )
{
detach();
@ -3719,45 +3526,6 @@ bool QgsExpression::prepare( const QgsExpressionContext *context )
return d->mRootNode->prepare( this, context );
}
QVariant QgsExpression::evaluate( const QgsFeature* f )
{
d->mEvalErrorString = QString();
if ( !d->mRootNode )
{
d->mEvalErrorString = tr( "No root node! Parsing failed?" );
return QVariant();
}
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f ? *f : QgsFeature(), QgsFields() );
return d->mRootNode->eval( this, &context );
}
QVariant QgsExpression::evaluate( const QgsFeature &f )
{
Q_NOWARN_DEPRECATED_PUSH
return evaluate( &f );
Q_NOWARN_DEPRECATED_POP
}
QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields )
{
// first prepare
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f ? *f : QgsFeature() , fields );
bool res = prepare( &context );
if ( !res )
return QVariant();
// then evaluate
return evaluate( &context );
}
inline QVariant QgsExpression::evaluate( const QgsFeature& f, const QgsFields& fields )
{
Q_NOWARN_DEPRECATED_PUSH
return evaluate( &f, fields );
Q_NOWARN_DEPRECATED_POP
}
QVariant QgsExpression::evaluate()
{
d->mEvalErrorString = QString();
@ -3797,13 +3565,6 @@ void QgsExpression::setEvalErrorString( const QString& str )
d->mEvalErrorString = str;
}
void QgsExpression::setCurrentRowNumber( int rowNumber )
{
d->mRowNumber = rowNumber;
}
int QgsExpression::currentRowNumber() { return d->mRowNumber; }
QString QgsExpression::dump() const
{
if ( !d->mRootNode )
@ -3843,35 +3604,10 @@ void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const
d->mRootNode->accept( v );
}
QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
{
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( feat ? *feat : QgsFeature(), layer ? layer->fields() : QgsFields() );
return replaceExpressionText( action, &context, substitutionMap, distanceArea );
}
QString QgsExpression::replaceExpressionText( const QString &action, const QgsExpressionContext *context, const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
{
QString expr_action;
QMap<QString, QVariant> savedValues;
if ( substitutionMap )
{
// variables with a local scope (must be restored after evaluation)
for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
{
Q_NOWARN_DEPRECATED_PUSH
QVariant oldValue = QgsExpression::specialColumn( sit.key() );
if ( !oldValue.isNull() )
savedValues.insert( sit.key(), oldValue );
// set the new value
QgsExpression::setSpecialColumn( sit.key(), sit.value() );
Q_NOWARN_DEPRECATED_POP
}
}
int index = 0;
while ( index < action.size() )
{
@ -3915,14 +3651,6 @@ QString QgsExpression::replaceExpressionText( const QString &action, const QgsEx
expr_action += action.midRef( index );
// restore overwritten local values
Q_NOWARN_DEPRECATED_PUSH
for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
{
QgsExpression::setSpecialColumn( sit.key(), sit.value() );
}
Q_NOWARN_DEPRECATED_POP
return expr_action;
}
@ -5131,69 +4859,6 @@ QString QgsExpression::formatPreviewString( const QVariant& value )
}
}
QVariant QgsExpression::Function::func( const QVariantList& values, const QgsFeature* feature, QgsExpression* parent )
{
//default implementation creates a QgsFeatureBasedExpressionContext
QgsExpressionContext c = QgsExpressionContextUtils::createFeatureBasedContext( feature ? *feature : QgsFeature(), QgsFields() );
return func( values, &c, parent );
}
QVariant QgsExpression::Function::func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent )
{
//base implementation calls deprecated func to avoid API breakage
QgsFeature f;
if ( context && context->hasVariable( QgsExpressionContext::EXPR_FEATURE ) )
f = qvariant_cast<QgsFeature>( context->variable( QgsExpressionContext::EXPR_FEATURE ) );
Q_NOWARN_DEPRECATED_PUSH
return func( values, &f, parent );
Q_NOWARN_DEPRECATED_POP
}
QVariant QgsExpression::Node::eval( QgsExpression* parent, const QgsFeature* feature )
{
//default implementation creates a QgsFeatureBasedExpressionContext
QgsExpressionContext c = QgsExpressionContextUtils::createFeatureBasedContext( feature ? *feature : QgsFeature(), QgsFields() );
return eval( parent, &c );
}
QVariant QgsExpression::Node::eval( QgsExpression *parent, const QgsExpressionContext *context )
{
//base implementation calls deprecated eval to avoid API breakage
QgsFeature f;
if ( context && context->hasVariable( QgsExpressionContext::EXPR_FEATURE ) )
f = qvariant_cast<QgsFeature>( context->variable( QgsExpressionContext::EXPR_FEATURE ) );
Q_NOWARN_DEPRECATED_PUSH
return eval( parent, &f );
Q_NOWARN_DEPRECATED_POP
}
bool QgsExpression::Node::prepare( QgsExpression* parent, const QgsFields &fields )
{
QgsExpressionContext c = QgsExpressionContextUtils::createFeatureBasedContext( 0, fields );
return prepare( parent, &c );
}
bool QgsExpression::Node::prepare( QgsExpression* parent, const QgsExpressionContext *context )
{
//base implementation calls deprecated prepare to avoid API breakage
QgsFields f;
if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
f = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
Q_NOWARN_DEPRECATED_PUSH
return prepare( parent, f );
Q_NOWARN_DEPRECATED_POP
}
QVariant QgsExpression::StaticFunction::func( const QVariantList &values, const QgsFeature* f, QgsExpression* parent )
{
Q_NOWARN_DEPRECATED_PUSH
return mFnc ? mFnc( values, f, parent ) : QVariant();
Q_NOWARN_DEPRECATED_POP
}
const QgsExpression::Node* QgsExpression::rootNode() const
{
return d->mRootNode;

View File

@ -105,7 +105,6 @@ Implicit sharing was added in 2.14
*/
Q_NOWARN_DEPRECATED_PUSH
class CORE_EXPORT QgsExpression
{
Q_DECLARE_TR_FUNCTIONS( QgsExpression )
@ -142,10 +141,6 @@ class CORE_EXPORT QgsExpression
//! Returns root node of the expression. Root node is null is parsing has failed
const Node* rootNode() const;
//! Get the expression ready for evaluation - find out column indexes.
//! @deprecated use prepare( const QgsExpressionContext *context ) instead
Q_DECL_DEPRECATED bool prepare( const QgsFields &fields );
/** Get the expression ready for evaluation - find out column indexes.
* @param context context for preparing expression
* @note added in QGIS 2.12
@ -167,28 +162,6 @@ class CORE_EXPORT QgsExpression
// evaluation
//! Evaluate the feature and return the result
//! @note prepare() should be called before calling this method
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature* f );
//! Evaluate the feature and return the result
//! @note prepare() should be called before calling this method
//! @note available in python bindings as evaluatePrepared
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature& f );
//! Evaluate the feature and return the result
//! @note this method does not expect that prepare() has been called on this instance
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
//! Evaluate the feature and return the result
//! @note this method does not expect that prepare() has been called on this instance
//! @note not available in python bindings
//! @deprecated use evaluate( const QgsExpressionContext* context ) instead
Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature& f, const QgsFields& fields );
/** Evaluate the feature and return the result.
* @note this method does not expect that prepare() has been called on this instance
* @note added in QGIS 2.12
@ -209,39 +182,11 @@ class CORE_EXPORT QgsExpression
//! Set evaluation error (used internally by evaluation functions)
void setEvalErrorString( const QString& str );
//! Set the number for $rownum special column
//! @deprecated use QgsExpressionContext to set row number instead
Q_DECL_DEPRECATED void setCurrentRowNumber( int rowNumber );
//! Return the number used for $rownum special column
//! @deprecated use QgsExpressionContext to retrieve row number instead
Q_DECL_DEPRECATED int currentRowNumber(); //TODO QGIS 3.0: make the following methods private. They are still required for replaceExpressionText
//but should not be publicly used
/** Assign a special column
* @deprecated use global or project QgsExpressionContext variables instead
*/
Q_DECL_DEPRECATED static void setSpecialColumn( const QString& name, const QVariant& value );
/** Unset a special column
* @deprecated use global or project QgsExpressionContext variables instead
*/
Q_DECL_DEPRECATED static void unsetSpecialColumn( const QString& name );
/** Return the value of the given special column or a null QVariant if undefined
* @deprecated use global or project QgsExpressionContext variables instead
*/
Q_DECL_DEPRECATED static QVariant specialColumn( const QString& name );
/** Check whether a special column exists
* @note added in 2.2
*/
static bool hasSpecialColumn( const QString& name );
/** Checks whether an expression consists only of a single field reference
* @note added in 2.9
*/
bool isField() const { return rootNode() && dynamic_cast<const NodeColumnRef*>( rootNode() ) ;}
//! @deprecated use QgsExpressionContext variant instead
Q_DECL_DEPRECATED static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
/** Tests whether a string is a valid expression.
* @param text string to test
* @param context optional expression context
@ -251,10 +196,6 @@ class CORE_EXPORT QgsExpression
*/
static bool isValid( const QString& text, const QgsExpressionContext* context, QString &errorMessage );
void setScale( double scale );
double scale();
//! Return the original, unmodified expression string.
//! If there was none supplied because it was constructed by sole
//! API calls, dump() will be used to create one instead.
@ -315,24 +256,6 @@ class CORE_EXPORT QgsExpression
*/
void setAreaUnits( QgsUnitTypes::AreaUnit unit );
/** This function currently replaces each expression between [% and %]
* in the string with the result of its evaluation on the feature
* passed as argument.
*
* Additional substitutions can be passed through the substitutionMap
* parameter
* @param action
* @param feat
* @param layer
* @param substitutionMap
* @param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance and area conversion
* @deprecated use QgsExpressionContext variant instead
*/
Q_DECL_DEPRECATED static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap = nullptr,
const QgsDistanceArea* distanceArea = nullptr );
/** This function replaces each expression between [% and %]
* in the string with the result of its evaluation with the specified context
*
@ -470,12 +393,9 @@ class CORE_EXPORT QgsExpression
//! List of parameters, used for function definition
typedef QList< Parameter > ParameterList;
//! @deprecated will be removed in QGIS 3.0
typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
/** Function definition for evaluation against an expression context, using a list of values as parameters to the function.
*/
typedef QVariant( *FcnEvalContext )( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent );
typedef QVariant( *FcnEval )( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent );
/** \ingroup core
* A abstract base class for defining QgsExpression functions.
@ -587,18 +507,13 @@ class CORE_EXPORT QgsExpression
//TODO QGIS 3.0 - rename to helpText()
const QString helptext() const { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
//! @deprecated Use QgsExpressionContext variant instead
Q_DECL_DEPRECATED virtual QVariant func( const QVariantList&, const QgsFeature*, QgsExpression* );
/** Returns result of evaluating the function.
* @param values list of values passed to the function
* @param context context expression is being evaluated against
* @param parent parent expression
* @returns result of function
* @note named funcV2 in Python bindings. Will be renamed to func to replace deprecated method in QGIS 3.0.
*/
//TODO QGIS 3.0 - rename python method
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent );
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) = 0;
bool operator==( const Function& other ) const
{
@ -630,30 +545,12 @@ class CORE_EXPORT QgsExpression
class StaticFunction : public Function
{
public:
//! @deprecated use QgsExpressionContext variant instead
Q_DECL_DEPRECATED StaticFunction( const QString& fnname,
int params,
FcnEval fcn,
const QString& group,
const QString& helpText = QString(),
bool usesGeometry = false,
const QStringList& referencedColumns = QStringList(),
bool lazyEval = false,
const QStringList& aliases = QStringList(),
bool handlesNull = false )
: Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
, mFnc( fcn )
, mContextFnc( nullptr )
, mAliases( aliases )
{}
virtual ~StaticFunction() {}
/** Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter values.
*/
StaticFunction( const QString& fnname,
int params,
FcnEvalContext fcn,
FcnEval fcn,
const QString& group,
const QString& helpText = QString(),
bool usesGeometry = false,
@ -662,8 +559,7 @@ class CORE_EXPORT QgsExpression
const QStringList& aliases = QStringList(),
bool handlesNull = false )
: Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
, mFnc( nullptr )
, mContextFnc( fcn )
, mFnc( fcn )
, mAliases( aliases )
{}
@ -671,7 +567,7 @@ class CORE_EXPORT QgsExpression
*/
StaticFunction( const QString& fnname,
const ParameterList& params,
FcnEvalContext fcn,
FcnEval fcn,
const QString& group,
const QString& helpText = QString(),
bool usesGeometry = false,
@ -680,13 +576,11 @@ class CORE_EXPORT QgsExpression
const QStringList& aliases = QStringList(),
bool handlesNull = false )
: Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
, mFnc( nullptr )
, mContextFnc( fcn )
, mFnc( fcn )
, mAliases( aliases )
{}
//! @deprecated use QgsExpressionContext variant instead
Q_DECL_DEPRECATED virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override;
virtual ~StaticFunction() {}
/** Returns result of evaluating the function.
* @param values list of values passed to the function
@ -696,14 +590,13 @@ class CORE_EXPORT QgsExpression
*/
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) override
{
return mContextFnc ? mContextFnc( values, context, parent ) : QVariant();
return mFnc ? mFnc( values, context, parent ) : QVariant();
}
virtual QStringList aliases() const override { return mAliases; }
private:
FcnEval mFnc;
FcnEvalContext mContextFnc;
QStringList mAliases;
};
@ -749,11 +642,6 @@ class CORE_EXPORT QgsExpression
*/
static int functionCount();
/**
* Returns a list of special Column definitions
*/
static QList<Function*> specialColumns();
/** Returns a quoted column reference (in double quotes)
* @see quotedString()
* @see quotedValue()
@ -814,33 +702,19 @@ class CORE_EXPORT QgsExpression
*/
virtual NodeType nodeType() const = 0;
/**
* Abstract virtual eval method
* Errors are reported to the parent
* @deprecated use QgsExpressionContext variant instead
*/
Q_DECL_DEPRECATED virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
/**
* Abstract virtual eval method
* Errors are reported to the parent
* @note added in QGIS 2.12
*/
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context );
/**
* Abstract virtual preparation method
* Errors are reported to the parent
* @deprecated use QgsExpressionContext variant instead
*/
Q_DECL_DEPRECATED virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) = 0;
/**
* Abstract virtual preparation method
* Errors are reported to the parent
* @note added in QGIS 2.12
*/
virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context );
virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) = 0;
/**
* Abstract virtual dump method
@ -965,11 +839,6 @@ class CORE_EXPORT QgsExpression
bool mHasNamedNodes;
};
//TODO QGIS 3.0 - remove
//! @deprecated use QgsInterval instead
//! \ingroup core
typedef QgsInterval Interval;
/** \ingroup core
*/
class CORE_EXPORT NodeUnaryOperator : public Node
@ -1476,9 +1345,6 @@ class CORE_EXPORT QgsExpression
friend class QgsOgcUtils;
};
Q_NOWARN_DEPRECATED_POP
Q_DECLARE_METATYPE( QgsExpression::Node* )
#endif // QGSEXPRESSION_H

View File

@ -247,23 +247,14 @@ expression:
| SPECIAL_COL
{
int fnIndex = QgsExpression::functionIndex(*$1);
if (fnIndex == -1)
if (fnIndex >= 0)
{
if ( !QgsExpression::hasSpecialColumn( *$1 ) )
{
exp_error(parser_ctx, "Special column is not known");
delete $1;
YYERROR;
}
// $var is equivalent to _specialcol_( "$var" )
QgsExpression::NodeList* args = new QgsExpression::NodeList();
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( *$1 );
args->append( literal );
$$ = new QgsExpression::NodeFunction( QgsExpression::functionIndex( "_specialcol_" ), args );
$$ = new QgsExpression::NodeFunction( fnIndex, nullptr );
}
else
{
$$ = new QgsExpression::NodeFunction( fnIndex, nullptr );
exp_error(parser_ctx, QString("%1 function is not known").arg(*$1).toLocal8Bit().constData());
YYERROR;
}
delete $1;
}
@ -351,4 +342,3 @@ void exp_error(expression_parser_context* parser_ctx, const char* msg)
{
parser_ctx->errorMsg = msg;
}

View File

@ -36,8 +36,6 @@ class QgsExpressionPrivate
QgsExpressionPrivate()
: ref( 1 )
, mRootNode( nullptr )
, mRowNumber( 0 )
, mScale( 0 )
, mCalc( nullptr )
, mDistanceUnit( QgsUnitTypes::DistanceUnknownUnit )
, mAreaUnit( QgsUnitTypes::AreaUnknownUnit )
@ -48,8 +46,6 @@ class QgsExpressionPrivate
, mRootNode( other.mRootNode ? other.mRootNode->clone() : nullptr )
, mParserErrorString( other.mParserErrorString )
, mEvalErrorString( other.mEvalErrorString )
, mRowNumber( 0 )
, mScale( other.mScale )
, mExp( other.mExp )
, mCalc( other.mCalc )
, mDistanceUnit( other.mDistanceUnit )
@ -68,8 +64,6 @@ class QgsExpressionPrivate
QString mParserErrorString;
QString mEvalErrorString;
int mRowNumber;
double mScale;
QString mExp;
QSharedPointer<QgsDistanceArea> mCalc;

View File

@ -2299,8 +2299,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
QgsDebugMsgLevel( QString( "Expression parser error:%1" ).arg( exp->parserErrorString() ), 4 );
return;
}
exp->setScale( context.rendererScale() );
// QVariant result = exp->evaluate( &f, layer->pendingFields() );
QVariant result = exp->evaluate( &context.expressionContext() ); // expression prepared in QgsPalLabeling::prepareLayer()
if ( exp->hasEvalError() )
{

View File

@ -195,16 +195,9 @@ bool QgsVectorLayerLabelProvider::prepare( const QgsRenderContext& context, QStr
continue;
}
// NOTE: the following also prepares any expressions for later use
// store parameters for data defined expressions
QMap<QString, QVariant> exprParams;
exprParams.insert( "scale", context.rendererScale() );
dd->setExpressionParams( exprParams );
// this will return columns for expressions or field name, depending upon what is set to be used
QStringList cols = dd->referencedColumns( context.expressionContext() ); // <-- prepares any expressions, too
// this also prepares any expressions, too
QStringList cols = dd->referencedColumns( context.expressionContext() );
//QgsDebugMsgLevel( QString( "Data defined referenced columns:" ) + cols.join( "," ), 4 );
Q_FOREACH ( const QString& name, cols )

View File

@ -342,12 +342,6 @@ void QgsSymbolLayer::prepareExpressions( const QgsSymbolRenderContext& context )
{
if ( it.value() )
{
QMap<QString, QVariant> params;
if ( context.renderContext().rendererScale() > 0 )
{
params.insert( "scale", context.renderContext().rendererScale() );
}
it.value()->setExpressionParams( params );
it.value()->prepareExpression( context.renderContext().expressionContext() );
}
}

View File

@ -494,13 +494,6 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
registerItem( func->group(), func->name(), ' ' + name + ' ', func->helptext() );
}
QList<QgsExpression::Function*> specials = QgsExpression::specialColumns();
for ( int i = 0; i < specials.size(); ++i )
{
QString name = specials[i]->name();
registerItem( specials[i]->group(), name, ' ' + name + ' ' );
}
loadExpressionContext();
}

View File

@ -179,16 +179,6 @@ void TestQgsComposerLabel::feature_evaluation()
QString expected = "Bretagne_ok";
QCOMPARE( evaluated, expected );
}
{
// evaluation with a feature and local variables
QMap<QString, QVariant> locals;
locals.insert( "$test", "OK" );
mComposerLabel->setSubstitutions( locals );
mComposerLabel->setText( "[%\"NAME_1\"||$test%]" );
QString evaluated = mComposerLabel->displayText();
QString expected = "BretagneOK";
QCOMPARE( evaluated, expected );
}
mComposition->atlasComposition().setEnabled( false );
}

View File

@ -1084,63 +1084,22 @@ class TestQgsExpression: public QObject
QCOMPARE( res2.type(), QVariant::Invalid );
}
void eval_rownum()
{
QgsExpression exp( "$rownum + 1" );
QVariant v1 = exp.evaluate();
QCOMPARE( v1.toInt(), 1 );
Q_NOWARN_DEPRECATED_PUSH
exp.setCurrentRowNumber( 100 );
Q_NOWARN_DEPRECATED_POP
QVariant v2 = exp.evaluate();
QCOMPARE( v2.toInt(), 101 );
QgsExpressionContext context;
context << new QgsExpressionContextScope();
context.lastScope()->setVariable( "row_number", 101 );
QVariant v3 = exp.evaluate();
QCOMPARE( v3.toInt(), 101 );
}
void eval_scale()
{
QgsExpression exp( "$scale" );
QVariant v1 = exp.evaluate();
QCOMPARE( v1.toInt(), 0 );
exp.setScale( 100.00 );
QVariant v2 = exp.evaluate();
QCOMPARE( v2.toDouble(), 100.00 );
}
void eval_feature_id()
{
QgsFeature f( 100 );
QgsExpression exp( "$id * 2" );
Q_NOWARN_DEPRECATED_PUSH
QVariant v = exp.evaluate( &f );
Q_NOWARN_DEPRECATED_POP
QCOMPARE( v.toInt(), 200 );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
QVariant v2 = exp.evaluate( &context );
QCOMPARE( v2.toInt(), 200 );
QVariant v = exp.evaluate( &context );
QCOMPARE( v.toInt(), 200 );
}
void eval_current_feature()
{
QgsFeature f( 100 );
QgsExpression exp( "$currentfeature" );
Q_NOWARN_DEPRECATED_PUSH
QVariant v = exp.evaluate( &f );
Q_NOWARN_DEPRECATED_POP
QgsFeature evalFeature = v.value<QgsFeature>();
QCOMPARE( evalFeature.id(), f.id() );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
v = exp.evaluate( &context );
evalFeature = v.value<QgsFeature>();
QVariant v = exp.evaluate( &context );
QgsFeature evalFeature = v.value<QgsFeature>();
QCOMPARE( evalFeature.id(), f.id() );
}
@ -1154,17 +1113,11 @@ class TestQgsExpression: public QObject
f.setAttribute( QString( "col1" ), QString( "test value" ) );
f.setAttribute( QString( "second_column" ), 5 );
QgsExpression exp( "attribute($currentfeature,'col1')" );
Q_NOWARN_DEPRECATED_PUSH
QVariant v = exp.evaluate( &f );
QCOMPARE( v.toString(), QString( "test value" ) );
QgsExpression exp2( "attribute($currentfeature,'second'||'_column')" );
v = exp2.evaluate( &f );
Q_NOWARN_DEPRECATED_POP
QCOMPARE( v.toInt(), 5 );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
v = exp.evaluate( &context );
QVariant v = exp.evaluate( &context );
QCOMPARE( v.toString(), QString( "test value" ) );
QgsExpression exp2( "attribute($currentfeature,'second'||'_column')" );
v = exp2.evaluate( &context );
QCOMPARE( v.toInt(), 5 );
}
@ -1564,14 +1517,9 @@ class TestQgsExpression: public QObject
QgsExpression exp( string );
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), true );
Q_NOWARN_DEPRECATED_PUSH
QVariant out = exp.evaluate( &f );
Q_NOWARN_DEPRECATED_POP
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.toDouble(), result );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
out = exp.evaluate( &context );
QVariant out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.toDouble(), result );
}
@ -1591,29 +1539,19 @@ class TestQgsExpression: public QObject
QgsExpressionContext context;
Q_NOWARN_DEPRECATED_PUSH
QgsExpression exp1( "$area" );
QVariant vArea = exp1.evaluate( &fPolygon );
QCOMPARE( vArea.toDouble(), 40. );
context.setFeature( fPolygon );
vArea = exp1.evaluate( &context );
QVariant vArea = exp1.evaluate( &context );
QCOMPARE( vArea.toDouble(), 40. );
QgsExpression exp2( "$length" );
QVariant vLength = exp2.evaluate( &fPolyline );
QCOMPARE( vLength.toDouble(), 10. );
context.setFeature( fPolyline );
vLength = exp2.evaluate( &context );
QVariant vLength = exp2.evaluate( &context );
QCOMPARE( vLength.toDouble(), 10. );
QgsExpression exp3( "$perimeter" );
QVariant vPerimeter = exp3.evaluate( &fPolygon );
QCOMPARE( vPerimeter.toDouble(), 26. );
context.setFeature( fPolygon );
vPerimeter = exp3.evaluate( &context );
QVariant vPerimeter = exp3.evaluate( &context );
QCOMPARE( vPerimeter.toDouble(), 26. );
QgsExpression deprecatedExpXAt( "$x_at(1)" );
@ -1671,66 +1609,47 @@ class TestQgsExpression: public QObject
QCOMPARE( yAt.toDouble(), 6.0 );
QgsExpression exp4( "bounds_width($geometry)" );
QVariant vBoundsWidth = exp4.evaluate( &fPolygon );
QCOMPARE( vBoundsWidth.toDouble(), 8.0 );
context.setFeature( fPolygon );
vBoundsWidth = exp4.evaluate( &context );
QVariant vBoundsWidth = exp4.evaluate( &context );
QCOMPARE( vBoundsWidth.toDouble(), 8.0 );
QgsExpression exp5( "bounds_height($geometry)" );
QVariant vBoundsHeight = exp5.evaluate( &fPolygon );
QCOMPARE( vBoundsHeight.toDouble(), 5.0 );
vBoundsHeight = exp5.evaluate( &context );
QVariant vBoundsHeight = exp5.evaluate( &context );
QCOMPARE( vBoundsHeight.toDouble(), 5.0 );
QgsExpression exp6( "xmin($geometry)" );
QVariant vXMin = exp6.evaluate( &fPolygon );
QCOMPARE( vXMin.toDouble(), 2.0 );
vXMin = exp6.evaluate( &context );
QVariant vXMin = exp6.evaluate( &context );
QCOMPARE( vXMin.toDouble(), 2.0 );
QgsExpression exp7( "xmax($geometry)" );
QVariant vXMax = exp7.evaluate( &fPolygon );
QCOMPARE( vXMax.toDouble(), 10.0 );
vXMax = exp7.evaluate( &context );
QVariant vXMax = exp7.evaluate( &context );
QCOMPARE( vXMax.toDouble(), 10.0 );
QgsExpression exp8( "ymin($geometry)" );
QVariant vYMin = exp8.evaluate( &fPolygon );
QCOMPARE( vYMin.toDouble(), 1.0 );
vYMin = exp8.evaluate( &context );
QVariant vYMin = exp8.evaluate( &context );
QCOMPARE( vYMin.toDouble(), 1.0 );
QgsExpression exp9( "ymax($geometry)" );
QVariant vYMax = exp9.evaluate( &fPolygon );
QCOMPARE( vYMax.toDouble(), 6.0 );
exp9.evaluate( &context );
QVariant vYMax = exp9.evaluate( &context );
QCOMPARE( vYMax.toDouble(), 6.0 );
QgsExpression exp10( "num_points($geometry)" );
QVariant vVertices = exp10.evaluate( &fPolygon );
QVariant vVertices = exp10.evaluate( &context );
QCOMPARE( vVertices.toInt(), 5 );
context.setFeature( fPolyline );
QgsExpression exp11( "length($geometry)" );
QVariant vLengthLine = exp11.evaluate( &fPolyline );
QVariant vLengthLine = exp11.evaluate( &context );
QCOMPARE( vLengthLine.toDouble(), 10.0 );
context.setFeature( fPolygon );
QgsExpression exp12( "area($geometry)" );
QVariant vAreaPoly = exp12.evaluate( &fPolygon );
QVariant vAreaPoly = exp12.evaluate( &context );
QCOMPARE( vAreaPoly.toDouble(), 40.0 );
QgsExpression exp13( "perimeter($geometry)" );
QVariant vPerimeterPoly = exp13.evaluate( &fPolygon );
QVariant vPerimeterPoly = exp13.evaluate( &context );
QCOMPARE( vPerimeterPoly.toDouble(), 26.0 );
Q_NOWARN_DEPRECATED_POP
}
void geom_calculator()
@ -1870,40 +1789,24 @@ class TestQgsExpression: public QObject
QgsExpressionContext context;
Q_NOWARN_DEPRECATED_PUSH
QgsExpression exp1( "geomToWKT($geometry)" );
QVariant vWktLine = exp1.evaluate( &fPolyline );
QCOMPARE( vWktLine.toString(), QString( "LineString (0 0, 10 0)" ) );
context.setFeature( fPolyline );
vWktLine = exp1.evaluate( &context );
QVariant vWktLine = exp1.evaluate( &context );
QCOMPARE( vWktLine.toString(), QString( "LineString (0 0, 10 0)" ) );
QgsExpression exp2( "geomToWKT($geometry)" );
QVariant vWktPolygon = exp2.evaluate( &fPolygon );
QCOMPARE( vWktPolygon.toString(), QString( "Polygon ((2 1, 10 1, 10 6, 2 6, 2 1))" ) );
context.setFeature( fPolygon );
vWktPolygon = exp2.evaluate( &context );
QVariant vWktPolygon = exp2.evaluate( &context );
QCOMPARE( vWktPolygon.toString(), QString( "Polygon ((2 1, 10 1, 10 6, 2 6, 2 1))" ) );
QgsExpression exp3( "geomToWKT($geometry)" );
QVariant vWktPoint = exp3.evaluate( &fPoint );
QCOMPARE( vWktPoint.toString(), QString( "Point (-1.23456789 9.87654321)" ) );
context.setFeature( fPoint );
vWktPoint = exp3.evaluate( &context );
QVariant vWktPoint = exp3.evaluate( &context );
QCOMPARE( vWktPoint.toString(), QString( "Point (-1.23456789 9.87654321)" ) );
QgsExpression exp4( "geomToWKT($geometry, 3)" );
QVariant vWktPointSimplify = exp4.evaluate( &fPoint );
QVariant vWktPointSimplify = exp4.evaluate( &context );
QCOMPARE( vWktPointSimplify.toString(), QString( "Point (-1.235 9.877)" ) );
vWktPointSimplify = exp4.evaluate( &context );
QCOMPARE( vWktPointSimplify.toString(), QString( "Point (-1.235 9.877)" ) );
Q_NOWARN_DEPRECATED_POP
}
void eval_geometry_constructor_data()
@ -1959,24 +1862,14 @@ class TestQgsExpression: public QObject
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), false );
//deprecated method
Q_NOWARN_DEPRECATED_PUSH
QVariant out = exp.evaluate( &f );
//replacement method
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
QVariant out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
QgsGeometry outGeom = out.value<QgsGeometry>();
QCOMPARE( geom.equals( outGeom ), true );
Q_NOWARN_DEPRECATED_POP
//replacement method
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
outGeom = out.value<QgsGeometry>();
QCOMPARE( geom.equals( outGeom ), true );
}
void eval_geometry_access_transform_data()
@ -2032,23 +1925,12 @@ class TestQgsExpression: public QObject
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), needsGeom );
//deprecated method
Q_NOWARN_DEPRECATED_PUSH
QVariant out = exp.evaluate( &f );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
QVariant out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
QgsGeometry outGeom = out.value<QgsGeometry>();
QCOMPARE( geom.equals( outGeom ), true );
Q_NOWARN_DEPRECATED_POP
//replacement method
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
outGeom = out.value<QgsGeometry>();
QCOMPARE( geom.equals( outGeom ), true );
}
void eval_spatial_operator_data()
@ -2101,15 +1983,8 @@ class TestQgsExpression: public QObject
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), true );
//deprecated method
Q_NOWARN_DEPRECATED_PUSH
QVariant out = exp.evaluate( &f );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.toInt(), result.toInt() );
Q_NOWARN_DEPRECATED_POP
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
out = exp.evaluate( &context );
QVariant out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.toInt(), result.toInt() );
}
@ -2179,52 +2054,13 @@ class TestQgsExpression: public QObject
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), needGeom );
//deprecated method
Q_NOWARN_DEPRECATED_PUSH
QVariant out = exp.evaluate( &f );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
QVariant out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
QgsGeometry outGeom = out.value<QgsGeometry>();
QVERIFY( compareWkt( outGeom.exportToWkt(), result.exportToWkt() ) );
Q_NOWARN_DEPRECATED_POP
//replacement method
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
out = exp.evaluate( &context );
QCOMPARE( exp.hasEvalError(), evalError );
QCOMPARE( out.canConvert<QgsGeometry>(), true );
outGeom = out.value<QgsGeometry>();
QVERIFY( compareWkt( outGeom.exportToWkt(), result.exportToWkt() ) );
}
void eval_special_columns()
{
Q_NOWARN_DEPRECATED_PUSH
QTest::addColumn<QString>( "string" );
QTest::addColumn<QVariant>( "result" );
QgsExpression::setSpecialColumn( "$var1", QVariant(( int )42 ) );
QgsExpression exp( "$var1 + 1" );
QVariant v1 = exp.evaluate();
QCOMPARE( v1.toInt(), 43 );
QgsExpression::setSpecialColumn( "$var1", QVariant(( int )100 ) );
QVariant v2 = exp.evaluate();
QCOMPARE( v2.toInt(), 101 );
QgsExpression exp2( "_specialcol_('$var1')+1" );
QVariant v3 = exp2.evaluate();
QCOMPARE( v3.toInt(), 101 );
QgsExpression exp3( "_specialcol_('undefined')" );
QVariant v4 = exp3.evaluate();
QCOMPARE( v4, QVariant() );
QgsExpression::unsetSpecialColumn( "$var1" );
Q_NOWARN_DEPRECATED_POP
}
void eval_eval()

View File

@ -102,7 +102,7 @@ class TestQgsAtlasComposition(unittest.TestCase):
# feature number label
self.mLabel2 = QgsComposerLabel(self.mComposition)
self.mComposition.addComposerLabel(self.mLabel2)
self.mLabel2.setText("# [%$feature || ' / ' || $numfeatures%]")
self.mLabel2.setText("# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]")
self.mLabel2.setFont(QgsFontUtils.getStandardTestFont())
self.mLabel2.adjustSizeToText()
self.mLabel2.setSceneRect(QRectF(150, 200, 60, 15))
@ -121,7 +121,7 @@ class TestQgsAtlasComposition(unittest.TestCase):
shutil.rmtree(tmppath, True)
def filename_test(self):
self.mAtlas.setFilenamePattern("'output_' || $feature")
self.mAtlas.setFilenamePattern("'output_' || @atlas_featurenumber")
self.mAtlas.beginRender()
for i in range(0, self.mAtlas.numFeatures()):
self.mAtlas.prepareForFeature(i)

View File

@ -83,29 +83,14 @@ class TestQgsComposerLabel(unittest.TestCase):
mLabel.setExpressionContext(feat, mVectorLayer)
assert mLabel.displayText() == "Bretagne_ok"
# evaluation with local variables
locs = {"$test": "OK"}
mLabel.setExpressionContext(feat, mVectorLayer, locs)
mLabel.setText("[%\"NAME_1\"||$test%]")
assert mLabel.displayText() == "BretagneOK"
def page_evaluation_test(self, mComposition, mLabel, mVectorLayer):
mComposition.setNumPages(2)
mLabel.setText("[%$page||'/'||$numpages%]")
mLabel.setText("[%@layout_page||'/'||@layout_numpages%]")
assert mLabel.displayText() == "1/2"
# move the the second page and re-evaluate
mLabel.setItemPosition(0, 320)
assert mLabel.displayText() == "2/2"
# use setSpecialColumn
mLabel.setText("[%$var1 + 1%]")
QgsExpression.setSpecialColumn("$var1", 41)
assert mLabel.displayText() == "42"
QgsExpression.setSpecialColumn("$var1", 99)
assert mLabel.displayText() == "100"
QgsExpression.unsetSpecialColumn("$var1")
assert mLabel.displayText() == "[%$var1 + 1%]"
if __name__ == '__main__':
unittest.main()