QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.cpp
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsexpression.h"
17 
18 #include <QtDebug>
19 #include <QDomDocument>
20 #include <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  QgsGeometry* g = f->geometry(); \
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  QgsGeometry* geom = f ? f->geometry() : 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->geometry() ) );
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->geometry() ) );
1119 }
1120 static QVariant fcnGeomPerimeter( const QVariantList&, const QgsFeature* f, QgsExpression* parent )
1121 {
1123  QgsDistanceArea* calc = parent->geomCalculator();
1124  return QVariant( calc->measurePerimeter( f->geometry() ) );
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  QgsGeometry* geom = feat.geometry();
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"
1670  << "toint" << "toreal" << "tostring"
1671  << "todatetime" << "todate" << "totime" << "tointerval"
1672  << "coalesce" << "regexp_match" << "$now" << "age" << "year"
1673  << "month" << "week" << "day" << "hour"
1674  << "minute" << "second" << "lower" << "upper"
1675  << "title" << "length" << "replace" << "trim" << "wordwrap"
1676  << "regexp_replace" << "regexp_substr"
1677  << "substr" << "concat" << "strpos" << "left"
1678  << "right" << "rpad" << "lpad"
1679  << "format_number" << "format_date"
1680  << "color_rgb" << "color_rgba" << "ramp_color"
1681  << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva"
1682  << "color_cymk" << "color_cymka"
1683  << "xat" << "yat" << "$area"
1684  << "$length" << "$perimeter" << "$x" << "$y"
1685  << "$rownum" << "$id" << "$scale" << "_specialcol_";
1686  }
1687  return gmBuiltinFunctions;
1688 }
1689 
1690 QList<QgsExpression::Function*> QgsExpression::gmFunctions;
1691 
1692 const QList<QgsExpression::Function*> &QgsExpression::Functions()
1693 {
1694  if ( gmFunctions.isEmpty() )
1695  {
1696  gmFunctions
1697  << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
1698  << new StaticFunction( "abs", 1, fcnAbs, "Math" )
1699  << new StaticFunction( "cos", 1, fcnCos, "Math" )
1700  << new StaticFunction( "sin", 1, fcnSin, "Math" )
1701  << new StaticFunction( "tan", 1, fcnTan, "Math" )
1702  << new StaticFunction( "asin", 1, fcnAsin, "Math" )
1703  << new StaticFunction( "acos", 1, fcnAcos, "Math" )
1704  << new StaticFunction( "atan", 1, fcnAtan, "Math" )
1705  << new StaticFunction( "atan2", 2, fcnAtan2, "Math" )
1706  << new StaticFunction( "exp", 1, fcnExp, "Math" )
1707  << new StaticFunction( "ln", 1, fcnLn, "Math" )
1708  << new StaticFunction( "log10", 1, fcnLog10, "Math" )
1709  << new StaticFunction( "log", 2, fcnLog, "Math" )
1710  << new StaticFunction( "round", -1, fcnRound, "Math" )
1711  << new StaticFunction( "rand", 2, fcnRnd, "Math" )
1712  << new StaticFunction( "randf", 2, fcnRndF, "Math" )
1713  << new StaticFunction( "max", -1, fcnMax, "Math" )
1714  << new StaticFunction( "min", -1, fcnMin, "Math" )
1715  << new StaticFunction( "clamp", 3, fcnClamp, "Math" )
1716  << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" )
1717  << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" )
1718  << new StaticFunction( "floor", 1, fcnFloor, "Math" )
1719  << new StaticFunction( "ceil", 1, fcnCeil, "Math" )
1720  << new StaticFunction( "$pi", 0, fcnPi, "Math" )
1721  << new StaticFunction( "toint", 1, fcnToInt, "Conversions" )
1722  << new StaticFunction( "toreal", 1, fcnToReal, "Conversions" )
1723  << new StaticFunction( "tostring", 1, fcnToString, "Conversions" )
1724  << new StaticFunction( "todatetime", 1, fcnToDateTime, "Conversions" )
1725  << new StaticFunction( "todate", 1, fcnToDate, "Conversions" )
1726  << new StaticFunction( "totime", 1, fcnToTime, "Conversions" )
1727  << new StaticFunction( "tointerval", 1, fcnToInterval, "Conversions" )
1728  << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" )
1729  << new StaticFunction( "if", 3, fcnIf, "Conditionals", "", False, QStringList(), true )
1730  << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
1731  << new StaticFunction( "$now", 0, fcnNow, "Date and Time" )
1732  << new StaticFunction( "age", 2, fcnAge, "Date and Time" )
1733  << new StaticFunction( "year", 1, fcnYear, "Date and Time" )
1734  << new StaticFunction( "month", 1, fcnMonth, "Date and Time" )
1735  << new StaticFunction( "week", 1, fcnWeek, "Date and Time" )
1736  << new StaticFunction( "day", 1, fcnDay, "Date and Time" )
1737  << new StaticFunction( "hour", 1, fcnHour, "Date and Time" )
1738  << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" )
1739  << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" )
1740  << new StaticFunction( "lower", 1, fcnLower, "String" )
1741  << new StaticFunction( "upper", 1, fcnUpper, "String" )
1742  << new StaticFunction( "title", 1, fcnTitle, "String" )
1743  << new StaticFunction( "trim", 1, fcnTrim, "String" )
1744  << new StaticFunction( "wordwrap", -1, fcnWordwrap, "String" )
1745  << new StaticFunction( "length", 1, fcnLength, "String" )
1746  << new StaticFunction( "replace", 3, fcnReplace, "String" )
1747  << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
1748  << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
1749  << new StaticFunction( "substr", 3, fcnSubstr, "String" )
1750  << new StaticFunction( "concat", -1, fcnConcat, "String" )
1751  << new StaticFunction( "strpos", 2, fcnStrpos, "String" )
1752  << new StaticFunction( "left", 2, fcnLeft, "String" )
1753  << new StaticFunction( "right", 2, fcnRight, "String" )
1754  << new StaticFunction( "rpad", 3, fcnRPad, "String" )
1755  << new StaticFunction( "lpad", 3, fcnLPad, "String" )
1756  << new StaticFunction( "format", -1, fcnFormatString, "String" )
1757  << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
1758  << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
1759  << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
1760  << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
1761  << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
1762  << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" )
1763  << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" )
1764  << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" )
1765  << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" )
1766  << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" )
1767  << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" )
1768  << new StaticFunction( "$geometry", 0, fcnGeometry, "GeometryGroup", "", true )
1769  << new StaticFunction( "$area", 0, fcnGeomArea, "GeometryGroup", "", true )
1770  << new StaticFunction( "$length", 0, fcnGeomLength, "GeometryGroup", "", true )
1771  << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "GeometryGroup", "", true )
1772  << new StaticFunction( "$x", 0, fcnX, "GeometryGroup", "", true )
1773  << new StaticFunction( "$y", 0, fcnY, "GeometryGroup", "", true )
1774  << new StaticFunction( "xat", 1, fcnXat, "GeometryGroup", "", true )
1775  << new StaticFunction( "yat", 1, fcnYat, "GeometryGroup", "", true )
1776  << new StaticFunction( "xmin", 1, fcnXMin, "GeometryGroup", "", true )
1777  << new StaticFunction( "xmax", 1, fcnXMax, "GeometryGroup", "", true )
1778  << new StaticFunction( "ymin", 1, fcnYMin, "GeometryGroup", "", true )
1779  << new StaticFunction( "ymax", 1, fcnYMax, "GeometryGroup", "", true )
1780  << new StaticFunction( "geomFromWKT", 1, fcnGeomFromWKT, "GeometryGroup" )
1781  << new StaticFunction( "geomFromGML", 1, fcnGeomFromGML, "GeometryGroup" )
1782  << new StaticFunction( "bbox", 2, fcnBbox, "GeometryGroup" )
1783  << new StaticFunction( "disjoint", 2, fcnDisjoint, "GeometryGroup" )
1784  << new StaticFunction( "intersects", 2, fcnIntersects, "GeometryGroup" )
1785  << new StaticFunction( "touches", 2, fcnTouches, "GeometryGroup" )
1786  << new StaticFunction( "crosses", 2, fcnCrosses, "GeometryGroup" )
1787  << new StaticFunction( "contains", 2, fcnContains, "GeometryGroup" )
1788  << new StaticFunction( "overlaps", 2, fcnOverlaps, "GeometryGroup" )
1789  << new StaticFunction( "within", 2, fcnWithin, "GeometryGroup" )
1790  << new StaticFunction( "buffer", -1, fcnBuffer, "GeometryGroup" )
1791  << new StaticFunction( "centroid", 1, fcnCentroid, "GeometryGroup" )
1792  << new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup", "", true )
1793  << new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "GeometryGroup", "", true )
1794  << new StaticFunction( "bounds_height", 1, fcnBoundsHeight, "GeometryGroup", "", true )
1795  << new StaticFunction( "convexHull", 1, fcnConvexHull, "GeometryGroup" )
1796  << new StaticFunction( "difference", 2, fcnDifference, "GeometryGroup" )
1797  << new StaticFunction( "distance", 2, fcnDistance, "GeometryGroup" )
1798  << new StaticFunction( "intersection", 2, fcnIntersection, "GeometryGroup" )
1799  << new StaticFunction( "symDifference", 2, fcnSymDifference, "GeometryGroup" )
1800  << new StaticFunction( "combine", 2, fcnCombine, "GeometryGroup" )
1801  << new StaticFunction( "union", 2, fcnCombine, "GeometryGroup" )
1802  << new StaticFunction( "geomToWKT", -1, fcnGeomToWKT, "GeometryGroup" )
1803  << new StaticFunction( "geometry", 1, fcnGetGeometry, "GeometryGroup" )
1804  << new StaticFunction( "transform", 3, fcnTransformGeometry, "GeometryGroup" )
1805  << new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
1806  << new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
1807  << new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
1808  << new StaticFunction( "$scale", 0, fcnScale, "Record" )
1809  << new StaticFunction( "$uuid", 0, fcnUuid, "Record" )
1810  << new StaticFunction( "getFeature", 3, fcnGetFeature, "Record" )
1811 
1812  //return all attributes string for referencedColumns - this is caught by
1813  // QgsFeatureRequest::setSubsetOfAttributes and causes all attributes to be fetched by the
1814  // feature request
1815  << new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
1816 
1817  << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
1818  ;
1819  }
1820  return gmFunctions;
1821 }
1822 
1823 QMap<QString, QVariant> QgsExpression::gmSpecialColumns;
1824 QMap<QString, QString> QgsExpression::gmSpecialColumnGroups;
1825 
1826 void QgsExpression::setSpecialColumn( const QString& name, QVariant variant )
1827 {
1828  int fnIdx = functionIndex( name );
1829  if ( fnIdx != -1 )
1830  {
1831  // function of the same name already exists
1832  return;
1833  }
1834  gmSpecialColumns[ name ] = variant;
1835 }
1836 
1837 void QgsExpression::unsetSpecialColumn( const QString& name )
1838 {
1839  QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name );
1840  if ( fit != gmSpecialColumns.end() )
1841  {
1842  gmSpecialColumns.erase( fit );
1843  }
1844 }
1845 
1846 QVariant QgsExpression::specialColumn( const QString& name )
1847 {
1848  int fnIdx = functionIndex( name );
1849  if ( fnIdx != -1 )
1850  {
1851  // function of the same name already exists
1852  return QVariant();
1853  }
1854  QMap<QString, QVariant>::iterator it = gmSpecialColumns.find( name );
1855  if ( it == gmSpecialColumns.end() )
1856  {
1857  return QVariant();
1858  }
1859  return it.value();
1860 }
1861 
1862 bool QgsExpression::hasSpecialColumn( const QString& name )
1863 {
1864  static bool initialized = false;
1865  if ( !initialized )
1866  {
1867  // Pre-register special columns that will exist within QGIS so that expressions that may use them are parsed correctly.
1868  // This is really sub-optimal, we should get rid of the special columns and instead have contexts in which some values
1869  // are defined and some are not ($rownum makes sense only in field calculator, $scale only when rendering, $page only for composer etc.)
1870 
1871  //pairs of column name to group name
1872  QList< QPair<QString, QString> > lst;
1873  lst << qMakePair( QString( "$page" ), QString( "Composer" ) );
1874  lst << qMakePair( QString( "$feature" ), QString( "Atlas" ) );
1875  lst << qMakePair( QString( "$numpages" ), QString( "Composer" ) );
1876  lst << qMakePair( QString( "$numfeatures" ), QString( "Atlas" ) );
1877  lst << qMakePair( QString( "$atlasfeatureid" ), QString( "Atlas" ) );
1878  lst << qMakePair( QString( "$atlasgeometry" ), QString( "Atlas" ) );
1879  lst << qMakePair( QString( "$atlasfeature" ), QString( "Atlas" ) );
1880  lst << qMakePair( QString( "$map" ), QString( "Composer" ) );
1881 
1882  QList< QPair<QString, QString> >::const_iterator it = lst.constBegin();
1883  for ( ; it != lst.constEnd(); ++it )
1884  {
1885  setSpecialColumn(( *it ).first, QVariant() );
1886  gmSpecialColumnGroups[( *it ).first ] = ( *it ).second;
1887  }
1888 
1889  initialized = true;
1890  }
1891 
1892  if ( functionIndex( name ) != -1 )
1893  return false;
1894  return gmSpecialColumns.contains( name );
1895 }
1896 
1897 bool QgsExpression::isValid( const QString &text, const QgsFields &fields, QString &errorMessage )
1898 {
1899  QgsExpression exp( text );
1900  exp.prepare( fields );
1901  errorMessage = exp.parserErrorString();
1902  return !exp.hasParserError();
1903 }
1904 
1905 QList<QgsExpression::Function*> QgsExpression::specialColumns()
1906 {
1907  QList<Function*> defs;
1908  for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.begin(); it != gmSpecialColumns.end(); ++it )
1909  {
1910  //check for special column group name
1911  QString group = gmSpecialColumnGroups.value( it.key(), "Record" );
1912  defs << new StaticFunction( it.key(), 0, 0, group );
1913  }
1914  return defs;
1915 }
1916 
1917 QString QgsExpression::quotedColumnRef( QString name )
1918 {
1919  return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) );
1920 }
1921 
1922 QString QgsExpression::quotedString( QString text )
1923 {
1924  text.replace( "'", "''" );
1925  text.replace( '\\', "\\\\" );
1926  text.replace( '\n', "\\n" );
1927  text.replace( '\t', "\\t" );
1928  return QString( "'%1'" ).arg( text );
1929 }
1930 
1931 bool QgsExpression::isFunctionName( QString name )
1932 {
1933  return functionIndex( name ) != -1;
1934 }
1935 
1936 int QgsExpression::functionIndex( QString name )
1937 {
1938  int count = functionCount();
1939  for ( int i = 0; i < count; i++ )
1940  {
1941  if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
1942  return i;
1943  }
1944  return -1;
1945 }
1946 
1948 {
1949  return Functions().size();
1950 }
1951 
1952 
1953 QgsExpression::QgsExpression( const QString& expr )
1954  : mRowNumber( 0 )
1955  , mScale( 0 )
1956  , mExp( expr )
1957  , mCalc( 0 )
1958 {
1960 
1961  if ( mParserErrorString.isNull() )
1962  Q_ASSERT( mRootNode );
1963 }
1964 
1966 {
1967  delete mCalc;
1968  delete mRootNode;
1969 }
1970 
1972 {
1973  if ( !mRootNode )
1974  return QStringList();
1975 
1976  QStringList columns = mRootNode->referencedColumns();
1977 
1978  // filter out duplicates
1979  for ( int i = 0; i < columns.count(); i++ )
1980  {
1981  QString col = columns.at( i );
1982  for ( int j = i + 1; j < columns.count(); j++ )
1983  {
1984  if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
1985  {
1986  // this column is repeated: remove it!
1987  columns.removeAt( j-- );
1988  }
1989  }
1990  }
1991 
1992  return columns;
1993 }
1994 
1996 {
1997  if ( !mRootNode )
1998  return false;
1999  return mRootNode->needsGeometry();
2000 }
2001 
2003 {
2004  if ( mCalc )
2005  return;
2006 
2007  // Use planimetric as default
2008  mCalc = new QgsDistanceArea();
2009  mCalc->setEllipsoidalMode( false );
2010 }
2011 
2013 {
2014  delete mCalc;
2015  mCalc = new QgsDistanceArea( calc );
2016 }
2017 
2018 bool QgsExpression::prepare( const QgsFields& fields )
2019 {
2020  mEvalErrorString = QString();
2021  if ( !mRootNode )
2022  {
2023  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
2024  return false;
2025  }
2026 
2027  return mRootNode->prepare( this, fields );
2028 }
2029 
2031 {
2032  mEvalErrorString = QString();
2033  if ( !mRootNode )
2034  {
2035  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
2036  return QVariant();
2037  }
2038 
2039  return mRootNode->eval( this, f );
2040 }
2041 
2042 QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields )
2043 {
2044  // first prepare
2045  bool res = prepare( fields );
2046  if ( !res )
2047  return QVariant();
2048 
2049  // then evaluate
2050  return evaluate( f );
2051 }
2052 
2053 QString QgsExpression::dump() const
2054 {
2055  if ( !mRootNode )
2056  return QObject::tr( "(no root)" );
2057 
2058  return mRootNode->dump();
2059 }
2060 
2062 {
2063  if ( mRootNode )
2064  mRootNode->accept( v );
2065 }
2066 
2067 QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
2068  QgsVectorLayer *layer,
2069  const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
2070 {
2071  QString expr_action;
2072 
2073  QMap<QString, QVariant> savedValues;
2074  if ( substitutionMap )
2075  {
2076  // variables with a local scope (must be restored after evaluation)
2077  for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
2078  {
2079  QVariant oldValue = QgsExpression::specialColumn( sit.key() );
2080  if ( !oldValue.isNull() )
2081  savedValues.insert( sit.key(), oldValue );
2082 
2083  // set the new value
2084  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2085  }
2086  }
2087 
2088  int index = 0;
2089  while ( index < action.size() )
2090  {
2091  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
2092 
2093  int pos = rx.indexIn( action, index );
2094  if ( pos < 0 )
2095  break;
2096 
2097  int start = index;
2098  index = pos + rx.matchedLength();
2099  QString to_replace = rx.cap( 1 ).trimmed();
2100  QgsDebugMsg( "Found expression: " + to_replace );
2101 
2102  QgsExpression exp( to_replace );
2103  if ( exp.hasParserError() )
2104  {
2105  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
2106  expr_action += action.mid( start, index - start );
2107  continue;
2108  }
2109 
2110  if ( distanceArea )
2111  {
2112  //if QgsDistanceArea specified for area/distance conversion, use it
2113  exp.setGeomCalculator( *distanceArea );
2114  }
2115 
2116  QVariant result;
2117  if ( layer )
2118  {
2119  result = exp.evaluate( feat, layer->pendingFields() );
2120  }
2121  else
2122  {
2123  result = exp.evaluate( feat );
2124  }
2125  if ( exp.hasEvalError() )
2126  {
2127  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
2128  expr_action += action.mid( start, index - start );
2129  continue;
2130  }
2131 
2132  QgsDebugMsg( "Expression result is: " + result.toString() );
2133  expr_action += action.mid( start, pos - start ) + result.toString();
2134  }
2135 
2136  expr_action += action.mid( index );
2137 
2138  // restore overwritten local values
2139  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
2140  {
2141  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2142  }
2143 
2144  return expr_action;
2145 }
2146 
2147 double QgsExpression::evaluateToDouble( const QString &text, const double fallbackValue )
2148 {
2149  bool ok;
2150  //first test if text is directly convertible to double
2151  double convertedValue = text.toDouble( &ok );
2152  if ( ok )
2153  {
2154  return convertedValue;
2155  }
2156 
2157  //otherwise try to evalute as expression
2158  QgsExpression expr( text );
2159  QVariant result = expr.evaluate();
2160  convertedValue = result.toDouble( &ok );
2161  if ( expr.hasEvalError() || !ok )
2162  {
2163  return fallbackValue;
2164  }
2165  return convertedValue;
2166 }
2167 
2168 
2170 // nodes
2171 
2173 {
2174  QString msg; bool first = true;
2175  foreach ( Node* n, mList )
2176  {
2177  if ( !first ) msg += ", "; else first = false;
2178  msg += n->dump();
2179  }
2180  return msg;
2181 }
2182 
2183 
2184 //
2185 
2187 {
2188  QVariant val = mOperand->eval( parent, f );
2190 
2191  switch ( mOp )
2192  {
2193  case uoNot:
2194  {
2195  TVL tvl = getTVLValue( val, parent );
2197  return tvl2variant( NOT[tvl] );
2198  }
2199 
2200  case uoMinus:
2201  if ( isIntSafe( val ) )
2202  return QVariant( - getIntValue( val, parent ) );
2203  else if ( isDoubleSafe( val ) )
2204  return QVariant( - getDoubleValue( val, parent ) );
2205  else
2206  SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
2207  break;
2208  default:
2209  Q_ASSERT( 0 && "unknown unary operation" );
2210  }
2211  return QVariant();
2212 }
2213 
2215 {
2216  return mOperand->prepare( parent, fields );
2217 }
2218 
2220 {
2221  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
2222 }
2223 
2224 //
2225 
2227 {
2228  QVariant vL = mOpLeft->eval( parent, f );
2230  QVariant vR = mOpRight->eval( parent, f );
2232 
2233  switch ( mOp )
2234  {
2235  case boPlus:
2236  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
2237  {
2238  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2239  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2240  return QVariant( sL + sR );
2241  }
2242  //intentional fall-through
2243  case boMinus:
2244  case boMul:
2245  case boDiv:
2246  case boMod:
2247  {
2248  if ( isNull( vL ) || isNull( vR ) )
2249  return QVariant();
2250  else if ( mOp != boDiv && isIntSafe( vL ) && isIntSafe( vR ) )
2251  {
2252  // both are integers - let's use integer arithmetics
2253  int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2254  int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2255  return QVariant( computeInt( iL, iR ) );
2256  }
2257  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
2258  {
2259  QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2261  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
2262  {
2263  parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
2264  return QVariant();
2265  }
2266  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
2267  }
2268  else
2269  {
2270  // general floating point arithmetic
2271  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2272  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2273  if ( mOp == boDiv && fR == 0 )
2274  return QVariant(); // silently handle division by zero and return NULL
2275  return QVariant( computeDouble( fL, fR ) );
2276  }
2277  }
2278  case boIntDiv:
2279  {
2280  //integer division
2281  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2282  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2283  if ( fR == 0 )
2284  return QVariant(); // silently handle division by zero and return NULL
2285  return QVariant( qFloor( fL / fR ) );
2286  }
2287  case boPow:
2288  if ( isNull( vL ) || isNull( vR ) )
2289  return QVariant();
2290  else
2291  {
2292  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2293  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2294  return QVariant( pow( fL, fR ) );
2295  }
2296 
2297  case boAnd:
2298  {
2299  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2301  return tvl2variant( AND[tvlL][tvlR] );
2302  }
2303 
2304  case boOr:
2305  {
2306  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2308  return tvl2variant( OR[tvlL][tvlR] );
2309  }
2310 
2311  case boEQ:
2312  case boNE:
2313  case boLT:
2314  case boGT:
2315  case boLE:
2316  case boGE:
2317  if ( isNull( vL ) || isNull( vR ) )
2318  {
2319  return TVL_Unknown;
2320  }
2321  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2322  {
2323  // do numeric comparison if both operators can be converted to numbers
2324  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2325  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2326  return compare( fL - fR ) ? TVL_True : TVL_False;
2327  }
2328  else
2329  {
2330  // do string comparison otherwise
2331  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2332  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2333  int diff = QString::compare( sL, sR );
2334  return compare( diff ) ? TVL_True : TVL_False;
2335  }
2336 
2337  case boIs:
2338  case boIsNot:
2339  if ( isNull( vL ) && isNull( vR ) ) // both operators null
2340  return ( mOp == boIs ? TVL_True : TVL_False );
2341  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
2342  return ( mOp == boIs ? TVL_False : TVL_True );
2343  else // both operators non-null
2344  {
2345  bool equal = false;
2346  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2347  {
2348  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2349  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2350  equal = fL == fR;
2351  }
2352  else
2353  {
2354  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2355  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2356  equal = QString::compare( sL, sR ) == 0;
2357  }
2358  if ( equal )
2359  return mOp == boIs ? TVL_True : TVL_False;
2360  else
2361  return mOp == boIs ? TVL_False : TVL_True;
2362  }
2363 
2364  case boRegexp:
2365  case boLike:
2366  case boNotLike:
2367  case boILike:
2368  case boNotILike:
2369  if ( isNull( vL ) || isNull( vR ) )
2370  return TVL_Unknown;
2371  else
2372  {
2373  QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2374  QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2375  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
2376  bool matches;
2377  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
2378  {
2379  QString esc_regexp = QRegExp::escape( regexp );
2380  // XXX escape % and _ ???
2381  esc_regexp.replace( "%", ".*" );
2382  esc_regexp.replace( "_", "." );
2383  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
2384  }
2385  else
2386  {
2387  matches = QRegExp( regexp ).indexIn( str ) != -1;
2388  }
2389 
2390  if ( mOp == boNotLike || mOp == boNotILike )
2391  {
2392  matches = !matches;
2393  }
2394 
2395  return matches ? TVL_True : TVL_False;
2396  }
2397 
2398  case boConcat:
2399  if ( isNull( vL ) || isNull( vR ) )
2400  return QVariant();
2401  else
2402  {
2403  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2404  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2405  return QVariant( sL + sR );
2406  }
2407 
2408  default: break;
2409  }
2410  Q_ASSERT( false );
2411  return QVariant();
2412 }
2413 
2415 {
2416  switch ( mOp )
2417  {
2418  case boEQ: return diff == 0;
2419  case boNE: return diff != 0;
2420  case boLT: return diff < 0;
2421  case boGT: return diff > 0;
2422  case boLE: return diff <= 0;
2423  case boGE: return diff >= 0;
2424  default: Q_ASSERT( false ); return false;
2425  }
2426 }
2427 
2429 {
2430  switch ( mOp )
2431  {
2432  case boPlus: return x+y;
2433  case boMinus: return x-y;
2434  case boMul: return x*y;
2435  case boDiv: return x/y;
2436  case boMod: return x%y;
2437  default: Q_ASSERT( false ); return 0;
2438  }
2439 }
2440 
2442 {
2443  switch ( mOp )
2444  {
2445  case boPlus: return d.addSecs( i->seconds() );
2446  case boMinus: return d.addSecs( -i->seconds() );
2447  default: Q_ASSERT( false ); return QDateTime();
2448  }
2449 }
2450 
2452 {
2453  switch ( mOp )
2454  {
2455  case boPlus: return x+y;
2456  case boMinus: return x-y;
2457  case boMul: return x*y;
2458  case boDiv: return x/y;
2459  case boMod: return fmod( x,y );
2460  default: Q_ASSERT( false ); return 0;
2461  }
2462 }
2463 
2464 
2466 {
2467  bool resL = mOpLeft->prepare( parent, fields );
2468  bool resR = mOpRight->prepare( parent, fields );
2469  return resL && resR;
2470 }
2471 
2473 {
2474  // see left/right in qgsexpressionparser.yy
2475  switch ( mOp )
2476  {
2477  case boOr:
2478  return 1;
2479 
2480  case boAnd:
2481  return 2;
2482 
2483  case boEQ:
2484  case boNE:
2485  case boLE:
2486  case boGE:
2487  case boLT:
2488  case boGT:
2489  case boRegexp:
2490  case boLike:
2491  case boILike:
2492  case boNotLike:
2493  case boNotILike:
2494  case boIs:
2495  case boIsNot:
2496  return 3;
2497 
2498  case boPlus:
2499  case boMinus:
2500  return 4;
2501 
2502  case boMul:
2503  case boDiv:
2504  case boIntDiv:
2505  case boMod:
2506  return 5;
2507 
2508  case boPow:
2509  return 6;
2510 
2511  case boConcat:
2512  return 7;
2513  }
2514  Q_ASSERT( 0 && "unexpected binary operator" );
2515  return -1;
2516 }
2517 
2519 {
2520  QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
2521  QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
2522 
2523  QString fmt;
2524  fmt += lOp && lOp->precedence() < precedence() ? "(%1)" : "%1";
2525  fmt += " %2 ";
2526  fmt += rOp && rOp->precedence() <= precedence() ? "(%3)" : "%3";
2527 
2528  return fmt.arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
2529 }
2530 
2531 //
2532 
2534 {
2535  if ( mList->count() == 0 )
2536  return mNotIn ? TVL_True : TVL_False;
2537  QVariant v1 = mNode->eval( parent, f );
2539  if ( isNull( v1 ) )
2540  return TVL_Unknown;
2541 
2542  bool listHasNull = false;
2543 
2544  foreach ( Node* n, mList->list() )
2545  {
2546  QVariant v2 = n->eval( parent, f );
2548  if ( isNull( v2 ) )
2549  listHasNull = true;
2550  else
2551  {
2552  bool equal = false;
2553  // check whether they are equal
2554  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
2555  {
2556  double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2557  double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2558  equal = f1 == f2;
2559  }
2560  else
2561  {
2562  QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2563  QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2564  equal = QString::compare( s1, s2 ) == 0;
2565  }
2566 
2567  if ( equal ) // we know the result
2568  return mNotIn ? TVL_False : TVL_True;
2569  }
2570  }
2571 
2572  // item not found
2573  if ( listHasNull )
2574  return TVL_Unknown;
2575  else
2576  return mNotIn ? TVL_True : TVL_False;
2577 }
2578 
2580 {
2581  bool res = mNode->prepare( parent, fields );
2582  foreach ( Node* n, mList->list() )
2583  {
2584  res = res && n->prepare( parent, fields );
2585  }
2586  return res;
2587 }
2588 
2590 {
2591  return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
2592 }
2593 
2594 //
2595 
2597 {
2598  Function* fd = Functions()[mFnIndex];
2599 
2600  // evaluate arguments
2601  QVariantList argValues;
2602  if ( mArgs )
2603  {
2604  foreach ( Node* n, mArgs->list() )
2605  {
2606  QVariant v;
2607  if ( fd->lazyEval() )
2608  {
2609  // Pass in the node for the function to eval as it needs.
2610  v = QVariant::fromValue( n );
2611  }
2612  else
2613  {
2614  v = n->eval( parent, f );
2616  if ( isNull( v ) && fd->name() != "coalesce" )
2617  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
2618  }
2619  argValues.append( v );
2620  }
2621  }
2622 
2623  // run the function
2624  QVariant res = fd->func( argValues, f, parent );
2626 
2627  // everything went fine
2628  return res;
2629 }
2630 
2632 {
2633  bool res = true;
2634  if ( mArgs )
2635  {
2636  foreach ( Node* n, mArgs->list() )
2637  {
2638  res = res && n->prepare( parent, fields );
2639  }
2640  }
2641  return res;
2642 }
2643 
2645 {
2646  Function* fd = Functions()[mFnIndex];
2647  if ( fd->params() == 0 )
2648  return fd->name(); // special column
2649  else
2650  return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
2651 }
2652 
2654 {
2655  Function* fd = Functions()[mFnIndex];
2656  QStringList functionColumns = fd->referencedColumns();
2657 
2658  if ( !mArgs )
2659  {
2660  //no referenced columns in arguments, just return function's referenced columns
2661  return functionColumns;
2662  }
2663 
2664  foreach ( Node* n, mArgs->list() )
2665  {
2666  functionColumns.append( n->referencedColumns() );
2667  }
2668 
2669  //remove duplicates and return
2670  return functionColumns.toSet().toList();
2671 }
2672 
2673 //
2674 
2676 {
2677  return mValue;
2678 }
2679 
2680 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ )
2681 {
2682  return true;
2683 }
2684 
2685 
2687 {
2688  if ( mValue.isNull() )
2689  return "NULL";
2690 
2691  switch ( mValue.type() )
2692  {
2693  case QVariant::Int: return QString::number( mValue.toInt() );
2694  case QVariant::Double: return QString::number( mValue.toDouble() );
2695  case QVariant::String: return quotedString( mValue.toString() );
2696  default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
2697  }
2698 }
2699 
2700 //
2701 
2703 {
2704  if ( f )
2705  {
2706  if ( mIndex >= 0 )
2707  return f->attribute( mIndex );
2708  else
2709  return f->attribute( mName );
2710  }
2711  return QVariant( "[" + mName + "]" );
2712 }
2713 
2715 {
2716  for ( int i = 0; i < fields.count(); ++i )
2717  {
2718  if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
2719  {
2720  mIndex = i;
2721  return true;
2722  }
2723  }
2724  parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName );
2725  mIndex = -1;
2726  return false;
2727 }
2728 
2730 {
2731  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
2732 }
2733 
2734 //
2735 
2737 {
2738  foreach ( WhenThen* cond, mConditions )
2739  {
2740  QVariant vWhen = cond->mWhenExp->eval( parent, f );
2741  TVL tvl = getTVLValue( vWhen, parent );
2743  if ( tvl == True )
2744  {
2745  QVariant vRes = cond->mThenExp->eval( parent, f );
2747  return vRes;
2748  }
2749  }
2750 
2751  if ( mElseExp )
2752  {
2753  QVariant vElse = mElseExp->eval( parent, f );
2755  return vElse;
2756  }
2757 
2758  // return NULL if no condition is matching
2759  return QVariant();
2760 }
2761 
2763 {
2764  bool res;
2765  foreach ( WhenThen* cond, mConditions )
2766  {
2767  res = cond->mWhenExp->prepare( parent, fields )
2768  & cond->mThenExp->prepare( parent, fields );
2769  if ( !res ) return false;
2770  }
2771 
2772  if ( mElseExp )
2773  return mElseExp->prepare( parent, fields );
2774 
2775  return true;
2776 }
2777 
2779 {
2780  QString msg = QString( "CASE" );
2781  foreach ( WhenThen* cond, mConditions )
2782  {
2783  msg += QString( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
2784  }
2785  if ( mElseExp )
2786  msg += QString( " ELSE %1" ).arg( mElseExp->dump() );
2787  msg += QString( " END" );
2788  return msg;
2789 }
2790 
2792 {
2793  QStringList lst;
2794  foreach ( WhenThen* cond, mConditions )
2795  {
2796  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2797  }
2798 
2799  if ( mElseExp )
2800  lst += mElseExp->referencedColumns();
2801 
2802  return lst;
2803 }
2804 
2806 {
2807  foreach ( WhenThen* cond, mConditions )
2808  {
2809  if ( cond->mWhenExp->needsGeometry() ||
2810  cond->mThenExp->needsGeometry() )
2811  return true;
2812  }
2813 
2814  if ( mElseExp && mElseExp->needsGeometry() )
2815  return true;
2816 
2817  return false;
2818 }
2819 
2820 QString QgsExpression::helptext( QString name )
2821 {
2823  return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) );
2824 }
2825 
2826 QHash<QString, QString> QgsExpression::gGroups;
2827 
2828 QString QgsExpression::group( QString name )
2829 {
2830  if ( gGroups.isEmpty() )
2831  {
2832  gGroups.insert( "Operators", QObject::tr( "Operators" ) );
2833  gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) );
2834  gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) );
2835  gGroups.insert( "Math", QObject::tr( "Math" ) );
2836  gGroups.insert( "Conversions", QObject::tr( "Conversions" ) );
2837  gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) );
2838  gGroups.insert( "String", QObject::tr( "String" ) );
2839  gGroups.insert( "Color", QObject::tr( "Color" ) );
2840  gGroups.insert( "GeometryGroup", QObject::tr( "Geometry" ) );
2841  gGroups.insert( "Record", QObject::tr( "Record" ) );
2842  }
2843 
2844  //return the translated name for this group. If group does not
2845  //have a translated name in the gGroups hash, return the name
2846  //unchanged
2847  return gGroups.value( name, name );
2848 }
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f) override
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
static QVariant fcnDifference(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCombine(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
static int functionIndex(QString name)
static QVariant fcnAge(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnColorHsv(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QStringList referencedColumns() const =0
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
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:94
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)
static bool unregisterFunction(QString name)
static QString quotedColumnRef(QString name)
return quoted column reference (in double quotes)
static QVariant fcnLog(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnYat(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnMinute(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRight(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool lazyEval()
True if this function should use lazy evaluation.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields) override
QgsGeometry * combine(QgsGeometry *geometry)
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static QVariant fcnYMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnReplace(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
void initGeomCalculator()
static QVariant fcnTouches(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
A abstract base class for defining QgsExpression functions.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QVariant fcnGeomLength(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnScale(const QVariantList &, const QgsFeature *, QgsExpression *parent)
double computeDouble(double x, double y)
virtual QString dump() const =0
static QDate getDateValue(const QVariant &value, QgsExpression *parent)
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
Definition: qgsgeometry.h:33
static QVariant fcnFloor(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f) override
static QString helptext(QString name)
static QVariant fcnXMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
static QVariant fcnFormatDate(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnIf(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f) override
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
QgsExpression()
Used by QgsOgcUtils to create an empty.
static QVariant fcnToTime(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSqrt(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnIntersects(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnNow(const QVariantList &, const QgsFeature *, QgsExpression *)
QVariant fcnRampColor(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool crosses(const QgsGeometry *geometry) const
Test for if geometry crosses another (uses GEOS)
Container of fields for a vector layer.
Definition: qgsfield.h:172
static QVariant fcnSin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnContains(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToInt(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)=0
QgsExpression::Node * parseExpression(const QString &str, QString &parserErrorMsg)
static QVariant fcnToDateTime(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString group(QString group)
static QTime getTimeValue(const QVariant &value, QgsExpression *parent)
QString dump() const
Return the expression string that represents this QgsExpression.
bool isDoubleSafe(const QVariant &v)
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:113
static QVariant fcnStrpos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnYMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static TVL getTVLValue(const QVariant &value, QgsExpression *parent)
int currentRowNumber()
Return the number used for $rownum special column.
static QVariant fcnBuffer(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool isValid(const QString &text, const QgsFields &fields, QString &errorMessage)
QgsGeometry * difference(QgsGeometry *geometry)
Returns a geometry representing the points making up this geometry that do not make up other...
QString mEvalErrorString
static QVariant fcnYear(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
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)
QgsGeometry * centroid()
Returns the center of mass of a geometry.
static QVariant fcnTan(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry getGeometry(const QVariant &value, QgsExpression *parent)
#define ENSURE_NO_EVAL_ERROR
QString mParserErrorString
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
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
QgsGeometry * buffer(double distance, int segments)
Returns a buffer region around this geometry having the given width and with a specified number of se...
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
static QVariant fcnFeature(const QVariantList &, const QgsFeature *f, QgsExpression *)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields) override
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
double measurePerimeter(QgsGeometry *geometry)
measures perimeter of polygon
virtual QString dump() const override
double measure(QgsGeometry *geometry)
general measurement (line distance or polygon area)
static bool registerFunction(Function *function)
static QVariant fcnAtan2(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsDistanceArea * mCalc
QgsGeometry * convexHull()
Returns the smallest convex polygon that contains all the points in the geometry. ...
static QVariant fncColorHsla(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry * geometryFromGML(const QString &xmlString)
static method that creates geometry from GML
Definition: qgsogcutils.cpp:81
#define SET_EVAL_ERROR(x)
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 scale()
int count() const
Return number of items.
Definition: qgsfield.h:214
#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
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 * intersection(QgsGeometry *geometry)
Returns a geometry representing the points shared by this geometry and other.
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)
QgsGeometry * symDifference(QgsGeometry *geometry)
Returns a Geometry representing the points making up this Geometry that do not make up other...
static QVariant fcnGeomFromGML(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
General purpose distance and area calculator.
static QMap< QString, QString > gmSpecialColumnGroups
virtual QString dump() const override
QgsRectangle boundingBox()
Returns the bounding box of this feature.
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)
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
static QVariant fcnConcat(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isDateTimeSafe(const QVariant &v)
static const char * UnaryOperatorText[]
static QgsExpression::Interval invalidInterVal()
static QVariant fcnXat(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnUpper(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnLinearScale(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
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)
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 CoordinateTranasform 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:198
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
static QVariant fcnBoundsHeight(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:96
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
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:183
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:203
static QgsExpression::Interval getInterval(const QVariant &value, QgsExpression *parent, bool report_error=false)
static QDateTime getDateTimeValue(const QVariant &value, QgsExpression *parent)
static QVariant fcnRound(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
double distance(QgsGeometry &geom)
static void unsetSpecialColumn(const QString &name)
Unset a special column.
#define tr(sourceText)
static const char * BinaryOperatorText[]
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...
static QMap< QString, QVariant > gmSpecialColumns