QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsexpression.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.h
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 #ifndef QGSEXPRESSION_H
17 #define QGSEXPRESSION_H
18 
19 #include <QMetaType>
20 #include <QStringList>
21 #include <QVariant>
22 #include <QList>
23 #include <QDomDocument>
24 
25 #include "qgsfield.h"
26 #include "qgsdistancearea.h"
27 
28 class QgsFeature;
29 class QgsGeometry;
30 class QgsOgcUtils;
31 class QgsVectorLayer;
33 
34 class QDomElement;
35 
87 class CORE_EXPORT QgsExpression
88 {
89  public:
90  QgsExpression( const QString& expr );
91  ~QgsExpression();
92 
94  bool hasParserError() const { return !mParserErrorString.isNull(); }
96  QString parserErrorString() const { return mParserErrorString; }
97 
98  class Node;
99 
101  const Node* rootNode() const { return mRootNode; }
102 
104  bool prepare( const QgsFields &fields );
105 
112  QStringList referencedColumns() const;
113 
115  bool needsGeometry() const;
116 
117  // evaluation
118 
121  QVariant evaluate( const QgsFeature* f = NULL );
122 
126  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
127 
130  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
131 
135  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
136 
138  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
140  QString evalErrorString() const { return mEvalErrorString; }
142  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
143 
145  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
147  int currentRowNumber() { return mRowNumber; }
148 
150  static void setSpecialColumn( const QString& name, QVariant value );
152  static void unsetSpecialColumn( const QString& name );
154  static QVariant specialColumn( const QString& name );
157  static bool hasSpecialColumn( const QString& name );
158 
159  static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
160 
161  void setScale( double scale ) { mScale = scale; }
162 
163  double scale() { return mScale; }
164 
166  const QString expression() const
167  {
168  if ( !mExp.isNull() )
169  return mExp;
170  else
171  return dump();
172  }
173 
175  QString dump() const;
176 
179  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
180 
182  // instead of the default.
183  void setGeomCalculator( const QgsDistanceArea &calc );
184 
198  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
199  QgsVectorLayer *layer,
200  const QMap<QString, QVariant> *substitutionMap = 0,
201  const QgsDistanceArea* distanceArea = 0
202  );
203 
211  static double evaluateToDouble( const QString& text, const double fallbackValue );
212 
218  {
221  };
222 
228  {
229  // logical
232 
233  // comparison
234  boEQ, // =
235  boNE, // <>
236  boLE, // <=
237  boGE, // >=
238  boLT, // <
239  boGT, // >
247 
248  // math
256 
257  // strings
259  };
261  {
271  };
272 
273  static const char* BinaryOperatorText[];
274  static const char* UnaryOperatorText[];
275 
276  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
277 
278 
282  class CORE_EXPORT Function
283  {
284  public:
285  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
286  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ), mLazyEval( lazyEval ) {}
288  QString name() { return mName; }
290  int params() { return mParams; }
292  bool usesgeometry() { return mUsesGeometry; }
293 
297  bool lazyEval() { return mLazyEval; }
298 
299  virtual QStringList referencedColumns() const { return mReferencedColumns; }
300 
302  QString group() { return mGroup; }
304  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
305 
306  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
307 
308  bool operator==( const Function& other ) const
309  {
310  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
311  return true;
312 
313  return false;
314  }
315 
316  private:
317  QString mName;
318  int mParams;
319  bool mUsesGeometry;
320  QString mGroup;
321  QString mHelpText;
322  QStringList mReferencedColumns;
323  bool mLazyEval;
324  };
325 
326  class StaticFunction : public Function
327  {
328  public:
329  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
330  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval ), mFnc( fcn ) {}
331 
332  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
333  {
334  return mFnc( values, f, parent );
335  }
336 
337  private:
338  FcnEval mFnc;
339  };
340 
341  static const QList<Function*> &Functions();
342  static QList<Function*> gmFunctions;
343 
344  static QStringList gmBuiltinFunctions;
345  static const QStringList &BuiltinFunctions();
346 
347  static bool registerFunction( Function* function );
348  static bool unregisterFunction( QString name );
349 
350  // tells whether the identifier is a name of existing function
351  static bool isFunctionName( QString name );
352 
353  // return index of the function in Functions array
354  static int functionIndex( QString name );
355 
359  static int functionCount();
360 
364  static QList<Function*> specialColumns();
365 
367  static QString quotedColumnRef( QString name );
369  static QString quotedString( QString text );
370 
372 
373  class Visitor; // visitor interface is defined below
374 
375  enum NodeType
376  {
383  ntCondition
384  };
385 
386  class CORE_EXPORT Node
387  {
388  public:
389  virtual ~Node() {}
390  virtual NodeType nodeType() const = 0;
391  // abstract virtual eval function
392  // errors are reported to the parent
393  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
394 
395  // abstract virtual preparation function
396  // errors are reported to the parent
397  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
398 
399  virtual QString dump() const = 0;
400 
401  virtual QStringList referencedColumns() const = 0;
402  virtual bool needsGeometry() const = 0;
403 
404  // support for visitor pattern
405  virtual void accept( Visitor& v ) const = 0;
406  };
407 
408  class CORE_EXPORT NodeList
409  {
410  public:
411  NodeList() {}
412  virtual ~NodeList() { qDeleteAll( mList ); }
413  void append( Node* node ) { mList.append( node ); }
414  int count() { return mList.count(); }
415  QList<Node*> list() { return mList; }
416 
417  virtual QString dump() const;
418 
419  protected:
420  QList<Node*> mList;
421  };
422 
423  class CORE_EXPORT Interval
424  {
425  // YEAR const value taken from postgres query
426  // SELECT EXTRACT(EPOCH FROM interval '1 year')
427  static const int YEARS = 31557600;
428  static const int MONTHS = 60 * 60 * 24 * 30;
429  static const int WEEKS = 60 * 60 * 24 * 7;
430  static const int DAY = 60 * 60 * 24;
431  static const int HOUR = 60 * 60;
432  static const int MINUTE = 60;
433  public:
434  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
435  ~Interval();
436  double years() { return mSeconds / YEARS;}
437  double months() { return mSeconds / MONTHS; }
438  double weeks() { return mSeconds / WEEKS;}
439  double days() { return mSeconds / DAY;}
440  double hours() { return mSeconds / HOUR;}
441  double minutes() { return mSeconds / MINUTE;}
442  double seconds() { return mSeconds; }
443  bool isValid() { return mValid; }
444  void setValid( bool valid ) { mValid = valid; }
445  bool operator==( const QgsExpression::Interval& other ) const;
446  static QgsExpression::Interval invalidInterVal();
447  static QgsExpression::Interval fromString( QString string );
448  private:
449  double mSeconds;
450  bool mValid;
451  };
452 
453  class CORE_EXPORT NodeUnaryOperator : public Node
454  {
455  public:
456  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
457  ~NodeUnaryOperator() { delete mOperand; }
458 
459  UnaryOperator op() const { return mOp; }
460  Node* operand() const { return mOperand; }
461 
462  virtual NodeType nodeType() const { return ntUnaryOperator; }
463  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
464  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
465  virtual QString dump() const;
466 
467  virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
468  virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
469  virtual void accept( Visitor& v ) const { v.visit( *this ); }
470 
471  protected:
474  };
475 
476  class CORE_EXPORT NodeBinaryOperator : public Node
477  {
478  public:
479  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
480  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
481 
482  BinaryOperator op() const { return mOp; }
483  Node* opLeft() const { return mOpLeft; }
484  Node* opRight() const { return mOpRight; }
485 
486  virtual NodeType nodeType() const { return ntBinaryOperator; }
487  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
488  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
489  virtual QString dump() const;
490 
491  virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
492  virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
493  virtual void accept( Visitor& v ) const { v.visit( *this ); }
494 
495  int precedence() const;
496 
497  protected:
498  bool compare( double diff );
499  int computeInt( int x, int y );
500  double computeDouble( double x, double y );
501  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
502 
506  };
507 
508  class CORE_EXPORT NodeInOperator : public Node
509  {
510  public:
511  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
512  virtual ~NodeInOperator() { delete mNode; delete mList; }
513 
514  Node* node() const { return mNode; }
515  bool isNotIn() const { return mNotIn; }
516  NodeList* list() const { return mList; }
517 
518  virtual NodeType nodeType() const { return ntInOperator; }
519  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
520  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
521  virtual QString dump() const;
522 
523  virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
524  virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
525  virtual void accept( Visitor& v ) const { v.visit( *this ); }
526 
527  protected:
530  bool mNotIn;
531  };
532 
533  class CORE_EXPORT NodeFunction : public Node
534  {
535  public:
536  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
537  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
538  virtual ~NodeFunction() { delete mArgs; }
539 
540  int fnIndex() const { return mFnIndex; }
541  NodeList* args() const { return mArgs; }
542 
543  virtual NodeType nodeType() const { return ntFunction; }
544  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
545  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
546  virtual QString dump() const;
547 
548  virtual QStringList referencedColumns() const;
549  virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
550  virtual void accept( Visitor& v ) const { v.visit( *this ); }
551 
552  protected:
553  //QString mName;
554  int mFnIndex;
556  };
557 
558  class CORE_EXPORT NodeLiteral : public Node
559  {
560  public:
561  NodeLiteral( QVariant value ) : mValue( value ) {}
562 
563  QVariant value() const { return mValue; }
564 
565  virtual NodeType nodeType() const { return ntLiteral; }
566  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
567  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
568  virtual QString dump() const;
569 
570  virtual QStringList referencedColumns() const { return QStringList(); }
571  virtual bool needsGeometry() const { return false; }
572  virtual void accept( Visitor& v ) const { v.visit( *this ); }
573 
574  protected:
575  QVariant mValue;
576  };
577 
578  class CORE_EXPORT NodeColumnRef : public Node
579  {
580  public:
581  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
582 
583  QString name() const { return mName; }
584 
585  virtual NodeType nodeType() const { return ntColumnRef; }
586  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
587  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
588  virtual QString dump() const;
589 
590  virtual QStringList referencedColumns() const { return QStringList( mName ); }
591  virtual bool needsGeometry() const { return false; }
592 
593  virtual void accept( Visitor& v ) const { v.visit( *this ); }
594 
595  protected:
596  QString mName;
597  int mIndex;
598  };
599 
600  class CORE_EXPORT WhenThen
601  {
602  public:
603  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
604  ~WhenThen() { delete mWhenExp; delete mThenExp; }
605 
606  //protected:
609  };
610  typedef QList<WhenThen*> WhenThenList;
611 
612  class CORE_EXPORT NodeCondition : public Node
613  {
614  public:
615  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
616  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
617 
618  virtual NodeType nodeType() const { return ntCondition; }
619  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
620  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
621  virtual QString dump() const;
622 
623  virtual QStringList referencedColumns() const;
624  virtual bool needsGeometry() const;
625  virtual void accept( Visitor& v ) const { v.visit( *this ); }
626 
627  protected:
628  WhenThenList mConditions;
630  };
631 
633 
636  class CORE_EXPORT Visitor
637  {
638  public:
639  virtual ~Visitor() {}
640  virtual void visit( const NodeUnaryOperator& n ) = 0;
641  virtual void visit( const NodeBinaryOperator& n ) = 0;
642  virtual void visit( const NodeInOperator& n ) = 0;
643  virtual void visit( const NodeFunction& n ) = 0;
644  virtual void visit( const NodeLiteral& n ) = 0;
645  virtual void visit( const NodeColumnRef& n ) = 0;
646  virtual void visit( const NodeCondition& n ) = 0;
647  };
648 
650  void acceptVisitor( Visitor& v ) const;
651 
652  static QString helptext( QString name );
653  static QString group( QString group );
654 
655  protected:
659  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
660 
661  void initGeomCalculator();
662 
664 
667 
669  double mScale;
670  QString mExp;
671 
673 
674  static QMap<QString, QVariant> gmSpecialColumns;
675  static QMap<QString, QString> gmSpecialColumnGroups;
676 
677  static QHash<QString, QString> gFunctionHelpTexts;
678  static QHash<QString, QString> gGroups;
679 
680  static void initFunctionHelp();
681 
682  friend class QgsOgcUtils;
683 
684  private:
685  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
686 };
687 
690 
691 #endif // QGSEXPRESSION_H
virtual void accept(Visitor &v) const
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
virtual QStringList referencedColumns() const =0
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QVariant evaluate(const QgsFeature &f, const QgsFields &fields)
Evaluate the feature and return the result.
UnaryOperator
list of unary operators
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:94
bool lazyEval()
True if this function should use lazy evaluation.
const QString expression() const
Alias for dump()
virtual bool needsGeometry() const
Node is a class used by Line3D.
Definition: Node.h:23
virtual QVariant func(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
A abstract base class for defining QgsExpression functions.
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
virtual bool needsGeometry() const
virtual QString dump() const =0
NodeCondition(WhenThenList *conditions, Node *elseExp=NULL)
static QString helptext(QString name)
virtual QStringList referencedColumns() const
QgsExpression()
Used by QgsOgcUtils to create an empty.
virtual NodeType nodeType() const
Container of fields for a vector layer.
Definition: qgsfield.h:172
Interval(double seconds=0)
virtual NodeType nodeType() const
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)=0
NodeList * list() const
virtual NodeType nodeType() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QVariant value() const
int currentRowNumber()
Return the number used for $rownum special column.
QString mEvalErrorString
NodeBinaryOperator(BinaryOperator op, Node *opLeft, Node *opRight)
QString mParserErrorString
virtual QStringList referencedColumns() const
static const QList< Function * > & Functions()
virtual QStringList referencedColumns() const
static QHash< QString, QString > gFunctionHelpTexts
virtual NodeType nodeType() const
QgsDistanceArea * geomCalculator()
Return calculator used for distance and area calculations (used by internal functions) ...
NodeList * args() const
virtual QStringList referencedColumns() const
QgsDistanceArea * mCalc
virtual bool needsGeometry() const
QList< Node * > mList
virtual void accept(Visitor &v) const
static QHash< QString, QString > gGroups
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
NodeInOperator(Node *node, NodeList *list, bool notin=false)
double scale()
QString helptext()
The help text for the function.
static QList< Function * > gmFunctions
QString name()
The name of the function.
void setCurrentRowNumber(int rowNumber)
Set the number for $rownum special column.
WhenThen(Node *whenExp, Node *thenExp)
NodeLiteral(QVariant value)
virtual NodeType nodeType() const
StaticFunction(QString fnname, int params, FcnEval fcn, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false)
NodeUnaryOperator(UnaryOperator op, Node *operand)
BinaryOperator op() const
virtual void accept(Visitor &v) const
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)=0
virtual QStringList referencedColumns() const
void setEvalErrorString(QString str)
Set evaluation error (used internally by evaluation functions)
NodeFunction(int fnIndex, NodeList *args)
General purpose distance and area calculator.
virtual void accept(Visitor &v) const
static QMap< QString, QString > gmSpecialColumnGroups
virtual void accept(Visitor &v) const
BinaryOperator
list of binary operators
QString group()
The group the function belongs to.
Function(QString fnname, int params, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false)
QList< WhenThen * > WhenThenList
virtual NodeType nodeType() const
virtual void accept(Visitor &v) const
virtual void visit(const NodeUnaryOperator &n)=0
QVariant evaluate(const QgsFeature &f)
Evaluate the feature and return the result.
int params()
The number of parameters this function takes.
virtual QStringList referencedColumns() const
virtual void accept(Visitor &v) const
support for visitor pattern - algorithms dealing with the expressions may be implemented without modi...
virtual bool needsGeometry() const
virtual bool needsGeometry() const =0
bool operator==(const Function &other) const
static QStringList gmBuiltinFunctions
void append(Node *node)
UnaryOperator op() const
void setValid(bool valid)
This is the base class for vector data providers.
void setScale(double scale)
Represents a vector layer which manages a vector based data sets.
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:96
Q_DECLARE_METATYPE(QgsExpression::Interval)
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
Definition: qgsogcutils.h:28
QString evalErrorString() const
Returns evaluation error.
virtual bool needsGeometry() const
virtual bool needsGeometry() const
bool usesgeometry()
Does this function use a geometry object.
virtual NodeType nodeType() const
QList< Node * > list()
static QMap< QString, QVariant > gmSpecialColumns