QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsexpressionutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsexpressionutils.cpp
3 -------------------
4 begin : May 2017
5 copyright : (C) 2017 Matthias Kuhn
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsexpressionutils.h"
17#include "qgsexpressionnode.h"
18#include "qgsvectorlayer.h"
19#include "qgscolorrampimpl.h"
20#include "qgsproviderregistry.h"
21#include "qgsvariantutils.h"
22
24
25QgsExpressionUtils::TVL QgsExpressionUtils::AND[3][3] =
26{
27 // false true unknown
28 { False, False, False }, // false
29 { False, True, Unknown }, // true
30 { False, Unknown, Unknown } // unknown
31};
32QgsExpressionUtils::TVL QgsExpressionUtils::OR[3][3] =
33{
34 { False, True, Unknown }, // false
35 { True, True, True }, // true
36 { Unknown, True, Unknown } // unknown
37};
38
39QgsExpressionUtils::TVL QgsExpressionUtils::NOT[3] = { True, False, Unknown };
40
41
42QgsGradientColorRamp QgsExpressionUtils::getRamp( const QVariant &value, QgsExpression *parent, bool report_error )
43{
44 if ( value.userType() == QMetaType::type( "QgsGradientColorRamp" ) )
45 return value.value<QgsGradientColorRamp>();
46
47 // If we get here then we can't convert so we just error and return invalid.
48 if ( report_error )
49 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to gradient ramp" ).arg( value.toString() ) );
50
51 return QgsGradientColorRamp();
52}
53
54QString QgsExpressionUtils::getFilePathValue( const QVariant &value, QgsExpression *parent )
55{
56 // if it's a map layer, return the file path of that layer...
57 QString res;
58 if ( QgsMapLayer *layer = getMapLayer( value, parent ) )
59 {
60 const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->source() );
61 res = parts.value( QStringLiteral( "path" ) ).toString();
62 }
63
64 if ( res.isEmpty() )
65 res = value.toString();
66
67 if ( res.isEmpty() && !QgsVariantUtils::isNull( value ) )
68 {
69 parent->setEvalErrorString( QObject::tr( "Cannot convert value to a file path" ) );
70 }
71 return res;
72}
73
75
76std::tuple<QVariant::Type, int> QgsExpressionUtils::determineResultType( const QString &expression, const QgsVectorLayer *layer, QgsFeatureRequest request, QgsExpressionContext context, bool *foundFeatures )
77{
78 QgsExpression exp( expression );
79 request.setFlags( ( exp.needsGeometry() ) ?
82 request.setLimit( 10 );
83 request.setExpressionContext( context );
84
85 // avoid endless recursion by removing virtual fields while going through features
86 // to determine result type
87 QgsAttributeList attributes;
88 const QgsFields fields = layer->fields();
89 for ( int i = 0; i < fields.count(); i++ )
90 {
91 if ( fields.fieldOrigin( i ) != QgsFields::OriginExpression )
92 attributes << i;
93 }
94 request.setSubsetOfAttributes( attributes );
95
96 QVariant value;
97 QgsFeature f;
98 QgsFeatureIterator it = layer->getFeatures( request );
99 bool hasFeature = it.nextFeature( f );
100 if ( foundFeatures )
101 *foundFeatures = hasFeature;
102 while ( hasFeature )
103 {
104 context.setFeature( f );
105 const QVariant value = exp.evaluate( &context );
106 if ( !QgsVariantUtils::isNull( value ) )
107 {
108 return std::make_tuple( value.type(), value.userType() );
109 }
110 hasFeature = it.nextFeature( f );
111 }
112 value = QVariant();
113 return std::make_tuple( value.type(), value.userType() );
114}
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
static std::tuple< QVariant::Type, int > determineResultType(const QString &expression, const QgsVectorLayer *layer, QgsFeatureRequest request=QgsFeatureRequest(), QgsExpressionContext context=QgsExpressionContext(), bool *foundFeatures=nullptr)
Returns a value type and user type for a given expression.
Class for 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)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
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...
Definition: qgsfeature.h:56
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ OriginExpression
Field is calculated from an expression.
Definition: qgsfields.h:54
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
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.
Definition: qgsmaplayer.h:73
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)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
@ Unknown
Unknown/invalid format.
QList< int > QgsAttributeList
Definition: qgsfield.h:26