QGIS API Documentation  3.3.0-Master (936b0c1)
qgsexpressioncontext.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpressioncontext.cpp
3  ------------------------
4  Date : April 2015
5  Copyright : (C) 2015 by Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
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 "qgsexpressioncontext.h"
17 
18 #include "qgslogger.h"
19 #include "qgsexpression.h"
20 #include "qgsexpressionfunction.h"
21 #include "qgsfields.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsproject.h"
24 #include "qgssymbollayerutils.h"
25 #include "qgsgeometry.h"
26 #include "qgsapplication.h"
27 #include "qgsmapsettings.h"
28 #include "qgsmaplayerlistutils.h"
29 #include "qgsprocessingcontext.h"
30 #include "qgsprocessingalgorithm.h"
31 #include "qgslayoutatlas.h"
32 #include "qgslayout.h"
34 #include "qgslayoutreportcontext.h"
35 
36 #include <QSettings>
37 #include <QDir>
38 
39 
40 const QString QgsExpressionContext::EXPR_FIELDS( QStringLiteral( "_fields_" ) );
41 const QString QgsExpressionContext::EXPR_ORIGINAL_VALUE( QStringLiteral( "value" ) );
42 const QString QgsExpressionContext::EXPR_SYMBOL_COLOR( QStringLiteral( "symbol_color" ) );
43 const QString QgsExpressionContext::EXPR_SYMBOL_ANGLE( QStringLiteral( "symbol_angle" ) );
44 const QString QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT( QStringLiteral( "geometry_part_count" ) );
45 const QString QgsExpressionContext::EXPR_GEOMETRY_PART_NUM( QStringLiteral( "geometry_part_num" ) );
46 const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT( QStringLiteral( "geometry_point_count" ) );
47 const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM( QStringLiteral( "geometry_point_num" ) );
48 const QString QgsExpressionContext::EXPR_CLUSTER_SIZE( QStringLiteral( "cluster_size" ) );
49 const QString QgsExpressionContext::EXPR_CLUSTER_COLOR( QStringLiteral( "cluster_color" ) );
50 
51 //
52 // QgsExpressionContextScope
53 //
54 
56  : mName( name )
57 {
58 
59 }
60 
62  : mName( other.mName )
63  , mVariables( other.mVariables )
64  , mHasFeature( other.mHasFeature )
65  , mFeature( other.mFeature )
66 {
67  QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin();
68  for ( ; it != other.mFunctions.constEnd(); ++it )
69  {
70  mFunctions.insert( it.key(), it.value()->clone() );
71  }
72 }
73 
75 {
76  mName = other.mName;
77  mVariables = other.mVariables;
78  mHasFeature = other.mHasFeature;
79  mFeature = other.mFeature;
80 
81  qDeleteAll( mFunctions );
82  mFunctions.clear();
83  QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin();
84  for ( ; it != other.mFunctions.constEnd(); ++it )
85  {
86  mFunctions.insert( it.key(), it.value()->clone() );
87  }
88 
89  return *this;
90 }
91 
93 {
94  qDeleteAll( mFunctions );
95 }
96 
97 void QgsExpressionContextScope::setVariable( const QString &name, const QVariant &value, bool isStatic )
98 {
99  if ( mVariables.contains( name ) )
100  {
101  StaticVariable existing = mVariables.value( name );
102  existing.value = value;
103  existing.isStatic = isStatic;
104  addVariable( existing );
105  }
106  else
107  {
108  addVariable( QgsExpressionContextScope::StaticVariable( name, value, false, isStatic ) );
109  }
110 }
111 
113 {
114  mVariables.insert( variable.name, variable );
115 }
116 
118 {
119  return mVariables.remove( name ) > 0;
120 }
121 
122 bool QgsExpressionContextScope::hasVariable( const QString &name ) const
123 {
124  return mVariables.contains( name );
125 }
126 
127 QVariant QgsExpressionContextScope::variable( const QString &name ) const
128 {
129  return hasVariable( name ) ? mVariables.value( name ).value : QVariant();
130 }
131 
133 {
134  QStringList names = mVariables.keys();
135  return names;
136 }
137 
138 bool QgsExpressionContextScope::variableNameSort( const QString &a, const QString &b )
139 {
140  return QString::localeAwareCompare( a, b ) < 0;
141 }
142 
144 class QgsExpressionContextVariableCompare
145 {
146  public:
147  explicit QgsExpressionContextVariableCompare( const QgsExpressionContextScope &scope )
148  : mScope( scope )
149  { }
150 
151  bool operator()( const QString &a, const QString &b ) const
152  {
153  bool aReadOnly = mScope.isReadOnly( a );
154  bool bReadOnly = mScope.isReadOnly( b );
155  if ( aReadOnly != bReadOnly )
156  return aReadOnly;
157  return QString::localeAwareCompare( a, b ) < 0;
158  }
159 
160  private:
161  const QgsExpressionContextScope &mScope;
162 };
164 
166 {
167  QStringList allVariables = mVariables.keys();
168  QStringList filtered;
169  Q_FOREACH ( const QString &variable, allVariables )
170  {
171  if ( variable.startsWith( '_' ) )
172  continue;
173 
174  filtered << variable;
175  }
176  QgsExpressionContextVariableCompare cmp( *this );
177  std::sort( filtered.begin(), filtered.end(), cmp );
178 
179  return filtered;
180 }
181 
182 bool QgsExpressionContextScope::isReadOnly( const QString &name ) const
183 {
184  return hasVariable( name ) ? mVariables.value( name ).readOnly : false;
185 }
186 
187 bool QgsExpressionContextScope::isStatic( const QString &name ) const
188 {
189  return hasVariable( name ) ? mVariables.value( name ).isStatic : false;
190 }
191 
192 QString QgsExpressionContextScope::description( const QString &name ) const
193 {
194  return hasVariable( name ) ? mVariables.value( name ).description : QString();
195 }
196 
197 bool QgsExpressionContextScope::hasFunction( const QString &name ) const
198 {
199  return mFunctions.contains( name );
200 }
201 
203 {
204  return mFunctions.contains( name ) ? mFunctions.value( name ) : nullptr;
205 }
206 
208 {
209  return mFunctions.keys();
210 }
211 
213 {
214  mFunctions.insert( name, function );
215 }
216 
217 
219 {
220  addVariable( StaticVariable( QgsExpressionContext::EXPR_FIELDS, QVariant::fromValue( fields ), true ) );
221 }
222 
223 
224 //
225 // QgsExpressionContext
226 //
227 
228 QgsExpressionContext::QgsExpressionContext( const QList<QgsExpressionContextScope *> &scopes )
229  : mStack( scopes )
230 {
231 }
232 
234 {
235  Q_FOREACH ( const QgsExpressionContextScope *scope, other.mStack )
236  {
237  mStack << new QgsExpressionContextScope( *scope );
238  }
239  mHighlightedVariables = other.mHighlightedVariables;
240  mCachedValues = other.mCachedValues;
241 }
242 
244 {
245  if ( this != &other )
246  {
247  qDeleteAll( mStack );
248  // move the stack over
249  mStack = other.mStack;
250  other.mStack.clear();
251 
252  mHighlightedVariables = other.mHighlightedVariables;
253  mCachedValues = other.mCachedValues;
254  }
255  return *this;
256 }
257 
259 {
260  qDeleteAll( mStack );
261  mStack.clear();
262  Q_FOREACH ( const QgsExpressionContextScope *scope, other.mStack )
263  {
264  mStack << new QgsExpressionContextScope( *scope );
265  }
266  mHighlightedVariables = other.mHighlightedVariables;
267  mCachedValues = other.mCachedValues;
268  return *this;
269 }
270 
272 {
273  qDeleteAll( mStack );
274  mStack.clear();
275 }
276 
277 bool QgsExpressionContext::hasVariable( const QString &name ) const
278 {
279  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
280  {
281  if ( scope->hasVariable( name ) )
282  return true;
283  }
284  return false;
285 }
286 
287 QVariant QgsExpressionContext::variable( const QString &name ) const
288 {
290  return scope ? scope->variable( name ) : QVariant();
291 }
292 
294 {
295  QStringList names = variableNames();
296  QVariantMap m;
297  Q_FOREACH ( const QString &name, names )
298  {
299  m.insert( name, variable( name ) );
300  }
301  return m;
302 }
303 
304 bool QgsExpressionContext::isHighlightedVariable( const QString &name ) const
305 {
306  return mHighlightedVariables.contains( name );
307 }
308 
310 {
311  mHighlightedVariables = variableNames;
312 }
313 
315 {
316  //iterate through stack backwards, so that higher priority variables take precedence
317  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
318  while ( it != mStack.constBegin() )
319  {
320  --it;
321  if ( ( *it )->hasVariable( name ) )
322  return ( *it );
323  }
324  return nullptr;
325 }
326 
328 {
329  //iterate through stack backwards, so that higher priority variables take precedence
330  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
331  while ( it != mStack.constBegin() )
332  {
333  --it;
334  if ( ( *it )->hasVariable( name ) )
335  return ( *it );
336  }
337  return nullptr;
338 }
339 
341 {
342  if ( index < 0 || index >= mStack.count() )
343  return nullptr;
344 
345  return mStack.at( index );
346 }
347 
349 {
350  if ( mStack.count() < 1 )
351  return nullptr;
352 
353  return mStack.last();
354 }
355 
357 {
358  if ( !scope )
359  return -1;
360 
361  return mStack.indexOf( scope );
362 }
363 
364 int QgsExpressionContext::indexOfScope( const QString &scopeName ) const
365 {
366  int index = 0;
367  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
368  {
369  if ( scope->name() == scopeName )
370  return index;
371 
372  index++;
373  }
374  return -1;
375 }
376 
378 {
379  QStringList names;
380  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
381  {
382  names << scope->variableNames();
383  }
384  return names.toSet().toList();
385 }
386 
388 {
389  QStringList allVariables = variableNames();
390  QStringList filtered;
391  Q_FOREACH ( const QString &variable, allVariables )
392  {
393  if ( variable.startsWith( '_' ) )
394  continue;
395 
396  filtered << variable;
397  }
398 
399  filtered.sort();
400  return filtered;
401 }
402 
403 bool QgsExpressionContext::isReadOnly( const QString &name ) const
404 {
405  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
406  {
407  if ( scope->isReadOnly( name ) )
408  return true;
409  }
410  return false;
411 }
412 
413 QString QgsExpressionContext::description( const QString &name ) const
414 {
416  return ( scope && !scope->description( name ).isEmpty() ) ? scope->description( name ) : QgsExpression::variableHelpText( name );
417 }
418 
419 bool QgsExpressionContext::hasFunction( const QString &name ) const
420 {
421  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
422  {
423  if ( scope->hasFunction( name ) )
424  return true;
425  }
426  return false;
427 }
428 
430 {
431  QStringList result;
432  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
433  {
434  result << scope->functionNames();
435  }
436  result = result.toSet().toList();
437  result.sort();
438  return result;
439 }
440 
442 {
443  //iterate through stack backwards, so that higher priority variables take precedence
444  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
445  while ( it != mStack.constBegin() )
446  {
447  --it;
448  if ( ( *it )->hasFunction( name ) )
449  return ( *it )->function( name );
450  }
451  return nullptr;
452 }
453 
455 {
456  return mStack.count();
457 }
458 
460 {
461  mStack.append( scope );
462 }
463 
464 void QgsExpressionContext::appendScopes( const QList<QgsExpressionContextScope *> &scopes )
465 {
466  mStack.append( scopes );
467 }
468 
470 {
471  if ( !mStack.isEmpty() )
472  return mStack.takeLast();
473 
474  return nullptr;
475 }
476 
477 QList<QgsExpressionContextScope *> QgsExpressionContext::takeScopes()
478 {
479  QList<QgsExpressionContextScope *> stack = mStack;
480  mStack.clear();
481  return stack;
482 }
483 
485 {
486  mStack.append( scope );
487  return *this;
488 }
489 
491 {
492  if ( mStack.isEmpty() )
493  mStack.append( new QgsExpressionContextScope() );
494 
495  mStack.last()->setFeature( feature );
496 }
497 
499 {
500  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
501  {
502  if ( scope->hasFeature() )
503  return true;
504  }
505  return false;
506 }
507 
509 {
510  //iterate through stack backwards, so that higher priority variables take precedence
511  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
512  while ( it != mStack.constBegin() )
513  {
514  --it;
515  if ( ( *it )->hasFeature() )
516  return ( *it )->feature();
517  }
518  return QgsFeature();
519 }
520 
522 {
523  if ( mStack.isEmpty() )
524  mStack.append( new QgsExpressionContextScope() );
525 
526  mStack.last()->setFields( fields );
527 }
528 
530 {
531  return qvariant_cast<QgsFields>( variable( QgsExpressionContext::EXPR_FIELDS ) );
532 }
533 
535 {
536  if ( mStack.isEmpty() )
537  mStack.append( new QgsExpressionContextScope() );
538 
540  value, true ) );
541 }
542 
543 void QgsExpressionContext::setCachedValue( const QString &key, const QVariant &value ) const
544 {
545  mCachedValues.insert( key, value );
546 }
547 
548 bool QgsExpressionContext::hasCachedValue( const QString &key ) const
549 {
550  return mCachedValues.contains( key );
551 }
552 
553 QVariant QgsExpressionContext::cachedValue( const QString &key ) const
554 {
555  return mCachedValues.value( key, QVariant() );
556 }
557 
559 {
560  mCachedValues.clear();
561 }
562 
563 
564 //
565 // QgsExpressionContextUtils
566 //
567 
569 {
570  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Global" ) );
571 
572  QVariantMap customVariables = QgsApplication::customVariables();
573 
574  for ( QVariantMap::const_iterator it = customVariables.constBegin(); it != customVariables.constEnd(); ++it )
575  {
576  scope->setVariable( it.key(), it.value(), true );
577  }
578 
579  //add some extra global variables
580  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version" ), Qgis::QGIS_VERSION, true, true ) );
581  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version_no" ), Qgis::QGIS_VERSION_INT, true, true ) );
582  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_short_version" ), QStringLiteral( "%1.%2" ).arg( Qgis::QGIS_VERSION_INT / 10000 ).arg( Qgis::QGIS_VERSION_INT / 100 % 100 ), true, true ) );
583  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_release_name" ), Qgis::QGIS_RELEASE_NAME, true, true ) );
584  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_platform" ), QgsApplication::platform(), true, true ) );
585  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_os_name" ), QgsApplication::osName(), true, true ) );
586  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_locale" ), QgsApplication::locale(), true, true ) );
587  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_account_name" ), QgsApplication::userLoginName(), true, true ) );
588  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_full_name" ), QgsApplication::userFullName(), true, true ) );
589 
590  return scope;
591 }
592 
593 void QgsExpressionContextUtils::setGlobalVariable( const QString &name, const QVariant &value )
594 {
595  QgsApplication::setCustomVariable( name, value );
596 }
597 
598 void QgsExpressionContextUtils::setGlobalVariables( const QVariantMap &variables )
599 {
601 }
602 
604 {
605  QVariantMap vars = QgsApplication::customVariables();
606  if ( vars.remove( name ) )
608 }
609 
610 
612 
613 class GetNamedProjectColor : public QgsScopedExpressionFunction
614 {
615  public:
616  GetNamedProjectColor( const QgsProject *project )
617  : QgsScopedExpressionFunction( QStringLiteral( "project_color" ), 1, QStringLiteral( "Color" ) )
618  , mProject( project )
619  {
620  if ( !project )
621  return;
622 
623  //build up color list from project. Do this in advance for speed
624  QStringList colorStrings = project->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Colors" ) );
625  QStringList colorLabels = project->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Labels" ) );
626 
627  //generate list from custom colors
628  int colorIndex = 0;
629  for ( QStringList::iterator it = colorStrings.begin();
630  it != colorStrings.end(); ++it )
631  {
632  QColor color = QgsSymbolLayerUtils::decodeColor( *it );
633  QString label;
634  if ( colorLabels.length() > colorIndex )
635  {
636  label = colorLabels.at( colorIndex );
637  }
638 
639  mColors.insert( label.toLower(), color );
640  colorIndex++;
641  }
642  }
643 
644  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
645  {
646  QString colorName = values.at( 0 ).toString().toLower();
647  if ( mColors.contains( colorName ) )
648  {
649  return QStringLiteral( "%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
650  }
651  else
652  return QVariant();
653  }
654 
655  QgsScopedExpressionFunction *clone() const override
656  {
657  return new GetNamedProjectColor( mProject );
658  }
659 
660  private:
661 
662  const QgsProject *mProject = nullptr;
663  QHash< QString, QColor > mColors;
664 
665 };
666 
667 class GetLayoutItemVariables : public QgsScopedExpressionFunction
668 {
669  public:
670  GetLayoutItemVariables( const QgsLayout *c )
671  : QgsScopedExpressionFunction( QStringLiteral( "item_variables" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "Layout" ) )
672  , mLayout( c )
673  {}
674 
675  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
676  {
677  if ( !mLayout )
678  return QVariant();
679 
680  QString id = values.at( 0 ).toString();
681 
682  const QgsLayoutItem *item = mLayout->itemById( id );
683  if ( !item )
684  return QVariant();
685 
687 
688  return c.variablesToMap();
689  }
690 
691  QgsScopedExpressionFunction *clone() const override
692  {
693  return new GetLayoutItemVariables( mLayout );
694  }
695 
696  private:
697 
698  const QgsLayout *mLayout = nullptr;
699 
700 };
701 
702 class GetLayerVisibility : public QgsScopedExpressionFunction
703 {
704  public:
705  GetLayerVisibility( const QList<QgsMapLayer *> &layers )
706  : QgsScopedExpressionFunction( QStringLiteral( "is_layer_visible" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "General" ) )
707  , mLayers( layers )
708  {}
709 
710  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
711  {
712  if ( mLayers.isEmpty() )
713  {
714  return QVariant( false );
715  }
716 
717  QgsMapLayer *layer = _qgis_findLayer( mLayers, values.at( 0 ).toString() );
718  if ( layer )
719  {
720  return QVariant( true );
721  }
722  else
723  {
724  return QVariant( false );
725  }
726  }
727 
728  QgsScopedExpressionFunction *clone() const override
729  {
730  return new GetLayerVisibility( mLayers );
731  }
732 
733  private:
734 
735  const QList<QgsMapLayer *> mLayers;
736 
737 };
738 
739 
740 class GetCurrentFormFieldValue : public QgsScopedExpressionFunction
741 {
742  public:
743  GetCurrentFormFieldValue( )
744  : QgsScopedExpressionFunction( QStringLiteral( "current_value" ), QgsExpressionFunction::ParameterList() << QStringLiteral( "field_name" ), QStringLiteral( "Form" ) )
745  {}
746 
747  QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * ) override
748  {
749  QString fieldName( values.at( 0 ).toString() );
750  const QgsFeature feat( context->variable( QStringLiteral( "current_feature" ) ).value<QgsFeature>() );
751  if ( fieldName.isEmpty() || ! feat.isValid( ) )
752  {
753  return QVariant();
754  }
755  return feat.attribute( fieldName ) ;
756  }
757 
758  QgsScopedExpressionFunction *clone() const override
759  {
760  return new GetCurrentFormFieldValue( );
761  }
762 
763 };
764 
765 
766 class GetProcessingParameterValue : public QgsScopedExpressionFunction
767 {
768  public:
769  GetProcessingParameterValue( const QVariantMap &params )
770  : QgsScopedExpressionFunction( QStringLiteral( "parameter" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "name" ) ), QStringLiteral( "Processing" ) )
771  , mParams( params )
772  {}
773 
774  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
775  {
776  return mParams.value( values.at( 0 ).toString() );
777  }
778 
779  QgsScopedExpressionFunction *clone() const override
780  {
781  return new GetProcessingParameterValue( mParams );
782  }
783 
784  private:
785 
786  const QVariantMap mParams;
787 
788 };
789 
791 
792 
793 QgsExpressionContextScope *QgsExpressionContextUtils::formScope( const QgsFeature &formFeature, const QString &formMode )
794 {
795  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Form" ) );
796  scope->addFunction( QStringLiteral( "current_value" ), new GetCurrentFormFieldValue( ) );
797  scope->setVariable( QStringLiteral( "current_geometry" ), formFeature.geometry( ), true );
798  scope->setVariable( QStringLiteral( "current_feature" ), formFeature, true );
799  scope->setVariable( QStringLiteral( "form_mode" ), formMode, true );
800  return scope;
801 }
802 
804 {
805  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Project" ) );
806 
807  if ( !project )
808  return scope;
809 
810  const QVariantMap vars = project->customVariables();
811 
812  QVariantMap::const_iterator it = vars.constBegin();
813 
814  for ( ; it != vars.constEnd(); ++it )
815  {
816  scope->setVariable( it.key(), it.value(), true );
817  }
818 
819  QString projectPath = project->projectStorage() ? project->fileName() : project->absoluteFilePath();
820  QString projectFolder = QFileInfo( projectPath ).path();
821  QString projectFilename = QFileInfo( projectPath ).fileName();
822  QString projectBasename = project->baseName();
823 
824  //add other known project variables
825  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), project->title(), true, true ) );
826  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_path" ), QDir::toNativeSeparators( projectPath ), true, true ) );
827  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_folder" ), QDir::toNativeSeparators( projectFolder ), true, true ) );
828  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_filename" ), projectFilename, true, true ) );
829  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_basename" ), projectBasename, true, true ) );
830  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_home" ), QDir::toNativeSeparators( project->homePath() ), true, true ) );
831  QgsCoordinateReferenceSystem projectCrs = project->crs();
832  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs" ), projectCrs.authid(), true, true ) );
833  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs_definition" ), projectCrs.toProj4(), true, true ) );
834 
835  // metadata
836  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_author" ), project->metadata().author(), true, true ) );
837  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_abstract" ), project->metadata().abstract(), true, true ) );
838  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_creation_date" ), project->metadata().creationDateTime(), true, true ) );
839  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_identifier" ), project->metadata().identifier(), true, true ) );
840 
841  // keywords
842  QVariantMap keywords;
843  QgsAbstractMetadataBase::KeywordMap metadataKeywords = project->metadata().keywords();
844  for ( auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
845  {
846  keywords.insert( it.key(), it.value() );
847  }
848  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_keywords" ), keywords, true, true ) );
849 
850  scope->addFunction( QStringLiteral( "project_color" ), new GetNamedProjectColor( project ) );
851  return scope;
852 }
853 
854 void QgsExpressionContextUtils::setProjectVariable( QgsProject *project, const QString &name, const QVariant &value )
855 {
856  if ( !project )
857  return;
858 
859  QVariantMap vars = project->customVariables();
860 
861  vars.insert( name, value );
862 
863  project->setCustomVariables( vars );
864 }
865 
866 void QgsExpressionContextUtils::setProjectVariables( QgsProject *project, const QVariantMap &variables )
867 {
868  if ( !project )
869  return;
870 
871  project->setCustomVariables( variables );
872 }
873 
875 {
876  if ( !project )
877  {
878  return;
879  }
880 
881  QVariantMap vars = project->customVariables();
882  if ( vars.remove( name ) )
883  project->setCustomVariables( vars );
884 }
885 
887 {
888  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) );
889 
890  if ( !layer )
891  return scope;
892 
893  //add variables defined in layer properties
894  QStringList variableNames = layer->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
895  QStringList variableValues = layer->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
896 
897  int varIndex = 0;
898  Q_FOREACH ( const QString &variableName, variableNames )
899  {
900  if ( varIndex >= variableValues.length() )
901  {
902  break;
903  }
904 
905  QVariant varValue = variableValues.at( varIndex );
906  varIndex++;
907  scope->setVariable( variableName, varValue, true );
908  }
909 
910  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_name" ), layer->name(), true, true ) );
911  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_id" ), layer->id(), true, true ) );
912  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer >( QgsWeakMapLayerPointer( const_cast<QgsMapLayer *>( layer ) ) ), true, true ) );
913 
914  const QgsVectorLayer *vLayer = qobject_cast< const QgsVectorLayer * >( layer );
915  if ( vLayer )
916  {
917  scope->setFields( vLayer->fields() );
918  }
919 
920  //TODO - add functions. Possibilities include:
921  //is_selected
922  //field summary stats
923 
924  return scope;
925 }
926 
927 QList<QgsExpressionContextScope *> QgsExpressionContextUtils::globalProjectLayerScopes( const QgsMapLayer *layer )
928 {
929  QList<QgsExpressionContextScope *> scopes;
930  scopes << globalScope();
931 
932  QgsProject *project = QgsProject::instance(); // TODO: use project associated with layer
933  if ( project )
934  scopes << projectScope( project );
935 
936  if ( layer )
937  scopes << layerScope( layer );
938  return scopes;
939 }
940 
941 
942 void QgsExpressionContextUtils::setLayerVariable( QgsMapLayer *layer, const QString &name, const QVariant &value )
943 {
944  if ( !layer )
945  return;
946 
947  //write variable to layer
948  QStringList variableNames = layer->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
949  QStringList variableValues = layer->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
950 
951  variableNames << name;
952  variableValues << value.toString();
953 
954  layer->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
955  layer->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
956 }
957 
958 void QgsExpressionContextUtils::setLayerVariables( QgsMapLayer *layer, const QVariantMap &variables )
959 {
960  if ( !layer )
961  return;
962 
963  QStringList variableNames;
964  QStringList variableValues;
965 
966  QVariantMap::const_iterator it = variables.constBegin();
967  for ( ; it != variables.constEnd(); ++it )
968  {
969  variableNames << it.key();
970  variableValues << it.value().toString();
971  }
972 
973  layer->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
974  layer->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
975 }
976 
978 {
979  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
980  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
981 
982  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Settings" ) );
983 
984  //add known map settings context variables
985  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), "canvas", true ) );
986  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mapSettings.rotation(), true ) );
987  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), mapSettings.scale(), true ) );
988  QgsGeometry extent = QgsGeometry::fromRect( mapSettings.visibleExtent() );
989  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( extent ), true ) );
990  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), mapSettings.visibleExtent().width(), true ) );
991  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), mapSettings.visibleExtent().height(), true ) );
992  QgsGeometry centerPoint = QgsGeometry::fromPointXY( mapSettings.visibleExtent().center() );
993  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
994 
995  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapSettings.destinationCrs().authid(), true ) );
996  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapSettings.destinationCrs().toProj4(), true ) );
997  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapSettings.mapUnits() ), true ) );
998 
999  QVariantList layersIds;
1000  QVariantList layers;
1001  const QList<QgsMapLayer *> layersInMap = mapSettings.layers();
1002  layersIds.reserve( layersInMap.count() );
1003  layers.reserve( layersInMap.count() );
1004  for ( QgsMapLayer *layer : layersInMap )
1005  {
1006  layersIds << layer->id();
1007  layers << QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( layer ) );
1008  }
1009  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
1010  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );
1011 
1012  scope->addFunction( QStringLiteral( "is_layer_visible" ), new GetLayerVisibility( mapSettings.layers() ) );
1013 
1014  return scope;
1015 }
1016 
1017 QgsExpressionContextScope *QgsExpressionContextUtils::mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches )
1018 {
1019  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Tool Capture" ) );
1020 
1021  QVariantList matchList;
1022 
1023  for ( const QgsPointLocator::Match &match : matches )
1024  {
1025  QVariantMap matchMap;
1026 
1027  matchMap.insert( QStringLiteral( "valid" ), match.isValid() );
1028  matchMap.insert( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( match.layer() ) ) );
1029  matchMap.insert( QStringLiteral( "feature_id" ), match.featureId() );
1030  matchMap.insert( QStringLiteral( "vertex_index" ), match.vertexIndex() );
1031  matchMap.insert( QStringLiteral( "distance" ), match.distance() );
1032 
1033  matchList.append( matchMap );
1034  }
1035 
1036  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "snapping_results" ), matchList ) );
1037 
1038  return scope;
1039 }
1040 
1042 {
1043  if ( !symbolScope )
1044  return nullptr;
1045 
1046  symbolScope->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_SYMBOL_COLOR, symbol ? symbol->color() : QColor(), true ) );
1047 
1048  double angle = 0.0;
1049  const QgsMarkerSymbol *markerSymbol = dynamic_cast< const QgsMarkerSymbol * >( symbol );
1050  if ( markerSymbol )
1051  {
1052  angle = markerSymbol->angle();
1053  }
1055 
1056  return symbolScope;
1057 }
1058 
1060 {
1061  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope( QObject::tr( "Layout" ) ) );
1062  if ( !layout )
1063  return scope.release();
1064 
1065  //add variables defined in layout properties
1066  QStringList variableNames = layout->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1067  QStringList variableValues = layout->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1068 
1069  int varIndex = 0;
1070  Q_FOREACH ( const QString &variableName, variableNames )
1071  {
1072  if ( varIndex >= variableValues.length() )
1073  {
1074  break;
1075  }
1076 
1077  QVariant varValue = variableValues.at( varIndex );
1078  varIndex++;
1079  scope->setVariable( variableName, varValue );
1080  }
1081 
1082  //add known layout context variables
1083  if ( const QgsMasterLayoutInterface *l = dynamic_cast< const QgsMasterLayoutInterface * >( layout ) )
1084  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_name" ), l->name(), true ) );
1085 
1086  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_numpages" ), layout->pageCollection()->pageCount(), true ) );
1087  if ( layout->pageCollection()->pageCount() > 0 )
1088  {
1089  // just take first page size
1090  QSizeF s = layout->pageCollection()->page( 0 )->sizeWithUnits().toQSizeF();
1091  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), s.height(), true ) );
1092  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), s.width(), true ) );
1093  }
1094  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_dpi" ), layout->renderContext().dpi(), true ) );
1095 
1096  scope->addFunction( QStringLiteral( "item_variables" ), new GetLayoutItemVariables( layout ) );
1097 
1098  if ( layout->reportContext().layer() )
1099  {
1100  scope->setFields( layout->reportContext().layer()->fields() );
1101  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layerid" ), layout->reportContext().layer()->id(), true ) );
1102  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layername" ), layout->reportContext().layer()->name(), true ) );
1103  }
1104 
1105  if ( layout->reportContext().feature().isValid() )
1106  {
1107  QgsFeature atlasFeature = layout->reportContext().feature();
1108  scope->setFeature( atlasFeature );
1109  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( atlasFeature ), true ) );
1110  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), atlasFeature.id(), true ) );
1111  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( atlasFeature.geometry() ), true ) );
1112  }
1113 
1114  return scope.release();
1115 }
1116 
1117 void QgsExpressionContextUtils::setLayoutVariable( QgsLayout *layout, const QString &name, const QVariant &value )
1118 {
1119  if ( !layout )
1120  return;
1121 
1122  //write variable to layout
1123  QStringList variableNames = layout->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1124  QStringList variableValues = layout->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1125 
1126  variableNames << name;
1127  variableValues << value.toString();
1128 
1129  layout->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1130  layout->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1131 }
1132 
1133 void QgsExpressionContextUtils::setLayoutVariables( QgsLayout *layout, const QVariantMap &variables )
1134 {
1135  if ( !layout )
1136  return;
1137 
1138  QStringList variableNames;
1139  QStringList variableValues;
1140 
1141  QVariantMap::const_iterator it = variables.constBegin();
1142  for ( ; it != variables.constEnd(); ++it )
1143  {
1144  variableNames << it.key();
1145  variableValues << it.value().toString();
1146  }
1147 
1148  layout->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1149  layout->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1150 }
1151 
1153 {
1154  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
1155  if ( !atlas )
1156  {
1157  //add some dummy atlas variables. This is done so that as in certain contexts we want to show
1158  //users that these variables are available even if they have no current value
1159  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), QString(), true ) );
1160  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( QgsFeature() ), true ) );
1161  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), 0, true ) );
1162  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( QgsGeometry() ), true ) );
1163  return scope;
1164  }
1165 
1166  //add known atlas variables
1167  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_totalfeatures" ), atlas->count(), true ) );
1168  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featurenumber" ), atlas->currentFeatureNumber() + 1, true ) );
1169  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_filename" ), atlas->currentFilename(), true ) );
1170  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), atlas->nameForPage( atlas->currentFeatureNumber() ), true ) );
1171 
1172  if ( atlas->enabled() && atlas->coverageLayer() )
1173  {
1174  scope->setFields( atlas->coverageLayer()->fields() );
1175  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layerid" ), atlas->coverageLayer()->id(), true ) );
1176  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layername" ), atlas->coverageLayer()->name(), true ) );
1177  }
1178 
1179  if ( atlas->enabled() )
1180  {
1181  QgsFeature atlasFeature = atlas->layout()->reportContext().feature();
1182  scope->setFeature( atlasFeature );
1183  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( atlasFeature ), true ) );
1184  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), atlasFeature.id(), true ) );
1185  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( atlasFeature.geometry() ), true ) );
1186  }
1187 
1188  return scope;
1189 }
1190 
1192 {
1193  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layout Item" ) );
1194  if ( !item )
1195  return scope;
1196 
1197  //add variables defined in layout item properties
1198  const QStringList variableNames = item->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1199  const QStringList variableValues = item->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1200 
1201  int varIndex = 0;
1202  for ( const QString &variableName : variableNames )
1203  {
1204  if ( varIndex >= variableValues.length() )
1205  {
1206  break;
1207  }
1208 
1209  QVariant varValue = variableValues.at( varIndex );
1210  varIndex++;
1211  scope->setVariable( variableName, varValue );
1212  }
1213 
1214  //add known layout item context variables
1215  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "item_id" ), item->id(), true ) );
1216  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "item_uuid" ), item->uuid(), true ) );
1217  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_page" ), item->page() + 1, true ) );
1218 
1219  if ( item->layout() )
1220  {
1221  const QgsLayoutItemPage *page = item->layout()->pageCollection()->page( item->page() );
1222  if ( page )
1223  {
1224  const QSizeF s = page->sizeWithUnits().toQSizeF();
1225  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), s.height(), true ) );
1226  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), s.width(), true ) );
1227  }
1228  else
1229  {
1230  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), QVariant(), true ) );
1231  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), QVariant(), true ) );
1232  }
1233  }
1234 
1235  return scope;
1236 }
1237 
1238 void QgsExpressionContextUtils::setLayoutItemVariable( QgsLayoutItem *item, const QString &name, const QVariant &value )
1239 {
1240  if ( !item )
1241  return;
1242 
1243  //write variable to layout item
1244  QStringList variableNames = item->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1245  QStringList variableValues = item->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1246 
1247  variableNames << name;
1248  variableValues << value.toString();
1249 
1250  item->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1251  item->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1252 }
1253 
1254 void QgsExpressionContextUtils::setLayoutItemVariables( QgsLayoutItem *item, const QVariantMap &variables )
1255 {
1256  if ( !item )
1257  return;
1258 
1259  QStringList variableNames;
1260  QStringList variableValues;
1261 
1262  QVariantMap::const_iterator it = variables.constBegin();
1263  for ( ; it != variables.constEnd(); ++it )
1264  {
1265  variableNames << it.key();
1266  variableValues << it.value().toString();
1267  }
1268 
1269  item->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1270  item->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1271 }
1272 
1274 {
1276  scope->setFeature( feature );
1277  scope->setFields( fields );
1278  return QgsExpressionContext() << scope;
1279 }
1280 
1282 {
1283  // set aside for future use
1284  Q_UNUSED( context );
1285 
1286  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope( QObject::tr( "Algorithm" ) ) );
1287  if ( !algorithm )
1288  return scope.release();
1289 
1290  //add standard algorithm variables
1291  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "algorithm_id" ), algorithm->id(), true ) );
1292 
1293  scope->addFunction( QStringLiteral( "parameter" ), new GetProcessingParameterValue( parameters ) );
1294 
1295  return scope.release();
1296 }
1297 
1299 {
1300  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope() );
1301  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "notification_message" ), message, true ) );
1302  return scope.release();
1303 }
1304 
1306 {
1307  QgsExpression::registerFunction( new GetNamedProjectColor( nullptr ) );
1308  QgsExpression::registerFunction( new GetLayoutItemVariables( nullptr ) );
1309  QgsExpression::registerFunction( new GetLayerVisibility( QList<QgsMapLayer *>() ) );
1310  QgsExpression::registerFunction( new GetProcessingParameterValue( QVariantMap() ) );
1311  QgsExpression::registerFunction( new GetCurrentFormFieldValue( ) );
1312 }
1313 
1315 {
1316  Q_UNUSED( node )
1317  return mUsesGeometry;
1318 }
1319 
1321 {
1322  Q_UNUSED( node )
1323  return mReferencedColumns;
1324 }
1325 
1327 {
1328  return allParamsStatic( node, parent, context );
1329 }
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:176
bool hasVariable(const QString &name) const
Tests whether a variable with the specified name exists in the scope.
static const QString EXPR_ORIGINAL_VALUE
Inbuilt variable name for value original value variable.
Class for parsing and evaluation of expressions (formerly called "search strings").
static QString locale()
Returns the QGIS locale.
QgsFeatureId id
Definition: qgsfeature.h:63
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
QString description(const QString &name) const
Returns the translated description for the variable with the specified name (if set).
static QgsExpressionContextScope * processingAlgorithmScope(const QgsProcessingAlgorithm *algorithm, const QVariantMap &parameters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing algorithm...
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
static void setLayoutItemVariable(QgsLayoutItem *item, const QString &name, const QVariant &value)
Sets a layout item context variable, with the given name and value.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Single variable definition for use within a QgsExpressionContextScope.
static void setGlobalVariable(const QString &name, const QVariant &value)
Sets a global context variable.
Base class for all map layer types.
Definition: qgsmaplayer.h:63
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
static void setLayoutItemVariables(QgsLayoutItem *item, const QVariantMap &variables)
Sets all layout item context variables for an item.
static const QString QGIS_VERSION
Version string.
Definition: qgis.h:65
QgsExpressionContextScope * scope(int index)
Returns the scope at the specified index within the context.
static void setLayerVariables(QgsMapLayer *layer, const QVariantMap &variables)
Sets all layer context variables.
QString id() const
Returns the unique ID for the algorithm, which is a combination of the algorithm provider&#39;s ID and th...
QgsAbstractMetadataBase::KeywordMap keywords() const
Returns the keywords map, which is a set of descriptive keywords associated with the resource...
bool isReadOnly(const QString &name) const
Returns whether a variable is read only, and should not be modifiable by users.
Base class for graphical items within a QgsLayout.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
static void setLayoutVariable(QgsLayout *layout, const QString &name, const QVariant &value)
Sets a layout context variable.
QStringList filteredVariableNames() const
Returns a filtered list of variables names set by all scopes in the context.
static void setCustomVariables(const QVariantMap &customVariables)
Custom expression variables for this application.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:63
QgsExpressionContext & operator=(const QgsExpressionContext &other)
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from the layout.
Definition: qgslayout.cpp:412
void addFunction(const QString &name, QgsScopedExpressionFunction *function)
Adds a function to the scope.
QgsExpressionContextScope(const QString &name=QString())
Constructor for QgsExpressionContextScope.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
static void removeProjectVariable(QgsProject *project, const QString &name)
Remove project context variable.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
static QgsExpressionContext createFeatureBasedContext(const QgsFeature &feature, const QgsFields &fields)
Helper function for creating an expression context which contains just a feature and fields collectio...
QStringList variableNames() const
Returns a list of variable names contained within the scope.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QgsLayoutSize sizeWithUnits() const
Returns the item&#39;s current size, including units.
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the object.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from the object.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
bool isReadOnly(const QString &name) const
Tests whether the specified variable is read only and should not be editable by users.
QString author() const
Returns the project author string.
Container of fields for a vector layer.
Definition: qgsfields.h:42
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:104
static QVariantMap customVariables()
Custom expression variables for this application.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
static QgsExpressionContextScope * mapToolCaptureScope(const QList< QgsPointLocator::Match > &matches)
Sets the expression context variables which are available for expressions triggered by a map tool cap...
static QString variableHelpText(const QString &variableName)
Returns the help text for a specified variable.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
QList< QgsMapLayer * > layers() const
Gets list of layers for map rendering The layers are stored in the reverse order of how they are rend...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:54
QgsExpressionContextScope & operator=(const QgsExpressionContextScope &other)
QList< QgsExpressionContextScope * > takeScopes()
Returns all scopes from this context and remove them, leaving this context without any context...
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 feat...
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
static void setLayoutVariables(QgsLayout *layout, const QVariantMap &variables)
Sets all layout context variables.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:1482
static const int QGIS_VERSION_INT
Version number used for comparing versions using the "Check QGIS Version" function.
Definition: qgis.h:67
Abstract base class for processing algorithms.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout&#39;s render context, which stores information relating to the current ...
Definition: qgslayout.cpp:356
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QgsExpressionContext & operator<<(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QString userFullName()
Returns the user&#39;s operating system login account full display name.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
QString description(const QString &name) const
Returns a translated description string for the variable with specified name.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsUnitTypes::DistanceUnit mapUnits() const
Gets units of map&#39;s geographical coordinates - used for scale calculation.
QgsLayout * layout() override
Returns the layout associated with the iterator.
The QgsMapSettings class contains configuration for rendering of the map.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
QString homePath
Definition: qgsproject.h:94
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
QSizeF toQSizeF() const
Converts the layout size to a QSizeF.
static QgsExpressionContextScope * layoutItemScope(const QgsLayoutItem *item)
Creates a new scope which contains variables and functions relating to a QgsLayoutItem.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
bool removeVariable(const QString &name)
Removes a variable from the context scope, if found.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
QgsVectorLayer * layer() const
Returns the vector layer associated with the layout&#39;s context.
bool hasFunction(const QString &name) const
Tests whether a function with the specified name exists in the scope.
static const QString EXPR_SYMBOL_ANGLE
Inbuilt variable name for symbol angle variable.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
const QgsLayout * layout() const
Returns the layout the object is attached to.
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int scopeCount() const
Returns the number of scopes contained in the context.
bool isHighlightedVariable(const QString &name) const
Returns true if the specified variable name is intended to be highlighted to the user.
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout&#39;s page collection, which stores and manages page items in the layout...
Definition: qgslayout.cpp:456
static void setProjectVariables(QgsProject *project, const QVariantMap &variables)
Sets all project context variables.
QgsProjectMetadata metadata
Definition: qgsproject.h:101
double scale() const
Returns the calculated map scale.
double dpi() const
Returns the dpi for outputting the layout.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:201
static QgsExpressionContextScope * notificationScope(const QString &message=QString())
Creates a new scope which contains variables and functions relating to provider notifications.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static void removeGlobalVariable(const QString &name)
Remove a global context variable.
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:95
QVariantMap variablesToMap() const
Returns a map of variable name to value representing all the expression variables contained by the co...
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
QVariant variable(const QString &name) const
Retrieves a variable&#39;s value from the scope.
static const QString EXPR_SYMBOL_COLOR
Inbuilt variable name for symbol color variable.
QDateTime creationDateTime() const
Returns the project&#39;s creation date/timestamp.
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
QStringList readListEntry(const QString &scope, const QString &key, const QStringList &def=QStringList(), bool *ok=nullptr) const
Key value accessors.
Reads and writes project states.
Definition: qgsproject.h:89
static void setCustomVariable(const QString &name, const QVariant &value)
Set a single custom expression variable.
QColor color() const
Returns the symbol&#39;s color.
Definition: qgssymbol.cpp:453
QString currentFilename() const
Returns the current feature filename.
int page() const
Returns the page the item is currently on, with the first page returning 0.
QString id() const
Returns the item&#39;s ID name.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
QgsExpressionFunction * function(const QString &name) const
Retrieves a function from the scope.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
QStringList variableNames() const
Returns a list of variables names set by all scopes in the context.
int count() override
Returns the number of features to iterate over.
Single scope for storing variables and functions for use within a QgsExpressionContext.
An expression node for expression functions.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
QStringList functionNames() const
Retrieves a list of names of functions contained in the scope.
void setCustomVariables(const QVariantMap &customVariables)
A map of custom project variables.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
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 allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
QgsProjectStorage * projectStorage() const
Returns pointer to project storage implementation that handles read/write of the project file...
Definition: qgsproject.cpp:544
QString abstract() const
Returns a free-form description of the resource.
static void setLayerVariable(QgsMapLayer *layer, const QString &name, const QVariant &value)
Sets a layer context variable.
static QString userLoginName()
Returns the user&#39;s operating system login account name.
static QString osName()
Returns a string name of the operating system QGIS is running on.
int pageCount() const
Returns the number of pages in the collection.
int currentFeatureNumber() const
Returns the current feature number, where a value of 0 corresponds to the first feature.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout&#39;s report context, which stores information relating to the current ...
Definition: qgslayout.cpp:366
static void setProjectVariable(QgsProject *project, const QString &name, const QVariant &value)
Sets a project context variable.
A abstract base class for defining QgsExpression functions.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects. ...
static QgsExpressionContextScope * atlasScope(QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
QStringList functionNames() const
Retrieves a list of function names contained in the context.
static const QString QGIS_RELEASE_NAME
Release name.
Definition: qgis.h:69
QgsExpressionContext()=default
Constructor for QgsExpressionContext.
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout...
void clearCachedValues() const
Clears all cached values from the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QMap< QString, QStringList > KeywordMap
Map of vocabulary string to keyword list.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:393
virtual QString uuid() const
Returns the item identification string.
This class represents a coordinate reference system (CRS).
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
QString nameForPage(int page) const
Returns the calculated name for a specified atlas page number.
static QString platform()
Returns the QGIS platform name, e.g., "desktop" or "server".
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the layout.
Definition: qgslayout.cpp:404
bool enabled() const
Returns whether the atlas generation is enabled.
bool hasFeature() const
Returns true if the scope has a feature associated with it.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
QgsFeature feature() const
Returns the current feature for evaluating the layout.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user...
QString name
Definition: qgsmaplayer.h:67
Represents a single parameter passed to a function.
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
QgsGeometry geometry
Definition: qgsfeature.h:66
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QString title() const
Returns the project&#39;s title.
Definition: qgsproject.cpp:413
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:229
QVariantMap customVariables() const
A map of custom project variables.
QString name() const
Returns the friendly display name of the context scope.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
Definition: qgsproject.cpp:585
Interface for master layout type objects, such as print layouts and reports.
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
QString absoluteFilePath() const
Returns full absolute path to the project file if the project is stored in a file system - derived fr...
Definition: qgsproject.cpp:574
bool isStatic
A static variable can be cached for the lifetime of a context.
Represents a vector layer which manages a vector based data sets.
int indexOfScope(QgsExpressionContextScope *scope) const
Returns the index of the specified scope if it exists within the context.
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
Contains information about the context in which a processing algorithm is executed.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
QStringList filteredVariableNames() const
Returns a filtered and sorted list of variable names contained within the scope.
QList< QgsExpressionContextScope *> scopes()
Returns a list of scopes contained within the stack.
QString fileName
Definition: qgsproject.h:93
static void setGlobalVariables(const QVariantMap &variables)
Sets all global context variables.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
Expression function for use within a QgsExpressionContextScope.
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1181
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QString authid() const
Returns the authority identifier for the CRS.
QString identifier() const
A reference, URI, URL or some other mechanism to identify the resource.
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
static QColor decodeColor(const QString &str)
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:208
Item representing the paper in a layout.