29#include <nlohmann/json.hpp> 
   30using namespace nlohmann;
 
   36  setFlags( 
flags() | QgsFieldFormatter::CanProvideAvailableValues );
 
 
   41  return QStringLiteral( 
"ValueRelation" );
 
 
   48  if ( cache.isValid() )
 
   57  if ( config.value( QStringLiteral( 
"AllowMulti" ) ).toBool() )
 
   61    if ( layer->
fields().
at( fieldIndex ).
type() == QMetaType::Type::QVariantMap )
 
   64      keyList = value.toStringList();
 
   71    QStringList valueList;
 
   75      if ( keyList.contains( item.key.toString() ) )
 
   77        valueList << item.value;
 
   81    return valueList.join( QLatin1String( 
", " ) ).prepend( 
'{' ).append( 
'}' );
 
   92      if ( item.key == value )
 
   99  return QStringLiteral( 
"(%1)" ).arg( value.toString() );
 
 
  110  Q_UNUSED( fieldIndex )
 
  111  return QVariant::fromValue<ValueRelationCache>( 
createCache( config ) );
 
 
  116  const QVariantMap &config,
 
  128  const int keyIdx = fields.
indexOf( config.value( QStringLiteral( 
"Key" ) ).toString() );
 
  129  const int valueIdx = fields.
indexOf( config.value( QStringLiteral( 
"Value" ) ).toString() );
 
  136  const int groupIdx = fields.
lookupField( config.value( QStringLiteral( 
"Group" ) ).toString() );
 
  139    subsetOfAttributes << groupIdx;
 
  142  const bool orderByField { config.value( QStringLiteral( 
"OrderByField" ) ).toBool() };
 
  143  const int fieldIdx { orderByField ? layer->
fields().
lookupField( config.value( QStringLiteral( 
"OrderByFieldName" ) ).toString() ) : -1 };
 
  144  const bool reverseSort { config.value( QStringLiteral( 
"OrderByDescending" ) ).toBool() };
 
  145  if ( fieldIdx != -1 )
 
  147    subsetOfAttributes << fieldIdx;
 
  150  const QString descriptionExpressionString = config.value( 
"Description" ).toString();
 
  151  QgsExpression descriptionExpression( descriptionExpressionString );
 
  153  descriptionExpression.
prepare( &context );
 
  157  const QString filterExpression = config.value( QStringLiteral( 
"FilterExpression" ) ).toString();
 
  177  QMap<QVariant, QVariant> orderByFieldValues;
 
  183    if ( descriptionExpression.
isValid() )
 
  186      description = descriptionExpression.
evaluate( &context ).toString();
 
  188    const QVariant group = groupIdx > -1 ? f.
attribute( groupIdx ) : QVariant();
 
  189    const QVariant keyValue = f.
attribute( keyIdx );
 
  190    if ( fieldIdx != -1 )
 
  192      orderByFieldValues.insert( keyValue, f.
attribute( fieldIdx ) );
 
  198  if ( config.value( QStringLiteral( 
"OrderByValue" ) ).toBool() )
 
  203        return p1.group == p2.group ? qgsVariantGreaterThan( p1.value, p2.value ) : qgsVariantGreaterThan( p1.group, p2.group );
 
  205        return p1.group == p2.group ? qgsVariantLessThan( p1.value, p2.value ) : qgsVariantLessThan( p1.group, p2.group );
 
  209  else if ( fieldIdx != -1 )
 
  214        return p1.group == p2.group ? qgsVariantGreaterThan( orderByFieldValues.value( p1.key ), orderByFieldValues.value( p2.key ) ) : qgsVariantGreaterThan( p1.group, p2.group );
 
  216        return p1.group == p2.group ? qgsVariantLessThan( orderByFieldValues.value( p1.key ), orderByFieldValues.value( p2.key ) ) : qgsVariantLessThan( p1.group, p2.group );
 
  226        return p1.group == p2.group ? qgsVariantGreaterThan( p1.key, p2.key ) : qgsVariantGreaterThan( p1.group, p2.group );
 
  228        return p1.group == p2.group ? qgsVariantLessThan( p1.key, p2.key ) : qgsVariantLessThan( p1.group, p2.group );
 
 
  238  QList<QgsVectorLayerRef> result;
 
  239  const QString layerId { config.value( QStringLiteral( 
"Layer" ) ).toString() };
 
  240  const QString layerName { config.value( QStringLiteral( 
"LayerName" ) ).toString() };
 
  241  const QString providerName { config.value( QStringLiteral( 
"LayerProviderName" ) ).toString() };
 
  242  const QString layerSource { config.value( QStringLiteral( 
"LayerSource" ) ).toString() };
 
  243  if ( ! layerId.isEmpty() && ! layerName.isEmpty() && ! providerName.isEmpty() && ! layerSource.isEmpty() )
 
  245    result.append( 
QgsVectorLayerRef( layerId, layerName, layerSource, providerName ) );
 
 
  254  if ( 
auto *lProject = context.
project() )
 
  256    const QgsVectorLayer *referencedLayer = qobject_cast<QgsVectorLayer *>( lProject->mapLayer( config[QStringLiteral( 
"Layer" )].toString() ) );
 
  257    if ( referencedLayer )
 
  259      int fieldIndex = referencedLayer->
fields().
indexOf( config.value( QStringLiteral( 
"Key" ) ).toString() );
 
  260      values = qgis::setToList( referencedLayer->
uniqueValues( fieldIndex, countLimit ) );
 
 
  268  QStringList checkList;
 
  269  if ( value.userType() == QMetaType::Type::QStringList )
 
  271    checkList = value.toStringList();
 
  275    QVariantList valuesList;
 
  276    if ( value.userType() == QMetaType::Type::QString )
 
  279      auto newVal { value };
 
  280      if ( newVal.toString().trimmed().startsWith( 
'{' ) )
 
  285      else if ( newVal.toString().trimmed().startsWith( 
'[' ) )
 
  290          for ( 
auto &element : json::parse( newVal.toString().toStdString() ) )
 
  292            if ( element.is_number_integer() )
 
  294              valuesList.push_back( element.get<
int>() );
 
  296            else if ( element.is_number_unsigned() )
 
  298              valuesList.push_back( element.get<
unsigned>() );
 
  300            else if ( element.is_string() )
 
  302              valuesList.push_back( QString::fromStdString( element.get<std::string>() ) );
 
  306        catch ( json::parse_error &ex )
 
  308          QgsMessageLog::logMessage( QObject::tr( 
"Cannot parse JSON like string '%1' Error: %2" ).arg( newVal.toString(), ex.what() ) );
 
  312    else if ( value.userType() == QMetaType::Type::QVariantList )
 
  314      valuesList = value.toList( );
 
  317    checkList.reserve( valuesList.size() );
 
  318    for ( 
const QVariant &listItem : std::as_const( valuesList ) )
 
  320      QString v( listItem.toString( ) );
 
  322        checkList.append( v );
 
 
  332  QSet< QString > formVariables = qgis::listToSet( scope->variableNames() );
 
  334  formVariables.intersect( usedVariables );
 
  335  return formVariables;
 
 
  341  QSet< QString > formVariables = qgis::listToSet( scope->variableNames() );
 
  343  formVariables.intersect( usedVariables );
 
  344  return formVariables;
 
 
  359  QSet<QString> attributes;
 
  363  const QSet<QString> formFunctions( qgis::listToSet( scope->functionNames() )
 
  367  for ( 
const auto &f : expFunctions )
 
  370    if ( formFunctions.contains( fd->
name( ) ) )
 
  372      const QList<QgsExpressionNode *> cExpressionNodes { f->args( )->list() };
 
  373      for ( 
const auto ¶m : std::as_const( cExpressionNodes ) )
 
  375        attributes.insert( param->eval( &exp, &context ).toString() );
 
 
  384  QSet<QString> attributes;
 
  388  const QSet<QString> formFunctions( qgis::listToSet( scope->functionNames() )
 
  392  for ( 
const auto &f : expFunctions )
 
  395    if ( formFunctions.contains( fd->
name( ) ) )
 
  397      const QList<QgsExpressionNode *> cExpressionNodes { f->args( )->list() };
 
  398      for ( 
const auto ¶m : std::as_const( cExpressionNodes ) )
 
  400        attributes.insert( param->eval( &exp, &context ).toString() );
 
 
  412  for ( 
auto it = attrs.constBegin() ; it != attrs.constEnd(); it++ )
 
  424    for ( 
auto it = parentAttrs.constBegin() ; it != parentAttrs.constEnd(); it++ )
 
  426      if ( ! parentFeature.
attribute( *it ).isValid() )
 
 
  438                          config.value( QStringLiteral( 
"LayerName" ) ).toString(),
 
  439                          config.value( QStringLiteral( 
"LayerSource" ) ).toString(),
 
  440                          config.value( QStringLiteral( 
"LayerProviderName" ) ).toString() };
 
 
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
 
static QString nullRepresentation()
Returns the string 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.
 
An abstract base class for defining QgsExpression functions.
 
QString name() const
The name of the function.
 
An expression node for expression functions.
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
 
QList< const T * > findNodes() const
Returns a list of all nodes of the given class which are used in this expression.
 
QSet< QString > referencedVariables() const
Returns a list of all variables 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)
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 & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
 
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
 
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...
 
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
 
bool isValid() const
Returns the validity of this feature.
 
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by 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.
 
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
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::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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.
 
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.
 
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
 
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.