QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.cpp
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsexpression.h"
17 
18 #include <QtDebug>
19 #include <QDomDocument>
20 #include <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 )rand() / 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 + ( rand() % ( 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  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  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1302  QString wkt = fGeom.exportToWkt();
1303  return QVariant( wkt );
1304 }
1305 
1306 static QVariant fcnRound( const QVariantList& values, const QgsFeature *f, QgsExpression* parent )
1307 {
1308  Q_UNUSED( f );
1309  if ( values.length() == 2 )
1310  {
1311  double number = getDoubleValue( values.at( 0 ), parent );
1312  double scaler = pow( 10.0, getIntValue( values.at( 1 ), parent ) );
1313  return QVariant( qRound( number * scaler ) / scaler );
1314  }
1315 
1316  if ( values.length() == 1 )
1317  {
1318  double number = getIntValue( values.at( 0 ), parent );
1319  return QVariant( qRound( number ) ).toInt();
1320  }
1321 
1322  return QVariant();
1323 }
1324 
1325 static QVariant fcnPi( const QVariantList& values, const QgsFeature *f, QgsExpression* parent )
1326 {
1327  Q_UNUSED( values );
1328  Q_UNUSED( f );
1329  Q_UNUSED( parent );
1330  return M_PI;
1331 }
1332 
1333 static QVariant fcnScale( const QVariantList&, const QgsFeature*, QgsExpression* parent )
1334 {
1335  return QVariant( parent->scale() );
1336 }
1337 
1338 static QVariant fcnFormatNumber( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1339 {
1340  double value = getDoubleValue( values.at( 0 ), parent );
1341  int places = getIntValue( values.at( 1 ), parent );
1342  return QString( "%L1" ).arg( value, 0, 'f', places );
1343 }
1344 
1345 static QVariant fcnFormatDate( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1346 {
1347  QDateTime dt = getDateTimeValue( values.at( 0 ), parent );
1348  QString format = getStringValue( values.at( 1 ), parent );
1349  return dt.toString( format );
1350 }
1351 
1352 static QVariant fcnColorRgb( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1353 {
1354  int red = getIntValue( values.at( 0 ), parent );
1355  int green = getIntValue( values.at( 1 ), parent );
1356  int blue = getIntValue( values.at( 2 ), parent );
1357  QColor color = QColor( red, green, blue );
1358  if ( ! color.isValid() )
1359  {
1360  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
1361  color = QColor( 0, 0, 0 );
1362  }
1363 
1364  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1365 }
1366 
1367 static QVariant fcnIf( const QVariantList &values, const QgsFeature *f, QgsExpression *parent )
1368 {
1369  QgsExpression::Node* node = getNode( values.at( 0 ), parent );
1371  QVariant value = node->eval( parent, f );
1373  if ( value.toBool() ) {
1374  node = getNode( values.at( 1 ), parent );
1376  value = node->eval( parent, f );
1378  }
1379  else {
1380  node = getNode( values.at( 2 ), parent );
1382  value = node->eval( parent, f );
1384  }
1385  return value;
1386 }
1387 
1388 static QVariant fncColorRgba( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1389 {
1390  int red = getIntValue( values.at( 0 ), parent );
1391  int green = getIntValue( values.at( 1 ), parent );
1392  int blue = getIntValue( values.at( 2 ), parent );
1393  int alpha = getIntValue( values.at( 3 ), parent );
1394  QColor color = QColor( red, green, blue, alpha );
1395  if ( ! color.isValid() )
1396  {
1397  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
1398  color = QColor( 0, 0, 0 );
1399  }
1400  return QgsSymbolLayerV2Utils::encodeColor( color );
1401 }
1402 
1403 QVariant fcnRampColor( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1404 {
1405  QString rampName = getStringValue( values.at( 0 ), parent );
1406  const QgsVectorColorRampV2 *mRamp = QgsStyleV2::defaultStyle()->colorRampRef( rampName );
1407  if ( ! mRamp )
1408  {
1409  parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) );
1410  return QColor( 0, 0, 0 ).name();
1411  }
1412  double value = getDoubleValue( values.at( 1 ), parent );
1413  QColor color = mRamp->color( value );
1414  return QgsSymbolLayerV2Utils::encodeColor( color );
1415 }
1416 
1417 static QVariant fcnColorHsl( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1418 {
1419  // Hue ranges from 0 - 360
1420  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1421  // Saturation ranges from 0 - 100
1422  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1423  // Lightness ranges from 0 - 100
1424  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1425 
1426  QColor color = QColor::fromHslF( hue, saturation, lightness );
1427 
1428  if ( ! color.isValid() )
1429  {
1430  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
1431  color = QColor( 0, 0, 0 );
1432  }
1433 
1434  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1435 }
1436 
1437 static QVariant fncColorHsla( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1438 {
1439  // Hue ranges from 0 - 360
1440  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1441  // Saturation ranges from 0 - 100
1442  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1443  // Lightness ranges from 0 - 100
1444  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1445  // Alpha ranges from 0 - 255
1446  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1447 
1448  QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
1449  if ( ! color.isValid() )
1450  {
1451  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
1452  color = QColor( 0, 0, 0 );
1453  }
1454  return QgsSymbolLayerV2Utils::encodeColor( color );
1455 }
1456 
1457 static QVariant fcnColorHsv( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1458 {
1459  // Hue ranges from 0 - 360
1460  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1461  // Saturation ranges from 0 - 100
1462  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1463  // Value ranges from 0 - 100
1464  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1465 
1466  QColor color = QColor::fromHsvF( hue, saturation, value );
1467 
1468  if ( ! color.isValid() )
1469  {
1470  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
1471  color = QColor( 0, 0, 0 );
1472  }
1473 
1474  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1475 }
1476 
1477 static QVariant fncColorHsva( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1478 {
1479  // Hue ranges from 0 - 360
1480  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1481  // Saturation ranges from 0 - 100
1482  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1483  // Value ranges from 0 - 100
1484  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1485  // Alpha ranges from 0 - 255
1486  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1487 
1488  QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
1489  if ( ! color.isValid() )
1490  {
1491  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
1492  color = QColor( 0, 0, 0 );
1493  }
1494  return QgsSymbolLayerV2Utils::encodeColor( color );
1495 }
1496 
1497 static QVariant fcnColorCmyk( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1498 {
1499  // Cyan ranges from 0 - 100
1500  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1501  // Magenta ranges from 0 - 100
1502  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1503  // Yellow ranges from 0 - 100
1504  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1505  // Black ranges from 0 - 100
1506  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1507 
1508  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
1509 
1510  if ( ! color.isValid() )
1511  {
1512  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
1513  color = QColor( 0, 0, 0 );
1514  }
1515 
1516  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1517 }
1518 
1519 static QVariant fncColorCmyka( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1520 {
1521  // Cyan ranges from 0 - 100
1522  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1523  // Magenta ranges from 0 - 100
1524  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1525  // Yellow ranges from 0 - 100
1526  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1527  // Black ranges from 0 - 100
1528  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1529  // Alpha ranges from 0 - 255
1530  double alpha = getIntValue( values.at( 4 ), parent ) / 255.0;
1531 
1532  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
1533  if ( ! color.isValid() )
1534  {
1535  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
1536  color = QColor( 0, 0, 0 );
1537  }
1538  return QgsSymbolLayerV2Utils::encodeColor( color );
1539 }
1540 
1541 static QVariant fcnSpecialColumn( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent )
1542 {
1543  QString varName = getStringValue( values.at( 0 ), parent );
1544  return QgsExpression::specialColumn( varName );
1545 }
1546 
1547 static QVariant fcnGetFeature( const QVariantList& values, const QgsFeature *, QgsExpression* parent )
1548 {
1549  //arguments: 1. layer id / name, 2. key attribute, 3. eq value
1550  QString layerString = getStringValue( values.at( 0 ), parent );
1551  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerString ) ); //search by id first
1552  if ( !vl )
1553  {
1554  QList<QgsMapLayer *> layersByName = QgsMapLayerRegistry::instance()->mapLayersByName( layerString );
1555  if ( layersByName.size() > 0 )
1556  {
1557  vl = qobject_cast<QgsVectorLayer*>( layersByName.at( 0 ) );
1558  }
1559  }
1560 
1561  //no layer found
1562  if ( !vl )
1563  {
1564  return QVariant();
1565  }
1566 
1567  QString attribute = getStringValue( values.at( 1 ), parent );
1568  int attributeId = vl->fieldNameIndex( attribute );
1569  if ( attributeId == -1 )
1570  {
1571  return QVariant();
1572  }
1573 
1574  const QVariant& attVal = values.at( 2 );
1575  QgsFeatureRequest req;
1576  if ( !parent->needsGeometry() )
1577  {
1579  }
1580  QgsFeatureIterator fIt = vl->getFeatures( req );
1581 
1582  QgsFeature fet;
1583  while ( fIt.nextFeature( fet ) )
1584  {
1585  if ( fet.attribute( attributeId ) == attVal )
1586  {
1587  return QVariant::fromValue( fet );
1588  }
1589  }
1590  return QVariant();
1591 }
1592 
1594 {
1595  int fnIdx = functionIndex( function->name() );
1596  if ( fnIdx != -1 )
1597  {
1598  return false;
1599  }
1600  QgsExpression::gmFunctions.append( function );
1601  return true;
1602 }
1603 
1605 {
1606  // You can never override the built in functions.
1607  if ( QgsExpression::BuiltinFunctions().contains( name ) )
1608  {
1609  return false;
1610  }
1611  int fnIdx = functionIndex( name );
1612  if ( fnIdx != -1 )
1613  {
1614  QgsExpression::gmFunctions.removeAt( fnIdx );
1615  return true;
1616  }
1617  return false;
1618 }
1619 
1620 
1621 
1623 
1625 {
1626  if ( gmBuiltinFunctions.isEmpty() )
1627  {
1629  << "abs" << "sqrt" << "cos" << "sin" << "tan"
1630  << "asin" << "acos" << "atan" << "atan2"
1631  << "exp" << "ln" << "log10" << "log"
1632  << "round" << "rand" << "randf" << "max" << "min" << "clamp"
1633  << "scale_linear" << "scale_exp" << "floor" << "ceil"
1634  << "toint" << "toreal" << "tostring"
1635  << "todatetime" << "todate" << "totime" << "tointerval"
1636  << "coalesce" << "regexp_match" << "$now" << "age" << "year"
1637  << "month" << "week" << "day" << "hour"
1638  << "minute" << "second" << "lower" << "upper"
1639  << "title" << "length" << "replace" << "trim" << "wordwrap"
1640  << "regexp_replace" << "regexp_substr"
1641  << "substr" << "concat" << "strpos" << "left"
1642  << "right" << "rpad" << "lpad"
1643  << "format_number" << "format_date"
1644  << "color_rgb" << "color_rgba" << "ramp_color"
1645  << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva"
1646  << "color_cymk" << "color_cymka"
1647  << "xat" << "yat" << "$area"
1648  << "$length" << "$perimeter" << "$x" << "$y"
1649  << "$rownum" << "$id" << "$scale" << "_specialcol_";
1650  }
1651  return gmBuiltinFunctions;
1652 }
1653 
1654 QList<QgsExpression::Function*> QgsExpression::gmFunctions;
1655 
1656 const QList<QgsExpression::Function*> &QgsExpression::Functions()
1657 {
1658  if ( gmFunctions.isEmpty() )
1659  {
1660  gmFunctions
1661  << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
1662  << new StaticFunction( "abs", 1, fcnAbs, "Math" )
1663  << new StaticFunction( "cos", 1, fcnCos, "Math" )
1664  << new StaticFunction( "sin", 1, fcnSin, "Math" )
1665  << new StaticFunction( "tan", 1, fcnTan, "Math" )
1666  << new StaticFunction( "asin", 1, fcnAsin, "Math" )
1667  << new StaticFunction( "acos", 1, fcnAcos, "Math" )
1668  << new StaticFunction( "atan", 1, fcnAtan, "Math" )
1669  << new StaticFunction( "atan2", 2, fcnAtan2, "Math" )
1670  << new StaticFunction( "exp", 1, fcnExp, "Math" )
1671  << new StaticFunction( "ln", 1, fcnLn, "Math" )
1672  << new StaticFunction( "log10", 1, fcnLog10, "Math" )
1673  << new StaticFunction( "log", 2, fcnLog, "Math" )
1674  << new StaticFunction( "round", -1, fcnRound, "Math" )
1675  << new StaticFunction( "rand", 2, fcnRnd, "Math" )
1676  << new StaticFunction( "randf", 2, fcnRndF, "Math" )
1677  << new StaticFunction( "max", -1, fcnMax, "Math" )
1678  << new StaticFunction( "min", -1, fcnMin, "Math" )
1679  << new StaticFunction( "clamp", 3, fcnClamp, "Math" )
1680  << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" )
1681  << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" )
1682  << new StaticFunction( "floor", 1, fcnFloor, "Math" )
1683  << new StaticFunction( "ceil", 1, fcnCeil, "Math" )
1684  << new StaticFunction( "$pi", 0, fcnPi, "Math" )
1685  << new StaticFunction( "toint", 1, fcnToInt, "Conversions" )
1686  << new StaticFunction( "toreal", 1, fcnToReal, "Conversions" )
1687  << new StaticFunction( "tostring", 1, fcnToString, "Conversions" )
1688  << new StaticFunction( "todatetime", 1, fcnToDateTime, "Conversions" )
1689  << new StaticFunction( "todate", 1, fcnToDate, "Conversions" )
1690  << new StaticFunction( "totime", 1, fcnToTime, "Conversions" )
1691  << new StaticFunction( "tointerval", 1, fcnToInterval, "Conversions" )
1692  << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" )
1693  << new StaticFunction( "if", 3, fcnIf, "Conditionals", "", False, QStringList(), true )
1694  << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
1695  << new StaticFunction( "$now", 0, fcnNow, "Date and Time" )
1696  << new StaticFunction( "age", 2, fcnAge, "Date and Time" )
1697  << new StaticFunction( "year", 1, fcnYear, "Date and Time" )
1698  << new StaticFunction( "month", 1, fcnMonth, "Date and Time" )
1699  << new StaticFunction( "week", 1, fcnWeek, "Date and Time" )
1700  << new StaticFunction( "day", 1, fcnDay, "Date and Time" )
1701  << new StaticFunction( "hour", 1, fcnHour, "Date and Time" )
1702  << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" )
1703  << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" )
1704  << new StaticFunction( "lower", 1, fcnLower, "String" )
1705  << new StaticFunction( "upper", 1, fcnUpper, "String" )
1706  << new StaticFunction( "title", 1, fcnTitle, "String" )
1707  << new StaticFunction( "trim", 1, fcnTrim, "String" )
1708  << new StaticFunction( "wordwrap", -1, fcnWordwrap, "String" )
1709  << new StaticFunction( "length", 1, fcnLength, "String" )
1710  << new StaticFunction( "replace", 3, fcnReplace, "String" )
1711  << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
1712  << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
1713  << new StaticFunction( "substr", 3, fcnSubstr, "String" )
1714  << new StaticFunction( "concat", -1, fcnConcat, "String" )
1715  << new StaticFunction( "strpos", 2, fcnStrpos, "String" )
1716  << new StaticFunction( "left", 2, fcnLeft, "String" )
1717  << new StaticFunction( "right", 2, fcnRight, "String" )
1718  << new StaticFunction( "rpad", 3, fcnRPad, "String" )
1719  << new StaticFunction( "lpad", 3, fcnLPad, "String" )
1720  << new StaticFunction( "format", -1, fcnFormatString, "String" )
1721  << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
1722  << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
1723  << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
1724  << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
1725  << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
1726  << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" )
1727  << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" )
1728  << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" )
1729  << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" )
1730  << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" )
1731  << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" )
1732  << new StaticFunction( "$geometry", 0, fcnGeometry, "Geometry", "", true )
1733  << new StaticFunction( "$area", 0, fcnGeomArea, "Geometry", "", true )
1734  << new StaticFunction( "$length", 0, fcnGeomLength, "Geometry", "", true )
1735  << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "Geometry", "", true )
1736  << new StaticFunction( "$x", 0, fcnX, "Geometry", "", true )
1737  << new StaticFunction( "$y", 0, fcnY, "Geometry", "", true )
1738  << new StaticFunction( "xat", 1, fcnXat, "Geometry", "", true )
1739  << new StaticFunction( "yat", 1, fcnYat, "Geometry", "", true )
1740  << new StaticFunction( "xmin", 1, fcnXMin, "Geometry", "", true )
1741  << new StaticFunction( "xmax", 1, fcnXMax, "Geometry", "", true )
1742  << new StaticFunction( "ymin", 1, fcnYMin, "Geometry", "", true )
1743  << new StaticFunction( "ymax", 1, fcnYMax, "Geometry", "", true )
1744  << new StaticFunction( "geomFromWKT", 1, fcnGeomFromWKT, "Geometry" )
1745  << new StaticFunction( "geomFromGML", 1, fcnGeomFromGML, "Geometry" )
1746  << new StaticFunction( "bbox", 2, fcnBbox, "Geometry" )
1747  << new StaticFunction( "disjoint", 2, fcnDisjoint, "Geometry" )
1748  << new StaticFunction( "intersects", 2, fcnIntersects, "Geometry" )
1749  << new StaticFunction( "touches", 2, fcnTouches, "Geometry" )
1750  << new StaticFunction( "crosses", 2, fcnCrosses, "Geometry" )
1751  << new StaticFunction( "contains", 2, fcnContains, "Geometry" )
1752  << new StaticFunction( "overlaps", 2, fcnOverlaps, "Geometry" )
1753  << new StaticFunction( "within", 2, fcnWithin, "Geometry" )
1754  << new StaticFunction( "buffer", -1, fcnBuffer, "Geometry" )
1755  << new StaticFunction( "centroid", 1, fcnCentroid, "Geometry" )
1756  << new StaticFunction( "bounds", 1, fcnBounds, "Geometry", "", true )
1757  << new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "Geometry", "", true )
1758  << new StaticFunction( "bounds_height", 1, fcnBoundsHeight, "Geometry", "", true )
1759  << new StaticFunction( "convexHull", 1, fcnConvexHull, "Geometry" )
1760  << new StaticFunction( "difference", 2, fcnDifference, "Geometry" )
1761  << new StaticFunction( "distance", 2, fcnDistance, "Geometry" )
1762  << new StaticFunction( "intersection", 2, fcnIntersection, "Geometry" )
1763  << new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" )
1764  << new StaticFunction( "combine", 2, fcnCombine, "Geometry" )
1765  << new StaticFunction( "union", 2, fcnCombine, "Geometry" )
1766  << new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" )
1767  << new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
1768  << new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
1769  << new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
1770  << new StaticFunction( "$scale", 0, fcnScale, "Record" )
1771  << new StaticFunction( "$uuid", 0, fcnUuid, "Record" )
1772  << new StaticFunction( "getFeature", 3, fcnGetFeature, "Record" )
1773 
1774  //return all attributes string for referencedColumns - this is caught by
1775  // QgsFeatureRequest::setSubsetOfAttributes and causes all attributes to be fetched by the
1776  // feature request
1777  << new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
1778 
1779  << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
1780  ;
1781  }
1782  return gmFunctions;
1783 }
1784 
1785 QMap<QString, QVariant> QgsExpression::gmSpecialColumns;
1786 QMap<QString, QString> QgsExpression::gmSpecialColumnGroups;
1787 
1788 void QgsExpression::setSpecialColumn( const QString& name, QVariant variant )
1789 {
1790  int fnIdx = functionIndex( name );
1791  if ( fnIdx != -1 )
1792  {
1793  // function of the same name already exists
1794  return;
1795  }
1796  gmSpecialColumns[ name ] = variant;
1797 }
1798 
1799 void QgsExpression::unsetSpecialColumn( const QString& name )
1800 {
1801  QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name );
1802  if ( fit != gmSpecialColumns.end() )
1803  {
1804  gmSpecialColumns.erase( fit );
1805  }
1806 }
1807 
1808 QVariant QgsExpression::specialColumn( const QString& name )
1809 {
1810  int fnIdx = functionIndex( name );
1811  if ( fnIdx != -1 )
1812  {
1813  // function of the same name already exists
1814  return QVariant();
1815  }
1816  QMap<QString, QVariant>::iterator it = gmSpecialColumns.find( name );
1817  if ( it == gmSpecialColumns.end() )
1818  {
1819  return QVariant();
1820  }
1821  return it.value();
1822 }
1823 
1824 bool QgsExpression::hasSpecialColumn( const QString& name )
1825 {
1826  static bool initialized = false;
1827  if ( !initialized )
1828  {
1829  // Pre-register special columns that will exist within QGIS so that expressions that may use them are parsed correctly.
1830  // This is really sub-optimal, we should get rid of the special columns and instead have contexts in which some values
1831  // are defined and some are not ($rownum makes sense only in field calculator, $scale only when rendering, $page only for composer etc.)
1832 
1833  //pairs of column name to group name
1834  QList< QPair<QString, QString> > lst;
1835  lst << qMakePair( QString( "$page" ), QString( "Composer" ) );
1836  lst << qMakePair( QString( "$feature" ), QString( "Atlas" ) );
1837  lst << qMakePair( QString( "$numpages" ), QString( "Composer" ) );
1838  lst << qMakePair( QString( "$numfeatures" ), QString( "Atlas" ) );
1839  lst << qMakePair( QString( "$atlasfeatureid" ), QString( "Atlas" ) );
1840  lst << qMakePair( QString( "$atlasgeometry" ), QString( "Atlas" ) );
1841  lst << qMakePair( QString( "$atlasfeature" ), QString( "Atlas" ) );
1842  lst << qMakePair( QString( "$map" ), QString( "Composer" ) );
1843 
1844  QList< QPair<QString, QString> >::const_iterator it = lst.constBegin();
1845  for ( ; it != lst.constEnd(); ++it )
1846  {
1847  setSpecialColumn(( *it ).first, QVariant() );
1848  gmSpecialColumnGroups[( *it ).first ] = ( *it ).second;
1849  }
1850 
1851  initialized = true;
1852  }
1853 
1854  if ( functionIndex( name ) != -1 )
1855  return false;
1856  return gmSpecialColumns.contains( name );
1857 }
1858 
1859 bool QgsExpression::isValid( const QString &text, const QgsFields &fields, QString &errorMessage )
1860 {
1861  QgsExpression exp( text );
1862  exp.prepare( fields );
1863  errorMessage = exp.parserErrorString();
1864  return !exp.hasParserError();
1865 }
1866 
1867 QList<QgsExpression::Function*> QgsExpression::specialColumns()
1868 {
1869  QList<Function*> defs;
1870  for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.begin(); it != gmSpecialColumns.end(); ++it )
1871  {
1872  //check for special column group name
1873  QString group = gmSpecialColumnGroups.value( it.key(), "Record" );
1874  defs << new StaticFunction( it.key(), 0, 0, group );
1875  }
1876  return defs;
1877 }
1878 
1879 QString QgsExpression::quotedColumnRef( QString name )
1880 {
1881  return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) );
1882 }
1883 
1884 QString QgsExpression::quotedString( QString text )
1885 {
1886  text.replace( "'", "''" );
1887  text.replace( '\\', "\\\\" );
1888  text.replace( '\n', "\\n" );
1889  text.replace( '\t', "\\t" );
1890  return QString( "'%1'" ).arg( text );
1891 }
1892 
1893 bool QgsExpression::isFunctionName( QString name )
1894 {
1895  return functionIndex( name ) != -1;
1896 }
1897 
1898 int QgsExpression::functionIndex( QString name )
1899 {
1900  int count = functionCount();
1901  for ( int i = 0; i < count; i++ )
1902  {
1903  if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
1904  return i;
1905  }
1906  return -1;
1907 }
1908 
1910 {
1911  return Functions().size();
1912 }
1913 
1914 
1915 QgsExpression::QgsExpression( const QString& expr )
1916  : mRowNumber( 0 )
1917  , mScale( 0 )
1918  , mExp( expr )
1919  , mCalc( 0 )
1920 {
1922 
1923  if ( mParserErrorString.isNull() )
1924  Q_ASSERT( mRootNode );
1925 }
1926 
1928 {
1929  delete mCalc;
1930  delete mRootNode;
1931 }
1932 
1934 {
1935  if ( !mRootNode )
1936  return QStringList();
1937 
1938  QStringList columns = mRootNode->referencedColumns();
1939 
1940  // filter out duplicates
1941  for ( int i = 0; i < columns.count(); i++ )
1942  {
1943  QString col = columns.at( i );
1944  for ( int j = i + 1; j < columns.count(); j++ )
1945  {
1946  if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
1947  {
1948  // this column is repeated: remove it!
1949  columns.removeAt( j-- );
1950  }
1951  }
1952  }
1953 
1954  return columns;
1955 }
1956 
1958 {
1959  if ( !mRootNode )
1960  return false;
1961  return mRootNode->needsGeometry();
1962 }
1963 
1965 {
1966  if ( mCalc )
1967  return;
1968 
1969  // Use planimetric as default
1970  mCalc = new QgsDistanceArea();
1971  mCalc->setEllipsoidalMode( false );
1972 }
1973 
1975 {
1976  delete mCalc;
1977  mCalc = new QgsDistanceArea( calc );
1978 }
1979 
1980 bool QgsExpression::prepare( const QgsFields& fields )
1981 {
1982  mEvalErrorString = QString();
1983  if ( !mRootNode )
1984  {
1985  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1986  return false;
1987  }
1988 
1989  return mRootNode->prepare( this, fields );
1990 }
1991 
1993 {
1994  mEvalErrorString = QString();
1995  if ( !mRootNode )
1996  {
1997  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1998  return QVariant();
1999  }
2000 
2001  return mRootNode->eval( this, f );
2002 }
2003 
2004 QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields )
2005 {
2006  // first prepare
2007  bool res = prepare( fields );
2008  if ( !res )
2009  return QVariant();
2010 
2011  // then evaluate
2012  return evaluate( f );
2013 }
2014 
2015 QString QgsExpression::dump() const
2016 {
2017  if ( !mRootNode )
2018  return QObject::tr( "(no root)" );
2019 
2020  return mRootNode->dump();
2021 }
2022 
2024 {
2025  if ( mRootNode )
2026  mRootNode->accept( v );
2027 }
2028 
2029 QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
2030  QgsVectorLayer *layer,
2031  const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
2032 {
2033  QString expr_action;
2034 
2035  QMap<QString, QVariant> savedValues;
2036  if ( substitutionMap )
2037  {
2038  // variables with a local scope (must be restored after evaluation)
2039  for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
2040  {
2041  QVariant oldValue = QgsExpression::specialColumn( sit.key() );
2042  if ( !oldValue.isNull() )
2043  savedValues.insert( sit.key(), oldValue );
2044 
2045  // set the new value
2046  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2047  }
2048  }
2049 
2050  int index = 0;
2051  while ( index < action.size() )
2052  {
2053  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
2054 
2055  int pos = rx.indexIn( action, index );
2056  if ( pos < 0 )
2057  break;
2058 
2059  int start = index;
2060  index = pos + rx.matchedLength();
2061  QString to_replace = rx.cap( 1 ).trimmed();
2062  QgsDebugMsg( "Found expression: " + to_replace );
2063 
2064  QgsExpression exp( to_replace );
2065  if ( exp.hasParserError() )
2066  {
2067  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
2068  expr_action += action.mid( start, index - start );
2069  continue;
2070  }
2071 
2072  if ( distanceArea )
2073  {
2074  //if QgsDistanceArea specified for area/distance conversion, use it
2075  exp.setGeomCalculator( *distanceArea );
2076  }
2077 
2078  QVariant result;
2079  if ( layer )
2080  {
2081  result = exp.evaluate( feat, layer->pendingFields() );
2082  }
2083  else
2084  {
2085  result = exp.evaluate( feat );
2086  }
2087  if ( exp.hasEvalError() )
2088  {
2089  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
2090  expr_action += action.mid( start, index - start );
2091  continue;
2092  }
2093 
2094  QgsDebugMsg( "Expression result is: " + result.toString() );
2095  expr_action += action.mid( start, pos - start ) + result.toString();
2096  }
2097 
2098  expr_action += action.mid( index );
2099 
2100  // restore overwritten local values
2101  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
2102  {
2103  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
2104  }
2105 
2106  return expr_action;
2107 }
2108 
2109 double QgsExpression::evaluateToDouble( const QString &text, const double fallbackValue )
2110 {
2111  bool ok;
2112  //first test if text is directly convertible to double
2113  double convertedValue = text.toDouble( &ok );
2114  if ( ok )
2115  {
2116  return convertedValue;
2117  }
2118 
2119  //otherwise try to evalute as expression
2120  QgsExpression expr( text );
2121  QVariant result = expr.evaluate();
2122  convertedValue = result.toDouble( &ok );
2123  if ( expr.hasEvalError() || !ok )
2124  {
2125  return fallbackValue;
2126  }
2127  return convertedValue;
2128 }
2129 
2130 
2132 // nodes
2133 
2135 {
2136  QString msg; bool first = true;
2137  foreach ( Node* n, mList )
2138  {
2139  if ( !first ) msg += ", "; else first = false;
2140  msg += n->dump();
2141  }
2142  return msg;
2143 }
2144 
2145 
2146 //
2147 
2149 {
2150  QVariant val = mOperand->eval( parent, f );
2152 
2153  switch ( mOp )
2154  {
2155  case uoNot:
2156  {
2157  TVL tvl = getTVLValue( val, parent );
2159  return tvl2variant( NOT[tvl] );
2160  }
2161 
2162  case uoMinus:
2163  if ( isIntSafe( val ) )
2164  return QVariant( - getIntValue( val, parent ) );
2165  else if ( isDoubleSafe( val ) )
2166  return QVariant( - getDoubleValue( val, parent ) );
2167  else
2168  SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
2169  break;
2170  default:
2171  Q_ASSERT( 0 && "unknown unary operation" );
2172  }
2173  return QVariant();
2174 }
2175 
2177 {
2178  return mOperand->prepare( parent, fields );
2179 }
2180 
2182 {
2183  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
2184 }
2185 
2186 //
2187 
2189 {
2190  QVariant vL = mOpLeft->eval( parent, f );
2192  QVariant vR = mOpRight->eval( parent, f );
2194 
2195  switch ( mOp )
2196  {
2197  case boPlus:
2198  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
2199  {
2200  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2201  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2202  return QVariant( sL + sR );
2203  }
2204  case boMinus:
2205  case boMul:
2206  case boDiv:
2207  case boMod:
2208  {
2209  if ( isNull( vL ) || isNull( vR ) )
2210  return QVariant();
2211  else if ( mOp != boDiv && isIntSafe( vL ) && isIntSafe( vR ) )
2212  {
2213  // both are integers - let's use integer arithmetics
2214  int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2215  int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2216  return QVariant( computeInt( iL, iR ) );
2217  }
2218  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
2219  {
2220  QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2222  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
2223  {
2224  parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
2225  return QVariant();
2226  }
2227  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
2228  }
2229  else
2230  {
2231  // general floating point arithmetic
2232  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2233  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2234  if ( mOp == boDiv && fR == 0 )
2235  return QVariant(); // silently handle division by zero and return NULL
2236  return QVariant( computeDouble( fL, fR ) );
2237  }
2238  }
2239  case boIntDiv:
2240  {
2241  //integer division
2242  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2243  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2244  if ( fR == 0 )
2245  return QVariant(); // silently handle division by zero and return NULL
2246  return QVariant( qFloor( fL / fR ) );
2247  }
2248  case boPow:
2249  if ( isNull( vL ) || isNull( vR ) )
2250  return QVariant();
2251  else
2252  {
2253  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2254  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2255  return QVariant( pow( fL, fR ) );
2256  }
2257 
2258  case boAnd:
2259  {
2260  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2262  return tvl2variant( AND[tvlL][tvlR] );
2263  }
2264 
2265  case boOr:
2266  {
2267  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
2269  return tvl2variant( OR[tvlL][tvlR] );
2270  }
2271 
2272  case boEQ:
2273  case boNE:
2274  case boLT:
2275  case boGT:
2276  case boLE:
2277  case boGE:
2278  if ( isNull( vL ) || isNull( vR ) )
2279  {
2280  return TVL_Unknown;
2281  }
2282  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2283  {
2284  // do numeric comparison if both operators can be converted to numbers
2285  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2286  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2287  return compare( fL - fR ) ? TVL_True : TVL_False;
2288  }
2289  else
2290  {
2291  // do string comparison otherwise
2292  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2293  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2294  int diff = QString::compare( sL, sR );
2295  return compare( diff ) ? TVL_True : TVL_False;
2296  }
2297 
2298  case boIs:
2299  case boIsNot:
2300  if ( isNull( vL ) && isNull( vR ) ) // both operators null
2301  return ( mOp == boIs ? TVL_True : TVL_False );
2302  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
2303  return ( mOp == boIs ? TVL_False : TVL_True );
2304  else // both operators non-null
2305  {
2306  bool equal = false;
2307  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
2308  {
2309  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2310  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2311  equal = fL == fR;
2312  }
2313  else
2314  {
2315  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2316  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2317  equal = QString::compare( sL, sR ) == 0;
2318  }
2319  if ( equal )
2320  return mOp == boIs ? TVL_True : TVL_False;
2321  else
2322  return mOp == boIs ? TVL_False : TVL_True;
2323  }
2324 
2325  case boRegexp:
2326  case boLike:
2327  case boNotLike:
2328  case boILike:
2329  case boNotILike:
2330  if ( isNull( vL ) || isNull( vR ) )
2331  return TVL_Unknown;
2332  else
2333  {
2334  QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2335  QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2336  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
2337  bool matches;
2338  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
2339  {
2340  QString esc_regexp = QRegExp::escape( regexp );
2341  // XXX escape % and _ ???
2342  esc_regexp.replace( "%", ".*" );
2343  esc_regexp.replace( "_", "." );
2344  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
2345  }
2346  else
2347  {
2348  matches = QRegExp( regexp ).indexIn( str ) != -1;
2349  }
2350 
2351  if ( mOp == boNotLike || mOp == boNotILike )
2352  {
2353  matches = !matches;
2354  }
2355 
2356  return matches ? TVL_True : TVL_False;
2357  }
2358 
2359  case boConcat:
2360  if ( isNull( vL ) || isNull( vR ) )
2361  return QVariant();
2362  else
2363  {
2364  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2365  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2366  return QVariant( sL + sR );
2367  }
2368 
2369  default: break;
2370  }
2371  Q_ASSERT( false );
2372  return QVariant();
2373 }
2374 
2376 {
2377  switch ( mOp )
2378  {
2379  case boEQ: return diff == 0;
2380  case boNE: return diff != 0;
2381  case boLT: return diff < 0;
2382  case boGT: return diff > 0;
2383  case boLE: return diff <= 0;
2384  case boGE: return diff >= 0;
2385  default: Q_ASSERT( false ); return false;
2386  }
2387 }
2388 
2390 {
2391  switch ( mOp )
2392  {
2393  case boPlus: return x+y;
2394  case boMinus: return x-y;
2395  case boMul: return x*y;
2396  case boDiv: return x/y;
2397  case boMod: return x%y;
2398  default: Q_ASSERT( false ); return 0;
2399  }
2400 }
2401 
2403 {
2404  switch ( mOp )
2405  {
2406  case boPlus: return d.addSecs( i->seconds() );
2407  case boMinus: return d.addSecs( -i->seconds() );
2408  default: Q_ASSERT( false ); return QDateTime();
2409  }
2410 }
2411 
2413 {
2414  switch ( mOp )
2415  {
2416  case boPlus: return x+y;
2417  case boMinus: return x-y;
2418  case boMul: return x*y;
2419  case boDiv: return x/y;
2420  case boMod: return fmod( x,y );
2421  default: Q_ASSERT( false ); return 0;
2422  }
2423 }
2424 
2425 
2427 {
2428  bool resL = mOpLeft->prepare( parent, fields );
2429  bool resR = mOpRight->prepare( parent, fields );
2430  return resL && resR;
2431 }
2432 
2434 {
2435  // see left/right in qgsexpressionparser.yy
2436  switch ( mOp )
2437  {
2438  case boOr:
2439  return 1;
2440 
2441  case boAnd:
2442  return 2;
2443 
2444  case boEQ:
2445  case boNE:
2446  case boLE:
2447  case boGE:
2448  case boLT:
2449  case boGT:
2450  case boRegexp:
2451  case boLike:
2452  case boILike:
2453  case boNotLike:
2454  case boNotILike:
2455  case boIs:
2456  case boIsNot:
2457  return 3;
2458 
2459  case boPlus:
2460  case boMinus:
2461  return 4;
2462 
2463  case boMul:
2464  case boDiv:
2465  case boIntDiv:
2466  case boMod:
2467  return 5;
2468 
2469  case boPow:
2470  return 6;
2471 
2472  case boConcat:
2473  return 7;
2474  }
2475  Q_ASSERT( 0 && "unexpected binary operator" );
2476  return -1;
2477 }
2478 
2480 {
2481  QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
2482  QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
2483 
2484  QString fmt;
2485  fmt += lOp && lOp->precedence() < precedence() ? "(%1)" : "%1";
2486  fmt += " %2 ";
2487  fmt += rOp && rOp->precedence() <= precedence() ? "(%3)" : "%3";
2488 
2489  return fmt.arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
2490 }
2491 
2492 //
2493 
2495 {
2496  if ( mList->count() == 0 )
2497  return mNotIn ? TVL_True : TVL_False;
2498  QVariant v1 = mNode->eval( parent, f );
2500  if ( isNull( v1 ) )
2501  return TVL_Unknown;
2502 
2503  bool listHasNull = false;
2504 
2505  foreach ( Node* n, mList->list() )
2506  {
2507  QVariant v2 = n->eval( parent, f );
2509  if ( isNull( v2 ) )
2510  listHasNull = true;
2511  else
2512  {
2513  bool equal = false;
2514  // check whether they are equal
2515  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
2516  {
2517  double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2518  double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2519  equal = f1 == f2;
2520  }
2521  else
2522  {
2523  QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2524  QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2525  equal = QString::compare( s1, s2 ) == 0;
2526  }
2527 
2528  if ( equal ) // we know the result
2529  return mNotIn ? TVL_False : TVL_True;
2530  }
2531  }
2532 
2533  // item not found
2534  if ( listHasNull )
2535  return TVL_Unknown;
2536  else
2537  return mNotIn ? TVL_True : TVL_False;
2538 }
2539 
2541 {
2542  bool res = mNode->prepare( parent, fields );
2543  foreach ( Node* n, mList->list() )
2544  {
2545  res = res && n->prepare( parent, fields );
2546  }
2547  return res;
2548 }
2549 
2551 {
2552  return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
2553 }
2554 
2555 //
2556 
2558 {
2559  Function* fd = Functions()[mFnIndex];
2560 
2561  // evaluate arguments
2562  QVariantList argValues;
2563  if ( mArgs )
2564  {
2565  foreach ( Node* n, mArgs->list() )
2566  {
2567  QVariant v;
2568  if ( fd->lazyEval() ) {
2569  // Pass in the node for the function to eval as it needs.
2570  v = QVariant::fromValue( n );
2571  }
2572  else {
2573  v = n->eval( parent, f );
2575  if ( isNull( v ) && fd->name() != "coalesce" )
2576  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
2577  }
2578  argValues.append( v );
2579  }
2580  }
2581 
2582  // run the function
2583  QVariant res = fd->func( argValues, f, parent );
2585 
2586  // everything went fine
2587  return res;
2588 }
2589 
2591 {
2592  bool res = true;
2593  if ( mArgs )
2594  {
2595  foreach ( Node* n, mArgs->list() )
2596  {
2597  res = res && n->prepare( parent, fields );
2598  }
2599  }
2600  return res;
2601 }
2602 
2604 {
2605  Function* fd = Functions()[mFnIndex];
2606  if ( fd->params() == 0 )
2607  return fd->name(); // special column
2608  else
2609  return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
2610 }
2611 
2613 {
2614  Function* fd = Functions()[mFnIndex];
2615  QStringList functionColumns = fd->referencedColumns();
2616 
2617  if ( !mArgs )
2618  {
2619  //no referenced columns in arguments, just return function's referenced columns
2620  return functionColumns;
2621  }
2622 
2623  foreach ( Node* n, mArgs->list() )
2624  {
2625  functionColumns.append( n->referencedColumns() );
2626  }
2627 
2628  //remove duplicates and return
2629  return functionColumns.toSet().toList();
2630 }
2631 
2632 //
2633 
2635 {
2636  return mValue;
2637 }
2638 
2639 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ )
2640 {
2641  return true;
2642 }
2643 
2644 
2646 {
2647  if ( mValue.isNull() )
2648  return "NULL";
2649 
2650  switch ( mValue.type() )
2651  {
2652  case QVariant::Int: return QString::number( mValue.toInt() );
2653  case QVariant::Double: return QString::number( mValue.toDouble() );
2654  case QVariant::String: return quotedString( mValue.toString() );
2655  default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
2656  }
2657 }
2658 
2659 //
2660 
2662 {
2663  if ( f )
2664  {
2665  if ( mIndex >= 0 )
2666  return f->attribute( mIndex );
2667  else
2668  return f->attribute( mName );
2669  }
2670  return QVariant( "[" + mName + "]" );
2671 }
2672 
2674 {
2675  for ( int i = 0; i < fields.count(); ++i )
2676  {
2677  if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
2678  {
2679  mIndex = i;
2680  return true;
2681  }
2682  }
2683  parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName );
2684  mIndex = -1;
2685  return false;
2686 }
2687 
2689 {
2690  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
2691 }
2692 
2693 //
2694 
2696 {
2697  foreach ( WhenThen* cond, mConditions )
2698  {
2699  QVariant vWhen = cond->mWhenExp->eval( parent, f );
2700  TVL tvl = getTVLValue( vWhen, parent );
2702  if ( tvl == True )
2703  {
2704  QVariant vRes = cond->mThenExp->eval( parent, f );
2706  return vRes;
2707  }
2708  }
2709 
2710  if ( mElseExp )
2711  {
2712  QVariant vElse = mElseExp->eval( parent, f );
2714  return vElse;
2715  }
2716 
2717  // return NULL if no condition is matching
2718  return QVariant();
2719 }
2720 
2722 {
2723  bool res;
2724  foreach ( WhenThen* cond, mConditions )
2725  {
2726  res = cond->mWhenExp->prepare( parent, fields )
2727  & cond->mThenExp->prepare( parent, fields );
2728  if ( !res ) return false;
2729  }
2730 
2731  if ( mElseExp )
2732  return mElseExp->prepare( parent, fields );
2733 
2734  return true;
2735 }
2736 
2738 {
2739  QString msg = QString( "CASE" );
2740  foreach ( WhenThen* cond, mConditions )
2741  {
2742  msg += QString( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
2743  }
2744  if ( mElseExp )
2745  msg += QString( " ELSE %1" ).arg( mElseExp->dump() );
2746  msg += QString( " END" );
2747  return msg;
2748 }
2749 
2751 {
2752  QStringList lst;
2753  foreach ( WhenThen* cond, mConditions )
2754  {
2755  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2756  }
2757 
2758  if ( mElseExp )
2759  lst += mElseExp->referencedColumns();
2760 
2761  return lst;
2762 }
2763 
2765 {
2766  foreach ( WhenThen* cond, mConditions )
2767  {
2768  if ( cond->mWhenExp->needsGeometry() ||
2769  cond->mThenExp->needsGeometry() )
2770  return true;
2771  }
2772 
2773  if ( mElseExp && mElseExp->needsGeometry() )
2774  return true;
2775 
2776  return false;
2777 }
2778 
2779 QString QgsExpression::helptext( QString name )
2780 {
2782  return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) );
2783 }
2784 
2785 QHash<QString, QString> QgsExpression::gGroups;
2786 
2787 QString QgsExpression::group( QString name )
2788 {
2789  if ( gGroups.isEmpty() )
2790  {
2791  gGroups.insert( "Operators", QObject::tr( "Operators" ) );
2792  gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) );
2793  gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) );
2794  gGroups.insert( "Math", QObject::tr( "Math" ) );
2795  gGroups.insert( "Conversions", QObject::tr( "Conversions" ) );
2796  gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) );
2797  gGroups.insert( "String", QObject::tr( "String" ) );
2798  gGroups.insert( "Color", QObject::tr( "Color" ) );
2799  gGroups.insert( "Geometry", QObject::tr( "Geometry" ) );
2800  gGroups.insert( "Record", QObject::tr( "Record" ) );
2801  }
2802 
2803  //return the translated name for this group. If group does not
2804  //have a translated name in the gGroups hash, return the name
2805  //unchanged
2806  return gGroups.value( name, name );
2807 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
static QVariant fcnDifference(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCombine(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
static int functionIndex(QString name)
static QVariant fcnAge(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnColorHsv(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QStringList referencedColumns() const =0
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
Wrapper for iterator of features from vector data provider or vector layer.
static QVariant fcnCeil(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnLog10(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnDistance(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsExpression::Interval fromString(QString string)
static unsigned index
virtual bool needsGeometry() const
static QVariant fcnFeatureId(const QVariantList &, const QgsFeature *f, QgsExpression *)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:94
static QVariant fcnAsin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
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.
QgsGeometry * combine(QgsGeometry *geometry)
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
static QVariant fcnYMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnReplace(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
void initGeomCalculator()
static QVariant fcnTouches(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
A abstract base class for defining QgsExpression functions.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QVariant fcnGeomLength(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnScale(const QVariantList &, const QgsFeature *, QgsExpression *parent)
double computeDouble(double x, double y)
virtual QString dump() const =0
static QDate getDateValue(const QVariant &value, QgsExpression *parent)
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
Definition: qgsgeometry.h:33
static QVariant fcnFloor(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString helptext(QString name)
static QVariant fcnXMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
static QVariant fcnFormatDate(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnIf(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
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)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
static QVariant fcnStrpos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnYMin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static TVL getTVLValue(const QVariant &value, QgsExpression *parent)
int currentRowNumber()
Return the number used for $rownum special column.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnBuffer(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool isValid(const QString &text, const QgsFields &fields, QString &errorMessage)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
QgsGeometry * difference(QgsGeometry *geometry)
Returns a geometry representing the points making up this geometry that do not make up other...
QString mEvalErrorString
static QVariant fcnYear(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static QVariant fcnFormatString(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToString(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCrosses(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnToInterval(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsGeometry * centroid()
Returns the center of mass of a geometry.
static QVariant fcnTan(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry getGeometry(const QVariant &value, QgsExpression *parent)
#define ENSURE_NO_EVAL_ERROR
QString mParserErrorString
static QVariant fcnLower(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QString encodeColor(QColor color)
static QVariant fcnAbs(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnCoalesce(const QVariantList &values, const QgsFeature *, QgsExpression *)
static QVariant fcnCentroid(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static const QStringList & BuiltinFunctions()
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
static const QList< Function * > & Functions()
static QVariant fcnToReal(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static bool isFunctionName(QString name)
static QVariant fcnIntersection(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QHash< QString, QString > gFunctionHelpTexts
static int functionCount()
Returns the number of functions defined in the parser.
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
void acceptVisitor(Visitor &v) const
entry function for the visitor pattern
virtual QStringList referencedColumns() const
bool contains(const QgsPoint *p) const
Test for containment of a point (uses GEOS)
static QVariant fcnAttribute(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnLPad(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QColor fill
Definition: qgssvgcache.cpp:81
static QVariant pointAt(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
QgsDistanceArea * geomCalculator()
Return calculator used for distance and area calculations (used by internal functions) ...
#define TVL_Unknown
static QVariant fcnOverlaps(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnHour(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
const QgsVectorColorRampV2 * colorRampRef(QString name) const
return a const pointer to a symbol (doesn't create new instance)
Definition: qgsstylev2.cpp:266
QgsGeometry * buffer(double distance, int segments)
Returns a buffer region around this geometry having the given width and with a specified number of se...
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
static QVariant fcnFeature(const QVariantList &, const QgsFeature *f, QgsExpression *)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
double measurePerimeter(QgsGeometry *geometry)
measures perimeter of polygon
double measure(QgsGeometry *geometry)
general measurement (line distance or polygon area)
static bool registerFunction(Function *function)
static QVariant fcnAtan2(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsDistanceArea * mCalc
QgsGeometry * convexHull()
Returns the smallest convex polygon that contains all the points in the geometry. ...
static QVariant fncColorHsla(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry * geometryFromGML(const QString &xmlString)
static method that creates geometry from GML
Definition: qgsogcutils.cpp:81
#define SET_EVAL_ERROR(x)
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)
#define M_PI
This class wraps a request for features to a vector layer (or directly its vector data provider)...
static QVariant fcnY(const QVariantList &, const QgsFeature *f, QgsExpression *)
static QVariant fcnRndF(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
virtual QString dump() const
static const QString AllAttributes
QDateTime computeDateTimeFromInterval(QDateTime d, QgsExpression::Interval *i)
double scale()
int count() const
Return number of items.
Definition: qgsfield.h:214
#define TVL_False
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnGeomToWKT(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnGetFeature(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSpecialColumn(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QList< Function * > gmFunctions
static QVariant fcnWordwrap(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
static QVariant fcnLength(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QString name()
The name of the function.
virtual QString dump() const
static QVariant tvl2variant(TVL v)
#define ENSURE_GEOM_TYPE(f, g, geomtype)
static QVariant fcnMonth(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnTitle(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
bool isIntervalSafe(const QVariant &v)
QgsGeometry * intersection(QgsGeometry *geometry)
Returns a geometry representing the points shared by this geometry and other.
virtual QString dump() const
static QVariant fcnRPad(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static int getIntValue(const QVariant &value, QgsExpression *parent)
static QVariant fcnToDate(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fncColorRgba(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
int min(int a, int b)
Definition: util.h:93
static QVariant fcnBbox(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnBoundsWidth(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QList< QgsMapLayer * > mapLayersByName(QString layerName)
Retrieve a pointer to a loaded layer by name.
static QVariant fcnGeomArea(const QVariantList &, const QgsFeature *f, QgsExpression *parent)
static QVariant fcnAcos(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)=0
static QString getStringValue(const QVariant &value, QgsExpression *)
static QVariant fcnWithin(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsFeature getFeature(const QVariant &value, QgsExpression *parent)
virtual QStringList referencedColumns() const
static QVariant fcnGeometry(const QVariantList &, const QgsFeature *f, QgsExpression *)
void setEvalErrorString(QString str)
Set evaluation error (used internally by evaluation functions)
static double getDoubleValue(const QVariant &value, QgsExpression *parent)
virtual QStringList referencedColumns() const
QgsGeometry * symDifference(QgsGeometry *geometry)
Returns a Geometry representing the points making up this Geometry that do not make up other...
static QVariant fcnGeomFromGML(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
General purpose distance and area calculator.
static QMap< QString, QString > gmSpecialColumnGroups
QgsRectangle boundingBox()
Returns the bounding box of this feature.
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnBounds(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnWeek(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRegexpReplace(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isIntSafe(const QVariant &v)
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)
virtual QString dump() const
static QVariant fncColorHsva(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QList< Function * > specialColumns()
Returns a list of special Column definitions.
static TVL OR[3][3]
static QVariant fcnDay(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
int params()
The number of parameters this function takes.
static QVariant fcnX(const QVariantList &, const QgsFeature *f, QgsExpression *)
static QVariant fcnClamp(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static TVL NOT[3]
bool within(const QgsGeometry *geometry) const
Test for if geometry is within another (uses GEOS)
static QVariant fcnRegexpMatch(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnSubstr(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnFormatNumber(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
#define TVL_True
static QVariant fcnXMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
support for visitor pattern - algorithms dealing with the expressions may be implemented without modi...
static QString quotedString(QString text)
return quoted string (in single quotes)
static QgsGeometry * fromRect(const QgsRectangle &rect)
construct geometry from a rectangle
static QVariant fcnExpScale(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnPi(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
virtual bool needsGeometry() const =0
static QVariant fcnSeconds(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QgsGeometry * fromWkt(QString wkt)
static method that creates geometry from Wkt
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used in evaluation of expressions,.
static QStringList gmBuiltinFunctions
static QVariant fcnColorHsl(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
bool disjoint(const QgsGeometry *geometry) const
Test for if geometry is disjoint of another (uses GEOS)
static QVariant fncColorCmyka(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnUuid(const QVariantList &, const QgsFeature *, QgsExpression *)
bool touches(const QgsGeometry *geometry) const
Test for if geometry touch another (uses GEOS)
static QVariant fcnMax(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant specialColumn(const QString &name)
Return the value of the given special column or a null QVariant if undefined.
static QVariant fcnRowNumber(const QVariantList &, const QgsFeature *, QgsExpression *parent)
static void initFunctionHelp()
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
static QVariant fcnConvexHull(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRnd(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnColorRgb(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QString dump() const
void setValid(bool valid)
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
static QVariant fcnGeomFromWKT(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool nextFeature(QgsFeature &f)
static QVariant fcnColorCmyk(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)
static QVariant fcnExp(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
static TVL AND[3][3]
static QVariant fcnAtan(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
static QVariant fcnBoundsHeight(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:96
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
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
QString evalErrorString() const
Returns evaluation error.
QString exportToWkt(const int &precision=17) const
Exports the geometry to WKT.
virtual void accept(Visitor &v) const =0
virtual QString dump() const
static QVariant fcnSymDifference(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
bool isNull(const QVariant &v)
static QVariant fcnLn(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnRegexpSubstr(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
static QVariant fcnDisjoint(const QVariantList &values, const QgsFeature *, QgsExpression *parent)
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
static QgsExpression::Interval getInterval(const QVariant &value, QgsExpression *parent, bool report_error=false)
static QDateTime getDateTimeValue(const QVariant &value, QgsExpression *parent)
static QVariant fcnRound(const QVariantList &values, const QgsFeature *f, QgsExpression *parent)
double distance(QgsGeometry &geom)
static void unsetSpecialColumn(const QString &name)
Unset a special column.
#define tr(sourceText)
static const char * BinaryOperatorText[]
static QString replaceExpressionText(const QString &action, const QgsFeature *feat, QgsVectorLayer *layer, const QMap< QString, QVariant > *substitutionMap=0, const QgsDistanceArea *distanceArea=0)
This function currently replaces each expression between [% and %] in the string with the result of i...
static QMap< QString, QVariant > gmSpecialColumns