30using namespace Qt::StringLiterals;
34QgsExpressionUtils::TVL QgsExpressionUtils::AND[3][3] = {
36 { False, False, False },
40QgsExpressionUtils::TVL QgsExpressionUtils::OR[3][3] = {
46QgsExpressionUtils::TVL QgsExpressionUtils::NOT[3] = { True, False,
Unknown };
49QColor QgsExpressionUtils::getColorValue(
const QVariant &value,
QgsExpression *parent,
bool &isQColor )
51 isQColor = value.userType() == QMetaType::Type::QColor;
52 QColor color = isQColor ? value.value<QColor>() : QgsSymbolLayerUtils::decodeColor( value.toString() );
53 if ( !color.isValid() )
55 parent->setEvalErrorString( isQColor ? QObject::tr(
"Input color is invalid" ) : QObject::tr(
"Cannot convert '%1' to color" ).arg( value.toString() ) );
63 if ( value.userType() == qMetaTypeId<QgsGradientColorRamp>() )
64 return value.
value<QgsGradientColorRamp>();
68 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to gradient ramp" ).arg( value.toString() ) );
70 return QgsGradientColorRamp();
75 return getMapLayerPrivate( value, context, parent );
84#ifdef __clang_analyzer__
90 ml = value.value< QgsMapLayer * >();
94 qWarning(
"Raw map layer pointer stored in expression evaluation, switch to QgsWeakMapLayerPointer instead" );
101 const QString identifier = value.toString();
106 const QList< QgsMapLayerStore * > stores = context->
layerStores();
107 for ( QgsMapLayerStore *store : stores )
109 auto findLayerInStoreFunction = [storePointer = QPointer< QgsMapLayerStore >( store ), &ml, identifier] {
110 if ( QgsMapLayerStore *store = storePointer.data() )
113 ml = store->mapLayer( identifier );
119 ml = store->mapLayersByName( identifier ).value( 0 );
125 if ( QThread::currentThread() == store->thread() )
126 findLayerInStoreFunction();
128 QMetaObject::invokeMethod( store, std::move( findLayerInStoreFunction ), Qt::BlockingQueuedConnection );
136 auto getMapLayerFromProjectInstance = [&ml, identifier] {
140 ml = project->
mapLayer( identifier );
148 if ( QThread::currentThread() == qApp->thread() )
149 getMapLayerFromProjectInstance();
151 QMetaObject::invokeMethod( qApp, std::move( getMapLayerFromProjectInstance ), Qt::BlockingQueuedConnection );
161 return QgsCoordinateReferenceSystem();
164 const bool isCrs = value.userType() == qMetaTypeId<QgsCoordinateReferenceSystem>();
166 if ( !isCrs && value.toString().isEmpty() )
168 return QgsCoordinateReferenceSystem();
171 QgsCoordinateReferenceSystem crs = isCrs ? value.value<QgsCoordinateReferenceSystem>() : QgsCoordinateReferenceSystem( value.toString() );
174 parent->setEvalErrorString( isCrs ? QObject::tr(
"Input CRS is invalid" ) : QObject::tr(
"Cannot convert '%1' to CRS" ).arg( value.toString() ) );
180QTimeZone QgsExpressionUtils::getTimeZoneValue(
const QVariant &value,
QgsExpression *parent )
189 if ( value.userType() == qMetaTypeId< QTimeZone>() )
192 tz = value.value<QTimeZone>();
197 parent->
setEvalErrorString( isTz ? QObject::tr(
"Input time zone is invalid" ) : QObject::tr(
"Cannot convert '%1' to a time zone" ).arg( value.toString() ) );
207#ifndef __clang_analyzer__
213 ml = value.value< QgsMapLayer * >();
217 qWarning(
"Raw map layer pointer stored in expression evaluation, switch to QgsWeakMapLayerPointer instead" );
223 auto runFunction = [layerPointer = QPointer< QgsMapLayer >( ml ), &function, &foundLayer] {
224 if ( QgsMapLayer *layer = layerPointer.data() )
234 if ( QThread::currentThread() == ml->thread() )
237 QMetaObject::invokeMethod( ml, std::move( runFunction ), Qt::BlockingQueuedConnection );
246 auto runFunction = [value, context, expression, &function, &foundLayer] {
247 if ( QgsMapLayer *layer = getMapLayerPrivate( value, context, expression ) )
270 const QString identifier = value.toString();
273 const QList< QgsMapLayerStore * > stores = context->layerStores();
275 for ( QgsMapLayerStore *store : stores )
277 QPointer< QgsMapLayerStore > storePointer( store );
278 auto findLayerInStoreFunction = [storePointer = std::move( storePointer ), identifier, function, &foundLayer] {
279 QgsMapLayer *ml =
nullptr;
280 if ( QgsMapLayerStore *store = storePointer.data() )
283 ml = store->mapLayer( identifier );
287 ml = store->mapLayersByName( identifier ).value( 0 );
300 if ( QThread::currentThread() == store->thread() )
301 findLayerInStoreFunction();
303 QMetaObject::invokeMethod( store, std::move( findLayerInStoreFunction ), Qt::BlockingQueuedConnection );
311 auto getMapLayerFromProjectInstance = [value, identifier, &function, &foundLayer] {
315 QgsMapLayer *ml = project->
mapLayer( identifier );
331 getMapLayerFromProjectInstance();
333 QMetaObject::invokeMethod(
QgsProject::instance(), getMapLayerFromProjectInstance, Qt::BlockingQueuedConnection );
338QVariant QgsExpressionUtils::runMapLayerFunctionThreadSafe(
345 executeLambdaForMapLayer(
349 [&res, function]( QgsMapLayer *layer ) {
351 res = function( layer );
359std::unique_ptr<QgsVectorLayerFeatureSource> QgsExpressionUtils::getFeatureSource(
const QVariant &value,
const QgsExpressionContext *context,
QgsExpression *e,
bool &foundLayer )
361 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
363 executeLambdaForMapLayer(
367 [&featureSource]( QgsMapLayer *layer ) {
368 if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( layer ) )
370 featureSource = std::make_unique<QgsVectorLayerFeatureSource>( vl );
376 return featureSource;
381 return qobject_cast<QgsVectorLayer *>( getMapLayerPrivate( value, context, e ) );
389 if ( QgsMapLayer *layer = getMapLayer( value, context, parent ) )
392 res = parts.value( u
"path"_s ).toString();
397 res = value.toString();
421 for (
int i = 0; i < fields.
count(); i++ )
433 *foundFeatures = hasFeature;
437 const QVariant value = exp.
evaluate( &context );
440 return std::make_tuple(
static_cast<QMetaType::Type
>( value.userType() ), value.userType() );
445 return std::make_tuple(
static_cast<QMetaType::Type
>( value.userType() ), value.userType() );
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
@ Expression
Field is calculated from an expression.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QList< QgsMapLayerStore * > layerStores() const
Returns the list of layer stores associated with the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
static std::tuple< QMetaType::Type, int > determineResultType(const QString &expression, const QgsVectorLayer *layer, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsExpressionContext &context=QgsExpressionContext(), bool *foundFeatures=nullptr)
Returns a value type and user type for a given expression.
Handles parsing and evaluation of expressions (formerly called "search strings").
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions).
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Container of fields for a vector layer.
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
double value(int index) const override
Returns relative value between [0,1] of color at specified index.
Base class for all map layer types.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
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.
Q_INVOKABLE QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
@ Unknown
Unknown/invalid format.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< int > QgsAttributeList
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.