QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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 
89 class CORE_EXPORT QgsExpression
90 {
91  public:
92  QgsExpression( const QString& expr );
93  ~QgsExpression();
94 
96  bool hasParserError() const { return !mParserErrorString.isNull(); }
98  QString parserErrorString() const { return mParserErrorString; }
99 
100  class Node;
101 
103  const Node* rootNode() const { return mRootNode; }
104 
106  bool prepare( const QgsFields &fields );
107 
113  QStringList referencedColumns();
114 
116  bool needsGeometry();
117 
118  // evaluation
119 
122  QVariant evaluate( const QgsFeature* f = NULL );
123 
127  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
128 
131  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
132 
136  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
137 
139  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
141  QString evalErrorString() const { return mEvalErrorString; }
143  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
144 
146  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
148  int currentRowNumber() { return mRowNumber; }
149 
151  static void setSpecialColumn( const QString& name, QVariant value );
153  static void unsetSpecialColumn( const QString& name );
155  static QVariant specialColumn( const QString& name );
158  static bool hasSpecialColumn( const QString& name );
159 
160  static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
161 
162  void setScale( double scale ) { mScale = scale; }
163 
164  double scale() { return mScale; }
165 
167  const QString expression() const { return dump(); }
168 
170  QString dump() const;
171 
174  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
175 
177  // instead of the default.
178  void setGeomCalculator( const QgsDistanceArea &calc );
179 
187  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
188  QgsVectorLayer *layer,
189  const QMap<QString, QVariant> *substitutionMap = 0 );
191  {
194  };
196  {
197  // logical
200 
201  // comparison
202  boEQ, // =
203  boNE, // <>
204  boLE, // <=
205  boGE, // >=
206  boLT, // <
207  boGT, // >
215 
216  // math
223 
224  // strings
226  };
228  {
238  };
239 
240  static const char* BinaryOperatorText[];
241  static const char* UnaryOperatorText[];
242 
243  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
244 
245 
249  class CORE_EXPORT Function
250  {
251  public:
252  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList() )
253  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ) {}
255  QString name() { return mName; }
257  int params() { return mParams; }
259  bool usesgeometry() { return mUsesGeometry; }
260 
261  virtual QStringList referencedColumns() const { return mReferencedColumns; }
262 
264  QString group() { return mGroup; }
266  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
267 
268  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
269 
270  bool operator==( const Function& other ) const
271  {
272  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
273  return true;
274 
275  return false;
276  }
277 
278  private:
279  QString mName;
280  int mParams;
282  QString mGroup;
283  QString mHelpText;
284  QStringList mReferencedColumns;
285  };
286 
287  class StaticFunction : public Function
288  {
289  public:
290  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList() )
291  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns ), mFnc( fcn ) {}
292 
293  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
294  {
295  return mFnc( values, f, parent );
296  }
297 
298  private:
299  FcnEval mFnc;
300  };
301 
302  static const QList<Function*> &Functions();
303  static QList<Function*> gmFunctions;
304 
305  static QStringList gmBuiltinFunctions;
306  static const QStringList &BuiltinFunctions();
307 
308  static bool registerFunction( Function* function );
309  static bool unregisterFunction( QString name );
310 
311  // tells whether the identifier is a name of existing function
312  static bool isFunctionName( QString name );
313 
314  // return index of the function in Functions array
315  static int functionIndex( QString name );
316 
320  static int functionCount();
321 
325  static QList<Function*> specialColumns();
326 
328  static QString quotedColumnRef( QString name );
330  static QString quotedString( QString text );
331 
333 
334  class Visitor; // visitor interface is defined below
335 
336  enum NodeType
337  {
344  ntCondition
345  };
346 
347  class CORE_EXPORT Node
348  {
349  public:
350  virtual ~Node() {}
351  virtual NodeType nodeType() const = 0;
352  // abstract virtual eval function
353  // errors are reported to the parent
354  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
355 
356  // abstract virtual preparation function
357  // errors are reported to the parent
358  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
359 
360  virtual QString dump() const = 0;
361 
362  virtual QStringList referencedColumns() const = 0;
363  virtual bool needsGeometry() const = 0;
364 
365  // support for visitor pattern
366  virtual void accept( Visitor& v ) const = 0;
367  };
368 
369  class CORE_EXPORT NodeList
370  {
371  public:
372  NodeList() {}
373  virtual ~NodeList() { qDeleteAll( mList ); }
374  void append( Node* node ) { mList.append( node ); }
375  int count() { return mList.count(); }
376  QList<Node*> list() { return mList; }
377 
378  virtual QString dump() const;
379 
380  protected:
381  QList<Node*> mList;
382  };
383 
384  class CORE_EXPORT Interval
385  {
386  // YEAR const value taken from postgres query
387  // SELECT EXTRACT(EPOCH FROM interval '1 year')
388  static const int YEARS = 31557600;
389  static const int MONTHS = 60 * 60 * 24 * 30;
390  static const int WEEKS = 60 * 60 * 24 * 7;
391  static const int DAY = 60 * 60 * 24;
392  static const int HOUR = 60 * 60;
393  static const int MINUTE = 60;
394  public:
395  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
396  ~Interval();
397  double years() { return mSeconds / YEARS;}
398  double months() { return mSeconds / MONTHS; }
399  double weeks() { return mSeconds / WEEKS;}
400  double days() { return mSeconds / DAY;}
401  double hours() { return mSeconds / HOUR;}
402  double minutes() { return mSeconds / MINUTE;}
403  double seconds() { return mSeconds; }
404  bool isValid() { return mValid; }
405  void setValid( bool valid ) { mValid = valid; }
406  bool operator==( const QgsExpression::Interval& other ) const;
407  static QgsExpression::Interval invalidInterVal();
408  static QgsExpression::Interval fromString( QString string );
409  private:
410  double mSeconds;
411  bool mValid;
412  };
413 
414  class CORE_EXPORT NodeUnaryOperator : public Node
415  {
416  public:
417  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
418  ~NodeUnaryOperator() { delete mOperand; }
419 
420  UnaryOperator op() const { return mOp; }
421  Node* operand() const { return mOperand; }
422 
423  virtual NodeType nodeType() const { return ntUnaryOperator; }
424  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
425  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
426  virtual QString dump() const;
427 
428  virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
429  virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
430  virtual void accept( Visitor& v ) const { v.visit( *this ); }
431 
432  protected:
435  };
436 
437  class CORE_EXPORT NodeBinaryOperator : public Node
438  {
439  public:
440  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
441  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
442 
443  BinaryOperator op() const { return mOp; }
444  Node* opLeft() const { return mOpLeft; }
445  Node* opRight() const { return mOpRight; }
446 
447  virtual NodeType nodeType() const { return ntBinaryOperator; }
448  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
449  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
450  virtual QString dump() const;
451 
452  virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
453  virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
454  virtual void accept( Visitor& v ) const { v.visit( *this ); }
455 
456  int precedence() const;
457 
458  protected:
459  bool compare( double diff );
460  int computeInt( int x, int y );
461  double computeDouble( double x, double y );
462  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
463 
467  };
468 
469  class CORE_EXPORT NodeInOperator : public Node
470  {
471  public:
472  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
473  virtual ~NodeInOperator() { delete mNode; delete mList; }
474 
475  Node* node() const { return mNode; }
476  bool isNotIn() const { return mNotIn; }
477  NodeList* list() const { return mList; }
478 
479  virtual NodeType nodeType() const { return ntInOperator; }
480  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
481  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
482  virtual QString dump() const;
483 
484  virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
485  virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
486  virtual void accept( Visitor& v ) const { v.visit( *this ); }
487 
488  protected:
491  bool mNotIn;
492  };
493 
494  class CORE_EXPORT NodeFunction : public Node
495  {
496  public:
497  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
498  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
499  virtual ~NodeFunction() { delete mArgs; }
500 
501  int fnIndex() const { return mFnIndex; }
502  NodeList* args() const { return mArgs; }
503 
504  virtual NodeType nodeType() const { return ntFunction; }
505  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
506  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
507  virtual QString dump() const;
508 
509  virtual QStringList referencedColumns() const;
510  virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
511  virtual void accept( Visitor& v ) const { v.visit( *this ); }
512 
513  protected:
514  //QString mName;
515  int mFnIndex;
517  };
518 
519  class CORE_EXPORT NodeLiteral : public Node
520  {
521  public:
522  NodeLiteral( QVariant value ) : mValue( value ) {}
523 
524  QVariant value() const { return mValue; }
525 
526  virtual NodeType nodeType() const { return ntLiteral; }
527  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
528  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
529  virtual QString dump() const;
530 
531  virtual QStringList referencedColumns() const { return QStringList(); }
532  virtual bool needsGeometry() const { return false; }
533  virtual void accept( Visitor& v ) const { v.visit( *this ); }
534 
535  protected:
536  QVariant mValue;
537  };
538 
539  class CORE_EXPORT NodeColumnRef : public Node
540  {
541  public:
542  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
543 
544  QString name() const { return mName; }
545 
546  virtual NodeType nodeType() const { return ntColumnRef; }
547  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
548  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
549  virtual QString dump() const;
550 
551  virtual QStringList referencedColumns() const { return QStringList( mName ); }
552  virtual bool needsGeometry() const { return false; }
553 
554  virtual void accept( Visitor& v ) const { v.visit( *this ); }
555 
556  protected:
557  QString mName;
558  int mIndex;
559  };
560 
561  class CORE_EXPORT WhenThen
562  {
563  public:
564  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
565  ~WhenThen() { delete mWhenExp; delete mThenExp; }
566 
567  //protected:
570  };
571  typedef QList<WhenThen*> WhenThenList;
572 
573  class CORE_EXPORT NodeCondition : public Node
574  {
575  public:
576  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
577  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
578 
579  virtual NodeType nodeType() const { return ntCondition; }
580  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
581  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
582  virtual QString dump() const;
583 
584  virtual QStringList referencedColumns() const;
585  virtual bool needsGeometry() const;
586  virtual void accept( Visitor& v ) const { v.visit( *this ); }
587 
588  protected:
589  WhenThenList mConditions;
591  };
592 
594 
597  class CORE_EXPORT Visitor
598  {
599  public:
600  virtual ~Visitor() {}
601  virtual void visit( const NodeUnaryOperator& n ) = 0;
602  virtual void visit( const NodeBinaryOperator& n ) = 0;
603  virtual void visit( const NodeInOperator& n ) = 0;
604  virtual void visit( const NodeFunction& n ) = 0;
605  virtual void visit( const NodeLiteral& n ) = 0;
606  virtual void visit( const NodeColumnRef& n ) = 0;
607  virtual void visit( const NodeCondition& n ) = 0;
608  };
609 
611  void acceptVisitor( Visitor& v ) const;
612 
613  static QString helptext( QString name );
614  static QString group( QString group );
615 
616  protected:
617  // internally used to create an empty expression
618  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
619 
620  void initGeomCalculator();
621 
623 
626 
628  double mScale;
629  QString mExp;
630 
631  static QMap<QString, QVariant> gmSpecialColumns;
632  static QMap<QString, QString> gmSpecialColumnGroups;
633 
635 
636  friend class QgsOgcUtils;
637 
638  static void initFunctionHelp();
639  static QHash<QString, QString> gFunctionHelpTexts;
640  static QHash<QString, QString> gGroups;
641 };
642 
644 
645 #endif // QGSEXPRESSION_H
virtual void accept(Visitor &v) const
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
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.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:96
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
QStringList mReferencedColumns
virtual NodeType nodeType() const
Container of fields for a vector layer.
Definition: qgsfield.h:163
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
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
QString group()
The group the function belongs to.
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:98
Q_DECLARE_METATYPE(QgsExpression::Interval)
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
Definition: qgsogcutils.h:30
QString evalErrorString() const
Returns evaluation error.
virtual bool needsGeometry() const
virtual bool needsGeometry() const
bool usesgeometry()
Does this function use a geometry object.
Function(QString fnname, int params, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList())
virtual NodeType nodeType() const
QList< Node * > list()
StaticFunction(QString fnname, int params, FcnEval fcn, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList())
static QMap< QString, QVariant > gmSpecialColumns