QGIS API Documentation  3.5.0-Master (5b7f808)
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 #include "qgsexpressionutils.h"
36 #include "qgslayoutrendercontext.h"
37 
38 #include <QSettings>
39 #include <QDir>
40 
41 
42 const QString QgsExpressionContext::EXPR_FIELDS( QStringLiteral( "_fields_" ) );
43 const QString QgsExpressionContext::EXPR_ORIGINAL_VALUE( QStringLiteral( "value" ) );
44 const QString QgsExpressionContext::EXPR_SYMBOL_COLOR( QStringLiteral( "symbol_color" ) );
45 const QString QgsExpressionContext::EXPR_SYMBOL_ANGLE( QStringLiteral( "symbol_angle" ) );
46 const QString QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT( QStringLiteral( "geometry_part_count" ) );
47 const QString QgsExpressionContext::EXPR_GEOMETRY_PART_NUM( QStringLiteral( "geometry_part_num" ) );
48 const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT( QStringLiteral( "geometry_point_count" ) );
49 const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM( QStringLiteral( "geometry_point_num" ) );
50 const QString QgsExpressionContext::EXPR_CLUSTER_SIZE( QStringLiteral( "cluster_size" ) );
51 const QString QgsExpressionContext::EXPR_CLUSTER_COLOR( QStringLiteral( "cluster_color" ) );
52 
53 //
54 // QgsExpressionContextScope
55 //
56 
58  : mName( name )
59 {
60 
61 }
62 
64  : mName( other.mName )
65  , mVariables( other.mVariables )
66  , mHasFeature( other.mHasFeature )
67  , mFeature( other.mFeature )
68 {
69  QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin();
70  for ( ; it != other.mFunctions.constEnd(); ++it )
71  {
72  mFunctions.insert( it.key(), it.value()->clone() );
73  }
74 }
75 
77 {
78  mName = other.mName;
79  mVariables = other.mVariables;
80  mHasFeature = other.mHasFeature;
81  mFeature = other.mFeature;
82 
83  qDeleteAll( mFunctions );
84  mFunctions.clear();
85  QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin();
86  for ( ; it != other.mFunctions.constEnd(); ++it )
87  {
88  mFunctions.insert( it.key(), it.value()->clone() );
89  }
90 
91  return *this;
92 }
93 
95 {
96  qDeleteAll( mFunctions );
97 }
98 
99 void QgsExpressionContextScope::setVariable( const QString &name, const QVariant &value, bool isStatic )
100 {
101  if ( mVariables.contains( name ) )
102  {
103  StaticVariable existing = mVariables.value( name );
104  existing.value = value;
105  existing.isStatic = isStatic;
106  addVariable( existing );
107  }
108  else
109  {
110  addVariable( QgsExpressionContextScope::StaticVariable( name, value, false, isStatic ) );
111  }
112 }
113 
115 {
116  mVariables.insert( variable.name, variable );
117 }
118 
120 {
121  return mVariables.remove( name ) > 0;
122 }
123 
124 bool QgsExpressionContextScope::hasVariable( const QString &name ) const
125 {
126  return mVariables.contains( name );
127 }
128 
129 QVariant QgsExpressionContextScope::variable( const QString &name ) const
130 {
131  return hasVariable( name ) ? mVariables.value( name ).value : QVariant();
132 }
133 
135 {
136  QStringList names = mVariables.keys();
137  return names;
138 }
139 
140 bool QgsExpressionContextScope::variableNameSort( const QString &a, const QString &b )
141 {
142  return QString::localeAwareCompare( a, b ) < 0;
143 }
144 
146 class QgsExpressionContextVariableCompare
147 {
148  public:
149  explicit QgsExpressionContextVariableCompare( const QgsExpressionContextScope &scope )
150  : mScope( scope )
151  { }
152 
153  bool operator()( const QString &a, const QString &b ) const
154  {
155  bool aReadOnly = mScope.isReadOnly( a );
156  bool bReadOnly = mScope.isReadOnly( b );
157  if ( aReadOnly != bReadOnly )
158  return aReadOnly;
159  return QString::localeAwareCompare( a, b ) < 0;
160  }
161 
162  private:
163  const QgsExpressionContextScope &mScope;
164 };
166 
168 {
169  QStringList allVariables = mVariables.keys();
170  QStringList filtered;
171  Q_FOREACH ( const QString &variable, allVariables )
172  {
173  if ( variable.startsWith( '_' ) )
174  continue;
175 
176  filtered << variable;
177  }
178  QgsExpressionContextVariableCompare cmp( *this );
179  std::sort( filtered.begin(), filtered.end(), cmp );
180 
181  return filtered;
182 }
183 
184 bool QgsExpressionContextScope::isReadOnly( const QString &name ) const
185 {
186  return hasVariable( name ) ? mVariables.value( name ).readOnly : false;
187 }
188 
189 bool QgsExpressionContextScope::isStatic( const QString &name ) const
190 {
191  return hasVariable( name ) ? mVariables.value( name ).isStatic : false;
192 }
193 
194 QString QgsExpressionContextScope::description( const QString &name ) const
195 {
196  return hasVariable( name ) ? mVariables.value( name ).description : QString();
197 }
198 
199 bool QgsExpressionContextScope::hasFunction( const QString &name ) const
200 {
201  return mFunctions.contains( name );
202 }
203 
205 {
206  return mFunctions.contains( name ) ? mFunctions.value( name ) : nullptr;
207 }
208 
210 {
211  return mFunctions.keys();
212 }
213 
215 {
216  mFunctions.insert( name, function );
217 }
218 
219 
221 {
222  addVariable( StaticVariable( QgsExpressionContext::EXPR_FIELDS, QVariant::fromValue( fields ), true ) );
223 }
224 
225 
226 //
227 // QgsExpressionContext
228 //
229 
230 QgsExpressionContext::QgsExpressionContext( const QList<QgsExpressionContextScope *> &scopes )
231  : mStack( scopes )
232 {
233 }
234 
236 {
237  Q_FOREACH ( const QgsExpressionContextScope *scope, other.mStack )
238  {
239  mStack << new QgsExpressionContextScope( *scope );
240  }
241  mHighlightedVariables = other.mHighlightedVariables;
242  mHighlightedFunctions = other.mHighlightedFunctions;
243  mCachedValues = other.mCachedValues;
244 }
245 
247 {
248  if ( this != &other )
249  {
250  qDeleteAll( mStack );
251  // move the stack over
252  mStack = other.mStack;
253  other.mStack.clear();
254 
255  mHighlightedVariables = other.mHighlightedVariables;
256  mHighlightedFunctions = other.mHighlightedFunctions;
257  mCachedValues = other.mCachedValues;
258  }
259  return *this;
260 }
261 
263 {
264  qDeleteAll( mStack );
265  mStack.clear();
266  Q_FOREACH ( const QgsExpressionContextScope *scope, other.mStack )
267  {
268  mStack << new QgsExpressionContextScope( *scope );
269  }
270  mHighlightedVariables = other.mHighlightedVariables;
271  mHighlightedFunctions = other.mHighlightedFunctions;
272  mCachedValues = other.mCachedValues;
273  return *this;
274 }
275 
277 {
278  qDeleteAll( mStack );
279  mStack.clear();
280 }
281 
282 bool QgsExpressionContext::hasVariable( const QString &name ) const
283 {
284  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
285  {
286  if ( scope->hasVariable( name ) )
287  return true;
288  }
289  return false;
290 }
291 
292 QVariant QgsExpressionContext::variable( const QString &name ) const
293 {
295  return scope ? scope->variable( name ) : QVariant();
296 }
297 
299 {
300  QStringList names = variableNames();
301  QVariantMap m;
302  Q_FOREACH ( const QString &name, names )
303  {
304  m.insert( name, variable( name ) );
305  }
306  return m;
307 }
308 
309 bool QgsExpressionContext::isHighlightedVariable( const QString &name ) const
310 {
311  return mHighlightedVariables.contains( name );
312 }
313 
315 {
316  mHighlightedVariables = variableNames;
317 }
318 
319 bool QgsExpressionContext::isHighlightedFunction( const QString &name ) const
320 {
321  return mHighlightedFunctions.contains( name );
322 }
323 
324 void QgsExpressionContext::setHighlightedFunctions( const QStringList &names )
325 {
326  mHighlightedFunctions = names;
327 }
328 
330 {
331  //iterate through stack backwards, so that higher priority variables take precedence
332  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
333  while ( it != mStack.constBegin() )
334  {
335  --it;
336  if ( ( *it )->hasVariable( name ) )
337  return ( *it );
338  }
339  return nullptr;
340 }
341 
343 {
344  //iterate through stack backwards, so that higher priority variables take precedence
345  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
346  while ( it != mStack.constBegin() )
347  {
348  --it;
349  if ( ( *it )->hasVariable( name ) )
350  return ( *it );
351  }
352  return nullptr;
353 }
354 
356 {
357  if ( index < 0 || index >= mStack.count() )
358  return nullptr;
359 
360  return mStack.at( index );
361 }
362 
364 {
365  if ( mStack.count() < 1 )
366  return nullptr;
367 
368  return mStack.last();
369 }
370 
372 {
373  if ( !scope )
374  return -1;
375 
376  return mStack.indexOf( scope );
377 }
378 
379 int QgsExpressionContext::indexOfScope( const QString &scopeName ) const
380 {
381  int index = 0;
382  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
383  {
384  if ( scope->name() == scopeName )
385  return index;
386 
387  index++;
388  }
389  return -1;
390 }
391 
393 {
394  QStringList names;
395  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
396  {
397  names << scope->variableNames();
398  }
399  return names.toSet().toList();
400 }
401 
403 {
404  QStringList allVariables = variableNames();
405  QStringList filtered;
406  Q_FOREACH ( const QString &variable, allVariables )
407  {
408  if ( variable.startsWith( '_' ) )
409  continue;
410 
411  filtered << variable;
412  }
413 
414  filtered.sort();
415  return filtered;
416 }
417 
418 bool QgsExpressionContext::isReadOnly( const QString &name ) const
419 {
420  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
421  {
422  if ( scope->isReadOnly( name ) )
423  return true;
424  }
425  return false;
426 }
427 
428 QString QgsExpressionContext::description( const QString &name ) const
429 {
431  return ( scope && !scope->description( name ).isEmpty() ) ? scope->description( name ) : QgsExpression::variableHelpText( name );
432 }
433 
434 bool QgsExpressionContext::hasFunction( const QString &name ) const
435 {
436  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
437  {
438  if ( scope->hasFunction( name ) )
439  return true;
440  }
441  return false;
442 }
443 
445 {
446  QStringList result;
447  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
448  {
449  result << scope->functionNames();
450  }
451  result = result.toSet().toList();
452  result.sort();
453  return result;
454 }
455 
457 {
458  //iterate through stack backwards, so that higher priority variables take precedence
459  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
460  while ( it != mStack.constBegin() )
461  {
462  --it;
463  if ( ( *it )->hasFunction( name ) )
464  return ( *it )->function( name );
465  }
466  return nullptr;
467 }
468 
470 {
471  return mStack.count();
472 }
473 
475 {
476  mStack.append( scope );
477 }
478 
479 void QgsExpressionContext::appendScopes( const QList<QgsExpressionContextScope *> &scopes )
480 {
481  mStack.append( scopes );
482 }
483 
485 {
486  if ( !mStack.isEmpty() )
487  return mStack.takeLast();
488 
489  return nullptr;
490 }
491 
492 QList<QgsExpressionContextScope *> QgsExpressionContext::takeScopes()
493 {
494  QList<QgsExpressionContextScope *> stack = mStack;
495  mStack.clear();
496  return stack;
497 }
498 
500 {
501  mStack.append( scope );
502  return *this;
503 }
504 
506 {
507  if ( mStack.isEmpty() )
508  mStack.append( new QgsExpressionContextScope() );
509 
510  mStack.last()->setFeature( feature );
511 }
512 
514 {
515  Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
516  {
517  if ( scope->hasFeature() )
518  return true;
519  }
520  return false;
521 }
522 
524 {
525  //iterate through stack backwards, so that higher priority variables take precedence
526  QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
527  while ( it != mStack.constBegin() )
528  {
529  --it;
530  if ( ( *it )->hasFeature() )
531  return ( *it )->feature();
532  }
533  return QgsFeature();
534 }
535 
537 {
538  if ( mStack.isEmpty() )
539  mStack.append( new QgsExpressionContextScope() );
540 
541  mStack.last()->setFields( fields );
542 }
543 
545 {
546  return qvariant_cast<QgsFields>( variable( QgsExpressionContext::EXPR_FIELDS ) );
547 }
548 
550 {
551  if ( mStack.isEmpty() )
552  mStack.append( new QgsExpressionContextScope() );
553 
555  value, true ) );
556 }
557 
558 void QgsExpressionContext::setCachedValue( const QString &key, const QVariant &value ) const
559 {
560  mCachedValues.insert( key, value );
561 }
562 
563 bool QgsExpressionContext::hasCachedValue( const QString &key ) const
564 {
565  return mCachedValues.contains( key );
566 }
567 
568 QVariant QgsExpressionContext::cachedValue( const QString &key ) const
569 {
570  return mCachedValues.value( key, QVariant() );
571 }
572 
574 {
575  mCachedValues.clear();
576 }
577 
578 
579 //
580 // QgsExpressionContextUtils
581 //
582 
584 {
585  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Global" ) );
586 
587  QVariantMap customVariables = QgsApplication::customVariables();
588 
589  for ( QVariantMap::const_iterator it = customVariables.constBegin(); it != customVariables.constEnd(); ++it )
590  {
591  scope->setVariable( it.key(), it.value(), true );
592  }
593 
594  //add some extra global variables
595  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version" ), Qgis::QGIS_VERSION, true, true ) );
596  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version_no" ), Qgis::QGIS_VERSION_INT, true, true ) );
597  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 ) );
598  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_release_name" ), Qgis::QGIS_RELEASE_NAME, true, true ) );
599  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_platform" ), QgsApplication::platform(), true, true ) );
600  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_os_name" ), QgsApplication::osName(), true, true ) );
601  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_locale" ), QgsApplication::locale(), true, true ) );
602  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_account_name" ), QgsApplication::userLoginName(), true, true ) );
603  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_full_name" ), QgsApplication::userFullName(), true, true ) );
604 
605  return scope;
606 }
607 
608 void QgsExpressionContextUtils::setGlobalVariable( const QString &name, const QVariant &value )
609 {
610  QgsApplication::setCustomVariable( name, value );
611 }
612 
613 void QgsExpressionContextUtils::setGlobalVariables( const QVariantMap &variables )
614 {
616 }
617 
619 {
620  QVariantMap vars = QgsApplication::customVariables();
621  if ( vars.remove( name ) )
623 }
624 
625 
627 
628 class GetNamedProjectColor : public QgsScopedExpressionFunction
629 {
630  public:
631  GetNamedProjectColor( const QgsProject *project )
632  : QgsScopedExpressionFunction( QStringLiteral( "project_color" ), 1, QStringLiteral( "Color" ) )
633  , mProject( project )
634  {
635  if ( !project )
636  return;
637 
638  //build up color list from project. Do this in advance for speed
639  QStringList colorStrings = project->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Colors" ) );
640  QStringList colorLabels = project->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Labels" ) );
641 
642  //generate list from custom colors
643  int colorIndex = 0;
644  for ( QStringList::iterator it = colorStrings.begin();
645  it != colorStrings.end(); ++it )
646  {
647  QColor color = QgsSymbolLayerUtils::decodeColor( *it );
648  QString label;
649  if ( colorLabels.length() > colorIndex )
650  {
651  label = colorLabels.at( colorIndex );
652  }
653 
654  mColors.insert( label.toLower(), color );
655  colorIndex++;
656  }
657  }
658 
659  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
660  {
661  QString colorName = values.at( 0 ).toString().toLower();
662  if ( mColors.contains( colorName ) )
663  {
664  return QStringLiteral( "%1,%2,%3" ).arg( mColors.value( colorName ).red() ).arg( mColors.value( colorName ).green() ).arg( mColors.value( colorName ).blue() );
665  }
666  else
667  return QVariant();
668  }
669 
670  QgsScopedExpressionFunction *clone() const override
671  {
672  return new GetNamedProjectColor( mProject );
673  }
674 
675  private:
676 
677  const QgsProject *mProject = nullptr;
678  QHash< QString, QColor > mColors;
679 
680 };
681 
682 class GetLayoutItemVariables : public QgsScopedExpressionFunction
683 {
684  public:
685  GetLayoutItemVariables( const QgsLayout *c )
686  : QgsScopedExpressionFunction( QStringLiteral( "item_variables" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "Layout" ) )
687  , mLayout( c )
688  {}
689 
690  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
691  {
692  if ( !mLayout )
693  return QVariant();
694 
695  QString id = values.at( 0 ).toString();
696 
697  const QgsLayoutItem *item = mLayout->itemById( id );
698  if ( !item )
699  return QVariant();
700 
702 
703  return c.variablesToMap();
704  }
705 
706  QgsScopedExpressionFunction *clone() const override
707  {
708  return new GetLayoutItemVariables( mLayout );
709  }
710 
711  private:
712 
713  const QgsLayout *mLayout = nullptr;
714 
715 };
716 
717 class GetCurrentFormFieldValue : public QgsScopedExpressionFunction
718 {
719  public:
720  GetCurrentFormFieldValue( )
721  : QgsScopedExpressionFunction( QStringLiteral( "current_value" ), QgsExpressionFunction::ParameterList() << QStringLiteral( "field_name" ), QStringLiteral( "Form" ) )
722  {}
723 
724  QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * ) override
725  {
726  QString fieldName( values.at( 0 ).toString() );
727  const QgsFeature feat( context->variable( QStringLiteral( "current_feature" ) ).value<QgsFeature>() );
728  if ( fieldName.isEmpty() || ! feat.isValid( ) )
729  {
730  return QVariant();
731  }
732  return feat.attribute( fieldName ) ;
733  }
734 
735  QgsScopedExpressionFunction *clone() const override
736  {
737  return new GetCurrentFormFieldValue( );
738  }
739 
740 };
741 
742 
743 class GetProcessingParameterValue : public QgsScopedExpressionFunction
744 {
745  public:
746  GetProcessingParameterValue( const QVariantMap &params )
747  : QgsScopedExpressionFunction( QStringLiteral( "parameter" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "name" ) ), QStringLiteral( "Processing" ) )
748  , mParams( params )
749  {}
750 
751  QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override
752  {
753  return mParams.value( values.at( 0 ).toString() );
754  }
755 
756  QgsScopedExpressionFunction *clone() const override
757  {
758  return new GetProcessingParameterValue( mParams );
759  }
760 
761  private:
762 
763  const QVariantMap mParams;
764 
765 };
766 
768 
769 
770 QgsExpressionContextScope *QgsExpressionContextUtils::formScope( const QgsFeature &formFeature, const QString &formMode )
771 {
772  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Form" ) );
773  scope->addFunction( QStringLiteral( "current_value" ), new GetCurrentFormFieldValue( ) );
774  scope->setVariable( QStringLiteral( "current_geometry" ), formFeature.geometry( ), true );
775  scope->setVariable( QStringLiteral( "current_feature" ), formFeature, true );
776  scope->setVariable( QStringLiteral( "form_mode" ), formMode, true );
777  return scope;
778 }
779 
781 {
782  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Project" ) );
783 
784  if ( !project )
785  return scope;
786 
787  const QVariantMap vars = project->customVariables();
788 
789  QVariantMap::const_iterator it = vars.constBegin();
790 
791  for ( ; it != vars.constEnd(); ++it )
792  {
793  scope->setVariable( it.key(), it.value(), true );
794  }
795 
796  QString projectPath = project->projectStorage() ? project->fileName() : project->absoluteFilePath();
797  QString projectFolder = QFileInfo( projectPath ).path();
798  QString projectFilename = QFileInfo( projectPath ).fileName();
799  QString projectBasename = project->baseName();
800 
801  //add other known project variables
802  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), project->title(), true, true ) );
803  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_path" ), QDir::toNativeSeparators( projectPath ), true, true ) );
804  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_folder" ), QDir::toNativeSeparators( projectFolder ), true, true ) );
805  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_filename" ), projectFilename, true, true ) );
806  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_basename" ), projectBasename, true, true ) );
807  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_home" ), QDir::toNativeSeparators( project->homePath() ), true, true ) );
808  QgsCoordinateReferenceSystem projectCrs = project->crs();
809  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs" ), projectCrs.authid(), true, true ) );
810  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs_definition" ), projectCrs.toProj4(), true, true ) );
811 
812  // metadata
813  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_author" ), project->metadata().author(), true, true ) );
814  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_abstract" ), project->metadata().abstract(), true, true ) );
815  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_creation_date" ), project->metadata().creationDateTime(), true, true ) );
816  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_identifier" ), project->metadata().identifier(), true, true ) );
817 
818  // keywords
819  QVariantMap keywords;
820  QgsAbstractMetadataBase::KeywordMap metadataKeywords = project->metadata().keywords();
821  for ( auto it = metadataKeywords.constBegin(); it != metadataKeywords.constEnd(); ++it )
822  {
823  keywords.insert( it.key(), it.value() );
824  }
825  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_keywords" ), keywords, true, true ) );
826 
827  scope->addFunction( QStringLiteral( "project_color" ), new GetNamedProjectColor( project ) );
828  return scope;
829 }
830 
831 void QgsExpressionContextUtils::setProjectVariable( QgsProject *project, const QString &name, const QVariant &value )
832 {
833  if ( !project )
834  return;
835 
836  QVariantMap vars = project->customVariables();
837 
838  vars.insert( name, value );
839 
840  project->setCustomVariables( vars );
841 }
842 
843 void QgsExpressionContextUtils::setProjectVariables( QgsProject *project, const QVariantMap &variables )
844 {
845  if ( !project )
846  return;
847 
848  project->setCustomVariables( variables );
849 }
850 
852 {
853  if ( !project )
854  {
855  return;
856  }
857 
858  QVariantMap vars = project->customVariables();
859  if ( vars.remove( name ) )
860  project->setCustomVariables( vars );
861 }
862 
864 {
865  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) );
866 
867  if ( !layer )
868  return scope;
869 
870  //add variables defined in layer properties
871  QStringList variableNames = layer->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
872  QStringList variableValues = layer->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
873 
874  int varIndex = 0;
875  Q_FOREACH ( const QString &variableName, variableNames )
876  {
877  if ( varIndex >= variableValues.length() )
878  {
879  break;
880  }
881 
882  QVariant varValue = variableValues.at( varIndex );
883  varIndex++;
884  scope->setVariable( variableName, varValue, true );
885  }
886 
887  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_name" ), layer->name(), true, true ) );
888  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_id" ), layer->id(), true, true ) );
889  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer >( QgsWeakMapLayerPointer( const_cast<QgsMapLayer *>( layer ) ) ), true, true ) );
890 
891  const QgsVectorLayer *vLayer = qobject_cast< const QgsVectorLayer * >( layer );
892  if ( vLayer )
893  {
894  scope->setFields( vLayer->fields() );
895  }
896 
897  //TODO - add functions. Possibilities include:
898  //is_selected
899  //field summary stats
900 
901  return scope;
902 }
903 
904 QList<QgsExpressionContextScope *> QgsExpressionContextUtils::globalProjectLayerScopes( const QgsMapLayer *layer )
905 {
906  QList<QgsExpressionContextScope *> scopes;
907  scopes << globalScope();
908 
909  QgsProject *project = QgsProject::instance(); // TODO: use project associated with layer
910  if ( project )
911  scopes << projectScope( project );
912 
913  if ( layer )
914  scopes << layerScope( layer );
915  return scopes;
916 }
917 
918 
919 void QgsExpressionContextUtils::setLayerVariable( QgsMapLayer *layer, const QString &name, const QVariant &value )
920 {
921  if ( !layer )
922  return;
923 
924  //write variable to layer
925  QStringList variableNames = layer->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
926  QStringList variableValues = layer->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
927 
928  variableNames << name;
929  variableValues << value.toString();
930 
931  layer->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
932  layer->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
933 }
934 
935 void QgsExpressionContextUtils::setLayerVariables( QgsMapLayer *layer, const QVariantMap &variables )
936 {
937  if ( !layer )
938  return;
939 
940  QStringList variableNames;
941  QStringList variableValues;
942 
943  QVariantMap::const_iterator it = variables.constBegin();
944  for ( ; it != variables.constEnd(); ++it )
945  {
946  variableNames << it.key();
947  variableValues << it.value().toString();
948  }
949 
950  layer->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
951  layer->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
952 }
953 
955 {
956  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
957  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
958 
959  // and because people don't read that ^^, I'm going to blast it all over this function
960 
961  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Settings" ) );
962 
963  //add known map settings context variables
964  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), "canvas", true ) );
965  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mapSettings.rotation(), true ) );
966  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), mapSettings.scale(), true ) );
967 
968  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
969  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
970 
971  QgsGeometry extent = QgsGeometry::fromRect( mapSettings.visibleExtent() );
972  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( extent ), true ) );
973  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), mapSettings.visibleExtent().width(), true ) );
974  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), mapSettings.visibleExtent().height(), true ) );
975 
976  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
977  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
978 
979  QgsGeometry centerPoint = QgsGeometry::fromPointXY( mapSettings.visibleExtent().center() );
980  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
981 
982  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
983  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
984 
985  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapSettings.destinationCrs().authid(), true ) );
986  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapSettings.destinationCrs().toProj4(), true ) );
987  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapSettings.mapUnits() ), true ) );
988 
989  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
990  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
991 
992  QVariantList layersIds;
993  QVariantList layers;
994  const QList<QgsMapLayer *> layersInMap = mapSettings.layers();
995  layersIds.reserve( layersInMap.count() );
996  layers.reserve( layersInMap.count() );
997  for ( QgsMapLayer *layer : layersInMap )
998  {
999  layersIds << layer->id();
1000  layers << QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( layer ) );
1001  }
1002 
1003  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
1004  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
1005 
1006  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
1007  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );
1008 
1009  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
1010  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
1011 
1012  scope->addFunction( QStringLiteral( "is_layer_visible" ), new GetLayerVisibility( mapSettings.layers() ) );
1013 
1014  // IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
1015  // (rationale is described in QgsLayoutItemMap::createExpressionContext() )
1016 
1017  return scope;
1018 }
1019 
1020 QgsExpressionContextScope *QgsExpressionContextUtils::mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches )
1021 {
1022  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Tool Capture" ) );
1023 
1024  QVariantList matchList;
1025 
1026  for ( const QgsPointLocator::Match &match : matches )
1027  {
1028  QVariantMap matchMap;
1029 
1030  matchMap.insert( QStringLiteral( "valid" ), match.isValid() );
1031  matchMap.insert( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( match.layer() ) ) );
1032  matchMap.insert( QStringLiteral( "feature_id" ), match.featureId() );
1033  matchMap.insert( QStringLiteral( "vertex_index" ), match.vertexIndex() );
1034  matchMap.insert( QStringLiteral( "distance" ), match.distance() );
1035 
1036  matchList.append( matchMap );
1037  }
1038 
1039  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "snapping_results" ), matchList ) );
1040 
1041  return scope;
1042 }
1043 
1045 {
1046  if ( !symbolScope )
1047  return nullptr;
1048 
1049  symbolScope->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_SYMBOL_COLOR, symbol ? symbol->color() : QColor(), true ) );
1050 
1051  double angle = 0.0;
1052  const QgsMarkerSymbol *markerSymbol = dynamic_cast< const QgsMarkerSymbol * >( symbol );
1053  if ( markerSymbol )
1054  {
1055  angle = markerSymbol->angle();
1056  }
1058 
1059  return symbolScope;
1060 }
1061 
1063 {
1064  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope( QObject::tr( "Layout" ) ) );
1065  if ( !layout )
1066  return scope.release();
1067 
1068  //add variables defined in layout properties
1069  QStringList variableNames = layout->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1070  QStringList variableValues = layout->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1071 
1072  int varIndex = 0;
1073  Q_FOREACH ( const QString &variableName, variableNames )
1074  {
1075  if ( varIndex >= variableValues.length() )
1076  {
1077  break;
1078  }
1079 
1080  QVariant varValue = variableValues.at( varIndex );
1081  varIndex++;
1082  scope->setVariable( variableName, varValue );
1083  }
1084 
1085  //add known layout context variables
1086  if ( const QgsMasterLayoutInterface *l = dynamic_cast< const QgsMasterLayoutInterface * >( layout ) )
1087  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_name" ), l->name(), true ) );
1088 
1089  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_numpages" ), layout->pageCollection()->pageCount(), true ) );
1090  if ( layout->pageCollection()->pageCount() > 0 )
1091  {
1092  // just take first page size
1093  QSizeF s = layout->pageCollection()->page( 0 )->sizeWithUnits().toQSizeF();
1094  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), s.height(), true ) );
1095  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), s.width(), true ) );
1096  }
1097  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_dpi" ), layout->renderContext().dpi(), true ) );
1098 
1099  scope->addFunction( QStringLiteral( "item_variables" ), new GetLayoutItemVariables( layout ) );
1100 
1101  if ( layout->reportContext().layer() )
1102  {
1103  scope->setFields( layout->reportContext().layer()->fields() );
1104  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layerid" ), layout->reportContext().layer()->id(), true ) );
1105  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layername" ), layout->reportContext().layer()->name(), true ) );
1106  }
1107 
1108  if ( layout->reportContext().feature().isValid() )
1109  {
1110  QgsFeature atlasFeature = layout->reportContext().feature();
1111  scope->setFeature( atlasFeature );
1112  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( atlasFeature ), true ) );
1113  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), atlasFeature.id(), true ) );
1114  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( atlasFeature.geometry() ), true ) );
1115  }
1116 
1117  return scope.release();
1118 }
1119 
1120 void QgsExpressionContextUtils::setLayoutVariable( QgsLayout *layout, const QString &name, const QVariant &value )
1121 {
1122  if ( !layout )
1123  return;
1124 
1125  //write variable to layout
1126  QStringList variableNames = layout->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1127  QStringList variableValues = layout->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1128 
1129  variableNames << name;
1130  variableValues << value.toString();
1131 
1132  layout->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1133  layout->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1134 }
1135 
1136 void QgsExpressionContextUtils::setLayoutVariables( QgsLayout *layout, const QVariantMap &variables )
1137 {
1138  if ( !layout )
1139  return;
1140 
1141  QStringList variableNames;
1142  QStringList variableValues;
1143 
1144  QVariantMap::const_iterator it = variables.constBegin();
1145  for ( ; it != variables.constEnd(); ++it )
1146  {
1147  variableNames << it.key();
1148  variableValues << it.value().toString();
1149  }
1150 
1151  layout->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1152  layout->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1153 }
1154 
1156 {
1157  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
1158  if ( !atlas )
1159  {
1160  //add some dummy atlas variables. This is done so that as in certain contexts we want to show
1161  //users that these variables are available even if they have no current value
1162  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), QString(), true ) );
1163  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( QgsFeature() ), true ) );
1164  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), 0, true ) );
1165  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( QgsGeometry() ), true ) );
1166  return scope;
1167  }
1168 
1169  //add known atlas variables
1170  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_totalfeatures" ), atlas->count(), true ) );
1171  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featurenumber" ), atlas->currentFeatureNumber() + 1, true ) );
1172  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_filename" ), atlas->currentFilename(), true ) );
1173  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), atlas->nameForPage( atlas->currentFeatureNumber() ), true ) );
1174 
1175  if ( atlas->enabled() && atlas->coverageLayer() )
1176  {
1177  scope->setFields( atlas->coverageLayer()->fields() );
1178  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layerid" ), atlas->coverageLayer()->id(), true ) );
1179  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layername" ), atlas->coverageLayer()->name(), true ) );
1180  }
1181 
1182  if ( atlas->enabled() )
1183  {
1184  QgsFeature atlasFeature = atlas->layout()->reportContext().feature();
1185  scope->setFeature( atlasFeature );
1186  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( atlasFeature ), true ) );
1187  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), atlasFeature.id(), true ) );
1188  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( atlasFeature.geometry() ), true ) );
1189  }
1190 
1191  return scope;
1192 }
1193 
1195 {
1196  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layout Item" ) );
1197  if ( !item )
1198  return scope;
1199 
1200  //add variables defined in layout item properties
1201  const QStringList variableNames = item->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1202  const QStringList variableValues = item->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1203 
1204  int varIndex = 0;
1205  for ( const QString &variableName : variableNames )
1206  {
1207  if ( varIndex >= variableValues.length() )
1208  {
1209  break;
1210  }
1211 
1212  QVariant varValue = variableValues.at( varIndex );
1213  varIndex++;
1214  scope->setVariable( variableName, varValue );
1215  }
1216 
1217  //add known layout item context variables
1218  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "item_id" ), item->id(), true ) );
1219  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "item_uuid" ), item->uuid(), true ) );
1220  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_page" ), item->page() + 1, true ) );
1221 
1222  if ( item->layout() )
1223  {
1224  const QgsLayoutItemPage *page = item->layout()->pageCollection()->page( item->page() );
1225  if ( page )
1226  {
1227  const QSizeF s = page->sizeWithUnits().toQSizeF();
1228  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), s.height(), true ) );
1229  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), s.width(), true ) );
1230  }
1231  else
1232  {
1233  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pageheight" ), QVariant(), true ) );
1234  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layout_pagewidth" ), QVariant(), true ) );
1235  }
1236  }
1237 
1238  return scope;
1239 }
1240 
1241 void QgsExpressionContextUtils::setLayoutItemVariable( QgsLayoutItem *item, const QString &name, const QVariant &value )
1242 {
1243  if ( !item )
1244  return;
1245 
1246  //write variable to layout item
1247  QStringList variableNames = item->customProperty( QStringLiteral( "variableNames" ) ).toStringList();
1248  QStringList variableValues = item->customProperty( QStringLiteral( "variableValues" ) ).toStringList();
1249 
1250  variableNames << name;
1251  variableValues << value.toString();
1252 
1253  item->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1254  item->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1255 }
1256 
1257 void QgsExpressionContextUtils::setLayoutItemVariables( QgsLayoutItem *item, const QVariantMap &variables )
1258 {
1259  if ( !item )
1260  return;
1261 
1262  QStringList variableNames;
1263  QStringList variableValues;
1264 
1265  QVariantMap::const_iterator it = variables.constBegin();
1266  for ( ; it != variables.constEnd(); ++it )
1267  {
1268  variableNames << it.key();
1269  variableValues << it.value().toString();
1270  }
1271 
1272  item->setCustomProperty( QStringLiteral( "variableNames" ), variableNames );
1273  item->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
1274 }
1275 
1277 {
1279  scope->setFeature( feature );
1280  scope->setFields( fields );
1281  return QgsExpressionContext() << scope;
1282 }
1283 
1285 {
1286  // set aside for future use
1287  Q_UNUSED( context );
1288 
1289  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope( QObject::tr( "Algorithm" ) ) );
1290  scope->addFunction( QStringLiteral( "parameter" ), new GetProcessingParameterValue( parameters ) );
1291 
1292  if ( !algorithm )
1293  return scope.release();
1294 
1295  //add standard algorithm variables
1296  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "algorithm_id" ), algorithm->id(), true ) );
1297 
1298  return scope.release();
1299 }
1300 
1302 {
1303  std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope() );
1304  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "notification_message" ), message, true ) );
1305  return scope.release();
1306 }
1307 
1309 {
1310  QgsExpression::registerFunction( new GetNamedProjectColor( nullptr ) );
1311  QgsExpression::registerFunction( new GetLayoutItemVariables( nullptr ) );
1312  QgsExpression::registerFunction( new GetLayerVisibility( QList<QgsMapLayer *>() ) );
1313  QgsExpression::registerFunction( new GetProcessingParameterValue( QVariantMap() ) );
1314  QgsExpression::registerFunction( new GetCurrentFormFieldValue( ) );
1315 }
1316 
1318 {
1319  Q_UNUSED( node )
1320  return mUsesGeometry;
1321 }
1322 
1324 {
1325  Q_UNUSED( node )
1326  return mReferencedColumns;
1327 }
1328 
1330 {
1331  return allParamsStatic( node, parent, context );
1332 }
1333 
1334 //
1335 // GetLayerVisibility
1336 //
1337 
1338 QgsExpressionContextUtils::GetLayerVisibility::GetLayerVisibility( const QList<QgsMapLayer *> &layers )
1339  : QgsScopedExpressionFunction( QStringLiteral( "is_layer_visible" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "General" ) )
1340  , mLayers( _qgis_listRawToQPointer( layers ) )
1341 {}
1342 
1343 QVariant QgsExpressionContextUtils::GetLayerVisibility::func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
1344 {
1345  if ( mLayers.isEmpty() )
1346  {
1347  return false;
1348  }
1349 
1350  QgsMapLayer *layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), parent );
1351  if ( layer )
1352  {
1353  return mLayers.contains( layer );
1354  }
1355  else
1356  {
1357  return false;
1358  }
1359 }
1360 
1361 QgsScopedExpressionFunction *QgsExpressionContextUtils::GetLayerVisibility::clone() const
1362 {
1363  return new GetLayerVisibility( _qgis_listQPointerToRaw( mLayers ) );
1364 }
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
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:64
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:64
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
bool isHighlightedFunction(const QString &name) const
Returns true if the specified function name is intended to be highlighted to the user.
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:64
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:61
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:106
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:55
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:1548
static const int QGIS_VERSION_INT
Version number used for comparing versions using the "Check QGIS Version" function.
Definition: qgis.h:66
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.
void setHighlightedFunctions(const QStringList &names)
Sets the list of function names intended to be highlighted to the user.
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:102
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:459
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:576
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:68
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:425
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:68
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:67
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:445
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:617
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:606
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:1188
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.