28 #include <nlohmann/json.hpp> 
   29 using namespace nlohmann;
 
   50   return QStringLiteral( 
"ValueRelation" );
 
   57   if ( cache.isValid() )
 
   66   if ( config.value( QStringLiteral( 
"AllowMulti" ) ).toBool() )
 
   70     if ( layer->
fields().
at( fieldIndex ).
type() == QVariant::Map )
 
   73       keyList = value.toStringList();
 
   77       keyList = valueToStringList( value );
 
   80     QStringList valueList;
 
   84       if ( keyList.contains( item.key.toString() ) )
 
   86         valueList << item.value;
 
   90     return valueList.join( QLatin1String( 
", " ) ).prepend( 
'{' ).append( 
'}' );
 
  101       if ( item.key == value )
 
  108   return QStringLiteral( 
"(%1)" ).arg( value.toString() );
 
  113   return value.isNull() ? QString() : representValue( layer, fieldIndex, config, cache, value );
 
  119   Q_UNUSED( fieldIndex )
 
  120   return QVariant::fromValue<ValueRelationCache>( createCache( config ) );
 
  125   const QVariantMap &config,
 
  137   int ki = fields.
indexOf( config.value( QStringLiteral( 
"Key" ) ).toString() );
 
  138   int vi = fields.
indexOf( config.value( QStringLiteral( 
"Value" ) ).toString() );
 
  145   const QString descriptionExpressionString = config.value( 
"Description" ).toString();
 
  146   QgsExpression descriptionExpression( descriptionExpressionString );
 
  148   descriptionExpression.
prepare( &context );
 
  152   const QString filterExpression = config.value( QStringLiteral( 
"FilterExpression" ) ).toString();
 
  159   if ( ! filterExpression.isEmpty() && ( !( expressionRequiresFormScope( filterExpression ) )
 
  160                                          || expressionIsUsable( filterExpression, formFeature ) ) )
 
  177     if ( descriptionExpression.
isValid() )
 
  180       description = descriptionExpression.
evaluate( &context ).toString();
 
  185   if ( config.value( QStringLiteral( 
"OrderByValue" ) ).toBool() )
 
  200   QList<QgsVectorLayerRef> result;
 
  201   const QString layerId { config.value( QStringLiteral( 
"Layer" ) ).toString() };
 
  202   const QString layerName { config.value( QStringLiteral( 
"LayerName" ) ).toString() };
 
  203   const QString providerName { config.value( QStringLiteral( 
"LayerProviderName" ) ).toString() };
 
  204   const QString layerSource { config.value( QStringLiteral( 
"LayerSource" ) ).toString() };
 
  205   if ( ! layerId.isEmpty() && ! layerName.isEmpty() && ! providerName.isEmpty() && ! layerSource.isEmpty() )
 
  207     result.append( 
QgsVectorLayerRef( layerId, layerName, layerSource, providerName ) );
 
  216   if ( 
auto *lProject = context.
project() )
 
  218     const QgsVectorLayer *referencedLayer = qobject_cast<QgsVectorLayer *>( lProject->mapLayer( config[QStringLiteral( 
"Layer" )].toString() ) );
 
  219     if ( referencedLayer )
 
  221       int fieldIndex = referencedLayer->
fields().
indexOf( config.value( QStringLiteral( 
"Key" ) ).toString() );
 
  222       values = qgis::setToList( referencedLayer->
uniqueValues( fieldIndex, countLimit ) );
 
  230   QStringList checkList;
 
  231   if ( value.type() == QVariant::StringList )
 
  233     checkList = value.toStringList();
 
  237     QVariantList valuesList;
 
  238     if ( value.type() == QVariant::String )
 
  241       auto newVal { value };
 
  242       if ( newVal.toString().trimmed().startsWith( 
'{' ) )
 
  247       else if ( newVal.toString().trimmed().startsWith( 
'[' ) )
 
  252           for ( 
auto &element : 
json::parse( newVal.toString().toStdString() ) )
 
  254             if ( element.is_number_integer() )
 
  256               valuesList.push_back( element.get<
int>() );
 
  258             else if ( element.is_number_unsigned() )
 
  260               valuesList.push_back( element.get<
unsigned>() );
 
  262             else if ( element.is_string() )
 
  264               valuesList.push_back( QString::fromStdString( element.get<std::string>() ) );
 
  268         catch ( json::parse_error &ex )
 
  270           QgsMessageLog::logMessage( QObject::tr( 
"Cannot parse JSON like string '%1' Error: %2" ).arg( newVal.toString(), ex.what() ) );
 
  274     else if ( value.type() == QVariant::List )
 
  276       valuesList = value.toList( );
 
  279     checkList.reserve( valuesList.size() );
 
  280     for ( 
const QVariant &listItem : qgis::as_const( valuesList ) )
 
  282       QString v( listItem.toString( ) );
 
  284         checkList.append( v );
 
  294   QSet< QString > formVariables = qgis::listToSet( scope->variableNames() );
 
  296   formVariables.intersect( usedVariables );
 
  297   return formVariables;
 
  303   QSet< QString > formVariables = qgis::listToSet( scope->variableNames() );
 
  305   formVariables.intersect( usedVariables );
 
  306   return formVariables;
 
  311   return !( expressionFormAttributes( expression ).isEmpty() && expressionFormVariables( expression ).isEmpty() );
 
  316   return !( expressionParentFormAttributes( expression ).isEmpty() && expressionParentFormVariables( expression ).isEmpty() );
 
  321   QSet<QString> attributes;
 
  325   const QSet<QString> formFunctions( qgis::listToSet( scope->functionNames() )
 
  329   for ( 
const auto &f : expFunctions )
 
  332     if ( formFunctions.contains( fd->
name( ) ) )
 
  334       for ( 
const auto ¶m : f->args( )->list() )
 
  336         attributes.insert( param->eval( &exp, &context ).toString() );
 
  345   QSet<QString> attributes;
 
  349   const QSet<QString> formFunctions( qgis::listToSet( scope->functionNames() )
 
  353   for ( 
const auto &f : expFunctions )
 
  356     if ( formFunctions.contains( fd->
name( ) ) )
 
  358       for ( 
const auto ¶m : f->args( )->list() )
 
  360         attributes.insert( param->eval( &exp, &context ).toString() );
 
  371   const QSet<QString> attrs = expressionFormAttributes( expression );
 
  372   for ( 
auto it = attrs.constBegin() ; it != attrs.constEnd(); it++ )
 
  374     if ( ! feature.
attribute( *it ).isValid() )
 
  378   if ( ! expressionFormVariables( expression ).isEmpty() && feature.
geometry().
isEmpty( ) )
 
  383     const QSet<QString> parentAttrs = expressionParentFormAttributes( expression );
 
  384     for ( 
auto it = parentAttrs.constBegin() ; it != parentAttrs.constEnd(); it++ )
 
  386       if ( ! parentFeature.
attribute( *it ).isValid() )
 
  389     if ( ! expressionParentFormVariables( expression ).isEmpty() && parentFeature.
geometry().
isEmpty( ) )
 
  398                           config.value( QStringLiteral( 
"LayerName" ) ).toString(),
 
  399                           config.value( QStringLiteral( 
"LayerSource" ) ).toString(),
 
  400                           config.value( QStringLiteral( 
"LayerProviderName" ) ).toString() };
 
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
A abstract base class for defining QgsExpression functions.
QString name() const
The name of the function.
An expression node for expression functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QSet< QString > referencedVariables() const
Returns a list of all variables which are used in this expression.
QList< const T * > findNodes() const
Returns a list of all nodes of the given class which are used in this expression.
QSet< QString > referencedFunctions() const
Returns a list of the names of all functions which are used in this expression.
QVariant evaluate()
Evaluate the feature and return the result.
bool isValid() const
Checks if this expression is valid.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
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 & 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.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ 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 id, geometry and a list of field/values...
bool isValid() const
Returns the validity of this feature.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
A context for field formatter containing information like the project.
QgsProject * project() const
Returns the project used in field formatter.
Container of fields for a vector layer.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QVariantList parseArray(const QString &string)
Returns a QVariantList created out of a string containing an array in postgres array format {1,...
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
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.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg, bool allowFragments)
QSet< int > QgsAttributeIds
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
TYPE * resolveByIdOrNameOnly(const QgsProject *project)
Resolves the map layer by attempting to find a matching layer in a project using a weak match.