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