QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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, const QgsDistanceArea *distanceArea )
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  if ( distanceArea )
2034  {
2035  //if QgsDistanceArea specified for area/distance conversion, use it
2036  exp.setGeomCalculator( *distanceArea );
2037  }
2038 
2039  QVariant result;
2040  if ( layer )
2041  {
2042  result = exp.evaluate( feat, layer->pendingFields() );
2043  }
2044  else
2045  {
2046  result = exp.evaluate( feat );
2047  }
2048  if ( exp.hasEvalError() )
2049  {
2050  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
2051  expr_action += action.mid( start, index - start );
2052  continue;
2053  }
2054 
2055  QgsDebugMsg( "Expression result is: " + result.toString() );
2056  expr_action += action.mid( start, pos - start ) + result.toString();
2057  }
2058 
2059  expr_action += action.mid( index );
2060 
2061  // restore overwritten local values
2062  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
2063  {
2064  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2065  }
2066 
2067  return expr_action;
2068 }
2069 
2070 
2072 // nodes
2073 
2075 {
2076  QString msg; bool first = true;
2077  foreach ( Node* n, mList )
2078  {
2079  if ( !first ) msg += ", "; else first = false;
2080  msg += n->dump();
2081  }
2082  return msg;
2083 }
2084 
2085 
2086 //
2087 
2089 {
2090  QVariant val = mOperand->eval( parent, f );
2092 
2093  switch ( mOp )
2094  {
2095  case uoNot:
2096  {
2097  TVL tvl = getTVLValue( val, parent );
2099  return tvl2variant( NOT[tvl] );
2100  }
2101 
2102  case uoMinus:
2103  if ( isIntSafe( val ) )
2104  return QVariant( - getIntValue( val, parent ) );
2105  else if ( isDoubleSafe( val ) )
2106  return QVariant( - getDoubleValue( val, parent ) );
2107  else
2108  SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
2109  break;
2110  default:
2111  Q_ASSERT( 0 && "unknown unary operation" );
2112  }
2113  return QVariant();
2114 }
2115 
2117 {
2118  return mOperand->prepare( parent, fields );
2119 }
2120 
2122 {
2123  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
2124 }
2125 
2126 //
2127 
2129 {
2130  QVariant vL = mOpLeft->eval( parent, f );
2132  QVariant vR = mOpRight->eval( parent, f );
2134 
2135  switch ( mOp )
2136  {
2137  case boPlus:
2138  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
2139  {
2140  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2141  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2142  return QVariant( sL + sR );
2143  }
2144  case boMinus:
2145  case boMul:
2146  case boDiv:
2147  case boMod:
2148  if ( isNull( vL ) || isNull( vR ) )
2149  return QVariant();
2150  else if ( isIntSafe( vL ) && isIntSafe( vR ) )
2151  {
2152  // both are integers - let's use integer arithmetics
2153  int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2154  int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2155  if ( mOp == boDiv && iR == 0 ) return QVariant(); // silently handle division by zero and return NULL
2156  return QVariant( computeInt( iL, iR ) );
2157  }
2158  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
2159  {
2160  QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2162  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
2163  {
2164  parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
2165  return QVariant();
2166  }
2167  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
2168  }
2169  else
2170  {
2171  // general floating point arithmetic
2172  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2173  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2174  if ( mOp == boDiv && fR == 0 )
2175  return QVariant(); // silently handle division by zero and return NULL
2176  return QVariant( computeDouble( fL, fR ) );
2177  }
2178 
2179  case boPow:
2180  if ( isNull( vL ) || isNull( vR ) )
2181  return QVariant();
2182  else
2183  {
2184  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2185  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2186  return QVariant( pow( fL, fR ) );
2187  }
2188 
2189  case boAnd:
2190  {
2191  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2193  return tvl2variant( AND[tvlL][tvlR] );
2194  }
2195 
2196  case boOr:
2197  {
2198  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2200  return tvl2variant( OR[tvlL][tvlR] );
2201  }
2202 
2203  case boEQ:
2204  case boNE:
2205  case boLT:
2206  case boGT:
2207  case boLE:
2208  case boGE:
2209  if ( isNull( vL ) || isNull( vR ) )
2210  {
2211  return TVL_Unknown;
2212  }
2213  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2214  {
2215  // do numeric comparison if both operators can be converted to numbers
2216  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2217  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2218  return compare( fL - fR ) ? TVL_True : TVL_False;
2219  }
2220  else
2221  {
2222  // do string comparison otherwise
2223  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2224  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2225  int diff = QString::compare( sL, sR );
2226  return compare( diff ) ? TVL_True : TVL_False;
2227  }
2228 
2229  case boIs:
2230  case boIsNot:
2231  if ( isNull( vL ) && isNull( vR ) ) // both operators null
2232  return ( mOp == boIs ? TVL_True : TVL_False );
2233  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
2234  return ( mOp == boIs ? TVL_False : TVL_True );
2235  else // both operators non-null
2236  {
2237  bool equal = false;
2238  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2239  {
2240  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2241  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2242  equal = fL == fR;
2243  }
2244  else
2245  {
2246  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2247  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2248  equal = QString::compare( sL, sR ) == 0;
2249  }
2250  if ( equal )
2251  return mOp == boIs ? TVL_True : TVL_False;
2252  else
2253  return mOp == boIs ? TVL_False : TVL_True;
2254  }
2255 
2256  case boRegexp:
2257  case boLike:
2258  case boNotLike:
2259  case boILike:
2260  case boNotILike:
2261  if ( isNull( vL ) || isNull( vR ) )
2262  return TVL_Unknown;
2263  else
2264  {
2265  QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2266  QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2267  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
2268  bool matches;
2269  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
2270  {
2271  QString esc_regexp = QRegExp::escape( regexp );
2272  // XXX escape % and _ ???
2273  esc_regexp.replace( "%", ".*" );
2274  esc_regexp.replace( "_", "." );
2275  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
2276  }
2277  else
2278  {
2279  matches = QRegExp( regexp ).indexIn( str ) != -1;
2280  }
2281 
2282  if ( mOp == boNotLike || mOp == boNotILike )
2283  {
2284  matches = !matches;
2285  }
2286 
2287  return matches ? TVL_True : TVL_False;
2288  }
2289 
2290  case boConcat:
2291  if ( isNull( vL ) || isNull( vR ) )
2292  return QVariant();
2293  else
2294  {
2295  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2296  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2297  return QVariant( sL + sR );
2298  }
2299 
2300  default: break;
2301  }
2302  Q_ASSERT( false );
2303  return QVariant();
2304 }
2305 
2307 {
2308  switch ( mOp )
2309  {
2310  case boEQ: return diff == 0;
2311  case boNE: return diff != 0;
2312  case boLT: return diff < 0;
2313  case boGT: return diff > 0;
2314  case boLE: return diff <= 0;
2315  case boGE: return diff >= 0;
2316  default: Q_ASSERT( false ); return false;
2317  }
2318 }
2319 
2321 {
2322  switch ( mOp )
2323  {
2324  case boPlus: return x+y;
2325  case boMinus: return x-y;
2326  case boMul: return x*y;
2327  case boDiv: return x/y;
2328  case boMod: return x%y;
2329  default: Q_ASSERT( false ); return 0;
2330  }
2331 }
2332 
2334 {
2335  switch ( mOp )
2336  {
2337  case boPlus: return d.addSecs( i->seconds() );
2338  case boMinus: return d.addSecs( -i->seconds() );
2339  default: Q_ASSERT( false ); return QDateTime();
2340  }
2341 }
2342 
2344 {
2345  switch ( mOp )
2346  {
2347  case boPlus: return x+y;
2348  case boMinus: return x-y;
2349  case boMul: return x*y;
2350  case boDiv: return x/y;
2351  case boMod: return fmod( x,y );
2352  default: Q_ASSERT( false ); return 0;
2353  }
2354 }
2355 
2356 
2358 {
2359  bool resL = mOpLeft->prepare( parent, fields );
2360  bool resR = mOpRight->prepare( parent, fields );
2361  return resL && resR;
2362 }
2363 
2365 {
2366  // see left/right in qgsexpressionparser.yy
2367  switch ( mOp )
2368  {
2369  case boOr:
2370  return 1;
2371 
2372  case boAnd:
2373  return 2;
2374 
2375  case boEQ:
2376  case boNE:
2377  case boLE:
2378  case boGE:
2379  case boLT:
2380  case boGT:
2381  case boRegexp:
2382  case boLike:
2383  case boILike:
2384  case boNotLike:
2385  case boNotILike:
2386  case boIs:
2387  case boIsNot:
2388  return 3;
2389 
2390  case boPlus:
2391  case boMinus:
2392  return 4;
2393 
2394  case boMul:
2395  case boDiv:
2396  case boMod:
2397  return 5;
2398 
2399  case boPow:
2400  return 6;
2401 
2402  case boConcat:
2403  return 7;
2404  }
2405  Q_ASSERT( 0 && "unexpected binary operator" );
2406  return -1;
2407 }
2408 
2410 {
2411  QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
2412  QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
2413 
2414  QString fmt;
2415  fmt += lOp && lOp->precedence() < precedence() ? "(%1)" : "%1";
2416  fmt += " %2 ";
2417  fmt += rOp && rOp->precedence() <= precedence() ? "(%3)" : "%3";
2418 
2419  return fmt.arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
2420 }
2421 
2422 //
2423 
2425 {
2426  if ( mList->count() == 0 )
2427  return mNotIn ? TVL_True : TVL_False;
2428  QVariant v1 = mNode->eval( parent, f );
2430  if ( isNull( v1 ) )
2431  return TVL_Unknown;
2432 
2433  bool listHasNull = false;
2434 
2435  foreach ( Node* n, mList->list() )
2436  {
2437  QVariant v2 = n->eval( parent, f );
2439  if ( isNull( v2 ) )
2440  listHasNull = true;
2441  else
2442  {
2443  bool equal = false;
2444  // check whether they are equal
2445  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
2446  {
2447  double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2448  double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2449  equal = f1 == f2;
2450  }
2451  else
2452  {
2453  QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2454  QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2455  equal = QString::compare( s1, s2 ) == 0;
2456  }
2457 
2458  if ( equal ) // we know the result
2459  return mNotIn ? TVL_False : TVL_True;
2460  }
2461  }
2462 
2463  // item not found
2464  if ( listHasNull )
2465  return TVL_Unknown;
2466  else
2467  return mNotIn ? TVL_True : TVL_False;
2468 }
2469 
2471 {
2472  bool res = mNode->prepare( parent, fields );
2473  foreach ( Node* n, mList->list() )
2474  {
2475  res = res && n->prepare( parent, fields );
2476  }
2477  return res;
2478 }
2479 
2481 {
2482  return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
2483 }
2484 
2485 //
2486 
2488 {
2489  Function* fd = Functions()[mFnIndex];
2490 
2491  // evaluate arguments
2492  QVariantList argValues;
2493  if ( mArgs )
2494  {
2495  foreach ( Node* n, mArgs->list() )
2496  {
2497  QVariant v = n->eval( parent, f );
2499  if ( isNull( v ) && fd->name() != "coalesce" )
2500  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
2501  argValues.append( v );
2502  }
2503  }
2504 
2505  // run the function
2506  QVariant res = fd->func( argValues, f, parent );
2508 
2509  // everything went fine
2510  return res;
2511 }
2512 
2514 {
2515  bool res = true;
2516  if ( mArgs )
2517  {
2518  foreach ( Node* n, mArgs->list() )
2519  {
2520  res = res && n->prepare( parent, fields );
2521  }
2522  }
2523  return res;
2524 }
2525 
2527 {
2528  Function* fd = Functions()[mFnIndex];
2529  if ( fd->params() == 0 )
2530  return fd->name(); // special column
2531  else
2532  return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
2533 }
2534 
2536 {
2537  Function* fd = Functions()[mFnIndex];
2538  QStringList functionColumns = fd->referencedColumns();
2539 
2540  if ( !mArgs )
2541  {
2542  //no referenced columns in arguments, just return function's referenced columns
2543  return functionColumns;
2544  }
2545 
2546  foreach ( Node* n, mArgs->list() )
2547  {
2548  functionColumns.append( n->referencedColumns() );
2549  }
2550 
2551  //remove duplicates and return
2552  return functionColumns.toSet().toList();
2553 }
2554 
2555 //
2556 
2558 {
2559  return mValue;
2560 }
2561 
2562 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ )
2563 {
2564  return true;
2565 }
2566 
2567 
2569 {
2570  if ( mValue.isNull() )
2571  return "NULL";
2572 
2573  switch ( mValue.type() )
2574  {
2575  case QVariant::Int: return QString::number( mValue.toInt() );
2576  case QVariant::Double: return QString::number( mValue.toDouble() );
2577  case QVariant::String: return quotedString( mValue.toString() );
2578  default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
2579  }
2580 }
2581 
2582 //
2583 
2585 {
2586  if ( f )
2587  {
2588  if ( mIndex >= 0 )
2589  return f->attribute( mIndex );
2590  else
2591  return f->attribute( mName );
2592  }
2593  return QVariant( "[" + mName + "]" );
2594 }
2595 
2597 {
2598  for ( int i = 0; i < fields.count(); ++i )
2599  {
2600  if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
2601  {
2602  mIndex = i;
2603  return true;
2604  }
2605  }
2606  parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName );
2607  mIndex = -1;
2608  return false;
2609 }
2610 
2612 {
2613  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
2614 }
2615 
2616 //
2617 
2619 {
2620  foreach ( WhenThen* cond, mConditions )
2621  {
2622  QVariant vWhen = cond->mWhenExp->eval( parent, f );
2623  TVL tvl = getTVLValue( vWhen, parent );
2625  if ( tvl == True )
2626  {
2627  QVariant vRes = cond->mThenExp->eval( parent, f );
2629  return vRes;
2630  }
2631  }
2632 
2633  if ( mElseExp )
2634  {
2635  QVariant vElse = mElseExp->eval( parent, f );
2637  return vElse;
2638  }
2639 
2640  // return NULL if no condition is matching
2641  return QVariant();
2642 }
2643 
2645 {
2646  bool res;
2647  foreach ( WhenThen* cond, mConditions )
2648  {
2649  res = cond->mWhenExp->prepare( parent, fields )
2650  & cond->mThenExp->prepare( parent, fields );
2651  if ( !res ) return false;
2652  }
2653 
2654  if ( mElseExp )
2655  return mElseExp->prepare( parent, fields );
2656 
2657  return true;
2658 }
2659 
2661 {
2662  QString msg = QString( "CASE" );
2663  foreach ( WhenThen* cond, mConditions )
2664  {
2665  msg += QString( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
2666  }
2667  if ( mElseExp )
2668  msg += QString( " ELSE %1" ).arg( mElseExp->dump() );
2669  msg += QString( " END" );
2670  return msg;
2671 }
2672 
2674 {
2675  QStringList lst;
2676  foreach ( WhenThen* cond, mConditions )
2677  {
2678  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2679  }
2680 
2681  if ( mElseExp )
2682  lst += mElseExp->referencedColumns();
2683 
2684  return lst;
2685 }
2686 
2688 {
2689  foreach ( WhenThen* cond, mConditions )
2690  {
2691  if ( cond->mWhenExp->needsGeometry() ||
2692  cond->mThenExp->needsGeometry() )
2693  return true;
2694  }
2695 
2696  if ( mElseExp && mElseExp->needsGeometry() )
2697  return true;
2698 
2699  return false;
2700 }
2701 
2702 QString QgsExpression::helptext( QString name )
2703 {
2705  return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) );
2706 }
2707 
2708 QHash<QString, QString> QgsExpression::gGroups;
2709 
2710 QString QgsExpression::group( QString name )
2711 {
2712  if ( gGroups.isEmpty() )
2713  {
2714  gGroups.insert( "Operators", QObject::tr( "Operators" ) );
2715  gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) );
2716  gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) );
2717  gGroups.insert( "Math", QObject::tr( "Math" ) );
2718  gGroups.insert( "Conversions", QObject::tr( "Conversions" ) );
2719  gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) );
2720  gGroups.insert( "String", QObject::tr( "String" ) );
2721  gGroups.insert( "Color", QObject::tr( "Color" ) );
2722  gGroups.insert( "Geometry", QObject::tr( "Geometry" ) );
2723  gGroups.insert( "Record", QObject::tr( "Record" ) );
2724  }
2725 
2726  //return the translated name for this group. If group does not
2727  //have a translated name in the gGroups hash, return the name
2728  //unchanged
2729  return gGroups.value( name, name );
2730 }
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:87
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:94
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:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
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:33
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:172
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:193
static QVariant fcnFeature(const QVariantList &, const QgsFeature *f, QgsExpression *)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
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:214
#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:198
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:96
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:183
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 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:203
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 QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...
static QMap< QString, QVariant > gmSpecialColumns