QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
18 #include <QtDebug>
19 #include <QDomDocument>
20 #include <QSettings>
21 #include <QDate>
22 #include <QRegExp>
23 #include <QColor>
24 #include <QUuid>
25 
26 #include <math.h>
27 #include <limits>
28 
29 #include "qgsdistancearea.h"
30 #include "qgsfeature.h"
31 #include "qgsgeometry.h"
32 #include "qgslogger.h"
33 #include "qgsmaplayerregistry.h"
34 #include "qgsogcutils.h"
35 #include "qgsvectorlayer.h"
36 #include "qgssymbollayerv2utils.h"
37 #include "qgsvectorcolorrampv2.h"
38 #include "qgsstylev2.h"
39 
40 // from parser
41 extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
42 
44 
46 {
48  inter.setValid( false );
49  return inter;
50 }
51 
53 {
54  int seconds = 0;
55  QRegExp rx( "([-+]?\\d?\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
56  QStringList list;
57  int pos = 0;
58 
59  while (( pos = rx.indexIn( string, pos ) ) != -1 )
60  {
61  list << rx.cap( 1 );
62  pos += rx.matchedLength();
63  }
64 
65  QMap<int, QStringList> map;
66  map.insert( 1, QStringList() << "second" << "seconds" << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( "|" ) );
67  map.insert( 0 + MINUTE, QStringList() << "minute" << "minutes" << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( "|" ) );
68  map.insert( 0 + HOUR, QStringList() << "hour" << "hours" << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( "|" ) );
69  map.insert( 0 + DAY, QStringList() << "day" << "days" << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( "|" ) );
70  map.insert( 0 + WEEKS, QStringList() << "week" << "weeks" << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( "|" ) );
71  map.insert( 0 + MONTHS, QStringList() << "month" << "months" << QObject::tr( "month|months", "list of words separated by | which reference months" ).split( "|" ) );
72  map.insert( 0 + YEARS, QStringList() << "year" << "years" << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( "|" ) );
73 
74  foreach ( QString match, list )
75  {
76  QStringList split = match.split( QRegExp( "\\s+" ) );
77  bool ok;
78  double value = split.at( 0 ).toDouble( &ok );
79  if ( !ok )
80  {
81  continue;
82  }
83 
84  bool matched = false;
85  foreach ( int duration, map.keys() )
86  {
87  foreach ( QString name, map[duration] )
88  {
89  if ( match.contains( name, Qt::CaseInsensitive ) )
90  {
91  matched = true;
92  break;
93  }
94  }
95 
96  if ( matched )
97  {
98  seconds += value * duration;
99  break;
100  }
101  }
102  }
103 
104  // If we can't parse the string at all then we just return invalid
105  if ( seconds == 0 )
107 
108  return QgsExpression::Interval( seconds );
109 }
110 
112 {
113  return ( mSeconds == other.mSeconds );
114 }
115 
117 // three-value logic
118 
119 enum TVL
120 {
124 };
125 
126 static TVL AND[3][3] =
127 {
128  // false true unknown
129  { False, False, False }, // false
130  { False, True, Unknown }, // true
131  { False, Unknown, Unknown } // unknown
132 };
133 
134 static TVL OR[3][3] =
135 {
136  { False, True, Unknown }, // false
137  { True, True, True }, // true
138  { Unknown, True, Unknown } // unknown
139 };
140 
141 static TVL NOT[3] = { True, False, Unknown };
142 
143 static QVariant tvl2variant( TVL v )
144 {
145  switch ( v )
146  {
147  case False: return 0;
148  case True: return 1;
149  case Unknown:
150  default:
151  return QVariant();
152  }
153 }
154 
155 #define TVL_True QVariant(1)
156 #define TVL_False QVariant(0)
157 #define TVL_Unknown QVariant()
158 
160 // QVariant checks and conversions
161 
162 inline bool isIntSafe( const QVariant& v )
163 {
164  if ( v.type() == QVariant::Int ) return true;
165  if ( v.type() == QVariant::Double ) return false;
166  if ( v.type() == QVariant::String ) { bool ok; v.toString().toInt( &ok ); return ok; }
167  return false;
168 }
169 inline bool isDoubleSafe( const QVariant& v )
170 {
171  if ( v.type() == QVariant::Double || v.type() == QVariant::Int ) return true;
172  if ( v.type() == QVariant::String ) { bool ok; v.toString().toDouble( &ok ); return ok; }
173  return false;
174 }
175 
176 inline bool isDateTimeSafe( const QVariant& v )
177 {
178  return v.type() == QVariant::DateTime || v.type() == QVariant::Date ||
179  v.type() == QVariant::Time;
180 }
181 
182 inline bool isIntervalSafe( const QVariant& v )
183 {
184  if ( v.canConvert<QgsExpression::Interval>() )
185  {
186  return true;
187  }
188 
189  if ( v.type() == QVariant::String )
190  {
191  return QgsExpression::Interval::fromString( v.toString() ).isValid();
192  }
193  return false;
194 }
195 
196 inline bool isNull( const QVariant& v ) { return v.isNull(); }
197 
199 // evaluation error macros
200 
201 #define ENSURE_NO_EVAL_ERROR { if (parent->hasEvalError()) return QVariant(); }
202 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString(x); return QVariant(); }
203 
205 // operators
206 
207 const char* QgsExpression::BinaryOperatorText[] =
208 {
209  "OR", "AND",
210  "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
211  "+", "-", "*", "/", "%", "^",
212  "||"
213 };
214 
215 const char* QgsExpression::UnaryOperatorText[] =
216 {
217  "NOT", "-"
218 };
219 
221 // functions
222 
223 // implicit conversion to string
224 static QString getStringValue( const QVariant& value, QgsExpression* )
225 {
226  return value.toString();
227 }
228 
229 static double getDoubleValue( const QVariant& value, QgsExpression* parent )
230 {
231  bool ok;
232  double x = value.toDouble( &ok );
233  if ( !ok )
234  {
235  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) );
236  return 0;
237  }
238  return x;
239 }
240 
241 static int getIntValue( const QVariant& value, QgsExpression* parent )
242 {
243  bool ok;
244  qint64 x = value.toLongLong( &ok );
246  {
247  return x;
248  }
249  else
250  {
251  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) );
252  return 0;
253  }
254 }
255 
256 static QDateTime getDateTimeValue( const QVariant& value, QgsExpression* parent )
257 {
258  QDateTime d = value.toDateTime();
259  if ( d.isValid() )
260  {
261  return d;
262  }
263  else
264  {
265  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
266  return QDateTime();
267  }
268 }
269 
270 static QDate getDateValue( const QVariant& value, QgsExpression* parent )
271 {
272  QDate d = value.toDate();
273  if ( d.isValid() )
274  {
275  return d;
276  }
277  else
278  {
279  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) );
280  return QDate();
281  }
282 }
283 
284 static QTime getTimeValue( const QVariant& value, QgsExpression* parent )
285 {
286  QTime t = value.toTime();
287  if ( t.isValid() )
288  {
289  return t;
290  }
291  else
292  {
293  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) );
294  return QTime();
295  }
296 }
297 
298 static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
299 {
300  if ( value.canConvert<QgsExpression::Interval>() )
301  return value.value<QgsExpression::Interval>();
302 
304  if ( inter.isValid() )
305  {
306  return inter;
307  }
308  // If we get here then we can't convert so we just error and return invalid.
309  if ( report_error )
310  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
311 
313 }
314 
315 static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent )
316 {
317  if ( value.canConvert<QgsGeometry>() )
318  return value.value<QgsGeometry>();
319 
320  parent->setEvalErrorString( "Cannot convert to QgsGeometry" );
321  return QgsGeometry();
322 }
323 
324 static QgsFeature getFeature( const QVariant& value, QgsExpression* parent )
325 {
326  if ( value.canConvert<QgsFeature>() )
327  return value.value<QgsFeature>();
328 
329  parent->setEvalErrorString( "Cannot convert to QgsFeature" );
330  return 0;
331 }
332 
333 // this handles also NULL values
334 static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
335 {
336  // we need to convert to TVL
337  if ( value.isNull() )
338  return Unknown;
339 
340  if ( value.type() == QVariant::Int )
341  return value.toInt() != 0 ? True : False;
342 
343  bool ok;
344  double x = value.toDouble( &ok );
345  if ( !ok )
346  {
347  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) );
348  return Unknown;
349  }
350  return x != 0 ? True : False;
351 }
352 
354 
355 static QVariant fcnSqrt( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent )
356 {
357  double x = getDoubleValue( values.at( 0 ), parent );
358  return QVariant( sqrt( x ) );
359 }
360 
361 static QVariant fcnAbs( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
362 {
363  double val = getDoubleValue( values.at( 0 ), parent );
364  return QVariant( fabs( val ) );
365 }
366 
367 static QVariant fcnSin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
368 {
369  double x = getDoubleValue( values.at( 0 ), parent );
370  return QVariant( sin( x ) );
371 }
372 static QVariant fcnCos( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
373 {
374  double x = getDoubleValue( values.at( 0 ), parent );
375  return QVariant( cos( x ) );
376 }
377 static QVariant fcnTan( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
378 {
379  double x = getDoubleValue( values.at( 0 ), parent );
380  return QVariant( tan( x ) );
381 }
382 static QVariant fcnAsin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
383 {
384  double x = getDoubleValue( values.at( 0 ), parent );
385  return QVariant( asin( x ) );
386 }
387 static QVariant fcnAcos( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
388 {
389  double x = getDoubleValue( values.at( 0 ), parent );
390  return QVariant( acos( x ) );
391 }
392 static QVariant fcnAtan( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
393 {
394  double x = getDoubleValue( values.at( 0 ), parent );
395  return QVariant( atan( x ) );
396 }
397 static QVariant fcnAtan2( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
398 {
399  double y = getDoubleValue( values.at( 0 ), parent );
400  double x = getDoubleValue( values.at( 1 ), parent );
401  return QVariant( atan2( y, x ) );
402 }
403 static QVariant fcnExp( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
404 {
405  double x = getDoubleValue( values.at( 0 ), parent );
406  return QVariant( exp( x ) );
407 }
408 static QVariant fcnLn( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
409 {
410  double x = getDoubleValue( values.at( 0 ), parent );
411  if ( x <= 0 )
412  return QVariant();
413  return QVariant( log( x ) );
414 }
415 static QVariant fcnLog10( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
416 {
417  double x = getDoubleValue( values.at( 0 ), parent );
418  if ( x <= 0 )
419  return QVariant();
420  return QVariant( log10( x ) );
421 }
422 static QVariant fcnLog( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
423 {
424  double b = getDoubleValue( values.at( 0 ), parent );
425  double x = getDoubleValue( values.at( 1 ), parent );
426  if ( x <= 0 || b <= 0 )
427  return QVariant();
428  return QVariant( log( x ) / log( b ) );
429 }
430 static QVariant fcnRndF( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
431 {
432  double min = getDoubleValue( values.at( 0 ), parent );
433  double max = getDoubleValue( values.at( 1 ), parent );
434  if ( max < min )
435  return QVariant();
436 
437  // Return a random double in the range [min, max] (inclusive)
438  double f = ( double )rand() / RAND_MAX;
439  return QVariant( min + f * ( max - min ) ) ;
440 }
441 static QVariant fcnRnd( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
442 {
443  int min = getIntValue( values.at( 0 ), parent );
444  int max = getIntValue( values.at( 1 ), parent );
445  if ( max < min )
446  return QVariant();
447 
448  // Return a random integer in the range [min, max] (inclusive)
449  return QVariant( min + ( rand() % ( int )( max - min + 1 ) ) );
450 }
451 
452 static QVariant fcnLinearScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
453 {
454  double val = getDoubleValue( values.at( 0 ), parent );
455  double domainMin = getDoubleValue( values.at( 1 ), parent );
456  double domainMax = getDoubleValue( values.at( 2 ), parent );
457  double rangeMin = getDoubleValue( values.at( 3 ), parent );
458  double rangeMax = getDoubleValue( values.at( 4 ), parent );
459 
460  if ( domainMin >= domainMax )
461  {
462  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
463  return QVariant();
464  }
465 
466  // outside of domain?
467  if ( val >= domainMax )
468  {
469  return rangeMax;
470  }
471  else if ( val <= domainMin )
472  {
473  return rangeMin;
474  }
475 
476  // calculate linear scale
477  double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
478  double c = rangeMin - ( domainMin * m );
479 
480  // Return linearly scaled value
481  return QVariant( m * val + c );
482 }
483 
484 static QVariant fcnExpScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
485 {
486  double val = getDoubleValue( values.at( 0 ), parent );
487  double domainMin = getDoubleValue( values.at( 1 ), parent );
488  double domainMax = getDoubleValue( values.at( 2 ), parent );
489  double rangeMin = getDoubleValue( values.at( 3 ), parent );
490  double rangeMax = getDoubleValue( values.at( 4 ), parent );
491  double exponent = getDoubleValue( values.at( 5 ), parent );
492 
493  if ( domainMin >= domainMax )
494  {
495  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
496  return QVariant();
497  }
498  if ( exponent <= 0 )
499  {
500  parent->setEvalErrorString( QObject::tr( "Exponent must be greater than 0" ) );
501  return QVariant();
502  }
503 
504  // outside of domain?
505  if ( val >= domainMax )
506  {
507  return rangeMax;
508  }
509  else if ( val <= domainMin )
510  {
511  return rangeMin;
512  }
513 
514  // Return exponentially scaled value
515  return QVariant((( rangeMax - rangeMin ) / pow( domainMax - domainMin, exponent ) ) * pow( val - domainMin, exponent ) + rangeMin );
516 }
517 
518 static QVariant fcnMax( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
519 {
520  //initially set max as first value
521  double maxVal = getDoubleValue( values.at( 0 ), parent );
522 
523  //check against all other values
524  for ( int i = 1; i < values.length(); ++i )
525  {
526  double testVal = getDoubleValue( values[i], parent );
527  if ( testVal > maxVal )
528  {
529  maxVal = testVal;
530  }
531  }
532 
533  return QVariant( maxVal );
534 }
535 
536 static QVariant fcnMin( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
537 {
538  //initially set min as first value
539  double minVal = getDoubleValue( values.at( 0 ), parent );
540 
541  //check against all other values
542  for ( int i = 1; i < values.length(); ++i )
543  {
544  double testVal = getDoubleValue( values[i], parent );
545  if ( testVal < minVal )
546  {
547  minVal = testVal;
548  }
549  }
550 
551  return QVariant( minVal );
552 }
553 
554 static QVariant fcnClamp( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
555 {
556  double minValue = getDoubleValue( values.at( 0 ), parent );
557  double testValue = getDoubleValue( values.at( 1 ), parent );
558  double maxValue = getDoubleValue( values.at( 2 ), parent );
559 
560  // force testValue to sit inside the range specified by the min and max value
561  if ( testValue <= minValue )
562  {
563  return QVariant( minValue );
564  }
565  else if ( testValue >= maxValue )
566  {
567  return QVariant( maxValue );
568  }
569  else
570  {
571  return QVariant( testValue );
572  }
573 }
574 
575 static QVariant fcnFloor( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
576 {
577  double x = getDoubleValue( values.at( 0 ), parent );
578  return QVariant( floor( x ) );
579 }
580 
581 static QVariant fcnCeil( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
582 {
583  double x = getDoubleValue( values.at( 0 ), parent );
584  return QVariant( ceil( x ) );
585 }
586 
587 static QVariant fcnToInt( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
588 {
589  return QVariant( getIntValue( values.at( 0 ), parent ) );
590 }
591 static QVariant fcnToReal( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
592 {
593  return QVariant( getDoubleValue( values.at( 0 ), parent ) );
594 }
595 static QVariant fcnToString( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
596 {
597  return QVariant( getStringValue( values.at( 0 ), parent ) );
598 }
599 
600 static QVariant fcnToDateTime( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
601 {
602  return QVariant( getDateTimeValue( values.at( 0 ), parent ) );
603 }
604 
605 static QVariant fcnCoalesce( const QVariantList& values, const QgsFeature* , QgsExpression* )
606 {
607  foreach ( const QVariant &value, values )
608  {
609  if ( value.isNull() )
610  continue;
611  return value;
612  }
613  return QVariant();
614 }
615 static QVariant fcnLower( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
616 {
617  QString str = getStringValue( values.at( 0 ), parent );
618  return QVariant( str.toLower() );
619 }
620 static QVariant fcnUpper( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
621 {
622  QString str = getStringValue( values.at( 0 ), parent );
623  return QVariant( str.toUpper() );
624 }
625 static QVariant fcnTitle( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
626 {
627  QString str = getStringValue( values.at( 0 ), parent );
628  QStringList elems = str.split( " " );
629  for ( int i = 0; i < elems.size(); i++ )
630  {
631  if ( elems[i].size() > 1 )
632  elems[i] = elems[i].left( 1 ).toUpper() + elems[i].mid( 1 ).toLower();
633  }
634  return QVariant( elems.join( " " ) );
635 }
636 
637 static QVariant fcnTrim( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
638 {
639  QString str = getStringValue( values.at( 0 ), parent );
640  return QVariant( str.trimmed() );
641 }
642 
643 static QVariant fcnWordwrap( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
644 {
645  if ( values.length() == 2 || values.length() == 3 )
646  {
647  QString str = getStringValue( values.at( 0 ), parent );
648  int wrap = getIntValue( values.at( 1 ), parent );
649 
650  if ( !str.isEmpty() && wrap != 0 )
651  {
652  QString newstr;
653  QString delimiterstr;
654  if ( values.length() == 3 ) delimiterstr = getStringValue( values.at( 2 ), parent );
655  if ( delimiterstr.isEmpty() ) delimiterstr = " ";
656  int delimiterlength = delimiterstr.length();
657 
658  QStringList lines = str.split( "\n" );
659  int strlength, strcurrent, strhit, lasthit;
660 
661  for ( int i = 0; i < lines.size(); i++ )
662  {
663  strlength = lines[i].length();
664  strcurrent = 0;
665  strhit = 0;
666  lasthit = 0;
667 
668  while ( strcurrent < strlength )
669  {
670  // positive wrap value = desired maximum line width to wrap
671  // negative wrap value = desired minimum line width before wrap
672  if ( wrap > 0 )
673  {
674  //first try to locate delimiter backwards
675  strhit = lines[i].lastIndexOf( delimiterstr, strcurrent + wrap );
676  if ( strhit == lasthit || strhit == -1 )
677  {
678  //if no new backward delimiter found, try to locate forward
679  strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
680  }
681  lasthit = strhit;
682  }
683  else
684  {
685  strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
686  }
687  if ( strhit > -1 )
688  {
689  newstr.append( lines[i].midRef( strcurrent , strhit - strcurrent ) );
690  newstr.append( "\n" );
691  strcurrent = strhit + delimiterlength;
692  }
693  else
694  {
695  newstr.append( lines[i].midRef( strcurrent ) );
696  strcurrent = strlength;
697  }
698  }
699  if ( i < lines.size() - 1 ) newstr.append( "\n" );
700  }
701 
702  return QVariant( newstr );
703  }
704  }
705 
706  return QVariant();
707 }
708 
709 static QVariant fcnLength( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
710 {
711  QString str = getStringValue( values.at( 0 ), parent );
712  return QVariant( str.length() );
713 }
714 static QVariant fcnReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
715 {
716  QString str = getStringValue( values.at( 0 ), parent );
717  QString before = getStringValue( values.at( 1 ), parent );
718  QString after = getStringValue( values.at( 2 ), parent );
719  return QVariant( str.replace( before, after ) );
720 }
721 static QVariant fcnRegexpReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
722 {
723  QString str = getStringValue( values.at( 0 ), parent );
724  QString regexp = getStringValue( values.at( 1 ), parent );
725  QString after = getStringValue( values.at( 2 ), parent );
726 
727  QRegExp re( regexp );
728  if ( !re.isValid() )
729  {
730  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
731  return QVariant();
732  }
733  return QVariant( str.replace( re, after ) );
734 }
735 
736 static QVariant fcnRegexpMatch( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
737 {
738  QString str = getStringValue( values.at( 0 ), parent );
739  QString regexp = getStringValue( values.at( 1 ), parent );
740 
741  QRegExp re( regexp );
742  if ( !re.isValid() )
743  {
744  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
745  return QVariant();
746  }
747  return QVariant( str.contains( re ) ? 1 : 0 );
748 }
749 
750 static QVariant fcnRegexpSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
751 {
752  QString str = getStringValue( values.at( 0 ), parent );
753  QString regexp = getStringValue( values.at( 1 ), parent );
754 
755  QRegExp re( regexp );
756  if ( !re.isValid() )
757  {
758  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
759  return QVariant();
760  }
761 
762  // extract substring
763  re.indexIn( str );
764  if ( re.captureCount() > 0 )
765  {
766  // return first capture
767  return QVariant( re.capturedTexts()[1] );
768  }
769  else
770  {
771  return QVariant( "" );
772  }
773 }
774 
775 static QVariant fcnUuid( const QVariantList&, const QgsFeature* , QgsExpression* )
776 {
777  return QUuid::createUuid().toString();
778 }
779 
780 static QVariant fcnSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
781 {
782  QString str = getStringValue( values.at( 0 ), parent );
783  int from = getIntValue( values.at( 1 ), parent );
784  int len = getIntValue( values.at( 2 ), parent );
785  return QVariant( str.mid( from -1, len ) );
786 }
787 
788 static QVariant fcnRowNumber( const QVariantList& , const QgsFeature* , QgsExpression* parent )
789 {
790  return QVariant( parent->currentRowNumber() );
791 }
792 
793 static QVariant fcnFeatureId( const QVariantList& , const QgsFeature* f, QgsExpression* )
794 {
795  // TODO: handling of 64-bit feature ids?
796  return f ? QVariant(( int )f->id() ) : QVariant();
797 }
798 
799 static QVariant fcnFeature( const QVariantList& , const QgsFeature* f, QgsExpression* )
800 {
801  return f ? QVariant::fromValue( *f ) : QVariant();
802 }
803 static QVariant fcnAttribute( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
804 {
805  QgsFeature feat = getFeature( values.at( 0 ), parent );
806  QString attr = getStringValue( values.at( 1 ), parent );
807 
808  return feat.attribute( attr );
809 }
810 static QVariant fcnConcat( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
811 {
812  QString concat;
813  foreach ( const QVariant &value, values )
814  {
815  concat += getStringValue( value, parent );
816  }
817  return concat;
818 }
819 
820 static QVariant fcnStrpos( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
821 {
822  QString string = getStringValue( values.at( 0 ), parent );
823  return string.indexOf( QRegExp( getStringValue( values.at( 1 ), parent ) ) );
824 }
825 
826 static QVariant fcnRight( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
827 {
828  QString string = getStringValue( values.at( 0 ), parent );
829  int pos = getIntValue( values.at( 1 ), parent );
830  return string.right( pos );
831 }
832 
833 static QVariant fcnLeft( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
834 {
835  QString string = getStringValue( values.at( 0 ), parent );
836  int pos = getIntValue( values.at( 1 ), parent );
837  return string.left( pos );
838 }
839 
840 static QVariant fcnRPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
841 {
842  QString string = getStringValue( values.at( 0 ), parent );
843  int length = getIntValue( values.at( 1 ), parent );
844  QString fill = getStringValue( values.at( 2 ), parent );
845  return string.leftJustified( length, fill.at( 0 ), true );
846 }
847 
848 static QVariant fcnLPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
849 {
850  QString string = getStringValue( values.at( 0 ), parent );
851  int length = getIntValue( values.at( 1 ), parent );
852  QString fill = getStringValue( values.at( 2 ), parent );
853  return string.rightJustified( length, fill.at( 0 ), true );
854 }
855 
856 static QVariant fcnFormatString( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
857 {
858  QString string = getStringValue( values.at( 0 ), parent );
859  for ( int n = 1; n < values.length(); n++ )
860  {
861  string = string.arg( getStringValue( values.at( n ), parent ) );
862  }
863  return string;
864 }
865 
866 
867 static QVariant fcnNow( const QVariantList&, const QgsFeature* , QgsExpression * )
868 {
869  return QVariant( QDateTime::currentDateTime() );
870 }
871 
872 static QVariant fcnToDate( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
873 {
874  return QVariant( getDateValue( values.at( 0 ), parent ) );
875 }
876 
877 static QVariant fcnToTime( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
878 {
879  return QVariant( getTimeValue( values.at( 0 ), parent ) );
880 }
881 
882 static QVariant fcnToInterval( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
883 {
884  return QVariant::fromValue( getInterval( values.at( 0 ), parent ) );
885 }
886 
887 static QVariant fcnAge( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
888 {
889  QDateTime d1 = getDateTimeValue( values.at( 0 ), parent );
890  QDateTime d2 = getDateTimeValue( values.at( 1 ), parent );
891  int seconds = d2.secsTo( d1 );
892  return QVariant::fromValue( QgsExpression::Interval( seconds ) );
893 }
894 
895 static QVariant fcnDay( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
896 {
897  QVariant value = values.at( 0 );
898  QgsExpression::Interval inter = getInterval( value, parent, false );
899  if ( inter.isValid() )
900  {
901  return QVariant( inter.days() );
902  }
903  else
904  {
905  QDateTime d1 = getDateTimeValue( value, parent );
906  return QVariant( d1.date().day() );
907  }
908 }
909 
910 static QVariant fcnYear( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
911 {
912  QVariant value = values.at( 0 );
913  QgsExpression::Interval inter = getInterval( value, parent, false );
914  if ( inter.isValid() )
915  {
916  return QVariant( inter.years() );
917  }
918  else
919  {
920  QDateTime d1 = getDateTimeValue( value, parent );
921  return QVariant( d1.date().year() );
922  }
923 }
924 
925 static QVariant fcnMonth( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
926 {
927  QVariant value = values.at( 0 );
928  QgsExpression::Interval inter = getInterval( value, parent, false );
929  if ( inter.isValid() )
930  {
931  return QVariant( inter.months() );
932  }
933  else
934  {
935  QDateTime d1 = getDateTimeValue( value, parent );
936  return QVariant( d1.date().month() );
937  }
938 }
939 
940 static QVariant fcnWeek( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
941 {
942  QVariant value = values.at( 0 );
943  QgsExpression::Interval inter = getInterval( value, parent, false );
944  if ( inter.isValid() )
945  {
946  return QVariant( inter.weeks() );
947  }
948  else
949  {
950  QDateTime d1 = getDateTimeValue( value, parent );
951  return QVariant( d1.date().weekNumber() );
952  }
953 }
954 
955 static QVariant fcnHour( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
956 {
957  QVariant value = values.at( 0 );
958  QgsExpression::Interval inter = getInterval( value, parent, false );
959  if ( inter.isValid() )
960  {
961  return QVariant( inter.hours() );
962  }
963  else
964  {
965  QDateTime d1 = getDateTimeValue( value, parent );
966  return QVariant( d1.time().hour() );
967  }
968 }
969 
970 static QVariant fcnMinute( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
971 {
972  QVariant value = values.at( 0 );
973  QgsExpression::Interval inter = getInterval( value, parent, false );
974  if ( inter.isValid() )
975  {
976  return QVariant( inter.minutes() );
977  }
978  else
979  {
980  QDateTime d1 = getDateTimeValue( value, parent );
981  return QVariant( d1.time().minute() );
982  }
983 }
984 
985 static QVariant fcnSeconds( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
986 {
987  QVariant value = values.at( 0 );
988  QgsExpression::Interval inter = getInterval( value, parent, false );
989  if ( inter.isValid() )
990  {
991  return QVariant( inter.seconds() );
992  }
993  else
994  {
995  QDateTime d1 = getDateTimeValue( value, parent );
996  return QVariant( d1.time().second() );
997  }
998 }
999 
1000 
1001 #define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \
1002  QgsGeometry* g = f->geometry(); \
1003  if (!g || g->type() != geomtype) return QVariant();
1004 
1005 
1006 static QVariant fcnX( const QVariantList& , const QgsFeature* f, QgsExpression* )
1007 {
1008  ENSURE_GEOM_TYPE( f, g, QGis::Point );
1009  if ( g->isMultipart() )
1010  {
1011  return g->asMultiPoint()[ 0 ].x();
1012  }
1013  else
1014  {
1015  return g->asPoint().x();
1016  }
1017 }
1018 static QVariant fcnY( const QVariantList& , const QgsFeature* f, QgsExpression* )
1019 {
1020  ENSURE_GEOM_TYPE( f, g, QGis::Point );
1021  if ( g->isMultipart() )
1022  {
1023  return g->asMultiPoint()[ 0 ].y();
1024  }
1025  else
1026  {
1027  return g->asPoint().y();
1028  }
1029 }
1030 
1031 static QVariant pointAt( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) // helper function
1032 {
1033  int idx = getIntValue( values.at( 0 ), parent );
1034  ENSURE_GEOM_TYPE( f, g, QGis::Line );
1035  QgsPolyline polyline = g->asPolyline();
1036  if ( idx < 0 )
1037  idx += polyline.count();
1038 
1039  if ( idx < 0 || idx >= polyline.count() )
1040  {
1041  parent->setEvalErrorString( QObject::tr( "Index is out of range" ) );
1042  return QVariant();
1043  }
1044  return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) );
1045 }
1046 
1047 static QVariant fcnXat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
1048 {
1049  QVariant v = pointAt( values, f, parent );
1050  if ( v.type() == QVariant::PointF )
1051  return QVariant( v.toPointF().x() );
1052  else
1053  return QVariant();
1054 }
1055 static QVariant fcnYat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
1056 {
1057  QVariant v = pointAt( values, f, parent );
1058  if ( v.type() == QVariant::PointF )
1059  return QVariant( v.toPointF().y() );
1060  else
1061  return QVariant();
1062 }
1063 static QVariant fcnGeometry( const QVariantList& , const QgsFeature* f, QgsExpression* )
1064 {
1065  QgsGeometry* geom = f ? f->geometry() : 0;
1066  if ( geom )
1067  return QVariant::fromValue( *geom );
1068  else
1069  return QVariant();
1070 }
1071 static QVariant fcnGeomFromWKT( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1072 {
1073  QString wkt = getStringValue( values.at( 0 ), parent );
1074  QgsGeometry* geom = QgsGeometry::fromWkt( wkt );
1075  if ( geom )
1076  return QVariant::fromValue( *geom );
1077  else
1078  return QVariant();
1079 }
1080 static QVariant fcnGeomFromGML( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1081 {
1082  QString gml = getStringValue( values.at( 0 ), parent );
1084 
1085  if ( geom )
1086  return QVariant::fromValue( *geom );
1087  else
1088  return QVariant();
1089 }
1090 
1091 static QVariant fcnGeomArea( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1092 {
1094  QgsDistanceArea* calc = parent->geomCalculator();
1095  return QVariant( calc->measure( f->geometry() ) );
1096 }
1097 static QVariant fcnGeomLength( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1098 {
1099  ENSURE_GEOM_TYPE( f, g, QGis::Line );
1100  QgsDistanceArea* calc = parent->geomCalculator();
1101  return QVariant( calc->measure( f->geometry() ) );
1102 }
1103 static QVariant fcnGeomPerimeter( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1104 {
1106  QgsDistanceArea* calc = parent->geomCalculator();
1107  return QVariant( calc->measurePerimeter( f->geometry() ) );
1108 }
1109 
1110 static QVariant fcnBounds( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1111 {
1112  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1113  QgsGeometry* geomBounds = QgsGeometry::fromRect( geom.boundingBox() );
1114  if ( geomBounds )
1115  {
1116  return QVariant::fromValue( *geomBounds );
1117  }
1118  else
1119  {
1120  return QVariant();
1121  }
1122 }
1123 
1124 static QVariant fcnBoundsWidth( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1125 {
1126  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1127  return QVariant::fromValue( geom.boundingBox().width() );
1128 }
1129 
1130 static QVariant fcnBoundsHeight( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1131 {
1132  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1133  return QVariant::fromValue( geom.boundingBox().height() );
1134 }
1135 
1136 static QVariant fcnXMin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1137 {
1138  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1139  return QVariant::fromValue( geom.boundingBox().xMinimum() );
1140 }
1141 
1142 static QVariant fcnXMax( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1143 {
1144  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1145  return QVariant::fromValue( geom.boundingBox().xMaximum() );
1146 }
1147 
1148 static QVariant fcnYMin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1149 {
1150  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1151  return QVariant::fromValue( geom.boundingBox().yMinimum() );
1152 }
1153 
1154 static QVariant fcnYMax( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1155 {
1156  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1157  return QVariant::fromValue( geom.boundingBox().yMaximum() );
1158 }
1159 
1160 static QVariant fcnBbox( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1161 {
1162  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1163  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1164  return fGeom.intersects( sGeom.boundingBox() ) ? TVL_True : TVL_False;
1165 }
1166 static QVariant fcnDisjoint( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1167 {
1168  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1169  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1170  return fGeom.disjoint( &sGeom ) ? TVL_True : TVL_False;
1171 }
1172 static QVariant fcnIntersects( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1173 {
1174  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1175  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1176  return fGeom.intersects( &sGeom ) ? TVL_True : TVL_False;
1177 }
1178 static QVariant fcnTouches( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1179 {
1180  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1181  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1182  return fGeom.touches( &sGeom ) ? TVL_True : TVL_False;
1183 }
1184 static QVariant fcnCrosses( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1185 {
1186  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1187  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1188  return fGeom.crosses( &sGeom ) ? TVL_True : TVL_False;
1189 }
1190 static QVariant fcnContains( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1191 {
1192  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1193  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1194  return fGeom.contains( &sGeom ) ? TVL_True : TVL_False;
1195 }
1196 static QVariant fcnOverlaps( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1197 {
1198  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1199  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1200  return fGeom.overlaps( &sGeom ) ? TVL_True : TVL_False;
1201 }
1202 static QVariant fcnWithin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1203 {
1204  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1205  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1206  return fGeom.within( &sGeom ) ? TVL_True : TVL_False;
1207 }
1208 static QVariant fcnBuffer( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1209 {
1210  if ( values.length() < 2 || values.length() > 3 )
1211  return QVariant();
1212 
1213  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1214  double dist = getDoubleValue( values.at( 1 ), parent );
1215  int seg = 8;
1216  if ( values.length() == 3 )
1217  seg = getIntValue( values.at( 2 ), parent );
1218 
1219  QgsGeometry* geom = fGeom.buffer( dist, seg );
1220  if ( geom )
1221  return QVariant::fromValue( *geom );
1222  return QVariant();
1223 }
1224 static QVariant fcnCentroid( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1225 {
1226  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1227  QgsGeometry* geom = fGeom.centroid();
1228  if ( geom )
1229  return QVariant::fromValue( *geom );
1230  return QVariant();
1231 }
1232 static QVariant fcnConvexHull( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1233 {
1234  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1235  QgsGeometry* geom = fGeom.convexHull();
1236  if ( geom )
1237  return QVariant::fromValue( *geom );
1238  return QVariant();
1239 }
1240 static QVariant fcnDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1241 {
1242  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1243  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1244  QgsGeometry* geom = fGeom.difference( &sGeom );
1245  if ( geom )
1246  return QVariant::fromValue( *geom );
1247  return QVariant();
1248 }
1249 static QVariant fcnDistance( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1250 {
1251  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1252  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1253  return QVariant( fGeom.distance( sGeom ) );
1254 }
1255 static QVariant fcnIntersection( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1256 {
1257  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1258  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1259  QgsGeometry* geom = fGeom.intersection( &sGeom );
1260  if ( geom )
1261  return QVariant::fromValue( *geom );
1262  return QVariant();
1263 }
1264 static QVariant fcnSymDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1265 {
1266  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1267  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1268  QgsGeometry* geom = fGeom.symDifference( &sGeom );
1269  if ( geom )
1270  return QVariant::fromValue( *geom );
1271  return QVariant();
1272 }
1273 static QVariant fcnCombine( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1274 {
1275  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1276  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1277  QgsGeometry* geom = fGeom.combine( &sGeom );
1278  if ( geom )
1279  return QVariant::fromValue( *geom );
1280  return QVariant();
1281 }
1282 static QVariant fcnGeomToWKT( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1283 {
1284  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1285  QString wkt = fGeom.exportToWkt();
1286  return QVariant( wkt );
1287 }
1288 
1289 static QVariant fcnRound( const QVariantList& values , const QgsFeature *f, QgsExpression* parent )
1290 {
1291  Q_UNUSED( f );
1292  if ( values.length() == 2 )
1293  {
1294  double number = getDoubleValue( values.at( 0 ), parent );
1295  double scaler = pow( 10.0, getIntValue( values.at( 1 ), parent ) );
1296  return QVariant( qRound( number * scaler ) / scaler );
1297  }
1298 
1299  if ( values.length() == 1 )
1300  {
1301  double number = getIntValue( values.at( 0 ), parent );
1302  return QVariant( qRound( number ) ).toInt();
1303  }
1304 
1305  return QVariant();
1306 }
1307 
1308 static QVariant fcnPi( const QVariantList& values , const QgsFeature *f, QgsExpression* parent )
1309 {
1310  Q_UNUSED( values );
1311  Q_UNUSED( f );
1312  Q_UNUSED( parent );
1313  return M_PI;
1314 }
1315 
1316 static QVariant fcnScale( const QVariantList&, const QgsFeature*, QgsExpression* parent )
1317 {
1318  return QVariant( parent->scale() );
1319 }
1320 
1321 static QVariant fcnFormatNumber( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1322 {
1323  double value = getDoubleValue( values.at( 0 ), parent );
1324  int places = getIntValue( values.at( 1 ), parent );
1325  return QString( "%L1" ).arg( value, 0, 'f', places );
1326 }
1327 
1328 static QVariant fcnFormatDate( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1329 {
1330  QDateTime dt = getDateTimeValue( values.at( 0 ), parent );
1331  QString format = getStringValue( values.at( 1 ), parent );
1332  return dt.toString( format );
1333 }
1334 
1335 static QVariant fcnColorRgb( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1336 {
1337  int red = getIntValue( values.at( 0 ), parent );
1338  int green = getIntValue( values.at( 1 ), parent );
1339  int blue = getIntValue( values.at( 2 ), parent );
1340  QColor color = QColor( red, green, blue );
1341  if ( ! color.isValid() )
1342  {
1343  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
1344  color = QColor( 0, 0, 0 );
1345  }
1346 
1347  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1348 }
1349 
1350 static QVariant fncColorRgba( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1351 {
1352  int red = getIntValue( values.at( 0 ), parent );
1353  int green = getIntValue( values.at( 1 ), parent );
1354  int blue = getIntValue( values.at( 2 ), parent );
1355  int alpha = getIntValue( values.at( 3 ), parent );
1356  QColor color = QColor( red, green, blue, alpha );
1357  if ( ! color.isValid() )
1358  {
1359  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
1360  color = QColor( 0, 0, 0 );
1361  }
1362  return QgsSymbolLayerV2Utils::encodeColor( color );
1363 }
1364 
1365 QVariant fcnRampColor( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1366 {
1367  QString rampName = getStringValue( values.at( 0 ), parent );
1368  const QgsVectorColorRampV2 *mRamp = QgsStyleV2::defaultStyle()->colorRampRef( rampName );
1369  if ( ! mRamp )
1370  {
1371  parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) );
1372  return QColor( 0, 0, 0 ).name();
1373  }
1374  double value = getDoubleValue( values.at( 1 ), parent );
1375  QColor color = mRamp->color( value );
1376  return QgsSymbolLayerV2Utils::encodeColor( color );
1377 }
1378 
1379 static QVariant fcnColorHsl( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1380 {
1381  // Hue ranges from 0 - 360
1382  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1383  // Saturation ranges from 0 - 100
1384  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1385  // Lightness ranges from 0 - 100
1386  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1387 
1388  QColor color = QColor::fromHslF( hue, saturation, lightness );
1389 
1390  if ( ! color.isValid() )
1391  {
1392  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
1393  color = QColor( 0, 0, 0 );
1394  }
1395 
1396  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1397 }
1398 
1399 static QVariant fncColorHsla( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1400 {
1401  // Hue ranges from 0 - 360
1402  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1403  // Saturation ranges from 0 - 100
1404  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1405  // Lightness ranges from 0 - 100
1406  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1407  // Alpha ranges from 0 - 255
1408  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1409 
1410  QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
1411  if ( ! color.isValid() )
1412  {
1413  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
1414  color = QColor( 0, 0, 0 );
1415  }
1416  return QgsSymbolLayerV2Utils::encodeColor( color );
1417 }
1418 
1419 static QVariant fcnColorHsv( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1420 {
1421  // Hue ranges from 0 - 360
1422  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1423  // Saturation ranges from 0 - 100
1424  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1425  // Value ranges from 0 - 100
1426  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1427 
1428  QColor color = QColor::fromHsvF( hue, saturation, value );
1429 
1430  if ( ! color.isValid() )
1431  {
1432  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
1433  color = QColor( 0, 0, 0 );
1434  }
1435 
1436  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1437 }
1438 
1439 static QVariant fncColorHsva( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1440 {
1441  // Hue ranges from 0 - 360
1442  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1443  // Saturation ranges from 0 - 100
1444  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1445  // Value ranges from 0 - 100
1446  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1447  // Alpha ranges from 0 - 255
1448  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1449 
1450  QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
1451  if ( ! color.isValid() )
1452  {
1453  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
1454  color = QColor( 0, 0, 0 );
1455  }
1456  return QgsSymbolLayerV2Utils::encodeColor( color );
1457 }
1458 
1459 static QVariant fcnColorCmyk( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1460 {
1461  // Cyan ranges from 0 - 100
1462  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1463  // Magenta ranges from 0 - 100
1464  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1465  // Yellow ranges from 0 - 100
1466  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1467  // Black ranges from 0 - 100
1468  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1469 
1470  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
1471 
1472  if ( ! color.isValid() )
1473  {
1474  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
1475  color = QColor( 0, 0, 0 );
1476  }
1477 
1478  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1479 }
1480 
1481 static QVariant fncColorCmyka( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1482 {
1483  // Cyan ranges from 0 - 100
1484  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1485  // Magenta ranges from 0 - 100
1486  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1487  // Yellow ranges from 0 - 100
1488  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1489  // Black ranges from 0 - 100
1490  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1491  // Alpha ranges from 0 - 255
1492  double alpha = getIntValue( values.at( 4 ), parent ) / 255.0;
1493 
1494  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
1495  if ( ! color.isValid() )
1496  {
1497  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
1498  color = QColor( 0, 0, 0 );
1499  }
1500  return QgsSymbolLayerV2Utils::encodeColor( color );
1501 }
1502 
1503 static QVariant fcnSpecialColumn( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent )
1504 {
1505  QString varName = getStringValue( values.at( 0 ), parent );
1506  return QgsExpression::specialColumn( varName );
1507 }
1508 
1509 static QVariant fcnGetFeature( const QVariantList& values, const QgsFeature *, QgsExpression* parent )
1510 {
1511  //arguments: 1. layer id / name, 2. key attribute, 3. eq value
1512  QString layerString = getStringValue( values.at( 0 ), parent );
1513  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerString ) ); //search by id first
1514  if ( !vl )
1515  {
1516  QList<QgsMapLayer *> layersByName = QgsMapLayerRegistry::instance()->mapLayersByName( layerString );
1517  if ( layersByName.size() > 0 )
1518  {
1519  vl = qobject_cast<QgsVectorLayer*>( layersByName.at( 0 ) );
1520  }
1521  }
1522 
1523  //no layer found
1524  if ( !vl )
1525  {
1526  return QVariant();
1527  }
1528 
1529  QString attribute = getStringValue( values.at( 1 ), parent );
1530  int attributeId = vl->fieldNameIndex( attribute );
1531  if ( attributeId == -1 )
1532  {
1533  return QVariant();
1534  }
1535 
1536  const QVariant& attVal = values.at( 2 );
1537  QgsFeatureRequest req;
1538  if ( !parent->needsGeometry() )
1539  {
1541  }
1542  QgsFeatureIterator fIt = vl->getFeatures( req );
1543 
1544  QgsFeature fet;
1545  while ( fIt.nextFeature( fet ) )
1546  {
1547  if ( fet.attribute( attributeId ) == attVal )
1548  {
1549  return QVariant::fromValue( fet );
1550  }
1551  }
1552  return QVariant();
1553 }
1554 
1556 {
1557  int fnIdx = functionIndex( function->name() );
1558  if ( fnIdx != -1 )
1559  {
1560  return false;
1561  }
1562  QgsExpression::gmFunctions.append( function );
1563  return true;
1564 }
1565 
1567 {
1568  // You can never override the built in functions.
1569  if ( QgsExpression::BuiltinFunctions().contains( name ) )
1570  {
1571  return false;
1572  }
1573  int fnIdx = functionIndex( name );
1574  if ( fnIdx != -1 )
1575  {
1576  QgsExpression::gmFunctions.removeAt( fnIdx );
1577  return true;
1578  }
1579  return false;
1580 }
1581 
1582 
1583 
1585 
1587 {
1588  if ( gmBuiltinFunctions.isEmpty() )
1589  {
1591  << "abs" << "sqrt" << "cos" << "sin" << "tan"
1592  << "asin" << "acos" << "atan" << "atan2"
1593  << "exp" << "ln" << "log10" << "log"
1594  << "round" << "rand" << "randf" << "max" << "min" << "clamp"
1595  << "scale_linear" << "scale_exp" << "floor" << "ceil"
1596  << "toint" << "toreal" << "tostring"
1597  << "todatetime" << "todate" << "totime" << "tointerval"
1598  << "coalesce" << "regexp_match" << "$now" << "age" << "year"
1599  << "month" << "week" << "day" << "hour"
1600  << "minute" << "second" << "lower" << "upper"
1601  << "title" << "length" << "replace" << "trim" << "wordwrap"
1602  << "regexp_replace" << "regexp_substr"
1603  << "substr" << "concat" << "strpos" << "left"
1604  << "right" << "rpad" << "lpad"
1605  << "format_number" << "format_date"
1606  << "color_rgb" << "color_rgba" << "ramp_color"
1607  << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva"
1608  << "color_cymk" << "color_cymka"
1609  << "xat" << "yat" << "$area"
1610  << "$length" << "$perimeter" << "$x" << "$y"
1611  << "$rownum" << "$id" << "$scale" << "_specialcol_";
1612  }
1613  return gmBuiltinFunctions;
1614 }
1615 
1616 QList<QgsExpression::Function*> QgsExpression::gmFunctions;
1617 
1618 const QList<QgsExpression::Function*> &QgsExpression::Functions()
1619 {
1620  if ( gmFunctions.isEmpty() )
1621  {
1622  gmFunctions
1623  << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
1624  << new StaticFunction( "abs", 1, fcnAbs, "Math" )
1625  << new StaticFunction( "cos", 1, fcnCos, "Math" )
1626  << new StaticFunction( "sin", 1, fcnSin, "Math" )
1627  << new StaticFunction( "tan", 1, fcnTan, "Math" )
1628  << new StaticFunction( "asin", 1, fcnAsin, "Math" )
1629  << new StaticFunction( "acos", 1, fcnAcos, "Math" )
1630  << new StaticFunction( "atan", 1, fcnAtan, "Math" )
1631  << new StaticFunction( "atan2", 2, fcnAtan2, "Math" )
1632  << new StaticFunction( "exp", 1, fcnExp, "Math" )
1633  << new StaticFunction( "ln", 1, fcnLn, "Math" )
1634  << new StaticFunction( "log10", 1, fcnLog10, "Math" )
1635  << new StaticFunction( "log", 2, fcnLog, "Math" )
1636  << new StaticFunction( "round", -1, fcnRound, "Math" )
1637  << new StaticFunction( "rand", 2, fcnRnd, "Math" )
1638  << new StaticFunction( "randf", 2, fcnRndF, "Math" )
1639  << new StaticFunction( "max", -1, fcnMax, "Math" )
1640  << new StaticFunction( "min", -1, fcnMin, "Math" )
1641  << new StaticFunction( "clamp", 3, fcnClamp, "Math" )
1642  << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" )
1643  << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" )
1644  << new StaticFunction( "floor", 1, fcnFloor, "Math" )
1645  << new StaticFunction( "ceil", 1, fcnCeil, "Math" )
1646  << new StaticFunction( "$pi", 0, fcnPi, "Math" )
1647  << new StaticFunction( "toint", 1, fcnToInt, "Conversions" )
1648  << new StaticFunction( "toreal", 1, fcnToReal, "Conversions" )
1649  << new StaticFunction( "tostring", 1, fcnToString, "Conversions" )
1650  << new StaticFunction( "todatetime", 1, fcnToDateTime, "Conversions" )
1651  << new StaticFunction( "todate", 1, fcnToDate, "Conversions" )
1652  << new StaticFunction( "totime", 1, fcnToTime, "Conversions" )
1653  << new StaticFunction( "tointerval", 1, fcnToInterval, "Conversions" )
1654  << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" )
1655  << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
1656  << new StaticFunction( "$now", 0, fcnNow, "Date and Time" )
1657  << new StaticFunction( "age", 2, fcnAge, "Date and Time" )
1658  << new StaticFunction( "year", 1, fcnYear, "Date and Time" )
1659  << new StaticFunction( "month", 1, fcnMonth, "Date and Time" )
1660  << new StaticFunction( "week", 1, fcnWeek, "Date and Time" )
1661  << new StaticFunction( "day", 1, fcnDay, "Date and Time" )
1662  << new StaticFunction( "hour", 1, fcnHour, "Date and Time" )
1663  << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" )
1664  << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" )
1665  << new StaticFunction( "lower", 1, fcnLower, "String" )
1666  << new StaticFunction( "upper", 1, fcnUpper, "String" )
1667  << new StaticFunction( "title", 1, fcnTitle, "String" )
1668  << new StaticFunction( "trim", 1, fcnTrim, "String" )
1669  << new StaticFunction( "wordwrap", -1, fcnWordwrap, "String" )
1670  << new StaticFunction( "length", 1, fcnLength, "String" )
1671  << new StaticFunction( "replace", 3, fcnReplace, "String" )
1672  << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
1673  << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
1674  << new StaticFunction( "substr", 3, fcnSubstr, "String" )
1675  << new StaticFunction( "concat", -1, fcnConcat, "String" )
1676  << new StaticFunction( "strpos", 2, fcnStrpos, "String" )
1677  << new StaticFunction( "left", 2, fcnLeft, "String" )
1678  << new StaticFunction( "right", 2, fcnRight, "String" )
1679  << new StaticFunction( "rpad", 3, fcnRPad, "String" )
1680  << new StaticFunction( "lpad", 3, fcnLPad, "String" )
1681  << new StaticFunction( "format", -1, fcnFormatString, "String" )
1682  << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
1683  << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
1684  << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
1685  << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
1686  << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
1687  << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" )
1688  << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" )
1689  << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" )
1690  << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" )
1691  << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" )
1692  << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" )
1693  << new StaticFunction( "$geometry", 0, fcnGeometry, "Geometry", "" , true )
1694  << new StaticFunction( "$area", 0, fcnGeomArea, "Geometry", "", true )
1695  << new StaticFunction( "$length", 0, fcnGeomLength, "Geometry", "", true )
1696  << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "Geometry", "", true )
1697  << new StaticFunction( "$x", 0, fcnX, "Geometry", "", true )
1698  << new StaticFunction( "$y", 0, fcnY, "Geometry", "" , true )
1699  << new StaticFunction( "xat", 1, fcnXat, "Geometry", "", true )
1700  << new StaticFunction( "yat", 1, fcnYat, "Geometry", "", true )
1701  << new StaticFunction( "xmin", 1, fcnXMin, "Geometry", "", true )
1702  << new StaticFunction( "xmax", 1, fcnXMax, "Geometry", "", true )
1703  << new StaticFunction( "ymin", 1, fcnYMin, "Geometry", "", true )
1704  << new StaticFunction( "ymax", 1, fcnYMax, "Geometry", "", true )
1705  << new StaticFunction( "geomFromWKT", 1, fcnGeomFromWKT, "Geometry" )
1706  << new StaticFunction( "geomFromGML", 1, fcnGeomFromGML, "Geometry" )
1707  << new StaticFunction( "bbox", 2, fcnBbox, "Geometry" )
1708  << new StaticFunction( "disjoint", 2, fcnDisjoint, "Geometry" )
1709  << new StaticFunction( "intersects", 2, fcnIntersects, "Geometry" )
1710  << new StaticFunction( "touches", 2, fcnTouches, "Geometry" )
1711  << new StaticFunction( "crosses", 2, fcnCrosses, "Geometry" )
1712  << new StaticFunction( "contains", 2, fcnContains, "Geometry" )
1713  << new StaticFunction( "overlaps", 2, fcnOverlaps, "Geometry" )
1714  << new StaticFunction( "within", 2, fcnWithin, "Geometry" )
1715  << new StaticFunction( "buffer", -1, fcnBuffer, "Geometry" )
1716  << new StaticFunction( "centroid", 1, fcnCentroid, "Geometry" )
1717  << new StaticFunction( "bounds", 1, fcnBounds, "Geometry", "", true )
1718  << new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "Geometry", "", true )
1719  << new StaticFunction( "bounds_height", 1, fcnBoundsHeight, "Geometry", "", true )
1720  << new StaticFunction( "convexHull", 1, fcnConvexHull, "Geometry" )
1721  << new StaticFunction( "difference", 2, fcnDifference, "Geometry" )
1722  << new StaticFunction( "distance", 2, fcnDistance, "Geometry" )
1723  << new StaticFunction( "intersection", 2, fcnIntersection, "Geometry" )
1724  << new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" )
1725  << new StaticFunction( "combine", 2, fcnCombine, "Geometry" )
1726  << new StaticFunction( "union", 2, fcnCombine, "Geometry" )
1727  << new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" )
1728  << new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
1729  << new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
1730  << new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
1731  << new StaticFunction( "$scale", 0, fcnScale, "Record" )
1732  << new StaticFunction( "$uuid", 0, fcnUuid, "Record" )
1733  << new StaticFunction( "getFeature", 3, fcnGetFeature, "Record" )
1734 
1735  //return all attributes string for referencedColumns - this is caught by
1736  // QgsFeatureRequest::setSubsetOfAttributes and causes all attributes to be fetched by the
1737  // feature request
1738  << new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
1739 
1740  << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
1741  ;
1742  }
1743  return gmFunctions;
1744 }
1745 
1746 QMap<QString, QVariant> QgsExpression::gmSpecialColumns;
1747 QMap<QString, QString> QgsExpression::gmSpecialColumnGroups;
1748 
1749 void QgsExpression::setSpecialColumn( const QString& name, QVariant variant )
1750 {
1751  int fnIdx = functionIndex( name );
1752  if ( fnIdx != -1 )
1753  {
1754  // function of the same name already exists
1755  return;
1756  }
1757  gmSpecialColumns[ name ] = variant;
1758 }
1759 
1760 void QgsExpression::unsetSpecialColumn( const QString& name )
1761 {
1762  QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name );
1763  if ( fit != gmSpecialColumns.end() )
1764  {
1765  gmSpecialColumns.erase( fit );
1766  }
1767 }
1768 
1769 QVariant QgsExpression::specialColumn( const QString& name )
1770 {
1771  int fnIdx = functionIndex( name );
1772  if ( fnIdx != -1 )
1773  {
1774  // function of the same name already exists
1775  return QVariant();
1776  }
1777  QMap<QString, QVariant>::iterator it = gmSpecialColumns.find( name );
1778  if ( it == gmSpecialColumns.end() )
1779  {
1780  return QVariant();
1781  }
1782  return it.value();
1783 }
1784 
1785 bool QgsExpression::hasSpecialColumn( const QString& name )
1786 {
1787  static bool initialized = false;
1788  if ( !initialized )
1789  {
1790  // Pre-register special columns that will exist within QGIS so that expressions that may use them are parsed correctly.
1791  // This is really sub-optimal, we should get rid of the special columns and instead have contexts in which some values
1792  // are defined and some are not ($rownum makes sense only in field calculator, $scale only when rendering, $page only for composer etc.)
1793 
1794  //pairs of column name to group name
1795  QList< QPair<QString, QString> > lst;
1796  lst << qMakePair( QString( "$page" ), QString( "Composer" ) );
1797  lst << qMakePair( QString( "$feature" ), QString( "Atlas" ) );
1798  lst << qMakePair( QString( "$numpages" ), QString( "Composer" ) );
1799  lst << qMakePair( QString( "$numfeatures" ), QString( "Atlas" ) );
1800  lst << qMakePair( QString( "$atlasfeatureid" ), QString( "Atlas" ) );
1801  lst << qMakePair( QString( "$atlasgeometry" ), QString( "Atlas" ) );
1802  lst << qMakePair( QString( "$atlasfeature" ), QString( "Atlas" ) );
1803  lst << qMakePair( QString( "$map" ), QString( "Composer" ) );
1804 
1805  QList< QPair<QString, QString> >::const_iterator it = lst.constBegin();
1806  for ( ; it != lst.constEnd(); ++it )
1807  {
1808  setSpecialColumn(( *it ).first, QVariant() );
1809  gmSpecialColumnGroups[( *it ).first ] = ( *it ).second;
1810  }
1811 
1812  initialized = true;
1813  }
1814 
1815  if ( functionIndex( name ) != -1 )
1816  return false;
1817  return gmSpecialColumns.contains( name );
1818 }
1819 
1820 bool QgsExpression::isValid( const QString &text, const QgsFields &fields, QString &errorMessage )
1821 {
1822  QgsExpression exp( text );
1823  exp.prepare( fields );
1824  errorMessage = exp.parserErrorString();
1825  return !exp.hasParserError();
1826 }
1827 
1828 QList<QgsExpression::Function*> QgsExpression::specialColumns()
1829 {
1830  QList<Function*> defs;
1831  for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.begin(); it != gmSpecialColumns.end(); ++it )
1832  {
1833  //check for special column group name
1834  QString group = gmSpecialColumnGroups.value( it.key(), "Record" );
1835  defs << new StaticFunction( it.key(), 0, 0, group );
1836  }
1837  return defs;
1838 }
1839 
1840 QString QgsExpression::quotedColumnRef( QString name )
1841 {
1842  return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) );
1843 }
1844 
1845 QString QgsExpression::quotedString( QString text )
1846 {
1847  text.replace( "'", "''" );
1848  text.replace( '\\', "\\\\" );
1849  text.replace( '\n', "\\n" );
1850  text.replace( '\t', "\\t" );
1851  return QString( "'%1'" ).arg( text );
1852 }
1853 
1854 bool QgsExpression::isFunctionName( QString name )
1855 {
1856  return functionIndex( name ) != -1;
1857 }
1858 
1859 int QgsExpression::functionIndex( QString name )
1860 {
1861  int count = functionCount();
1862  for ( int i = 0; i < count; i++ )
1863  {
1864  if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
1865  return i;
1866  }
1867  return -1;
1868 }
1869 
1871 {
1872  return Functions().size();
1873 }
1874 
1875 
1876 QgsExpression::QgsExpression( const QString& expr )
1877  : mRowNumber( 0 )
1878  , mScale( 0 )
1879  , mExp( expr )
1880  , mCalc( 0 )
1881 {
1883 
1884  if ( mParserErrorString.isNull() )
1885  Q_ASSERT( mRootNode );
1886 }
1887 
1889 {
1890  delete mCalc;
1891  delete mRootNode;
1892 }
1893 
1895 {
1896  if ( !mRootNode )
1897  return QStringList();
1898 
1899  QStringList columns = mRootNode->referencedColumns();
1900 
1901  // filter out duplicates
1902  for ( int i = 0; i < columns.count(); i++ )
1903  {
1904  QString col = columns.at( i );
1905  for ( int j = i + 1; j < columns.count(); j++ )
1906  {
1907  if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
1908  {
1909  // this column is repeated: remove it!
1910  columns.removeAt( j-- );
1911  }
1912  }
1913  }
1914 
1915  return columns;
1916 }
1917 
1919 {
1920  if ( !mRootNode )
1921  return false;
1922  return mRootNode->needsGeometry();
1923 }
1924 
1926 {
1927  if ( mCalc )
1928  return;
1929 
1930  // Use planimetric as default
1931  mCalc = new QgsDistanceArea();
1932  mCalc->setEllipsoidalMode( false );
1933 }
1934 
1936 {
1937  delete mCalc;
1938  mCalc = new QgsDistanceArea( calc );
1939 }
1940 
1941 bool QgsExpression::prepare( const QgsFields& fields )
1942 {
1943  mEvalErrorString = QString();
1944  if ( !mRootNode )
1945  {
1946  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1947  return false;
1948  }
1949 
1950  return mRootNode->prepare( this, fields );
1951 }
1952 
1954 {
1955  mEvalErrorString = QString();
1956  if ( !mRootNode )
1957  {
1958  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1959  return QVariant();
1960  }
1961 
1962  return mRootNode->eval( this, f );
1963 }
1964 
1965 QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields )
1966 {
1967  // first prepare
1968  bool res = prepare( fields );
1969  if ( !res )
1970  return QVariant();
1971 
1972  // then evaluate
1973  return evaluate( f );
1974 }
1975 
1976 QString QgsExpression::dump() const
1977 {
1978  if ( !mRootNode )
1979  return QObject::tr( "(no root)" );
1980 
1981  return mRootNode->dump();
1982 }
1983 
1985 {
1986  if ( mRootNode )
1987  mRootNode->accept( v );
1988 }
1989 
1990 QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
1991  QgsVectorLayer *layer,
1992  const QMap<QString, QVariant> *substitutionMap )
1993 {
1994  QString expr_action;
1995 
1996  QMap<QString, QVariant> savedValues;
1997  if ( substitutionMap )
1998  {
1999  // variables with a local scope (must be restored after evaluation)
2000  for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
2001  {
2002  QVariant oldValue = QgsExpression::specialColumn( sit.key() );
2003  if ( !oldValue.isNull() )
2004  savedValues.insert( sit.key(), oldValue );
2005 
2006  // set the new value
2007  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2008  }
2009  }
2010 
2011  int index = 0;
2012  while ( index < action.size() )
2013  {
2014  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
2015 
2016  int pos = rx.indexIn( action, index );
2017  if ( pos < 0 )
2018  break;
2019 
2020  int start = index;
2021  index = pos + rx.matchedLength();
2022  QString to_replace = rx.cap( 1 ).trimmed();
2023  QgsDebugMsg( "Found expression: " + to_replace );
2024 
2025  QgsExpression exp( to_replace );
2026  if ( exp.hasParserError() )
2027  {
2028  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
2029  expr_action += action.mid( start, index - start );
2030  continue;
2031  }
2032 
2033  QVariant result;
2034  if ( layer )
2035  {
2036  result = exp.evaluate( feat, layer->pendingFields() );
2037  }
2038  else
2039  {
2040  result = exp.evaluate( feat );
2041  }
2042  if ( exp.hasEvalError() )
2043  {
2044  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
2045  expr_action += action.mid( start, index - start );
2046  continue;
2047  }
2048 
2049  QgsDebugMsg( "Expression result is: " + result.toString() );
2050  expr_action += action.mid( start, pos - start ) + result.toString();
2051  }
2052 
2053  expr_action += action.mid( index );
2054 
2055  // restore overwritten local values
2056  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
2057  {
2058  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2059  }
2060 
2061  return expr_action;
2062 }
2063 
2064 
2066 // nodes
2067 
2069 {
2070  QString msg; bool first = true;
2071  foreach ( Node* n, mList )
2072  {
2073  if ( !first ) msg += ", "; else first = false;
2074  msg += n->dump();
2075  }
2076  return msg;
2077 }
2078 
2079 
2080 //
2081 
2083 {
2084  QVariant val = mOperand->eval( parent, f );
2086 
2087  switch ( mOp )
2088  {
2089  case uoNot:
2090  {
2091  TVL tvl = getTVLValue( val, parent );
2093  return tvl2variant( NOT[tvl] );
2094  }
2095 
2096  case uoMinus:
2097  if ( isIntSafe( val ) )
2098  return QVariant( - getIntValue( val, parent ) );
2099  else if ( isDoubleSafe( val ) )
2100  return QVariant( - getDoubleValue( val, parent ) );
2101  else
2102  SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
2103  break;
2104  default:
2105  Q_ASSERT( 0 && "unknown unary operation" );
2106  }
2107  return QVariant();
2108 }
2109 
2111 {
2112  return mOperand->prepare( parent, fields );
2113 }
2114 
2116 {
2117  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
2118 }
2119 
2120 //
2121 
2123 {
2124  QVariant vL = mOpLeft->eval( parent, f );
2126  QVariant vR = mOpRight->eval( parent, f );
2128 
2129  switch ( mOp )
2130  {
2131  case boPlus:
2132  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
2133  {
2134  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2135  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2136  return QVariant( sL + sR );
2137  }
2138  case boMinus:
2139  case boMul:
2140  case boDiv:
2141  case boMod:
2142  if ( isNull( vL ) || isNull( vR ) )
2143  return QVariant();
2144  else if ( isIntSafe( vL ) && isIntSafe( vR ) )
2145  {
2146  // both are integers - let's use integer arithmetics
2147  int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2148  int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2149  if ( mOp == boDiv && iR == 0 ) return QVariant(); // silently handle division by zero and return NULL
2150  return QVariant( computeInt( iL, iR ) );
2151  }
2152  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
2153  {
2154  QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2156  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
2157  {
2158  parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
2159  return QVariant();
2160  }
2161  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
2162  }
2163  else
2164  {
2165  // general floating point arithmetic
2166  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2167  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2168  if ( mOp == boDiv && fR == 0 )
2169  return QVariant(); // silently handle division by zero and return NULL
2170  return QVariant( computeDouble( fL, fR ) );
2171  }
2172 
2173  case boPow:
2174  if ( isNull( vL ) || isNull( vR ) )
2175  return QVariant();
2176  else
2177  {
2178  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2179  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2180  return QVariant( pow( fL, fR ) );
2181  }
2182 
2183  case boAnd:
2184  {
2185  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2187  return tvl2variant( AND[tvlL][tvlR] );
2188  }
2189 
2190  case boOr:
2191  {
2192  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2194  return tvl2variant( OR[tvlL][tvlR] );
2195  }
2196 
2197  case boEQ:
2198  case boNE:
2199  case boLT:
2200  case boGT:
2201  case boLE:
2202  case boGE:
2203  if ( isNull( vL ) || isNull( vR ) )
2204  {
2205  return TVL_Unknown;
2206  }
2207  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2208  {
2209  // do numeric comparison if both operators can be converted to numbers
2210  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2211  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2212  return compare( fL - fR ) ? TVL_True : TVL_False;
2213  }
2214  else
2215  {
2216  // do string comparison otherwise
2217  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2218  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2219  int diff = QString::compare( sL, sR );
2220  return compare( diff ) ? TVL_True : TVL_False;
2221  }
2222 
2223  case boIs:
2224  case boIsNot:
2225  if ( isNull( vL ) && isNull( vR ) ) // both operators null
2226  return ( mOp == boIs ? TVL_True : TVL_False );
2227  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
2228  return ( mOp == boIs ? TVL_False : TVL_True );
2229  else // both operators non-null
2230  {
2231  bool equal = false;
2232  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2233  {
2234  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2235  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2236  equal = fL == fR;
2237  }
2238  else
2239  {
2240  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2241  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2242  equal = QString::compare( sL, sR ) == 0;
2243  }
2244  if ( equal )
2245  return mOp == boIs ? TVL_True : TVL_False;
2246  else
2247  return mOp == boIs ? TVL_False : TVL_True;
2248  }
2249 
2250  case boRegexp:
2251  case boLike:
2252  case boNotLike:
2253  case boILike:
2254  case boNotILike:
2255  if ( isNull( vL ) || isNull( vR ) )
2256  return TVL_Unknown;
2257  else
2258  {
2259  QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2260  QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2261  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
2262  bool matches;
2263  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
2264  {
2265  QString esc_regexp = QRegExp::escape( regexp );
2266  // XXX escape % and _ ???
2267  esc_regexp.replace( "%", ".*" );
2268  esc_regexp.replace( "_", "." );
2269  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
2270  }
2271  else
2272  {
2273  matches = QRegExp( regexp ).indexIn( str ) != -1;
2274  }
2275 
2276  if ( mOp == boNotLike || mOp == boNotILike )
2277  {
2278  matches = !matches;
2279  }
2280 
2281  return matches ? TVL_True : TVL_False;
2282  }
2283 
2284  case boConcat:
2285  if ( isNull( vL ) || isNull( vR ) )
2286  return QVariant();
2287  else
2288  {
2289  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2290  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2291  return QVariant( sL + sR );
2292  }
2293 
2294  default: break;
2295  }
2296  Q_ASSERT( false );
2297  return QVariant();
2298 }
2299 
2301 {
2302  switch ( mOp )
2303  {
2304  case boEQ: return diff == 0;
2305  case boNE: return diff != 0;
2306  case boLT: return diff < 0;
2307  case boGT: return diff > 0;
2308  case boLE: return diff <= 0;
2309  case boGE: return diff >= 0;
2310  default: Q_ASSERT( false ); return false;
2311  }
2312 }
2313 
2315 {
2316  switch ( mOp )
2317  {
2318  case boPlus: return x+y;
2319  case boMinus: return x-y;
2320  case boMul: return x*y;
2321  case boDiv: return x/y;
2322  case boMod: return x%y;
2323  default: Q_ASSERT( false ); return 0;
2324  }
2325 }
2326 
2328 {
2329  switch ( mOp )
2330  {
2331  case boPlus: return d.addSecs( i->seconds() );
2332  case boMinus: return d.addSecs( -i->seconds() );
2333  default: Q_ASSERT( false ); return QDateTime();
2334  }
2335 }
2336 
2338 {
2339  switch ( mOp )
2340  {
2341  case boPlus: return x+y;
2342  case boMinus: return x-y;
2343  case boMul: return x*y;
2344  case boDiv: return x/y;
2345  case boMod: return fmod( x,y );
2346  default: Q_ASSERT( false ); return 0;
2347  }
2348 }
2349 
2350 
2352 {
2353  bool resL = mOpLeft->prepare( parent, fields );
2354  bool resR = mOpRight->prepare( parent, fields );
2355  return resL && resR;
2356 }
2357 
2359 {
2360  // see left/right in qgsexpressionparser.yy
2361  switch ( mOp )
2362  {
2363  case boOr:
2364  return 1;
2365 
2366  case boAnd:
2367  return 2;
2368 
2369  case boEQ:
2370  case boNE:
2371  case boLE:
2372  case boGE:
2373  case boLT:
2374  case boGT:
2375  case boRegexp:
2376  case boLike:
2377  case boILike:
2378  case boNotLike:
2379  case boNotILike:
2380  case boIs:
2381  case boIsNot:
2382  return 3;
2383 
2384  case boPlus:
2385  case boMinus:
2386  return 4;
2387 
2388  case boMul:
2389  case boDiv:
2390  case boMod:
2391  return 5;
2392 
2393  case boPow:
2394  return 6;
2395 
2396  case boConcat:
2397  return 7;
2398  }
2399  Q_ASSERT( 0 && "unexpected binary operator" );
2400  return -1;
2401 }
2402 
2404 {
2405  QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
2406  QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
2407 
2408  QString fmt;
2409  fmt += lOp && lOp->precedence() < precedence() ? "(%1)" : "%1";
2410  fmt += " %2 ";
2411  fmt += rOp && rOp->precedence() < precedence() ? "(%3)" : "%3";
2412 
2413  return fmt.arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
2414 }
2415 
2416 //
2417 
2419 {
2420  if ( mList->count() == 0 )
2421  return mNotIn ? TVL_True : TVL_False;
2422  QVariant v1 = mNode->eval( parent, f );
2424  if ( isNull( v1 ) )
2425  return TVL_Unknown;
2426 
2427  bool listHasNull = false;
2428 
2429  foreach ( Node* n, mList->list() )
2430  {
2431  QVariant v2 = n->eval( parent, f );
2433  if ( isNull( v2 ) )
2434  listHasNull = true;
2435  else
2436  {
2437  bool equal = false;
2438  // check whether they are equal
2439  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
2440  {
2441  double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2442  double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2443  equal = f1 == f2;
2444  }
2445  else
2446  {
2447  QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2448  QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2449  equal = QString::compare( s1, s2 ) == 0;
2450  }
2451 
2452  if ( equal ) // we know the result
2453  return mNotIn ? TVL_False : TVL_True;
2454  }
2455  }
2456 
2457  // item not found
2458  if ( listHasNull )
2459  return TVL_Unknown;
2460  else
2461  return mNotIn ? TVL_True : TVL_False;
2462 }
2463 
2465 {
2466  bool res = mNode->prepare( parent, fields );
2467  foreach ( Node* n, mList->list() )
2468  {
2469  res = res && n->prepare( parent, fields );
2470  }
2471  return res;
2472 }
2473 
2475 {
2476  return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
2477 }
2478 
2479 //
2480 
2482 {
2483  Function* fd = Functions()[mFnIndex];
2484 
2485  // evaluate arguments
2486  QVariantList argValues;
2487  if ( mArgs )
2488  {
2489  foreach ( Node* n, mArgs->list() )
2490  {
2491  QVariant v = n->eval( parent, f );
2493  if ( isNull( v ) && fd->name() != "coalesce" )
2494  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
2495  argValues.append( v );
2496  }
2497  }
2498 
2499  // run the function
2500  QVariant res = fd->func( argValues, f, parent );
2502 
2503  // everything went fine
2504  return res;
2505 }
2506 
2508 {
2509  bool res = true;
2510  if ( mArgs )
2511  {
2512  foreach ( Node* n, mArgs->list() )
2513  {
2514  res = res && n->prepare( parent, fields );
2515  }
2516  }
2517  return res;
2518 }
2519 
2521 {
2522  Function* fd = Functions()[mFnIndex];
2523  if ( fd->params() == 0 )
2524  return fd->name(); // special column
2525  else
2526  return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
2527 }
2528 
2530 {
2531  Function* fd = Functions()[mFnIndex];
2532  QStringList functionColumns = fd->referencedColumns();
2533 
2534  if ( !mArgs )
2535  {
2536  //no referenced columns in arguments, just return function's referenced columns
2537  return functionColumns;
2538  }
2539 
2540  foreach ( Node* n, mArgs->list() )
2541  {
2542  functionColumns.append( n->referencedColumns() );
2543  }
2544 
2545  //remove duplicates and return
2546  return functionColumns.toSet().toList();
2547 }
2548 
2549 //
2550 
2552 {
2553  return mValue;
2554 }
2555 
2556 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ )
2557 {
2558  return true;
2559 }
2560 
2561 
2563 {
2564  if ( mValue.isNull() )
2565  return "NULL";
2566 
2567  switch ( mValue.type() )
2568  {
2569  case QVariant::Int: return QString::number( mValue.toInt() );
2570  case QVariant::Double: return QString::number( mValue.toDouble() );
2571  case QVariant::String: return quotedString( mValue.toString() );
2572  default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
2573  }
2574 }
2575 
2576 //
2577 
2579 {
2580  if ( f )
2581  {
2582  if ( mIndex >= 0 )
2583  return f->attribute( mIndex );
2584  else
2585  return f->attribute( mName );
2586  }
2587  return QVariant( "[" + mName + "]" );
2588 }
2589 
2591 {
2592  for ( int i = 0; i < fields.count(); ++i )
2593  {
2594  if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
2595  {
2596  mIndex = i;
2597  return true;
2598  }
2599  }
2600  parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName );
2601  mIndex = -1;
2602  return false;
2603 }
2604 
2606 {
2607  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
2608 }
2609 
2610 //
2611 
2613 {
2614  foreach ( WhenThen* cond, mConditions )
2615  {
2616  QVariant vWhen = cond->mWhenExp->eval( parent, f );
2617  TVL tvl = getTVLValue( vWhen, parent );
2619  if ( tvl == True )
2620  {
2621  QVariant vRes = cond->mThenExp->eval( parent, f );
2623  return vRes;
2624  }
2625  }
2626 
2627  if ( mElseExp )
2628  {
2629  QVariant vElse = mElseExp->eval( parent, f );
2631  return vElse;
2632  }
2633 
2634  // return NULL if no condition is matching
2635  return QVariant();
2636 }
2637 
2639 {
2640  bool res;
2641  foreach ( WhenThen* cond, mConditions )
2642  {
2643  res = cond->mWhenExp->prepare( parent, fields )
2644  & cond->mThenExp->prepare( parent, fields );
2645  if ( !res ) return false;
2646  }
2647 
2648  if ( mElseExp )
2649  return mElseExp->prepare( parent, fields );
2650 
2651  return true;
2652 }
2653 
2655 {
2656  QString msg = QString( "CASE" );
2657  foreach ( WhenThen* cond, mConditions )
2658  {
2659  msg += QString( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
2660  }
2661  if ( mElseExp )
2662  msg += QString( " ELSE %1" ).arg( mElseExp->dump() );
2663  msg += QString( " END" );
2664  return msg;
2665 }
2666 
2668 {
2669  QStringList lst;
2670  foreach ( WhenThen* cond, mConditions )
2671  {
2672  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2673  }
2674 
2675  if ( mElseExp )
2676  lst += mElseExp->referencedColumns();
2677 
2678  return lst;
2679 }
2680 
2682 {
2683  foreach ( WhenThen* cond, mConditions )
2684  {
2685  if ( cond->mWhenExp->needsGeometry() ||
2686  cond->mThenExp->needsGeometry() )
2687  return true;
2688  }
2689 
2690  if ( mElseExp && mElseExp->needsGeometry() )
2691  return true;
2692 
2693  return false;
2694 }
2695 
2696 QString QgsExpression::helptext( QString name )
2697 {
2699  return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) );
2700 }
2701 
2702 QHash<QString, QString> QgsExpression::gGroups;
2703 
2704 QString QgsExpression::group( QString name )
2705 {
2706  if ( gGroups.isEmpty() )
2707  {
2708  gGroups.insert( "Operators", QObject::tr( "Operators" ) );
2709  gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) );
2710  gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) );
2711  gGroups.insert( "Math", QObject::tr( "Math" ) );
2712  gGroups.insert( "Conversions", QObject::tr( "Conversions" ) );
2713  gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) );
2714  gGroups.insert( "String", QObject::tr( "String" ) );
2715  gGroups.insert( "Color", QObject::tr( "Color" ) );
2716  gGroups.insert( "Geometry", QObject::tr( "Geometry" ) );
2717  gGroups.insert( "Record", QObject::tr( "Record" ) );
2718  }
2719 
2720  //return the translated name for this group. If group does not
2721  //have a translated name in the gGroups hash, return the name
2722  //unchanged
2723  return gGroups.value( name, name );
2724 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
static QVariant fcnDifference(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCombine(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
static int functionIndex(QString name)
static QVariant fcnAge(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnColorHsv(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QStringList referencedColumns() const =0
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
Wrapper for iterator of features from vector data provider or vector layer.
static QVariant fcnCeil(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnLog10(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnDistance(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsExpression::Interval fromString(QString string)
static unsigned index
virtual bool needsGeometry() const
static QVariant fcnFeatureId(const QVariantList &, const QgsFeature *f, QgsExpression *)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:96
static QVariant fcnAsin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnTrim(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnLeft(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool unregisterFunction(QString name)
static QString quotedColumnRef(QString name)
return quoted column reference (in double quotes)
static QVariant fcnLog(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnYat(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnMinute(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRight(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * combine(QgsGeometry *geometry)
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static QVariant fcnYMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnReplace(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
void initGeomCalculator()
static QVariant fcnTouches(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
A abstract base class for defining QgsExpression functions.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:194
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
static QVariant fcnGeomLength(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnScale(const QVariantList &, const QgsFeature *, QgsExpression *parent)
double computeDouble(double x, double y)
virtual QString dump() const =0
static QDate getDateValue(const QVariant &value, QgsExpression *parent)
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
Definition: qgsgeometry.h:38
static QVariant fcnFloor(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString helptext(QString name)
static QVariant fcnXMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
static QVariant fcnFormatDate(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToTime(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSqrt(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnIntersects(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnNow(const QVariantList &, const QgsFeature *, QgsExpression *)
QVariant fcnRampColor(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool crosses(const QgsGeometry *geometry) const
Test for if geometry crosses another (uses GEOS)
Container of fields for a vector layer.
Definition: qgsfield.h:163
static QVariant fcnSin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnContains(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToInt(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)=0
QgsExpression::Node * parseExpression(const QString &str, QString &parserErrorMsg)
static QVariant fcnToDateTime(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString group(QString group)
static QTime getTimeValue(const QVariant &value, QgsExpression *parent)
QString dump() const
Return the expression string that represents this QgsExpression.
bool isDoubleSafe(const QVariant &v)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
static QVariant fcnStrpos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnYMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static TVL getTVLValue(const QVariant &value, QgsExpression *parent)
int currentRowNumber()
Return the number used for $rownum special column.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnBuffer(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool isValid(const QString &text, const QgsFields &fields, QString &errorMessage)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
QgsGeometry * difference(QgsGeometry *geometry)
Returns a geometry representing the points making up this geometry that do not make up other...
QString mEvalErrorString
static QVariant fcnYear(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnFormatString(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToString(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCrosses(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToInterval(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * centroid()
Returns the center of mass of a geometry.
static QVariant fcnTan(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry getGeometry(const QVariant &value, QgsExpression *parent)
#define ENSURE_NO_EVAL_ERROR
QString mParserErrorString
static QVariant fcnLower(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString encodeColor(QColor color)
static QVariant fcnAbs(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCoalesce(const QVariantList &values, const QgsFeature *, QgsExpression *)
static QVariant fcnCentroid(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static const QStringList & BuiltinFunctions()
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static const QList< Function * > & Functions()
static QVariant fcnToReal(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool isFunctionName(QString name)
static QVariant fcnIntersection(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QHash< QString, QString > gFunctionHelpTexts
static int functionCount()
Returns the number of functions defined in the parser.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
void acceptVisitor(Visitor &v) const
entry function for the visitor pattern
virtual QStringList referencedColumns() const
bool contains(const QgsPoint *p) const
Test for containment of a point (uses GEOS)
static QVariant fcnAttribute(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnLPad(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QColor fill
Definition: qgssvgcache.cpp:81
static QVariant pointAt(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
QgsDistanceArea * geomCalculator()
Return calculator used for distance and area calculations (used by internal functions) ...
#define TVL_Unknown
static QVariant fcnOverlaps(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnHour(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
const QgsVectorColorRampV2 * colorRampRef(QString name) const
return a const pointer to a symbol (doesn't create new instance)
Definition: qgsstylev2.cpp:266
QgsGeometry * buffer(double distance, int segments)
Returns a buffer region around this geometry having the given width and with a specified number of se...
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
static QVariant fcnFeature(const QVariantList &, const QgsFeature *f, QgsExpression *)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
double measurePerimeter(QgsGeometry *geometry)
measures perimeter of polygon
double measure(QgsGeometry *geometry)
general measurement (line distance or polygon area)
static bool registerFunction(Function *function)
static QVariant fcnAtan2(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsDistanceArea * mCalc
QgsGeometry * convexHull()
Returns the smallest convex polygon that contains all the points in the geometry. ...
static QVariant fncColorHsla(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry * geometryFromGML(const QString &xmlString)
static method that creates geometry from GML
Definition: qgsogcutils.cpp:81
#define SET_EVAL_ERROR(x)
QList< Node * > mList
bool overlaps(const QgsGeometry *geometry) const
Test for if geometry overlaps another (uses GEOS)
static QHash< QString, QString > gGroups
static QgsStyleV2 * defaultStyle()
return default application-wide style
Definition: qgsstylev2.cpp:51
virtual QVariant func(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)=0
bool operator==(const QgsExpression::Interval &other) const
static bool hasSpecialColumn(const QString &name)
Check whether a special column exists.
static QVariant fcnGeomPerimeter(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
QStringList referencedColumns()
Get list of columns referenced by the expression.
#define M_PI
This class wraps a request for features to a vector layer (or directly its vector data provider)...
static QVariant fcnY(const QVariantList &, const QgsFeature *f, QgsExpression *)
static QVariant fcnRndF(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
virtual QString dump() const
static const QString AllAttributes
QDateTime computeDateTimeFromInterval(QDateTime d, QgsExpression::Interval *i)
double scale()
int count() const
Return number of items.
Definition: qgsfield.h:200
#define TVL_False
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnGeomToWKT(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnGetFeature(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSpecialColumn(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QList< Function * > gmFunctions
static QVariant fcnWordwrap(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
static QVariant fcnLength(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QString name()
The name of the function.
virtual QString dump() const
static QVariant tvl2variant(TVL v)
#define ENSURE_GEOM_TYPE(f, g, geomtype)
static QVariant fcnMonth(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnTitle(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
bool isIntervalSafe(const QVariant &v)
QgsGeometry * intersection(QgsGeometry *geometry)
Returns a geometry representing the points shared by this geometry and other.
virtual QString dump() const
static QVariant fcnRPad(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static int getIntValue(const QVariant &value, QgsExpression *parent)
static QVariant fcnToDate(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fncColorRgba(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
int min(int a, int b)
Definition: util.h:93
static QVariant fcnBbox(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnBoundsWidth(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QList< QgsMapLayer * > mapLayersByName(QString layerName)
Retrieve a pointer to a loaded layer by name.
static QVariant fcnGeomArea(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnAcos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
bool needsGeometry()
Returns true if the expression uses feature geometry for some computation.
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)=0
static QString getStringValue(const QVariant &value, QgsExpression *)
static QVariant fcnWithin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsFeature getFeature(const QVariant &value, QgsExpression *parent)
virtual QStringList referencedColumns() const
static QVariant fcnGeometry(const QVariantList &, const QgsFeature *f, QgsExpression *)
void setEvalErrorString(QString str)
Set evaluation error (used internally by evaluation functions)
static double getDoubleValue(const QVariant &value, QgsExpression *parent)
virtual QStringList referencedColumns() const
QgsGeometry * symDifference(QgsGeometry *geometry)
Returns a Geometry representing the points making up this Geometry that do not make up other...
static QVariant fcnGeomFromGML(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
General purpose distance and area calculator.
static QMap< QString, QString > gmSpecialColumnGroups
QgsRectangle boundingBox()
Returns the bounding box of this feature.
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnBounds(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnWeek(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRegexpReplace(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isIntSafe(const QVariant &v)
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
static QVariant fcnConcat(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isDateTimeSafe(const QVariant &v)
static const char * UnaryOperatorText[]
static QgsExpression::Interval invalidInterVal()
static QVariant fcnXat(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnUpper(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnLinearScale(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
static QVariant fncColorHsva(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QList< Function * > specialColumns()
Returns a list of special Column definitions.
static TVL OR[3][3]
static QVariant fcnDay(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
int params()
The number of parameters this function takes.
static QVariant fcnX(const QVariantList &, const QgsFeature *f, QgsExpression *)
static QVariant fcnClamp(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static TVL NOT[3]
bool within(const QgsGeometry *geometry) const
Test for if geometry is within another (uses GEOS)
static QVariant fcnRegexpMatch(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSubstr(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnFormatNumber(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
#define TVL_True
static QVariant fcnXMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
support for visitor pattern - algorithms dealing with the expressions may be implemented without modi...
static QString quotedString(QString text)
return quoted string (in single quotes)
static QgsGeometry * fromRect(const QgsRectangle &rect)
construct geometry from a rectangle
static QVariant fcnExpScale(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnPi(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
virtual bool needsGeometry() const =0
static QVariant fcnSeconds(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry * fromWkt(QString wkt)
static method that creates geometry from Wkt
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used in evaluation of expressions,.
static QStringList gmBuiltinFunctions
static QVariant fcnColorHsl(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
bool disjoint(const QgsGeometry *geometry) const
Test for if geometry is disjoint of another (uses GEOS)
static QVariant fncColorCmyka(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnUuid(const QVariantList &, const QgsFeature *, QgsExpression *)
bool touches(const QgsGeometry *geometry) const
Test for if geometry touch another (uses GEOS)
static QVariant fcnMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant specialColumn(const QString &name)
Return the value of the given special column or a null QVariant if undefined.
static QVariant fcnRowNumber(const QVariantList &, const QgsFeature *, QgsExpression *parent)
static void initFunctionHelp()
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
static QVariant fcnConvexHull(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRnd(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnColorRgb(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
void setValid(bool valid)
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
static QVariant fcnGeomFromWKT(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool nextFeature(QgsFeature &f)
static QVariant fcnColorCmyk(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnExp(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
static TVL AND[3][3]
static QVariant fcnAtan(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:204
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
static QVariant fcnBoundsHeight(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:98
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
int max(int a, int b)
Definition: util.h:87
QString evalErrorString() const
Returns evaluation error.
QString exportToWkt(const int &precision=17) const
Exports the geometry to WKT.
virtual void accept(Visitor &v) const =0
virtual QString dump() const
static QVariant fcnSymDifference(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isNull(const QVariant &v)
static QVariant fcnLn(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRegexpSubstr(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0)
This function currently replaces each expression between [% and %] in the string with the result of i...
static QVariant fcnDisjoint(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:209
static QgsExpression::Interval getInterval(const QVariant &value, QgsExpression *parent, bool report_error=false)
static QDateTime getDateTimeValue(const QVariant &value, QgsExpression *parent)
static QVariant fcnRound(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
double distance(QgsGeometry &geom)
static void unsetSpecialColumn(const QString &name)
Unset a special column.
#define tr(sourceText)
static const char * BinaryOperatorText[]
static QMap< QString, QVariant > gmSpecialColumns