17 #ifndef QGSEXPRESSIONUTILS_H
18 #define QGSEXPRESSIONUTILS_H
36 #define ENSURE_NO_EVAL_ERROR { if ( parent->hasEvalError() ) return QVariant(); }
37 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString( x ); return QVariant(); }
39 #define FEAT_FROM_CONTEXT(c, f) if ( !(c) || !( c )->hasFeature() ) return QVariant(); \
40 QgsFeature f = ( c )->feature();
69 #define TVL_True QVariant( 1 )
70 #define TVL_False QVariant( 0 )
71 #define TVL_Unknown QVariant()
73 static QVariant tvl2variant( TVL v )
88 static TVL getTVLValue(
const QVariant &value,
QgsExpression *parent )
99 return geom.
isNull() ? False : True;
105 return feat.
isValid() ? True : False;
108 if ( value.type() == QVariant::Int )
109 return value.toInt() != 0 ? True : False;
112 const double x = value.toDouble( &ok );
115 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to boolean" ).arg( value.toString() ) );
122 static inline bool isIntSafe(
const QVariant &v )
124 if ( v.type() == QVariant::Int )
126 if ( v.type() == QVariant::UInt )
128 if ( v.type() == QVariant::LongLong )
130 if ( v.type() == QVariant::ULongLong )
132 if ( v.type() == QVariant::Double )
134 if ( v.type() == QVariant::String )
137 v.toString().toInt( &ok );
143 static inline bool isDoubleSafe(
const QVariant &v )
145 if ( v.type() == QVariant::Double )
147 if ( v.type() == QVariant::Int )
149 if ( v.type() == QVariant::UInt )
151 if ( v.type() == QVariant::LongLong )
153 if ( v.type() == QVariant::ULongLong )
155 if ( v.type() == QVariant::String )
158 const double val = v.toString().toDouble( &ok );
159 ok = ok && std::isfinite( val ) && !std::isnan( val );
165 static inline bool isDateTimeSafe(
const QVariant &v )
167 return v.type() == QVariant::DateTime
168 || v.type() == QVariant::Date
169 || v.type() == QVariant::Time;
172 static inline bool isIntervalSafe(
const QVariant &v )
179 if ( v.type() == QVariant::String )
186 static inline bool isNull(
const QVariant &v )
191 static inline bool isList(
const QVariant &v )
193 return v.type() == QVariant::List || v.type() == QVariant::StringList;
197 static QString getStringValue(
const QVariant &value,
QgsExpression * )
199 return value.toString();
209 static QByteArray getBinaryValue(
const QVariant &value,
QgsExpression *parent )
211 if ( value.type() != QVariant::ByteArray )
216 return value.toByteArray();
219 static double getDoubleValue(
const QVariant &value,
QgsExpression *parent )
222 const double x = value.toDouble( &ok );
223 if ( !ok || std::isnan( x ) || !std::isfinite( x ) )
225 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to double" ).arg( value.toString() ) );
231 static qlonglong getIntValue(
const QVariant &value,
QgsExpression *parent )
234 const qlonglong x = value.toLongLong( &ok );
241 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to int" ).arg( value.toString() ) );
246 static int getNativeIntValue(
const QVariant &value,
QgsExpression *parent )
249 const qlonglong x = value.toLongLong( &ok );
250 if ( ok && x >= std::numeric_limits<int>::min() && x <= std::numeric_limits<int>::max() )
252 return static_cast<int>( x );
256 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to native int" ).arg( value.toString() ) );
261 static QDateTime getDateTimeValue(
const QVariant &value,
QgsExpression *parent )
263 QDateTime d = value.toDateTime();
270 const QTime t = value.toTime();
273 return QDateTime( QDate( 1, 1, 1 ), t );
276 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
281 static QDate getDateValue(
const QVariant &value,
QgsExpression *parent )
283 QDate d = value.toDate();
290 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( value.toString() ) );
295 static QTime getTimeValue(
const QVariant &value,
QgsExpression *parent )
297 QTime t = value.toTime();
304 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( value.toString() ) );
315 if ( inter.isValid() )
321 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to interval" ).arg( value.toString() ) );
365 qWarning(
"Raw map layer pointer stored in expression evaluation, switch to QgsWeakMapLayerPointer instead" );
374 ml = project->
mapLayer( value.toString() );
383 static std::unique_ptr<QgsVectorLayerFeatureSource> getFeatureSource(
const QVariant &value,
QgsExpression *e )
385 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
387 auto getFeatureSource = [ &value, e, &featureSource ]
399 if ( QThread::currentThread() == qApp->thread() )
402 QMetaObject::invokeMethod( qApp, getFeatureSource, Qt::BlockingQueuedConnection );
404 return featureSource;
409 return qobject_cast<QgsVectorLayer *>( getMapLayer( value, e ) );
414 return qobject_cast<QgsRasterLayer *>( getMapLayer( value, e ) );
419 return qobject_cast<QgsMeshLayer *>( getMapLayer( value, e ) );
427 static QString getFilePathValue(
const QVariant &value,
QgsExpression *parent );
429 static QVariantList getListValue(
const QVariant &value,
QgsExpression *parent )
431 if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
433 return value.toList();
437 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to array" ).arg( value.toString() ) );
438 return QVariantList();
442 static QVariantMap getMapValue(
const QVariant &value,
QgsExpression *parent )
444 if ( value.type() == QVariant::Map )
446 return value.toMap();
450 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to map" ).arg( value.toString() ) );
451 return QVariantMap();
461 static QString toLocalizedString(
const QVariant &value )
463 if ( value.type() == QVariant::Int || value.type() == QVariant::UInt || value.type() == QVariant::LongLong || value.type() == QVariant::ULongLong )
468 if ( value.type() == QVariant::ULongLong )
470 res = QLocale().toString( value.toULongLong( &ok ) );
474 res = QLocale().toString( value.toLongLong( &ok ) );
483 return value.toString();
487 else if ( value.type() == QVariant::Double || value.type() ==
static_cast<QVariant::Type
>( QMetaType::Float ) )
490 const QString strVal = value.toString();
491 const int dotPosition = strVal.indexOf(
'.' );
492 const int precision = dotPosition > 0 ? strVal.length() - dotPosition - 1 : 0;
493 const QString res = QLocale().toString( value.toDouble( &ok ),
'f',
precision );
501 return value.toString();
506 return value.toString();
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Abstract base class for all nodes that can appear in an expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
This class wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isValid() const
Returns the validity of this feature.
A geometry is the spatial representation of a feature.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
static QgsInterval fromString(const QString &string)
Converts a string to an interval.
Base class for all map layer types.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
Represents a raster layer.
Partial snapshot of vector layer's state (only the members necessary for access to features)
Represents a vector layer which manages a vector based data sets.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.