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