QGIS API Documentation  3.12.1-București (121cc00ff0)
qgsexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.cpp
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk 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 "qgsexpression.h"
17 #include "qgsexpressionfunction.h"
18 #include "qgsexpressionnodeimpl.h"
19 #include "qgsfeaturerequest.h"
20 #include "qgscolorramp.h"
21 #include "qgslogger.h"
22 #include "qgsexpressioncontext.h"
23 #include "qgsgeometry.h"
24 #include "qgsproject.h"
26 #include "qgsexpression_p.h"
27 
28 // from parser
29 extern QgsExpressionNode *parseExpression( const QString &str, QString &parserErrorMsg, QList<QgsExpression::ParserError> &parserErrors );
30 
31 Q_GLOBAL_STATIC( HelpTextHash, sFunctionHelpTexts )
32 Q_GLOBAL_STATIC( QgsStringMap, sVariableHelpTexts )
33 Q_GLOBAL_STATIC( QgsStringMap, sGroups )
34 
35 HelpTextHash &functionHelpTexts()
36 {
37  return *sFunctionHelpTexts();
38 }
39 
40 bool QgsExpression::checkExpression( const QString &text, const QgsExpressionContext *context, QString &errorMessage )
41 {
42  QgsExpression exp( text );
43  exp.prepare( context );
44  errorMessage = exp.parserErrorString();
45  return !exp.hasParserError();
46 }
47 
49 {
50  detach();
51  d->mRootNode = ::parseExpression( expression, d->mParserErrorString, d->mParserErrors );
52  d->mEvalErrorString = QString();
53  d->mExp = expression;
54  d->mIsPrepared = false;
55 }
56 
58 {
59  if ( !d->mExp.isNull() )
60  return d->mExp;
61  else
62  return dump();
63 }
64 
65 QString QgsExpression::quotedColumnRef( QString name )
66 {
67  return QStringLiteral( "\"%1\"" ).arg( name.replace( '\"', QLatin1String( "\"\"" ) ) );
68 }
69 
70 QString QgsExpression::quotedString( QString text )
71 {
72  text.replace( '\'', QLatin1String( "''" ) );
73  text.replace( '\\', QLatin1String( "\\\\" ) );
74  text.replace( '\n', QLatin1String( "\\n" ) );
75  text.replace( '\t', QLatin1String( "\\t" ) );
76  return QStringLiteral( "'%1'" ).arg( text );
77 }
78 
79 QString QgsExpression::quotedValue( const QVariant &value )
80 {
81  return quotedValue( value, value.type() );
82 }
83 
84 QString QgsExpression::quotedValue( const QVariant &value, QVariant::Type type )
85 {
86  if ( value.isNull() )
87  return QStringLiteral( "NULL" );
88 
89  switch ( type )
90  {
91  case QVariant::Int:
92  case QVariant::LongLong:
93  case QVariant::Double:
94  return value.toString();
95 
96  case QVariant::Bool:
97  return value.toBool() ? QStringLiteral( "TRUE" ) : QStringLiteral( "FALSE" );
98 
99  case QVariant::List:
100  {
101  QStringList quotedValues;
102  const QVariantList values = value.toList();
103  quotedValues.reserve( values.count() );
104  for ( const QVariant &v : values )
105  {
106  quotedValues += quotedValue( v );
107  }
108  return QStringLiteral( "array( %1 )" ).arg( quotedValues.join( QStringLiteral( ", " ) ) );
109  }
110 
111  default:
112  case QVariant::String:
113  return quotedString( value.toString() );
114  }
115 
116 }
117 
118 bool QgsExpression::isFunctionName( const QString &name )
119 {
120  return functionIndex( name ) != -1;
121 }
122 
123 int QgsExpression::functionIndex( const QString &name )
124 {
125  int count = functionCount();
126  for ( int i = 0; i < count; i++ )
127  {
128  if ( QString::compare( name, QgsExpression::Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
129  return i;
130  const QStringList aliases = QgsExpression::Functions()[i]->aliases();
131  for ( const QString &alias : aliases )
132  {
133  if ( QString::compare( name, alias, Qt::CaseInsensitive ) == 0 )
134  return i;
135  }
136  }
137  return -1;
138 }
139 
141 {
142  return Functions().size();
143 }
144 
145 
146 QgsExpression::QgsExpression( const QString &expr )
147  : d( new QgsExpressionPrivate )
148 {
149  d->mRootNode = ::parseExpression( expr, d->mParserErrorString, d->mParserErrors );
150  d->mExp = expr;
151  Q_ASSERT( !d->mParserErrorString.isNull() || d->mRootNode );
152 }
153 
155  : d( other.d )
156 {
157  d->ref.ref();
158 }
159 
161 {
162  if ( !d->ref.deref() )
163  {
164  delete d;
165  }
166 
167  d = other.d;
168  d->ref.ref();
169  return *this;
170 }
171 
172 QgsExpression::operator QString() const
173 {
174  return d->mExp;
175 }
176 
178  : d( new QgsExpressionPrivate )
179 {
180 }
181 
183 {
184  Q_ASSERT( d );
185  if ( !d->ref.deref() )
186  delete d;
187 }
188 
189 bool QgsExpression::operator==( const QgsExpression &other ) const
190 {
191  return ( d == other.d || d->mExp == other.d->mExp );
192 }
193 
195 {
196  return d->mRootNode;
197 }
198 
200 {
201  return d->mParserErrors.count() > 0;
202 }
203 
205 {
206  return d->mParserErrorString;
207 }
208 
209 QList<QgsExpression::ParserError> QgsExpression::parserErrors() const
210 {
211  return d->mParserErrors;
212 }
213 
214 QSet<QString> QgsExpression::referencedColumns() const
215 {
216  if ( !d->mRootNode )
217  return QSet<QString>();
218 
219  return d->mRootNode->referencedColumns();
220 }
221 
223 {
224  if ( !d->mRootNode )
225  return QSet<QString>();
226 
227  return d->mRootNode->referencedVariables();
228 }
229 
231 {
232  if ( !d->mRootNode )
233  return QSet<QString>();
234 
235  return d->mRootNode->referencedFunctions();
236 }
237 
238 QSet<int> QgsExpression::referencedAttributeIndexes( const QgsFields &fields ) const
239 {
240  if ( !d->mRootNode )
241  return QSet<int>();
242 
243  const QSet<QString> referencedFields = d->mRootNode->referencedColumns();
244  QSet<int> referencedIndexes;
245 
246  for ( const QString &fieldName : referencedFields )
247  {
248  if ( fieldName == QgsFeatureRequest::ALL_ATTRIBUTES )
249  {
250  referencedIndexes = fields.allAttributesList().toSet();
251  break;
252  }
253  const int idx = fields.lookupField( fieldName );
254  if ( idx >= 0 )
255  {
256  referencedIndexes << idx;
257  }
258  }
259 
260  return referencedIndexes;
261 }
262 
264 {
265  if ( !d->mRootNode )
266  return false;
267  return d->mRootNode->needsGeometry();
268 }
269 
270 void QgsExpression::initGeomCalculator( const QgsExpressionContext *context )
271 {
272  // Set the geometry calculator from the context if it has not been set by setGeomCalculator()
273  if ( context && ! d->mCalc )
274  {
275  QString ellipsoid = context->variable( QStringLiteral( "project_ellipsoid" ) ).toString();
276  QgsCoordinateReferenceSystem crs = context->variable( QStringLiteral( "_layer_crs" ) ).value<QgsCoordinateReferenceSystem>();
277  QgsCoordinateTransformContext tContext = context->variable( QStringLiteral( "_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
278  if ( crs.isValid() )
279  {
280  d->mCalc = std::shared_ptr<QgsDistanceArea>( new QgsDistanceArea() );
281  d->mCalc->setEllipsoid( ellipsoid.isEmpty() ? geoNone() : ellipsoid );
282  d->mCalc->setSourceCrs( crs, tContext );
283  }
284  }
285 
286  // Set the distance units from the context if it has not been set by setDistanceUnits()
287  if ( context && distanceUnits() == QgsUnitTypes::DistanceUnknownUnit )
288  {
289  QString distanceUnitsStr = context->variable( QStringLiteral( "project_distance_units" ) ).toString();
290  if ( ! distanceUnitsStr.isEmpty() )
292  }
293 
294  // Set the area units from the context if it has not been set by setAreaUnits()
295  if ( context && areaUnits() == QgsUnitTypes::AreaUnknownUnit )
296  {
297  QString areaUnitsStr = context->variable( QStringLiteral( "project_area_units" ) ).toString();
298  if ( ! areaUnitsStr.isEmpty() )
299  setAreaUnits( QgsUnitTypes::stringToAreaUnit( areaUnitsStr ) );
300  }
301 }
302 
303 void QgsExpression::detach()
304 {
305  Q_ASSERT( d );
306 
307  if ( d->ref > 1 )
308  {
309  ( void )d->ref.deref();
310 
311  d = new QgsExpressionPrivate( *d );
312  }
313 }
314 
316 {
317  detach();
318  if ( calc )
319  d->mCalc = std::shared_ptr<QgsDistanceArea>( new QgsDistanceArea( *calc ) );
320  else
321  d->mCalc.reset();
322 }
323 
325 {
326  detach();
327  d->mEvalErrorString = QString();
328  if ( !d->mRootNode )
329  {
330  //re-parse expression. Creation of QgsExpressionContexts may have added extra
331  //known functions since this expression was created, so we have another try
332  //at re-parsing it now that the context must have been created
333  d->mRootNode = ::parseExpression( d->mExp, d->mParserErrorString, d->mParserErrors );
334  }
335 
336  if ( !d->mRootNode )
337  {
338  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
339  return false;
340  }
341 
342  initGeomCalculator( context );
343  d->mIsPrepared = true;
344  return d->mRootNode->prepare( this, context );
345 }
346 
348 {
349  d->mEvalErrorString = QString();
350  if ( !d->mRootNode )
351  {
352  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
353  return QVariant();
354  }
355 
356  return d->mRootNode->eval( this, static_cast<const QgsExpressionContext *>( nullptr ) );
357 }
358 
360 {
361  d->mEvalErrorString = QString();
362  if ( !d->mRootNode )
363  {
364  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
365  return QVariant();
366  }
367 
368  if ( ! d->mIsPrepared )
369  {
370  prepare( context );
371  }
372  return d->mRootNode->eval( this, context );
373 }
374 
376 {
377  return !d->mEvalErrorString.isNull();
378 }
379 
381 {
382  return d->mEvalErrorString;
383 }
384 
385 void QgsExpression::setEvalErrorString( const QString &str )
386 {
387  d->mEvalErrorString = str;
388 }
389 
390 QString QgsExpression::dump() const
391 {
392  if ( !d->mRootNode )
393  return QString();
394 
395  return d->mRootNode->dump();
396 }
397 
399 {
400  return d->mCalc.get();
401 }
402 
404 {
405  return d->mDistanceUnit;
406 }
407 
409 {
410  d->mDistanceUnit = unit;
411 }
412 
414 {
415  return d->mAreaUnit;
416 }
417 
419 {
420  d->mAreaUnit = unit;
421 }
422 
423 QString QgsExpression::replaceExpressionText( const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea )
424 {
425  QString expr_action;
426 
427  int index = 0;
428  while ( index < action.size() )
429  {
430  static const QRegularExpression sRegEx{ QStringLiteral( "\\[%(.*?)%\\]" ), QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption };
431 
432  const QRegularExpressionMatch match = sRegEx.match( action, index );
433  if ( !match.hasMatch() )
434  break;
435 
436  const int pos = action.indexOf( sRegEx, index );
437  const int start = index;
438  index = pos + match.capturedLength( 0 );
439  const QString toReplace = match.captured( 1 ).trimmed();
440  QgsDebugMsgLevel( "Found expression: " + toReplace, 3 );
441 
442  QgsExpression exp( toReplace );
443  if ( exp.hasParserError() )
444  {
445  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
446  expr_action += action.midRef( start, index - start );
447  continue;
448  }
449 
450  if ( distanceArea )
451  {
452  //if QgsDistanceArea specified for area/distance conversion, use it
453  exp.setGeomCalculator( distanceArea );
454  }
455 
456  QVariant result = exp.evaluate( context );
457 
458  if ( exp.hasEvalError() )
459  {
460  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
461  expr_action += action.midRef( start, index - start );
462  continue;
463  }
464 
465  QgsDebugMsgLevel( "Expression result is: " + result.toString(), 3 );
466  expr_action += action.mid( start, pos - start ) + result.toString();
467  }
468 
469  expr_action += action.midRef( index );
470 
471  return expr_action;
472 }
473 
474 QSet<QString> QgsExpression::referencedVariables( const QString &text )
475 {
476  QSet<QString> variables;
477  int index = 0;
478  while ( index < text.size() )
479  {
480  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
481 
482  int pos = rx.indexIn( text, index );
483  if ( pos < 0 )
484  break;
485 
486  index = pos + rx.matchedLength();
487  QString to_replace = rx.cap( 1 ).trimmed();
488 
489  QgsExpression exp( to_replace );
490  variables.unite( exp.referencedVariables() );
491  }
492 
493  return variables;
494 }
495 
496 double QgsExpression::evaluateToDouble( const QString &text, const double fallbackValue )
497 {
498  bool ok;
499  //first test if text is directly convertible to double
500  // use system locale: e.g. in German locale, user is presented with numbers "1,23" instead of "1.23" in C locale
501  // so we also want to allow user to rewrite it to "5,23" and it is still accepted
502  double convertedValue = QLocale().toDouble( text, &ok );
503  if ( ok )
504  {
505  return convertedValue;
506  }
507 
508  //otherwise try to evaluate as expression
509  QgsExpression expr( text );
510 
511  QgsExpressionContext context;
514 
515  QVariant result = expr.evaluate( &context );
516  convertedValue = result.toDouble( &ok );
517  if ( expr.hasEvalError() || !ok )
518  {
519  return fallbackValue;
520  }
521  return convertedValue;
522 }
523 
524 QString QgsExpression::helpText( QString name )
525 {
526  QgsExpression::initFunctionHelp();
527 
528  if ( !sFunctionHelpTexts()->contains( name ) )
529  return tr( "function help for %1 missing" ).arg( name );
530 
531  const Help &f = ( *sFunctionHelpTexts() )[ name ];
532 
533  name = f.mName;
534  if ( f.mType == tr( "group" ) )
535  {
536  name = group( name );
537  name = name.toLower();
538  }
539 
540  name = name.toHtmlEscaped();
541 
542  QString helpContents( QStringLiteral( "<h3>%1</h3>\n<div class=\"description\"><p>%2</p></div>" )
543  .arg( tr( "%1 %2" ).arg( f.mType, name ),
544  f.mDescription ) );
545 
546  for ( const HelpVariant &v : qgis::as_const( f.mVariants ) )
547  {
548  if ( f.mVariants.size() > 1 )
549  {
550  helpContents += QStringLiteral( "<h3>%1</h3>\n<div class=\"description\">%2</p></div>" ).arg( v.mName, v.mDescription );
551  }
552 
553  if ( f.mType != tr( "group" ) && f.mType != tr( "expression" ) )
554  helpContents += QStringLiteral( "<h4>%1</h4>\n<div class=\"syntax\">\n" ).arg( tr( "Syntax" ) );
555 
556  if ( f.mType == tr( "operator" ) )
557  {
558  if ( v.mArguments.size() == 1 )
559  {
560  helpContents += QStringLiteral( "<code><span class=\"functionname\">%1</span> <span class=\"argument\">%2</span></code>" )
561  .arg( name, v.mArguments[0].mArg );
562  }
563  else if ( v.mArguments.size() == 2 )
564  {
565  helpContents += QStringLiteral( "<code><span class=\"argument\">%1</span> <span class=\"functionname\">%2</span> <span class=\"argument\">%3</span></code>" )
566  .arg( v.mArguments[0].mArg, name, v.mArguments[1].mArg );
567  }
568  }
569  else if ( f.mType != tr( "group" ) && f.mType != tr( "expression" ) )
570  {
571  helpContents += QStringLiteral( "<code><span class=\"functionname\">%1</span>" ).arg( name );
572 
573  bool hasOptionalArgs = false;
574 
575  if ( f.mType == tr( "function" ) && ( f.mName[0] != '$' || !v.mArguments.isEmpty() || v.mVariableLenArguments ) )
576  {
577  helpContents += '(';
578 
579  QString delim;
580  for ( const HelpArg &a : qgis::as_const( v.mArguments ) )
581  {
582  if ( !a.mDescOnly )
583  {
584  if ( a.mOptional )
585  {
586  hasOptionalArgs = true;
587  helpContents += QStringLiteral( "[" );
588  }
589 
590  helpContents += delim;
591  helpContents += QStringLiteral( "<span class=\"argument\">%2%3</span>" ).arg(
592  a.mArg,
593  a.mDefaultVal.isEmpty() ? QString() : '=' + a.mDefaultVal
594  );
595 
596  if ( a.mOptional )
597  helpContents += QStringLiteral( "]" );
598  }
599  delim = QStringLiteral( "," );
600  }
601 
602  if ( v.mVariableLenArguments )
603  {
604  helpContents += QChar( 0x2026 );
605  }
606 
607  helpContents += ')';
608  }
609 
610  helpContents += QLatin1String( "</code>" );
611 
612  if ( hasOptionalArgs )
613  {
614  helpContents += QLatin1String( "<br/><br/>" ) + tr( "[ ] marks optional components" );
615  }
616  }
617 
618  if ( !v.mArguments.isEmpty() )
619  {
620  helpContents += QStringLiteral( "<h4>%1</h4>\n<div class=\"arguments\">\n<table>" ).arg( tr( "Arguments" ) );
621 
622  for ( const HelpArg &a : qgis::as_const( v.mArguments ) )
623  {
624  if ( a.mSyntaxOnly )
625  continue;
626 
627  helpContents += QStringLiteral( "<tr><td class=\"argument\">%1</td><td>%2</td></tr>" ).arg( a.mArg, a.mDescription );
628  }
629 
630  helpContents += QLatin1String( "</table>\n</div>\n" );
631  }
632 
633  if ( !v.mExamples.isEmpty() )
634  {
635  helpContents += QStringLiteral( "<h4>%1</h4>\n<div class=\"examples\">\n<ul>\n" ).arg( tr( "Examples" ) );
636 
637  for ( const HelpExample &e : qgis::as_const( v.mExamples ) )
638  {
639  helpContents += "<li><code>" + e.mExpression + "</code> &rarr; <code>" + e.mReturns + "</code>";
640 
641  if ( !e.mNote.isEmpty() )
642  helpContents += QStringLiteral( " (%1)" ).arg( e.mNote );
643 
644  helpContents += QLatin1String( "</li>\n" );
645  }
646 
647  helpContents += QLatin1String( "</ul>\n</div>\n" );
648  }
649 
650  if ( !v.mNotes.isEmpty() )
651  {
652  helpContents += QStringLiteral( "<h4>%1</h4>\n<div class=\"notes\"><p>%2</p></div>\n" ).arg( tr( "Notes" ), v.mNotes );
653  }
654  }
655 
656  return helpContents;
657 }
658 
659 QStringList QgsExpression::tags( const QString &name )
660 {
661  QStringList tags = QStringList();
662 
663  QgsExpression::initFunctionHelp();
664 
665  if ( sFunctionHelpTexts()->contains( name ) )
666  {
667  const Help &f = ( *sFunctionHelpTexts() )[ name ];
668 
669  for ( const HelpVariant &v : qgis::as_const( f.mVariants ) )
670  {
671  tags << v.mTags;
672  }
673  }
674 
675  return tags;
676 }
677 
678 void QgsExpression::initVariableHelp()
679 {
680  if ( !sVariableHelpTexts()->isEmpty() )
681  return;
682 
683  //global variables
684  sVariableHelpTexts()->insert( QStringLiteral( "qgis_version" ), QCoreApplication::translate( "variable_help", "Current QGIS version string." ) );
685  sVariableHelpTexts()->insert( QStringLiteral( "qgis_version_no" ), QCoreApplication::translate( "variable_help", "Current QGIS version number." ) );
686  sVariableHelpTexts()->insert( QStringLiteral( "qgis_release_name" ), QCoreApplication::translate( "variable_help", "Current QGIS release name." ) );
687  sVariableHelpTexts()->insert( QStringLiteral( "qgis_short_version" ), QCoreApplication::translate( "variable_help", "Short QGIS version string." ) );
688  sVariableHelpTexts()->insert( QStringLiteral( "qgis_os_name" ), QCoreApplication::translate( "variable_help", "Operating system name, e.g., 'windows', 'linux' or 'osx'." ) );
689  sVariableHelpTexts()->insert( QStringLiteral( "qgis_platform" ), QCoreApplication::translate( "variable_help", "QGIS platform, e.g., 'desktop' or 'server'." ) );
690  sVariableHelpTexts()->insert( QStringLiteral( "qgis_locale" ), QCoreApplication::translate( "variable_help", "Two letter identifier for current QGIS locale." ) );
691  sVariableHelpTexts()->insert( QStringLiteral( "user_account_name" ), QCoreApplication::translate( "variable_help", "Current user's operating system account name." ) );
692  sVariableHelpTexts()->insert( QStringLiteral( "user_full_name" ), QCoreApplication::translate( "variable_help", "Current user's operating system user name (if available)." ) );
693 
694  //project variables
695  sVariableHelpTexts()->insert( QStringLiteral( "project_title" ), QCoreApplication::translate( "variable_help", "Title of current project." ) );
696  sVariableHelpTexts()->insert( QStringLiteral( "project_path" ), QCoreApplication::translate( "variable_help", "Full path (including file name) of current project." ) );
697  sVariableHelpTexts()->insert( QStringLiteral( "project_folder" ), QCoreApplication::translate( "variable_help", "Folder for current project." ) );
698  sVariableHelpTexts()->insert( QStringLiteral( "project_filename" ), QCoreApplication::translate( "variable_help", "Filename of current project." ) );
699  sVariableHelpTexts()->insert( QStringLiteral( "project_basename" ), QCoreApplication::translate( "variable_help", "Base name of current project's filename (without path and extension)." ) );
700  sVariableHelpTexts()->insert( QStringLiteral( "project_home" ), QCoreApplication::translate( "variable_help", "Home path of current project." ) );
701  sVariableHelpTexts()->insert( QStringLiteral( "project_crs" ), QCoreApplication::translate( "variable_help", "Coordinate reference system of project (e.g., 'EPSG:4326')." ) );
702  sVariableHelpTexts()->insert( QStringLiteral( "project_crs_definition" ), QCoreApplication::translate( "variable_help", "Coordinate reference system of project (full definition)." ) );
703  sVariableHelpTexts()->insert( QStringLiteral( "project_author" ), QCoreApplication::translate( "variable_help", "Project author, taken from project metadata." ) );
704  sVariableHelpTexts()->insert( QStringLiteral( "project_abstract" ), QCoreApplication::translate( "variable_help", "Project abstract, taken from project metadata." ) );
705  sVariableHelpTexts()->insert( QStringLiteral( "project_creation_date" ), QCoreApplication::translate( "variable_help", "Project creation date, taken from project metadata." ) );
706  sVariableHelpTexts()->insert( QStringLiteral( "project_identifier" ), QCoreApplication::translate( "variable_help", "Project identifier, taken from project metadata." ) );
707  sVariableHelpTexts()->insert( QStringLiteral( "project_keywords" ), QCoreApplication::translate( "variable_help", "Project keywords, taken from project metadata." ) );
708  sVariableHelpTexts()->insert( QStringLiteral( "project_area_units" ), QCoreApplication::translate( "variable_help", "Area unit for current project, used when calculating areas of geometries." ) );
709  sVariableHelpTexts()->insert( QStringLiteral( "project_distance_units" ), QCoreApplication::translate( "variable_help", "Distance unit for current project, used when calculating lengths of geometries." ) );
710  sVariableHelpTexts()->insert( QStringLiteral( "project_ellipsoid" ), QCoreApplication::translate( "variable_help", "Name of ellipsoid of current project, used when calculating geodetic areas and lengths of geometries." ) );
711 
712  //layer variables
713  sVariableHelpTexts()->insert( QStringLiteral( "layer_name" ), QCoreApplication::translate( "variable_help", "Name of current layer." ) );
714  sVariableHelpTexts()->insert( QStringLiteral( "layer_id" ), QCoreApplication::translate( "variable_help", "ID of current layer." ) );
715  sVariableHelpTexts()->insert( QStringLiteral( "layer" ), QCoreApplication::translate( "variable_help", "The current layer." ) );
716 
717  //composition variables
718  sVariableHelpTexts()->insert( QStringLiteral( "layout_name" ), QCoreApplication::translate( "variable_help", "Name of composition." ) );
719  sVariableHelpTexts()->insert( QStringLiteral( "layout_numpages" ), QCoreApplication::translate( "variable_help", "Number of pages in composition." ) );
720  sVariableHelpTexts()->insert( QStringLiteral( "layout_page" ), QCoreApplication::translate( "variable_help", "Current page number in composition." ) );
721  sVariableHelpTexts()->insert( QStringLiteral( "layout_pageheight" ), QCoreApplication::translate( "variable_help", "Composition page height in mm." ) );
722  sVariableHelpTexts()->insert( QStringLiteral( "layout_pagewidth" ), QCoreApplication::translate( "variable_help", "Composition page width in mm." ) );
723  sVariableHelpTexts()->insert( QStringLiteral( "layout_dpi" ), QCoreApplication::translate( "variable_help", "Composition resolution (DPI)." ) );
724 
725  //atlas variables
726  sVariableHelpTexts()->insert( QStringLiteral( "atlas_layerid" ), QCoreApplication::translate( "variable_help", "Current atlas coverage layer ID." ) );
727  sVariableHelpTexts()->insert( QStringLiteral( "atlas_layername" ), QCoreApplication::translate( "variable_help", "Current atlas coverage layer name." ) );
728  sVariableHelpTexts()->insert( QStringLiteral( "atlas_totalfeatures" ), QCoreApplication::translate( "variable_help", "Total number of features in atlas." ) );
729  sVariableHelpTexts()->insert( QStringLiteral( "atlas_featurenumber" ), QCoreApplication::translate( "variable_help", "Current atlas feature number." ) );
730  sVariableHelpTexts()->insert( QStringLiteral( "atlas_filename" ), QCoreApplication::translate( "variable_help", "Current atlas file name." ) );
731  sVariableHelpTexts()->insert( QStringLiteral( "atlas_pagename" ), QCoreApplication::translate( "variable_help", "Current atlas page name." ) );
732  sVariableHelpTexts()->insert( QStringLiteral( "atlas_feature" ), QCoreApplication::translate( "variable_help", "Current atlas feature (as feature object)." ) );
733  sVariableHelpTexts()->insert( QStringLiteral( "atlas_featureid" ), QCoreApplication::translate( "variable_help", "Current atlas feature ID." ) );
734  sVariableHelpTexts()->insert( QStringLiteral( "atlas_geometry" ), QCoreApplication::translate( "variable_help", "Current atlas feature geometry." ) );
735 
736  //layout item variables
737  sVariableHelpTexts()->insert( QStringLiteral( "item_id" ), QCoreApplication::translate( "variable_help", "Layout item user ID (not necessarily unique)." ) );
738  sVariableHelpTexts()->insert( QStringLiteral( "item_uuid" ), QCoreApplication::translate( "variable_help", "layout item unique ID." ) );
739  sVariableHelpTexts()->insert( QStringLiteral( "item_left" ), QCoreApplication::translate( "variable_help", "Left position of layout item (in mm)." ) );
740  sVariableHelpTexts()->insert( QStringLiteral( "item_top" ), QCoreApplication::translate( "variable_help", "Top position of layout item (in mm)." ) );
741  sVariableHelpTexts()->insert( QStringLiteral( "item_width" ), QCoreApplication::translate( "variable_help", "Width of layout item (in mm)." ) );
742  sVariableHelpTexts()->insert( QStringLiteral( "item_height" ), QCoreApplication::translate( "variable_help", "Height of layout item (in mm)." ) );
743 
744  //map settings item variables
745  sVariableHelpTexts()->insert( QStringLiteral( "map_id" ), QCoreApplication::translate( "variable_help", "ID of current map destination. This will be 'canvas' for canvas renders, and the item ID for layout map renders." ) );
746  sVariableHelpTexts()->insert( QStringLiteral( "map_rotation" ), QCoreApplication::translate( "variable_help", "Current rotation of map." ) );
747  sVariableHelpTexts()->insert( QStringLiteral( "map_scale" ), QCoreApplication::translate( "variable_help", "Current scale of map." ) );
748  sVariableHelpTexts()->insert( QStringLiteral( "map_extent" ), QCoreApplication::translate( "variable_help", "Geometry representing the current extent of the map." ) );
749  sVariableHelpTexts()->insert( QStringLiteral( "map_extent_center" ), QCoreApplication::translate( "variable_help", "Center of map." ) );
750  sVariableHelpTexts()->insert( QStringLiteral( "map_extent_width" ), QCoreApplication::translate( "variable_help", "Width of map." ) );
751  sVariableHelpTexts()->insert( QStringLiteral( "map_extent_height" ), QCoreApplication::translate( "variable_help", "Height of map." ) );
752  sVariableHelpTexts()->insert( QStringLiteral( "map_crs" ), QCoreApplication::translate( "variable_help", "Coordinate reference system of map (e.g., 'EPSG:4326')." ) );
753  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_description" ), QCoreApplication::translate( "variable_help", "Name of the coordinate reference system of the map." ) );
754  sVariableHelpTexts()->insert( QStringLiteral( "map_units" ), QCoreApplication::translate( "variable_help", "Units for map measurements." ) );
755  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_definition" ), QCoreApplication::translate( "variable_help", "Coordinate reference system of map (full definition)." ) );
756  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_acronym" ), QCoreApplication::translate( "variable_help", "Acronym of the coordinate reference system of the map." ) );
757  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_ellipsoid" ), QCoreApplication::translate( "variable_help", "Acronym of the ellipsoid of the coordinate reference system of the map." ) );
758  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_proj4" ), QCoreApplication::translate( "variable_help", "Proj4 definition of the coordinate reference system." ) );
759  sVariableHelpTexts()->insert( QStringLiteral( "map_crs_wkt" ), QCoreApplication::translate( "variable_help", "WKT definition of the coordinate reference system." ) );
760  sVariableHelpTexts()->insert( QStringLiteral( "map_layer_ids" ), QCoreApplication::translate( "variable_help", "List of map layer IDs visible in the map." ) );
761  sVariableHelpTexts()->insert( QStringLiteral( "map_layers" ), QCoreApplication::translate( "variable_help", "List of map layers visible in the map." ) );
762 
763  sVariableHelpTexts()->insert( QStringLiteral( "row_number" ), QCoreApplication::translate( "variable_help", "Stores the number of the current row." ) );
764  sVariableHelpTexts()->insert( QStringLiteral( "grid_number" ), QCoreApplication::translate( "variable_help", "Current grid annotation value." ) );
765  sVariableHelpTexts()->insert( QStringLiteral( "grid_axis" ), QCoreApplication::translate( "variable_help", "Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
766 
767  // map canvas item variables
768  sVariableHelpTexts()->insert( QStringLiteral( "canvas_cursor_point" ), QCoreApplication::translate( "variable_help", "Last cursor position on the canvas in the project's geographical coordinates." ) );
769 
770  // legend canvas item variables
771  sVariableHelpTexts()->insert( QStringLiteral( "legend_title" ), QCoreApplication::translate( "variable_help", "Title of the legend." ) );
772  sVariableHelpTexts()->insert( QStringLiteral( "legend_column_count" ), QCoreApplication::translate( "variable_help", "Number of column in the legend." ) );
773  sVariableHelpTexts()->insert( QStringLiteral( "legend_split_layers" ), QCoreApplication::translate( "variable_help", "Boolean indicating if layers can be split in the legend." ) );
774  sVariableHelpTexts()->insert( QStringLiteral( "legend_wrap_string" ), QCoreApplication::translate( "variable_help", "Characters used to wrap the legend text." ) );
775  sVariableHelpTexts()->insert( QStringLiteral( "legend_filter_by_map" ), QCoreApplication::translate( "variable_help", "Boolean indicating if the content of the legend is filtered by the map." ) );
776  sVariableHelpTexts()->insert( QStringLiteral( "legend_filter_out_atlas" ), QCoreApplication::translate( "variable_help", "Boolean indicating if the Atlas is filtered out of the legend." ) );
777 
778  // scalebar rendering
779  sVariableHelpTexts()->insert( QStringLiteral( "scale_value" ), QCoreApplication::translate( "variable_help", "Current scale bar distance value." ) );
780 
781  // map tool capture variables
782  sVariableHelpTexts()->insert( QStringLiteral( "snapping_results" ), QCoreApplication::translate( "variable_help",
783  "<p>An array with an item for each snapped point.</p>"
784  "<p>Each item is a map with the following keys:</p>"
785  "<dl>"
786  "<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>"
787  "<dt>layer</dt><dd>The layer on which the snapped feature is</dd>"
788  "<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>"
789  "<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>"
790  "<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>"
791  "</dl>" ) );
792 
793 
794  //symbol variables
795  sVariableHelpTexts()->insert( QStringLiteral( "geometry_part_count" ), QCoreApplication::translate( "variable_help", "Number of parts in rendered feature's geometry." ) );
796  sVariableHelpTexts()->insert( QStringLiteral( "geometry_part_num" ), QCoreApplication::translate( "variable_help", "Current geometry part number for feature being rendered." ) );
797  sVariableHelpTexts()->insert( QStringLiteral( "geometry_point_count" ), QCoreApplication::translate( "variable_help", "Number of points in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable." ) );
798  sVariableHelpTexts()->insert( QStringLiteral( "geometry_point_num" ), QCoreApplication::translate( "variable_help", "Current point number in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable." ) );
799 
800  sVariableHelpTexts()->insert( QStringLiteral( "symbol_color" ), QCoreApplication::translate( "symbol_color", "Color of symbol used to render the feature." ) );
801  sVariableHelpTexts()->insert( QStringLiteral( "symbol_angle" ), QCoreApplication::translate( "symbol_angle", "Angle of symbol used to render the feature (valid for marker symbols only)." ) );
802 
803  sVariableHelpTexts()->insert( QStringLiteral( "symbol_label" ), QCoreApplication::translate( "symbol_label", "Label for the symbol (either a user defined label or the default autogenerated label)." ) );
804  sVariableHelpTexts()->insert( QStringLiteral( "symbol_id" ), QCoreApplication::translate( "symbol_id", "Internal ID of the symbol." ) );
805  sVariableHelpTexts()->insert( QStringLiteral( "symbol_count" ), QCoreApplication::translate( "symbol_count", "Total number of features represented by the symbol." ) );
806 
807  //cluster variables
808  sVariableHelpTexts()->insert( QStringLiteral( "cluster_color" ), QCoreApplication::translate( "cluster_color", "Color of symbols within a cluster, or NULL if symbols have mixed colors." ) );
809  sVariableHelpTexts()->insert( QStringLiteral( "cluster_size" ), QCoreApplication::translate( "cluster_size", "Number of symbols contained within a cluster." ) );
810 
811  //processing variables
812  sVariableHelpTexts()->insert( QStringLiteral( "algorithm_id" ), QCoreApplication::translate( "algorithm_id", "Unique ID for algorithm." ) );
813  sVariableHelpTexts()->insert( QStringLiteral( "model_path" ), QCoreApplication::translate( "variable_help", "Full path (including file name) of current model (or project path if model is embedded in a project)." ) );
814  sVariableHelpTexts()->insert( QStringLiteral( "model_folder" ), QCoreApplication::translate( "variable_help", "Folder containing current model (or project folder if model is embedded in a project)." ) );
815  sVariableHelpTexts()->insert( QStringLiteral( "model_name" ), QCoreApplication::translate( "variable_help", "Name of current model." ) );
816  sVariableHelpTexts()->insert( QStringLiteral( "model_group" ), QCoreApplication::translate( "variable_help", "Group for current model." ) );
817  sVariableHelpTexts()->insert( QStringLiteral( "fullextent_minx" ), QCoreApplication::translate( "fullextent_minx", "Minimum x-value from full canvas extent (including all layers)." ) );
818  sVariableHelpTexts()->insert( QStringLiteral( "fullextent_miny" ), QCoreApplication::translate( "fullextent_miny", "Minimum y-value from full canvas extent (including all layers)." ) );
819  sVariableHelpTexts()->insert( QStringLiteral( "fullextent_maxx" ), QCoreApplication::translate( "fullextent_maxx", "Maximum x-value from full canvas extent (including all layers)." ) );
820  sVariableHelpTexts()->insert( QStringLiteral( "fullextent_maxy" ), QCoreApplication::translate( "fullextent_maxy", "Maximum y-value from full canvas extent (including all layers)." ) );
821 
822  //provider notification
823  sVariableHelpTexts()->insert( QStringLiteral( "notification_message" ), QCoreApplication::translate( "notification_message", "Content of the notification message sent by the provider (available only for actions triggered by provider notifications)." ) );
824 
825  //form context variable
826  sVariableHelpTexts()->insert( QStringLiteral( "current_geometry" ), QCoreApplication::translate( "current_geometry", "Represents the geometry of the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );
827  sVariableHelpTexts()->insert( QStringLiteral( "current_feature" ), QCoreApplication::translate( "current_feature", "Represents the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );
828 
829  //form variable
830  sVariableHelpTexts()->insert( QStringLiteral( "form_mode" ), QCoreApplication::translate( "form_mode", "What the form is used for, like AddFeatureMode, SingleEditMode, MultiEditMode, SearchMode, AggregateSearchMode or IdentifyMode as string." ) );
831 }
832 
833 QString QgsExpression::variableHelpText( const QString &variableName )
834 {
835  QgsExpression::initVariableHelp();
836  return sVariableHelpTexts()->value( variableName, QString() );
837 }
838 
839 QString QgsExpression::formatVariableHelp( const QString &description, bool showValue, const QVariant &value )
840 {
841  QString text = !description.isEmpty() ? QStringLiteral( "<p>%1</p>" ).arg( description ) : QString();
842  if ( showValue )
843  {
844  QString valueString;
845  if ( !value.isValid() )
846  {
847  valueString = QCoreApplication::translate( "variable_help", "not set" );
848  }
849  else
850  {
851  valueString = QStringLiteral( "<b>%1</b>" ).arg( formatPreviewString( value ) );
852  }
853  text.append( QCoreApplication::translate( "variable_help", "<p>Current value: %1</p>" ).arg( valueString ) );
854  }
855  return text;
856 }
857 
858 QString QgsExpression::group( const QString &name )
859 {
860  if ( sGroups()->isEmpty() )
861  {
862  sGroups()->insert( QStringLiteral( "Aggregates" ), tr( "Aggregates" ) );
863  sGroups()->insert( QStringLiteral( "Arrays" ), tr( "Arrays" ) );
864  sGroups()->insert( QStringLiteral( "Color" ), tr( "Color" ) );
865  sGroups()->insert( QStringLiteral( "Conditionals" ), tr( "Conditionals" ) );
866  sGroups()->insert( QStringLiteral( "Conversions" ), tr( "Conversions" ) );
867  sGroups()->insert( QStringLiteral( "Date and Time" ), tr( "Date and Time" ) );
868  sGroups()->insert( QStringLiteral( "Fields and Values" ), tr( "Fields and Values" ) );
869  sGroups()->insert( QStringLiteral( "Files and Paths" ), tr( "Files and Paths" ) );
870  sGroups()->insert( QStringLiteral( "Fuzzy Matching" ), tr( "Fuzzy Matching" ) );
871  sGroups()->insert( QStringLiteral( "General" ), tr( "General" ) );
872  sGroups()->insert( QStringLiteral( "GeometryGroup" ), tr( "Geometry" ) );
873  sGroups()->insert( QStringLiteral( "Map Layers" ), tr( "Map Layers" ) );
874  sGroups()->insert( QStringLiteral( "Maps" ), tr( "Maps" ) );
875  sGroups()->insert( QStringLiteral( "Math" ), tr( "Math" ) );
876  sGroups()->insert( QStringLiteral( "Operators" ), tr( "Operators" ) );
877  sGroups()->insert( QStringLiteral( "Rasters" ), tr( "Rasters" ) );
878  sGroups()->insert( QStringLiteral( "Record and Attributes" ), tr( "Record and Attributes" ) );
879  sGroups()->insert( QStringLiteral( "String" ), tr( "String" ) );
880  sGroups()->insert( QStringLiteral( "Variables" ), tr( "Variables" ) );
881  sGroups()->insert( QStringLiteral( "Recent (%1)" ), tr( "Recent (%1)" ) );
882  sGroups()->insert( QStringLiteral( "UserGroup" ), tr( "User expressions" ) );
883  }
884 
885  //return the translated name for this group. If group does not
886  //have a translated name in the gGroups hash, return the name
887  //unchanged
888  return sGroups()->value( name, name );
889 }
890 
891 QString QgsExpression::formatPreviewString( const QVariant &value, const bool htmlOutput )
892 {
893  static const int MAX_PREVIEW = 60;
894 
895  const QString startToken = htmlOutput ? QStringLiteral( "<i>&lt;" ) : QStringLiteral( "<" );
896  const QString endToken = htmlOutput ? QStringLiteral( "&gt;</i>" ) : QStringLiteral( ">" );
897 
898  if ( value.canConvert<QgsGeometry>() )
899  {
900  //result is a geometry
901  QgsGeometry geom = value.value<QgsGeometry>();
902  if ( geom.isNull() )
903  return startToken + tr( "empty geometry" ) + endToken;
904  else
905  return startToken + tr( "geometry: %1" ).arg( QgsWkbTypes::displayString( geom.constGet()->wkbType() ) )
906  + endToken;
907  }
908  else if ( value.value< QgsWeakMapLayerPointer >().data() )
909  {
910  return startToken + tr( "map layer" ) + endToken;
911  }
912  else if ( !value.isValid() )
913  {
914  return htmlOutput ? tr( "<i>NULL</i>" ) : QString();
915  }
916  else if ( value.canConvert< QgsFeature >() )
917  {
918  //result is a feature
919  QgsFeature feat = value.value<QgsFeature>();
920  return startToken + tr( "feature: %1" ).arg( feat.id() ) + endToken;
921  }
922  else if ( value.canConvert< QgsInterval >() )
923  {
924  //result is a feature
925  QgsInterval interval = value.value<QgsInterval>();
926  return startToken + tr( "interval: %1 days" ).arg( interval.days() ) + endToken;
927  }
928  else if ( value.canConvert< QgsGradientColorRamp >() )
929  {
930  return startToken + tr( "gradient ramp" ) + endToken;
931  }
932  else if ( value.type() == QVariant::Date )
933  {
934  QDate dt = value.toDate();
935  return startToken + tr( "date: %1" ).arg( dt.toString( QStringLiteral( "yyyy-MM-dd" ) ) ) + endToken;
936  }
937  else if ( value.type() == QVariant::Time )
938  {
939  QTime tm = value.toTime();
940  return startToken + tr( "time: %1" ).arg( tm.toString( QStringLiteral( "hh:mm:ss" ) ) ) + endToken;
941  }
942  else if ( value.type() == QVariant::DateTime )
943  {
944  QDateTime dt = value.toDateTime();
945  return startToken + tr( "datetime: %1" ).arg( dt.toString( QStringLiteral( "yyyy-MM-dd hh:mm:ss" ) ) ) + endToken;
946  }
947  else if ( value.type() == QVariant::String )
948  {
949  const QString previewString = value.toString();
950  if ( previewString.length() > MAX_PREVIEW + 3 )
951  {
952  return tr( "'%1…'" ).arg( previewString.left( MAX_PREVIEW ) );
953  }
954  else
955  {
956  return '\'' + previewString + '\'';
957  }
958  }
959  else if ( value.type() == QVariant::Map )
960  {
961  QString mapStr = QStringLiteral( "{" );
962  const QVariantMap map = value.toMap();
963  QString separator;
964  for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
965  {
966  mapStr.append( separator );
967  if ( separator.isEmpty() )
968  separator = QStringLiteral( "," );
969 
970  mapStr.append( QStringLiteral( " '%1': %2" ).arg( it.key(), formatPreviewString( it.value(), htmlOutput ) ) );
971  if ( mapStr.length() > MAX_PREVIEW - 3 )
972  {
973  mapStr = tr( "%1…" ).arg( mapStr.left( MAX_PREVIEW - 2 ) );
974  break;
975  }
976  }
977  if ( !map.empty() )
978  mapStr += QStringLiteral( " " );
979  mapStr += QStringLiteral( "}" );
980  return mapStr;
981  }
982  else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
983  {
984  QString listStr = QStringLiteral( "[" );
985  const QVariantList list = value.toList();
986  QString separator;
987  for ( const QVariant &arrayValue : list )
988  {
989  listStr.append( separator );
990  if ( separator.isEmpty() )
991  separator = QStringLiteral( "," );
992 
993  listStr.append( " " );
994  listStr.append( formatPreviewString( arrayValue, htmlOutput ) );
995  if ( listStr.length() > MAX_PREVIEW - 3 )
996  {
997  listStr = QString( tr( "%1…" ) ).arg( listStr.left( MAX_PREVIEW - 2 ) );
998  break;
999  }
1000  }
1001  if ( !list.empty() )
1002  listStr += QStringLiteral( " " );
1003  listStr += QStringLiteral( "]" );
1004  return listStr;
1005  }
1006  else
1007  {
1008  return value.toString();
1009  }
1010 }
1011 
1012 QString QgsExpression::createFieldEqualityExpression( const QString &fieldName, const QVariant &value )
1013 {
1014  QString expr;
1015 
1016  if ( value.isNull() )
1017  expr = QStringLiteral( "%1 IS NULL" ).arg( quotedColumnRef( fieldName ) );
1018  else
1019  expr = QStringLiteral( "%1 = %2" ).arg( quotedColumnRef( fieldName ), quotedValue( value ) );
1020 
1021  return expr;
1022 }
1023 
1025 {
1026  return d->mRootNode;
1027 }
1028 
1030 {
1031  return d->mRootNode && d->mRootNode->nodeType() == QgsExpressionNode::ntColumnRef;
1032 }
1033 
1034 QList<const QgsExpressionNode *> QgsExpression::nodes() const
1035 {
1036  if ( !d->mRootNode )
1037  return QList<const QgsExpressionNode *>();
1038 
1039  return d->mRootNode->nodes();
1040 }
1041 
1042 
1043 
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
static bool isFunctionName(const QString &name)
tells whether the identifier is a name of existing function
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsFeatureId id
Definition: qgsfeature.h:64
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
static QString formatPreviewString(const QVariant &value, bool htmlOutput=true)
Formats an expression result for friendly display to the user.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static QString group(const QString &group)
Returns the translated name for a function group.
bool operator==(const QgsExpression &other) const
Compares two expressions.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
static Q_INVOKABLE QgsUnitTypes::AreaUnit stringToAreaUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to an areal unit.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree. ...
QVariant evaluate()
Evaluate the feature and return the result.
CONSTLATIN1STRING geoNone()
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.h:652
QgsExpression()
Create an empty expression.
static double evaluateToDouble(const QString &text, double fallbackValue)
Attempts to evaluate a text string as an expression to a resultant double value.
QgsExpressionNode * parseExpression(const QString &str, QString &parserErrorMsg, QList< QgsExpression::ParserError > &parserErrors)
QString evalErrorString() const
Returns evaluation error.
Container of fields for a vector layer.
Definition: qgsfields.h:42
Unknown areal unit.
Definition: qgsunittypes.h:105
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QList< QgsExpression::ParserError > parserErrors() const
Returns parser error details including location of error.
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.
static QStringList tags(const QString &name)
Returns a string list of search tags for a specified function.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCoordinateReferenceSystem & crs
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:1650
QString parserErrorString() const
Returns parser error.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:694
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QSet< QString > referencedVariables() const
Returns a list of all variables which are used in this expression.
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
QgsUnitTypes::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area".
static int functionCount()
Returns the number of functions defined in the parser.
static bool checkExpression(const QString &text, const QgsExpressionContext *context, QString &errorMessage)
Tests whether a string is a valid expression.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfields.cpp:351
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
bool isValid() const
Checks if this expression is valid.
QgsExpression & operator=(const QgsExpression &other)
Create a copy of this expression.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
Abstract base class for all nodes that can appear in an expression.
Contains information about the context in which a coordinate transform is executed.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
static const QList< QgsExpressionFunction * > & Functions()
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
static QString formatVariableHelp(const QString &description, bool showValue=true, const QVariant &value=QVariant())
Returns formatted help text for a variable.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsUnitTypes::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
QString expression() const
Returns the original, unmodified expression string.
A representation of the interval between two datetime values.
Definition: qgsinterval.h:39
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:66
double days() const
Returns the interval duration in days.
Definition: qgsinterval.h:112
Unknown distance unit.
Definition: qgsunittypes.h:77
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
static Q_INVOKABLE QgsUnitTypes::DistanceUnit stringToDistanceUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to a distance unit.
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
void setDistanceUnits(QgsUnitTypes::DistanceUnit unit)
Sets the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:450
This class represents a coordinate reference system (CRS).
bool isField() const
Checks whether an expression consists only of a single field reference.
HelpTextHash & functionHelpTexts()
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
static QString helpText(QString name)
Returns the help text for a specified function.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required...
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorramp.h:139
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QList< const QgsExpressionNode * > nodes() const
Returns a list of all nodes which are used in this expression.
AreaUnit
Units of area.
Definition: qgsunittypes.h:92
QSet< QString > referencedFunctions() const
Returns a list of the names of all functions which are used in this expression.
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
bool isValid() const
Returns whether this CRS is correctly initialized and usable.