QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.cpp
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsexpression.h"
17 
18 #include <QtDebug>
19 #include <QDomDocument>
20 #include <QSettings>
21 #include <QDate>
22 #include <QRegExp>
23 #include <QColor>
24 
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 "qgsogcutils.h"
33 #include "qgsvectorlayer.h"
34 #include "qgssymbollayerv2utils.h"
35 #include "qgsvectorcolorrampv2.h"
36 #include "qgsstylev2.h"
37 
38 // from parser
39 extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
40 
42 
44 {
46  inter.setValid( false );
47  return inter;
48 }
49 
51 {
52  int seconds = 0;
53  QRegExp rx( "(\\d?\\.?\\d+\\s+[a-z]+)", Qt::CaseInsensitive );
54  QStringList list;
55  int pos = 0;
56 
57  while (( pos = rx.indexIn( string, pos ) ) != -1 )
58  {
59  list << rx.cap( 1 );
60  pos += rx.matchedLength();
61  }
62 
63  foreach ( QString match, list )
64  {
65  QStringList split = match.split( QRegExp( "\\s+" ) );
66  bool ok;
67  int value = split.at( 0 ).toInt( &ok );
68  if ( !ok )
69  {
70  continue;
71  }
72 
73  if ( match.contains( "day", Qt::CaseInsensitive ) ||
74  match.contains( QObject::tr( "day", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
75  match.contains( QObject::tr( "days", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
76  seconds += value * QgsExpression::Interval::DAY;
77  if ( match.contains( "week", Qt::CaseInsensitive ) ||
78  match.contains( QObject::tr( "week", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
79  match.contains( QObject::tr( "weeks", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
80  seconds += value * QgsExpression::Interval::WEEKS;
81  if ( match.contains( "month", Qt::CaseInsensitive ) ||
82  match.contains( QObject::tr( "month", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
83  match.contains( QObject::tr( "months", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
84  seconds += value * QgsExpression::Interval::MONTHS;
85  if ( match.contains( "year", Qt::CaseInsensitive ) ||
86  match.contains( QObject::tr( "year", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
87  match.contains( QObject::tr( "years", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
88  seconds += value * QgsExpression::Interval::YEARS;
89  if ( match.contains( "second", Qt::CaseInsensitive ) ||
90  match.contains( QObject::tr( "second", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
91  match.contains( QObject::tr( "seconds", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
92  seconds += value;
93  if ( match.contains( "minute", Qt::CaseInsensitive ) ||
94  match.contains( QObject::tr( "minute", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
95  match.contains( QObject::tr( "minutes", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
96  seconds += value * QgsExpression::Interval::MINUTE;
97  if ( match.contains( "hour", Qt::CaseInsensitive ) ||
98  match.contains( QObject::tr( "hour", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
99  match.contains( QObject::tr( "hours", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
100  seconds += value * QgsExpression::Interval::HOUR;
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::Double ) return false;
165  if ( v.type() == QVariant::String ) { bool ok; v.toString().toInt( &ok ); return ok; }
166  return false;
167 }
168 inline bool isDoubleSafe( const QVariant& v )
169 {
170  if ( v.type() == QVariant::Double || v.type() == QVariant::Int ) return true;
171  if ( v.type() == QVariant::String ) { bool ok; v.toString().toDouble( &ok ); return ok; }
172  return false;
173 }
174 
175 inline bool isDateTimeSafe( const QVariant& v )
176 {
177  return v.type() == QVariant::DateTime || v.type() == QVariant::Date ||
178  v.type() == QVariant::Time;
179 }
180 
181 inline bool isIntervalSafe( const QVariant& v )
182 {
183  if ( v.canConvert<QgsExpression::Interval>() )
184  {
185  return true;
186  }
187 
188  if ( v.type() == QVariant::String )
189  {
190  return QgsExpression::Interval::fromString( v.toString() ).isValid();
191  }
192  return false;
193 }
194 
195 inline bool isNull( const QVariant& v ) { return v.isNull(); }
196 
198 // evaluation error macros
199 
200 #define ENSURE_NO_EVAL_ERROR { if (parent->hasEvalError()) return QVariant(); }
201 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString(x); return QVariant(); }
202 
204 // operators
205 
206 const char* QgsExpression::BinaryOperatorText[] =
207 {
208  "OR", "AND",
209  "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
210  "+", "-", "*", "/", "%", "^",
211  "||"
212 };
213 
214 const char* QgsExpression::UnaryOperatorText[] =
215 {
216  "NOT", "-"
217 };
218 
220 // functions
221 
222 // implicit conversion to string
223 static QString getStringValue( const QVariant& value, QgsExpression* )
224 {
225  return value.toString();
226 }
227 
228 static double getDoubleValue( const QVariant& value, QgsExpression* parent )
229 {
230  bool ok;
231  double x = value.toDouble( &ok );
232  if ( !ok )
233  {
234  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) );
235  return 0;
236  }
237  return x;
238 }
239 
240 static int getIntValue( const QVariant& value, QgsExpression* parent )
241 {
242  bool ok;
243  qint64 x = value.toLongLong( &ok );
245  {
246  return x;
247  }
248  else
249  {
250  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) );
251  return 0;
252  }
253 }
254 
255 static QDateTime getDateTimeValue( const QVariant& value, QgsExpression* parent )
256 {
257  QDateTime d = value.toDateTime();
258  if ( d.isValid() )
259  {
260  return d;
261  }
262  else
263  {
264  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
265  return QDateTime();
266  }
267 }
268 
269 static QDate getDateValue( const QVariant& value, QgsExpression* parent )
270 {
271  QDate d = value.toDate();
272  if ( d.isValid() )
273  {
274  return d;
275  }
276  else
277  {
278  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) );
279  return QDate();
280  }
281 }
282 
283 static QTime getTimeValue( const QVariant& value, QgsExpression* parent )
284 {
285  QTime t = value.toTime();
286  if ( t.isValid() )
287  {
288  return t;
289  }
290  else
291  {
292  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) );
293  return QTime();
294  }
295 }
296 
297 static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
298 {
299  if ( value.canConvert<QgsExpression::Interval>() )
300  return value.value<QgsExpression::Interval>();
301 
303  if ( inter.isValid() )
304  {
305  return inter;
306  }
307  // If we get here then we can't convert so we just error and return invalid.
308  if ( report_error )
309  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
310 
312 }
313 static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent )
314 {
315  if ( value.canConvert<QgsGeometry>() )
316  return value.value<QgsGeometry>();
317 
318  parent->setEvalErrorString( "Cannot convert to QgsGeometry" );
319  return QgsGeometry();
320 }
321 
322 
323 // this handles also NULL values
324 static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
325 {
326  // we need to convert to TVL
327  if ( value.isNull() )
328  return Unknown;
329 
330  if ( value.type() == QVariant::Int )
331  return value.toInt() != 0 ? True : False;
332 
333  bool ok;
334  double x = value.toDouble( &ok );
335  if ( !ok )
336  {
337  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) );
338  return Unknown;
339  }
340  return x != 0 ? True : False;
341 }
342 
344 
345 static QVariant fcnSqrt( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent )
346 {
347  double x = getDoubleValue( values.at( 0 ), parent );
348  return QVariant( sqrt( x ) );
349 }
350 
351 static QVariant fcnAbs( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
352 {
353  double val = getDoubleValue( values.at( 0 ), parent );
354  return QVariant( fabs( val ) );
355 }
356 
357 static QVariant fcnSin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
358 {
359  double x = getDoubleValue( values.at( 0 ), parent );
360  return QVariant( sin( x ) );
361 }
362 static QVariant fcnCos( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
363 {
364  double x = getDoubleValue( values.at( 0 ), parent );
365  return QVariant( cos( x ) );
366 }
367 static QVariant fcnTan( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
368 {
369  double x = getDoubleValue( values.at( 0 ), parent );
370  return QVariant( tan( x ) );
371 }
372 static QVariant fcnAsin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
373 {
374  double x = getDoubleValue( values.at( 0 ), parent );
375  return QVariant( asin( x ) );
376 }
377 static QVariant fcnAcos( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
378 {
379  double x = getDoubleValue( values.at( 0 ), parent );
380  return QVariant( acos( x ) );
381 }
382 static QVariant fcnAtan( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
383 {
384  double x = getDoubleValue( values.at( 0 ), parent );
385  return QVariant( atan( x ) );
386 }
387 static QVariant fcnAtan2( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
388 {
389  double y = getDoubleValue( values.at( 0 ), parent );
390  double x = getDoubleValue( values.at( 1 ), parent );
391  return QVariant( atan2( y, x ) );
392 }
393 static QVariant fcnExp( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
394 {
395  double x = getDoubleValue( values.at( 0 ), parent );
396  return QVariant( exp( x ) );
397 }
398 static QVariant fcnLn( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
399 {
400  double x = getDoubleValue( values.at( 0 ), parent );
401  if ( x <= 0 )
402  return QVariant();
403  return QVariant( log( x ) );
404 }
405 static QVariant fcnLog10( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
406 {
407  double x = getDoubleValue( values.at( 0 ), parent );
408  if ( x <= 0 )
409  return QVariant();
410  return QVariant( log10( x ) );
411 }
412 static QVariant fcnLog( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
413 {
414  double b = getDoubleValue( values.at( 0 ), parent );
415  double x = getDoubleValue( values.at( 1 ), parent );
416  if ( x <= 0 || b <= 0 )
417  return QVariant();
418  return QVariant( log( x ) / log( b ) );
419 }
420 static QVariant fcnRndF( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
421 {
422  double min = getDoubleValue( values.at( 0 ), parent );
423  double max = getDoubleValue( values.at( 1 ), parent );
424  if ( max < min )
425  return QVariant();
426 
427  // Return a random double in the range [min, max] (inclusive)
428  double f = ( double )rand() / RAND_MAX;
429  return QVariant( min + f * ( max - min ) ) ;
430 }
431 static QVariant fcnRnd( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
432 {
433  int min = getIntValue( values.at( 0 ), parent );
434  int max = getIntValue( values.at( 1 ), parent );
435  if ( max < min )
436  return QVariant();
437 
438  // Return a random integer in the range [min, max] (inclusive)
439  return QVariant( min + ( rand() % ( int )( max - min + 1 ) ) );
440 }
441 
442 static QVariant fcnLinearScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
443 {
444  double val = getDoubleValue( values.at( 0 ), parent );
445  double domainMin = getDoubleValue( values.at( 1 ), parent );
446  double domainMax = getDoubleValue( values.at( 2 ), parent );
447  double rangeMin = getDoubleValue( values.at( 3 ), parent );
448  double rangeMax = getDoubleValue( values.at( 4 ), parent );
449 
450  if ( domainMin >= domainMax )
451  {
452  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
453  return QVariant();
454  }
455 
456  // outside of domain?
457  if ( val >= domainMax )
458  {
459  return rangeMax;
460  }
461  else if ( val <= domainMin )
462  {
463  return rangeMin;
464  }
465 
466  // calculate linear scale
467  double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
468  double c = rangeMin - ( domainMin * m );
469 
470  // Return linearly scaled value
471  return QVariant( m * val + c );
472 }
473 
474 static QVariant fcnExpScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
475 {
476  double val = getDoubleValue( values.at( 0 ), parent );
477  double domainMin = getDoubleValue( values.at( 1 ), parent );
478  double domainMax = getDoubleValue( values.at( 2 ), parent );
479  double rangeMin = getDoubleValue( values.at( 3 ), parent );
480  double rangeMax = getDoubleValue( values.at( 4 ), parent );
481  double exponent = getDoubleValue( values.at( 5 ), parent );
482 
483  if ( domainMin >= domainMax )
484  {
485  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
486  return QVariant();
487  }
488  if ( exponent <= 0 )
489  {
490  parent->setEvalErrorString( QObject::tr( "Exponent must be greater than 0" ) );
491  return QVariant();
492  }
493 
494  // outside of domain?
495  if ( val >= domainMax )
496  {
497  return rangeMax;
498  }
499  else if ( val <= domainMin )
500  {
501  return rangeMin;
502  }
503 
504  // Return exponentially scaled value
505  return QVariant((( rangeMax - rangeMin ) / pow( domainMax - domainMin, exponent ) ) * pow( val - domainMin, exponent ) + rangeMin );
506 }
507 
508 static QVariant fcnMax( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
509 {
510  //initially set max as first value
511  double maxVal = getDoubleValue( values.at( 0 ), parent );
512 
513  //check against all other values
514  for ( int i = 1; i < values.length(); ++i )
515  {
516  double testVal = getDoubleValue( values[i], parent );
517  if ( testVal > maxVal )
518  {
519  maxVal = testVal;
520  }
521  }
522 
523  return QVariant( maxVal );
524 }
525 
526 static QVariant fcnMin( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
527 {
528  //initially set min as first value
529  double minVal = getDoubleValue( values.at( 0 ), parent );
530 
531  //check against all other values
532  for ( int i = 1; i < values.length(); ++i )
533  {
534  double testVal = getDoubleValue( values[i], parent );
535  if ( testVal < minVal )
536  {
537  minVal = testVal;
538  }
539  }
540 
541  return QVariant( minVal );
542 }
543 
544 static QVariant fcnClamp( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
545 {
546  double minValue = getDoubleValue( values.at( 0 ), parent );
547  double testValue = getDoubleValue( values.at( 1 ), parent );
548  double maxValue = getDoubleValue( values.at( 2 ), parent );
549 
550  // force testValue to sit inside the range specified by the min and max value
551  if ( testValue <= minValue )
552  {
553  return QVariant( minValue );
554  }
555  else if ( testValue >= maxValue )
556  {
557  return QVariant( maxValue );
558  }
559  else
560  {
561  return QVariant( testValue );
562  }
563 }
564 
565 static QVariant fcnFloor( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
566 {
567  double x = getDoubleValue( values.at( 0 ), parent );
568  return QVariant( floor( x ) );
569 }
570 
571 static QVariant fcnCeil( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
572 {
573  double x = getDoubleValue( values.at( 0 ), parent );
574  return QVariant( ceil( x ) );
575 }
576 
577 static QVariant fcnToInt( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
578 {
579  return QVariant( getIntValue( values.at( 0 ), parent ) );
580 }
581 static QVariant fcnToReal( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
582 {
583  return QVariant( getDoubleValue( values.at( 0 ), parent ) );
584 }
585 static QVariant fcnToString( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
586 {
587  return QVariant( getStringValue( values.at( 0 ), parent ) );
588 }
589 
590 static QVariant fcnToDateTime( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
591 {
592  return QVariant( getDateTimeValue( values.at( 0 ), parent ) );
593 }
594 
595 static QVariant fcnCoalesce( const QVariantList& values, const QgsFeature* , QgsExpression* )
596 {
597  foreach ( const QVariant &value, values )
598  {
599  if ( value.isNull() )
600  continue;
601  return value;
602  }
603  return QVariant();
604 }
605 static QVariant fcnLower( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
606 {
607  QString str = getStringValue( values.at( 0 ), parent );
608  return QVariant( str.toLower() );
609 }
610 static QVariant fcnUpper( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
611 {
612  QString str = getStringValue( values.at( 0 ), parent );
613  return QVariant( str.toUpper() );
614 }
615 static QVariant fcnTitle( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
616 {
617  QString str = getStringValue( values.at( 0 ), parent );
618  QStringList elems = str.split( " " );
619  for ( int i = 0; i < elems.size(); i++ )
620  {
621  if ( elems[i].size() > 1 )
622  elems[i] = elems[i].left( 1 ).toUpper() + elems[i].mid( 1 ).toLower();
623  }
624  return QVariant( elems.join( " " ) );
625 }
626 
627 static QVariant fcnTrim( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
628 {
629  QString str = getStringValue( values.at( 0 ), parent );
630  return QVariant( str.trimmed() );
631 }
632 
633 static QVariant fcnLength( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
634 {
635  QString str = getStringValue( values.at( 0 ), parent );
636  return QVariant( str.length() );
637 }
638 static QVariant fcnReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
639 {
640  QString str = getStringValue( values.at( 0 ), parent );
641  QString before = getStringValue( values.at( 1 ), parent );
642  QString after = getStringValue( values.at( 2 ), parent );
643  return QVariant( str.replace( before, after ) );
644 }
645 static QVariant fcnRegexpReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
646 {
647  QString str = getStringValue( values.at( 0 ), parent );
648  QString regexp = getStringValue( values.at( 1 ), parent );
649  QString after = getStringValue( values.at( 2 ), parent );
650 
651  QRegExp re( regexp );
652  if ( !re.isValid() )
653  {
654  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
655  return QVariant();
656  }
657  return QVariant( str.replace( re, after ) );
658 }
659 
660 static QVariant fcnRegexpMatch( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
661 {
662  QString str = getStringValue( values.at( 0 ), parent );
663  QString regexp = getStringValue( values.at( 1 ), parent );
664 
665  QRegExp re( regexp );
666  if ( !re.isValid() )
667  {
668  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
669  return QVariant();
670  }
671  return QVariant( str.contains( re ) ? 1 : 0 );
672 }
673 
674 static QVariant fcnRegexpSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
675 {
676  QString str = getStringValue( values.at( 0 ), parent );
677  QString regexp = getStringValue( values.at( 1 ), parent );
678 
679  QRegExp re( regexp );
680  if ( !re.isValid() )
681  {
682  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
683  return QVariant();
684  }
685 
686  // extract substring
687  re.indexIn( str );
688  if ( re.captureCount() > 0 )
689  {
690  // return first capture
691  return QVariant( re.capturedTexts()[1] );
692  }
693  else
694  {
695  return QVariant( "" );
696  }
697 }
698 
699 static QVariant fcnSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
700 {
701  QString str = getStringValue( values.at( 0 ), parent );
702  int from = getIntValue( values.at( 1 ), parent );
703  int len = getIntValue( values.at( 2 ), parent );
704  return QVariant( str.mid( from -1, len ) );
705 }
706 
707 static QVariant fcnRowNumber( const QVariantList& , const QgsFeature* , QgsExpression* parent )
708 {
709  return QVariant( parent->currentRowNumber() );
710 }
711 
712 static QVariant fcnFeatureId( const QVariantList& , const QgsFeature* f, QgsExpression* )
713 {
714  // TODO: handling of 64-bit feature ids?
715  return f ? QVariant(( int )f->id() ) : QVariant();
716 }
717 
718 static QVariant fcnConcat( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
719 {
720  QString concat;
721  foreach ( const QVariant &value, values )
722  {
723  concat += getStringValue( value, parent );
724  }
725  return concat;
726 }
727 
728 static QVariant fcnStrpos( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
729 {
730  QString string = getStringValue( values.at( 0 ), parent );
731  return string.indexOf( QRegExp( getStringValue( values.at( 1 ), parent ) ) );
732 }
733 
734 static QVariant fcnRight( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
735 {
736  QString string = getStringValue( values.at( 0 ), parent );
737  int pos = getIntValue( values.at( 1 ), parent );
738  return string.right( pos );
739 }
740 
741 static QVariant fcnLeft( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
742 {
743  QString string = getStringValue( values.at( 0 ), parent );
744  int pos = getIntValue( values.at( 1 ), parent );
745  return string.left( pos );
746 }
747 
748 static QVariant fcnRPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
749 {
750  QString string = getStringValue( values.at( 0 ), parent );
751  int length = getIntValue( values.at( 1 ), parent );
752  QString fill = getStringValue( values.at( 2 ), parent );
753  return string.rightJustified( length, fill.at( 0 ), true );
754 }
755 
756 static QVariant fcnLPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
757 {
758  QString string = getStringValue( values.at( 0 ), parent );
759  int length = getIntValue( values.at( 1 ), parent );
760  QString fill = getStringValue( values.at( 2 ), parent );
761  return string.leftJustified( length, fill.at( 0 ), true );
762 }
763 
764 static QVariant fcnFormatString( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
765 {
766  QString string = getStringValue( values.at( 0 ), parent );
767  for ( int n = 1; n < values.length(); n++ )
768  {
769  string = string.arg( getStringValue( values.at( n ), parent ) );
770  }
771  return string;
772 }
773 
774 
775 static QVariant fcnNow( const QVariantList&, const QgsFeature* , QgsExpression * )
776 {
777  return QVariant( QDateTime::currentDateTime() );
778 }
779 
780 static QVariant fcnToDate( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
781 {
782  return QVariant( getDateValue( values.at( 0 ), parent ) );
783 }
784 
785 static QVariant fcnToTime( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
786 {
787  return QVariant( getTimeValue( values.at( 0 ), parent ) );
788 }
789 
790 static QVariant fcnToInterval( const QVariantList& values, const QgsFeature* , QgsExpression * parent )
791 {
792  return QVariant::fromValue( getInterval( values.at( 0 ), parent ) );
793 }
794 
795 static QVariant fcnAge( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
796 {
797  QDateTime d1 = getDateTimeValue( values.at( 0 ), parent );
798  QDateTime d2 = getDateTimeValue( values.at( 1 ), parent );
799  int seconds = d2.secsTo( d1 );
800  return QVariant::fromValue( QgsExpression::Interval( seconds ) );
801 }
802 
803 static QVariant fcnDay( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
804 {
805  QVariant value = values.at( 0 );
806  QgsExpression::Interval inter = getInterval( value, parent, false );
807  if ( inter.isValid() )
808  {
809  return QVariant( inter.days() );
810  }
811  else
812  {
813  QDateTime d1 = getDateTimeValue( value, parent );
814  return QVariant( d1.date().day() );
815  }
816 }
817 
818 static QVariant fcnYear( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
819 {
820  QVariant value = values.at( 0 );
821  QgsExpression::Interval inter = getInterval( value, parent, false );
822  if ( inter.isValid() )
823  {
824  return QVariant( inter.years() );
825  }
826  else
827  {
828  QDateTime d1 = getDateTimeValue( value, parent );
829  return QVariant( d1.date().year() );
830  }
831 }
832 
833 static QVariant fcnMonth( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
834 {
835  QVariant value = values.at( 0 );
836  QgsExpression::Interval inter = getInterval( value, parent, false );
837  if ( inter.isValid() )
838  {
839  return QVariant( inter.months() );
840  }
841  else
842  {
843  QDateTime d1 = getDateTimeValue( value, parent );
844  return QVariant( d1.date().month() );
845  }
846 }
847 
848 static QVariant fcnWeek( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
849 {
850  QVariant value = values.at( 0 );
851  QgsExpression::Interval inter = getInterval( value, parent, false );
852  if ( inter.isValid() )
853  {
854  return QVariant( inter.weeks() );
855  }
856  else
857  {
858  QDateTime d1 = getDateTimeValue( value, parent );
859  return QVariant( d1.date().weekNumber() );
860  }
861 }
862 
863 static QVariant fcnHour( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
864 {
865  QVariant value = values.at( 0 );
866  QgsExpression::Interval inter = getInterval( value, parent, false );
867  if ( inter.isValid() )
868  {
869  return QVariant( inter.hours() );
870  }
871  else
872  {
873  QDateTime d1 = getDateTimeValue( value, parent );
874  return QVariant( d1.time().hour() );
875  }
876 }
877 
878 static QVariant fcnMinute( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
879 {
880  QVariant value = values.at( 0 );
881  QgsExpression::Interval inter = getInterval( value, parent, false );
882  if ( inter.isValid() )
883  {
884  return QVariant( inter.minutes() );
885  }
886  else
887  {
888  QDateTime d1 = getDateTimeValue( value, parent );
889  return QVariant( d1.time().minute() );
890  }
891 }
892 
893 static QVariant fcnSeconds( const QVariantList& values, const QgsFeature* , QgsExpression *parent )
894 {
895  QVariant value = values.at( 0 );
896  QgsExpression::Interval inter = getInterval( value, parent, false );
897  if ( inter.isValid() )
898  {
899  return QVariant( inter.seconds() );
900  }
901  else
902  {
903  QDateTime d1 = getDateTimeValue( value, parent );
904  return QVariant( d1.time().second() );
905  }
906 }
907 
908 
909 #define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \
910  QgsGeometry* g = f->geometry(); \
911  if (!g || g->type() != geomtype) return QVariant();
912 
913 
914 static QVariant fcnX( const QVariantList& , const QgsFeature* f, QgsExpression* )
915 {
916  ENSURE_GEOM_TYPE( f, g, QGis::Point );
917  if ( g->isMultipart() )
918  {
919  return g->asMultiPoint()[ 0 ].x();
920  }
921  else
922  {
923  return g->asPoint().x();
924  }
925 }
926 static QVariant fcnY( const QVariantList& , const QgsFeature* f, QgsExpression* )
927 {
928  ENSURE_GEOM_TYPE( f, g, QGis::Point );
929  if ( g->isMultipart() )
930  {
931  return g->asMultiPoint()[ 0 ].y();
932  }
933  else
934  {
935  return g->asPoint().y();
936  }
937 }
938 
939 static QVariant pointAt( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) // helper function
940 {
941  int idx = getIntValue( values.at( 0 ), parent );
942  ENSURE_GEOM_TYPE( f, g, QGis::Line );
943  QgsPolyline polyline = g->asPolyline();
944  if ( idx < 0 )
945  idx += polyline.count();
946 
947  if ( idx < 0 || idx >= polyline.count() )
948  {
949  parent->setEvalErrorString( QObject::tr( "Index is out of range" ) );
950  return QVariant();
951  }
952  return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) );
953 }
954 
955 static QVariant fcnXat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
956 {
957  QVariant v = pointAt( values, f, parent );
958  if ( v.type() == QVariant::PointF )
959  return QVariant( v.toPointF().x() );
960  else
961  return QVariant();
962 }
963 static QVariant fcnYat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
964 {
965  QVariant v = pointAt( values, f, parent );
966  if ( v.type() == QVariant::PointF )
967  return QVariant( v.toPointF().y() );
968  else
969  return QVariant();
970 }
971 static QVariant fcnGeometry( const QVariantList& , const QgsFeature* f, QgsExpression* )
972 {
973  QgsGeometry* geom = f->geometry();
974  if ( geom )
975  return QVariant::fromValue( *geom );
976  else
977  return QVariant();
978 }
979 static QVariant fcnGeomFromWKT( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
980 {
981  QString wkt = getStringValue( values.at( 0 ), parent );
982  QgsGeometry* geom = QgsGeometry::fromWkt( wkt );
983  if ( geom )
984  return QVariant::fromValue( *geom );
985  else
986  return QVariant();
987 }
988 static QVariant fcnGeomFromGML( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
989 {
990  QString gml = getStringValue( values.at( 0 ), parent );
992 
993  if ( geom )
994  return QVariant::fromValue( *geom );
995  else
996  return QVariant();
997 }
998 
999 static QVariant fcnGeomArea( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1000 {
1002  QgsDistanceArea* calc = parent->geomCalculator();
1003  return QVariant( calc->measure( f->geometry() ) );
1004 }
1005 static QVariant fcnGeomLength( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1006 {
1007  ENSURE_GEOM_TYPE( f, g, QGis::Line );
1008  QgsDistanceArea* calc = parent->geomCalculator();
1009  return QVariant( calc->measure( f->geometry() ) );
1010 }
1011 static QVariant fcnGeomPerimeter( const QVariantList& , const QgsFeature* f, QgsExpression* parent )
1012 {
1014  QgsDistanceArea* calc = parent->geomCalculator();
1015  return QVariant( calc->measurePerimeter( f->geometry() ) );
1016 }
1017 
1018 static QVariant fcnBbox( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1019 {
1020  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1021  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1022  return fGeom.intersects( sGeom.boundingBox() ) ? TVL_True : TVL_False;
1023 }
1024 static QVariant fcnDisjoint( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1025 {
1026  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1027  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1028  return fGeom.disjoint( &sGeom ) ? TVL_True : TVL_False;
1029 }
1030 static QVariant fcnIntersects( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1031 {
1032  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1033  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1034  return fGeom.intersects( &sGeom ) ? TVL_True : TVL_False;
1035 }
1036 static QVariant fcnTouches( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1037 {
1038  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1039  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1040  return fGeom.touches( &sGeom ) ? TVL_True : TVL_False;
1041 }
1042 static QVariant fcnCrosses( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1043 {
1044  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1045  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1046  return fGeom.crosses( &sGeom ) ? TVL_True : TVL_False;
1047 }
1048 static QVariant fcnContains( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1049 {
1050  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1051  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1052  return fGeom.contains( &sGeom ) ? TVL_True : TVL_False;
1053 }
1054 static QVariant fcnOverlaps( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1055 {
1056  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1057  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1058  return fGeom.overlaps( &sGeom ) ? TVL_True : TVL_False;
1059 }
1060 static QVariant fcnWithin( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1061 {
1062  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1063  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1064  return fGeom.within( &sGeom ) ? TVL_True : TVL_False;
1065 }
1066 static QVariant fcnBuffer( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1067 {
1068  if ( values.length() < 2 || values.length() > 3 )
1069  return QVariant();
1070 
1071  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1072  double dist = getDoubleValue( values.at( 1 ), parent );
1073  int seg = 8;
1074  if ( values.length() == 3 )
1075  seg = getIntValue( values.at( 2 ), parent );
1076 
1077  QgsGeometry* geom = fGeom.buffer( dist, seg );
1078  if ( geom )
1079  return QVariant::fromValue( *geom );
1080  return QVariant();
1081 }
1082 static QVariant fcnCentroid( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1083 {
1084  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1085  QgsGeometry* geom = fGeom.centroid();
1086  if ( geom )
1087  return QVariant::fromValue( *geom );
1088  return QVariant();
1089 }
1090 static QVariant fcnConvexHull( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1091 {
1092  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1093  QgsGeometry* geom = fGeom.convexHull();
1094  if ( geom )
1095  return QVariant::fromValue( *geom );
1096  return QVariant();
1097 }
1098 static QVariant fcnDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1099 {
1100  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1101  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1102  QgsGeometry* geom = fGeom.difference( &sGeom );
1103  if ( geom )
1104  return QVariant::fromValue( *geom );
1105  return QVariant();
1106 }
1107 static QVariant fcnDistance( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1108 {
1109  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1110  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1111  return QVariant( fGeom.distance( sGeom ) );
1112 }
1113 static QVariant fcnIntersection( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1114 {
1115  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1116  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1117  QgsGeometry* geom = fGeom.intersection( &sGeom );
1118  if ( geom )
1119  return QVariant::fromValue( *geom );
1120  return QVariant();
1121 }
1122 static QVariant fcnSymDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1123 {
1124  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1125  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1126  QgsGeometry* geom = fGeom.symDifference( &sGeom );
1127  if ( geom )
1128  return QVariant::fromValue( *geom );
1129  return QVariant();
1130 }
1131 static QVariant fcnCombine( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1132 {
1133  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1134  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1135  QgsGeometry* geom = fGeom.combine( &sGeom );
1136  if ( geom )
1137  return QVariant::fromValue( *geom );
1138  return QVariant();
1139 }
1140 static QVariant fcnGeomToWKT( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
1141 {
1142  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1143  QString wkt = fGeom.exportToWkt();
1144  return QVariant( wkt );
1145 }
1146 
1147 static QVariant fcnRound( const QVariantList& values , const QgsFeature *f, QgsExpression* parent )
1148 {
1149  Q_UNUSED( f );
1150  if ( values.length() == 2 )
1151  {
1152  double number = getDoubleValue( values.at( 0 ), parent );
1153  double scaler = pow( 10.0, getIntValue( values.at( 1 ), parent ) );
1154  return QVariant( qRound( number * scaler ) / scaler );
1155  }
1156 
1157  if ( values.length() == 1 )
1158  {
1159  double number = getIntValue( values.at( 0 ), parent );
1160  return QVariant( qRound( number ) ).toInt();
1161  }
1162 
1163  return QVariant();
1164 }
1165 
1166 static QVariant fcnPi( const QVariantList& values , const QgsFeature *f, QgsExpression* parent )
1167 {
1168  Q_UNUSED( values );
1169  Q_UNUSED( f );
1170  Q_UNUSED( parent );
1171  return M_PI;
1172 }
1173 
1174 static QVariant fcnScale( const QVariantList&, const QgsFeature*, QgsExpression* parent )
1175 {
1176  return QVariant( parent->scale() );
1177 }
1178 
1179 static QVariant fcnFormatNumber( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1180 {
1181  double value = getDoubleValue( values.at( 0 ), parent );
1182  int places = getIntValue( values.at( 1 ), parent );
1183  return QString( "%L1" ).arg( value, 0, 'f', places );
1184 }
1185 
1186 static QVariant fcnFormatDate( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1187 {
1188  QDateTime dt = getDateTimeValue( values.at( 0 ), parent );
1189  QString format = getStringValue( values.at( 1 ), parent );
1190  return dt.toString( format );
1191 }
1192 
1193 static QVariant fcnColorRgb( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1194 {
1195  int red = getIntValue( values.at( 0 ), parent );
1196  int green = getIntValue( values.at( 1 ), parent );
1197  int blue = getIntValue( values.at( 2 ), parent );
1198  QColor color = QColor( red, green, blue );
1199  if ( ! color.isValid() )
1200  {
1201  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
1202  color = QColor( 0, 0, 0 );
1203  }
1204 
1205  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1206 }
1207 
1208 static QVariant fncColorRgba( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1209 {
1210  int red = getIntValue( values.at( 0 ), parent );
1211  int green = getIntValue( values.at( 1 ), parent );
1212  int blue = getIntValue( values.at( 2 ), parent );
1213  int alpha = getIntValue( values.at( 3 ), parent );
1214  QColor color = QColor( red, green, blue, alpha );
1215  if ( ! color.isValid() )
1216  {
1217  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
1218  color = QColor( 0, 0, 0 );
1219  }
1220  return QgsSymbolLayerV2Utils::encodeColor( color );
1221 }
1222 
1223 QVariant fcnRampColor( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1224 {
1225  QString rampName = getStringValue( values.at( 0 ), parent );
1226  const QgsVectorColorRampV2 *mRamp = QgsStyleV2::defaultStyle()->colorRampRef( rampName );
1227  if ( ! mRamp )
1228  {
1229  parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) );
1230  return QColor( 0, 0, 0 ).name();
1231  }
1232  double value = getDoubleValue( values.at( 1 ), parent );
1233  QColor color = mRamp->color( value );
1234  return QgsSymbolLayerV2Utils::encodeColor( color );
1235 }
1236 
1237 static QVariant fcnColorHsl( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1238 {
1239  // Hue ranges from 0 - 360
1240  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1241  // Saturation ranges from 0 - 100
1242  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1243  // Lightness ranges from 0 - 100
1244  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1245 
1246  QColor color = QColor::fromHslF( hue, saturation, lightness );
1247 
1248  if ( ! color.isValid() )
1249  {
1250  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
1251  color = QColor( 0, 0, 0 );
1252  }
1253 
1254  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1255 }
1256 
1257 static QVariant fncColorHsla( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1258 {
1259  // Hue ranges from 0 - 360
1260  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1261  // Saturation ranges from 0 - 100
1262  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1263  // Lightness ranges from 0 - 100
1264  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
1265  // Alpha ranges from 0 - 255
1266  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1267 
1268  QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
1269  if ( ! color.isValid() )
1270  {
1271  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
1272  color = QColor( 0, 0, 0 );
1273  }
1274  return QgsSymbolLayerV2Utils::encodeColor( color );
1275 }
1276 
1277 static QVariant fcnColorHsv( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1278 {
1279  // Hue ranges from 0 - 360
1280  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1281  // Saturation ranges from 0 - 100
1282  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1283  // Value ranges from 0 - 100
1284  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1285 
1286  QColor color = QColor::fromHsvF( hue, saturation, value );
1287 
1288  if ( ! color.isValid() )
1289  {
1290  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
1291  color = QColor( 0, 0, 0 );
1292  }
1293 
1294  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1295 }
1296 
1297 static QVariant fncColorHsva( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1298 {
1299  // Hue ranges from 0 - 360
1300  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
1301  // Saturation ranges from 0 - 100
1302  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
1303  // Value ranges from 0 - 100
1304  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
1305  // Alpha ranges from 0 - 255
1306  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
1307 
1308  QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
1309  if ( ! color.isValid() )
1310  {
1311  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
1312  color = QColor( 0, 0, 0 );
1313  }
1314  return QgsSymbolLayerV2Utils::encodeColor( color );
1315 }
1316 
1317 static QVariant fcnColorCmyk( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1318 {
1319  // Cyan ranges from 0 - 100
1320  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1321  // Magenta ranges from 0 - 100
1322  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1323  // Yellow ranges from 0 - 100
1324  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1325  // Black ranges from 0 - 100
1326  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1327 
1328  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
1329 
1330  if ( ! color.isValid() )
1331  {
1332  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
1333  color = QColor( 0, 0, 0 );
1334  }
1335 
1336  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
1337 }
1338 
1339 static QVariant fncColorCmyka( const QVariantList &values, const QgsFeature *, QgsExpression *parent )
1340 {
1341  // Cyan ranges from 0 - 100
1342  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
1343  // Magenta ranges from 0 - 100
1344  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
1345  // Yellow ranges from 0 - 100
1346  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
1347  // Black ranges from 0 - 100
1348  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
1349  // Alpha ranges from 0 - 255
1350  double alpha = getIntValue( values.at( 4 ), parent ) / 255.0;
1351 
1352  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
1353  if ( ! color.isValid() )
1354  {
1355  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
1356  color = QColor( 0, 0, 0 );
1357  }
1358  return QgsSymbolLayerV2Utils::encodeColor( color );
1359 }
1360 
1361 static QVariant fcnSpecialColumn( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent )
1362 {
1363  QString varName = getStringValue( values.at( 0 ), parent );
1364  return QgsExpression::specialColumn( varName );
1365 }
1366 
1368 {
1369  int fnIdx = functionIndex( function->name() );
1370  if ( fnIdx != -1 )
1371  {
1372  return false;
1373  }
1374  QgsExpression::gmFunctions.append( function );
1375  return true;
1376 }
1377 
1379 {
1380  // You can never override the built in functions.
1381  if ( QgsExpression::BuiltinFunctions().contains( name ) )
1382  {
1383  return false;
1384  }
1385  int fnIdx = functionIndex( name );
1386  if ( fnIdx != -1 )
1387  {
1388  QgsExpression::gmFunctions.removeAt( fnIdx );
1389  return true;
1390  }
1391  return false;
1392 }
1393 
1394 
1395 
1397 
1399 {
1400  if ( gmBuiltinFunctions.isEmpty() )
1401  {
1403  << "abs" << "sqrt" << "cos" << "sin" << "tan"
1404  << "asin" << "acos" << "atan" << "atan2"
1405  << "exp" << "ln" << "log10" << "log"
1406  << "round" << "rand" << "randf" << "max" << "min" << "clamp"
1407  << "scale_linear" << "scale_exp" << "floor" << "ceil"
1408  << "toint" << "toreal" << "tostring"
1409  << "todatetime" << "todate" << "totime" << "tointerval"
1410  << "coalesce" << "regexp_match" << "$now" << "age" << "year"
1411  << "month" << "week" << "day" << "hour"
1412  << "minute" << "second" << "lower" << "upper"
1413  << "title" << "length" << "replace" << "trim"
1414  << "regexp_replace" << "regexp_substr"
1415  << "substr" << "concat" << "strpos" << "left"
1416  << "right" << "rpad" << "lpad"
1417  << "format_number" << "format_date"
1418  << "color_rgb" << "color_rgba" << "ramp_color"
1419  << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva"
1420  << "color_cymk" << "color_cymka"
1421  << "xat" << "yat" << "$area"
1422  << "$length" << "$perimeter" << "$x" << "$y"
1423  << "$rownum" << "$id" << "$scale" << "_specialcol_";
1424  }
1425  return gmBuiltinFunctions;
1426 }
1427 
1428 QList<QgsExpression::Function*> QgsExpression::gmFunctions;
1429 
1430 const QList<QgsExpression::Function*> &QgsExpression::Functions()
1431 {
1432  if ( gmFunctions.isEmpty() )
1433  {
1434  gmFunctions
1435  << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
1436  << new StaticFunction( "abs", 1, fcnAbs, "Math" )
1437  << new StaticFunction( "cos", 1, fcnCos, "Math" )
1438  << new StaticFunction( "sin", 1, fcnSin, "Math" )
1439  << new StaticFunction( "tan", 1, fcnTan, "Math" )
1440  << new StaticFunction( "asin", 1, fcnAsin, "Math" )
1441  << new StaticFunction( "acos", 1, fcnAcos, "Math" )
1442  << new StaticFunction( "atan", 1, fcnAtan, "Math" )
1443  << new StaticFunction( "atan2", 2, fcnAtan2, "Math" )
1444  << new StaticFunction( "exp", 1, fcnExp, "Math" )
1445  << new StaticFunction( "ln", 1, fcnLn, "Math" )
1446  << new StaticFunction( "log10", 1, fcnLog10, "Math" )
1447  << new StaticFunction( "log", 2, fcnLog, "Math" )
1448  << new StaticFunction( "round", -1, fcnRound, "Math" )
1449  << new StaticFunction( "rand", 2, fcnRnd, "Math" )
1450  << new StaticFunction( "randf", 2, fcnRndF, "Math" )
1451  << new StaticFunction( "max", -1, fcnMax, "Math" )
1452  << new StaticFunction( "min", -1, fcnMin, "Math" )
1453  << new StaticFunction( "clamp", 3, fcnClamp, "Math" )
1454  << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" )
1455  << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" )
1456  << new StaticFunction( "floor", 1, fcnFloor, "Math" )
1457  << new StaticFunction( "ceil", 1, fcnCeil, "Math" )
1458  << new StaticFunction( "$pi", 0, fcnPi, "Math" )
1459  << new StaticFunction( "toint", 1, fcnToInt, "Conversions" )
1460  << new StaticFunction( "toreal", 1, fcnToReal, "Conversions" )
1461  << new StaticFunction( "tostring", 1, fcnToString, "Conversions" )
1462  << new StaticFunction( "todatetime", 1, fcnToDateTime, "Conversions" )
1463  << new StaticFunction( "todate", 1, fcnToDate, "Conversions" )
1464  << new StaticFunction( "totime", 1, fcnToTime, "Conversions" )
1465  << new StaticFunction( "tointerval", 1, fcnToInterval, "Conversions" )
1466  << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" )
1467  << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
1468  << new StaticFunction( "$now", 0, fcnNow, "Date and Time" )
1469  << new StaticFunction( "age", 2, fcnAge, "Date and Time" )
1470  << new StaticFunction( "year", 1, fcnYear, "Date and Time" )
1471  << new StaticFunction( "month", 1, fcnMonth, "Date and Time" )
1472  << new StaticFunction( "week", 1, fcnWeek, "Date and Time" )
1473  << new StaticFunction( "day", 1, fcnDay, "Date and Time" )
1474  << new StaticFunction( "hour", 1, fcnHour, "Date and Time" )
1475  << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" )
1476  << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" )
1477  << new StaticFunction( "lower", 1, fcnLower, "String" )
1478  << new StaticFunction( "upper", 1, fcnUpper, "String" )
1479  << new StaticFunction( "title", 1, fcnTitle, "String" )
1480  << new StaticFunction( "trim", 1, fcnTrim, "String" )
1481  << new StaticFunction( "length", 1, fcnLength, "String" )
1482  << new StaticFunction( "replace", 3, fcnReplace, "String" )
1483  << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
1484  << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
1485  << new StaticFunction( "substr", 3, fcnSubstr, "String" )
1486  << new StaticFunction( "concat", -1, fcnConcat, "String" )
1487  << new StaticFunction( "strpos", 2, fcnStrpos, "String" )
1488  << new StaticFunction( "left", 2, fcnLeft, "String" )
1489  << new StaticFunction( "right", 2, fcnRight, "String" )
1490  << new StaticFunction( "rpad", 3, fcnRPad, "String" )
1491  << new StaticFunction( "lpad", 3, fcnLPad, "String" )
1492  << new StaticFunction( "format", -1, fcnFormatString, "String" )
1493  << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
1494  << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
1495  << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
1496  << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
1497  << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
1498  << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" )
1499  << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" )
1500  << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" )
1501  << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" )
1502  << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" )
1503  << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" )
1504  << new StaticFunction( "xat", 1, fcnXat, "Geometry", "", true )
1505  << new StaticFunction( "yat", 1, fcnYat, "Geometry", "", true )
1506  << new StaticFunction( "$area", 0, fcnGeomArea, "Geometry", "", true )
1507  << new StaticFunction( "$length", 0, fcnGeomLength, "Geometry", "", true )
1508  << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "Geometry", "", true )
1509  << new StaticFunction( "$x", 0, fcnX, "Geometry", "", true )
1510  << new StaticFunction( "$y", 0, fcnY, "Geometry", "" , true )
1511  << new StaticFunction( "$geometry", 0, fcnGeometry, "Geometry", "" , true )
1512  << new StaticFunction( "geomFromWKT", 1, fcnGeomFromWKT, "Geometry" )
1513  << new StaticFunction( "geomFromGML", 1, fcnGeomFromGML, "Geometry" )
1514  << new StaticFunction( "bbox", 2, fcnBbox, "Geometry" )
1515  << new StaticFunction( "disjoint", 2, fcnDisjoint, "Geometry" )
1516  << new StaticFunction( "intersects", 2, fcnIntersects, "Geometry" )
1517  << new StaticFunction( "touches", 2, fcnTouches, "Geometry" )
1518  << new StaticFunction( "crosses", 2, fcnCrosses, "Geometry" )
1519  << new StaticFunction( "contains", 2, fcnContains, "Geometry" )
1520  << new StaticFunction( "overlaps", 2, fcnOverlaps, "Geometry" )
1521  << new StaticFunction( "within", 2, fcnWithin, "Geometry" )
1522  << new StaticFunction( "buffer", -1, fcnBuffer, "Geometry" )
1523  << new StaticFunction( "centroid", 1, fcnCentroid, "Geometry" )
1524  << new StaticFunction( "convexHull", 1, fcnConvexHull, "Geometry" )
1525  << new StaticFunction( "difference", 2, fcnDifference, "Geometry" )
1526  << new StaticFunction( "distance", 2, fcnDistance, "Geometry" )
1527  << new StaticFunction( "intersection", 2, fcnIntersection, "Geometry" )
1528  << new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" )
1529  << new StaticFunction( "combine", 2, fcnCombine, "Geometry" )
1530  << new StaticFunction( "union", 2, fcnCombine, "Geometry" )
1531  << new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" )
1532  << new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
1533  << new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
1534  << new StaticFunction( "$scale", 0, fcnScale, "Record" )
1535  << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
1536  ;
1537  }
1538  return gmFunctions;
1539 }
1540 
1541 QMap<QString, QVariant> QgsExpression::gmSpecialColumns;
1542 
1543 void QgsExpression::setSpecialColumn( const QString& name, QVariant variant )
1544 {
1545  int fnIdx = functionIndex( name );
1546  if ( fnIdx != -1 )
1547  {
1548  // function of the same name already exists
1549  return;
1550  }
1551  gmSpecialColumns[ name ] = variant;
1552 }
1553 
1554 void QgsExpression::unsetSpecialColumn( const QString& name )
1555 {
1556  QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name );
1557  if ( fit != gmSpecialColumns.end() )
1558  {
1559  gmSpecialColumns.erase( fit );
1560  }
1561 }
1562 
1563 QVariant QgsExpression::specialColumn( const QString& name )
1564 {
1565  int fnIdx = functionIndex( name );
1566  if ( fnIdx != -1 )
1567  {
1568  // function of the same name already exists
1569  return QVariant();
1570  }
1571  QMap<QString, QVariant>::iterator it = gmSpecialColumns.find( name );
1572  if ( it == gmSpecialColumns.end() )
1573  {
1574  return QVariant();
1575  }
1576  return it.value();
1577 }
1578 
1579 QList<QgsExpression::Function*> QgsExpression::specialColumns()
1580 {
1581  QList<Function*> defs;
1582  for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.begin(); it != gmSpecialColumns.end(); ++it )
1583  {
1584  defs << new StaticFunction( it.key(), 0, 0, "Record" );
1585  }
1586  return defs;
1587 }
1588 
1589 bool QgsExpression::isFunctionName( QString name )
1590 {
1591  return functionIndex( name ) != -1;
1592 }
1593 
1594 int QgsExpression::functionIndex( QString name )
1595 {
1596  int count = functionCount();
1597  for ( int i = 0; i < count; i++ )
1598  {
1599  if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
1600  return i;
1601  }
1602  return -1;
1603 }
1604 
1606 {
1607  return Functions().size();
1608 }
1609 
1610 
1611 QgsExpression::QgsExpression( const QString& expr )
1612  : mExpression( expr )
1613  , mRowNumber( 0 )
1614  , mScale( 0 )
1615  , mCalc( 0 )
1616 {
1618 
1619  if ( mParserErrorString.isNull() )
1620  Q_ASSERT( mRootNode );
1621 }
1622 
1624 {
1625  delete mCalc;
1626  delete mRootNode;
1627 }
1628 
1630 {
1631  if ( !mRootNode )
1632  return QStringList();
1633  QStringList columns = mRootNode->referencedColumns();
1634 
1635  // filter out duplicates
1636  for ( int i = 0; i < columns.count(); i++ )
1637  {
1638  QString col = columns.at( i );
1639  for ( int j = i + 1; j < columns.count(); j++ )
1640  {
1641  if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
1642  {
1643  // this column is repeated: remove it!
1644  columns.removeAt( j-- );
1645  }
1646  }
1647  }
1648 
1649  return columns;
1650 }
1651 
1653 {
1654  if ( !mRootNode )
1655  return false;
1656  return mRootNode->needsGeometry();
1657 }
1658 
1660 {
1661  if ( mCalc )
1662  return;
1663 
1664  // Use planimetric as default
1665  mCalc = new QgsDistanceArea();
1666  mCalc->setEllipsoidalMode( false );
1667 }
1668 
1670 {
1671  if ( !mCalc )
1672  mCalc = new QgsDistanceArea();
1673 
1674  // Copy from supplied calculator
1675  mCalc->setEllipsoid( calc.ellipsoid() );
1677  mCalc->setSourceCrs( calc.sourceCrs() );
1678 }
1679 
1680 bool QgsExpression::prepare( const QgsFields& fields )
1681 {
1682  mEvalErrorString = QString();
1683  if ( !mRootNode )
1684  {
1685  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1686  return false;
1687  }
1688 
1689  return mRootNode->prepare( this, fields );
1690 }
1691 
1693 {
1694  mEvalErrorString = QString();
1695  if ( !mRootNode )
1696  {
1697  mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
1698  return QVariant();
1699  }
1700 
1701  return mRootNode->eval( this, f );
1702 }
1703 
1704 QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields )
1705 {
1706  // first prepare
1707  bool res = prepare( fields );
1708  if ( !res )
1709  return QVariant();
1710 
1711  // then evaluate
1712  return evaluate( f );
1713 }
1714 
1715 QString QgsExpression::dump() const
1716 {
1717  if ( !mRootNode )
1718  return QObject::tr( "(no root)" );
1719 
1720  return mRootNode->dump();
1721 }
1722 
1724 {
1725  if ( mRootNode )
1726  mRootNode->accept( v );
1727 }
1728 
1729 QString QgsExpression::replaceExpressionText( QString action, QgsFeature* feat,
1730  QgsVectorLayer* layer,
1731  const QMap<QString, QVariant> *substitutionMap )
1732 {
1733  QString expr_action;
1734 
1735  QMap<QString, QVariant> savedValues;
1736  if ( substitutionMap )
1737  {
1738  // variables with a local scope (must be restored after evaluation)
1739  for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
1740  {
1741  QVariant oldValue = QgsExpression::specialColumn( sit.key() );
1742  if ( !oldValue.isNull() )
1743  savedValues.insert( sit.key(), oldValue );
1744 
1745  // set the new value
1746  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
1747  }
1748  }
1749 
1750  int index = 0;
1751  while ( index < action.size() )
1752  {
1753  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
1754 
1755  int pos = rx.indexIn( action, index );
1756  if ( pos < 0 )
1757  break;
1758 
1759  int start = index;
1760  index = pos + rx.matchedLength();
1761  QString to_replace = rx.cap( 1 ).trimmed();
1762  QgsDebugMsg( "Found expression: " + to_replace );
1763 
1764  QgsExpression exp( to_replace );
1765  if ( exp.hasParserError() )
1766  {
1767  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
1768  expr_action += action.mid( start, index - start );
1769  continue;
1770  }
1771 
1772  QVariant result;
1773  if ( layer )
1774  {
1775  result = exp.evaluate( feat, layer->pendingFields() );
1776  }
1777  else
1778  {
1779  result = exp.evaluate( feat );
1780  }
1781  if ( exp.hasEvalError() )
1782  {
1783  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
1784  expr_action += action.mid( start, index - start );
1785  continue;
1786  }
1787 
1788  QgsDebugMsg( "Expression result is: " + result.toString() );
1789  expr_action += action.mid( start, pos - start ) + result.toString();
1790  }
1791 
1792  expr_action += action.mid( index );
1793 
1794  // restore overwritten local values
1795  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
1796  {
1797  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
1798  }
1799 
1800  return expr_action;
1801 }
1802 
1803 
1804 QString QgsExpression::replaceExpressionText( QString action, QgsFeature& feat,
1805  QgsVectorLayer* layer,
1806  const QMap<QString, QVariant> *substitutionMap )
1807 {
1808  return replaceExpressionText( action, &feat, layer, substitutionMap );
1809 }
1810 
1811 
1813 // nodes
1814 
1816 {
1817  QString msg; bool first = true;
1818  foreach ( Node* n, mList )
1819  {
1820  if ( !first ) msg += ", "; else first = false;
1821  msg += n->dump();
1822  }
1823  return msg;
1824 }
1825 
1826 
1827 //
1828 
1830 {
1831  QVariant val = mOperand->eval( parent, f );
1833 
1834  switch ( mOp )
1835  {
1836  case uoNot:
1837  {
1838  TVL tvl = getTVLValue( val, parent );
1840  return tvl2variant( NOT[tvl] );
1841  }
1842 
1843  case uoMinus:
1844  if ( isIntSafe( val ) )
1845  return QVariant( - getIntValue( val, parent ) );
1846  else if ( isDoubleSafe( val ) )
1847  return QVariant( - getDoubleValue( val, parent ) );
1848  else
1849  SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
1850  break;
1851  default:
1852  Q_ASSERT( 0 && "unknown unary operation" );
1853  }
1854  return QVariant();
1855 }
1856 
1858 {
1859  return mOperand->prepare( parent, fields );
1860 }
1861 
1863 {
1864  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
1865 }
1866 
1867 //
1868 
1870 {
1871  QVariant vL = mOpLeft->eval( parent, f );
1873  QVariant vR = mOpRight->eval( parent, f );
1875 
1876  switch ( mOp )
1877  {
1878  case boPlus:
1879  case boMinus:
1880  case boMul:
1881  case boDiv:
1882  case boMod:
1883  if ( isNull( vL ) || isNull( vR ) )
1884  return QVariant();
1885  else if ( isIntSafe( vL ) && isIntSafe( vR ) )
1886  {
1887  // both are integers - let's use integer arithmetics
1888  int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1889  int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1890  if ( mOp == boDiv && iR == 0 ) return QVariant(); // silently handle division by zero and return NULL
1891  return QVariant( computeInt( iL, iR ) );
1892  }
1893  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
1894  {
1895  QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1897  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
1898  {
1899  parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
1900  return QVariant();
1901  }
1902  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
1903  }
1904  else
1905  {
1906  // general floating point arithmetic
1907  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1908  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1909  if ( mOp == boDiv && fR == 0 )
1910  return QVariant(); // silently handle division by zero and return NULL
1911  return QVariant( computeDouble( fL, fR ) );
1912  }
1913 
1914  case boPow:
1915  if ( isNull( vL ) || isNull( vR ) )
1916  return QVariant();
1917  else
1918  {
1919  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1920  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1921  return QVariant( pow( fL, fR ) );
1922  }
1923 
1924  case boAnd:
1925  {
1926  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
1928  return tvl2variant( AND[tvlL][tvlR] );
1929  }
1930 
1931  case boOr:
1932  {
1933  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
1935  return tvl2variant( OR[tvlL][tvlR] );
1936  }
1937 
1938  case boEQ:
1939  case boNE:
1940  case boLT:
1941  case boGT:
1942  case boLE:
1943  case boGE:
1944  if ( isNull( vL ) || isNull( vR ) )
1945  {
1946  return TVL_Unknown;
1947  }
1948  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
1949  {
1950  // do numeric comparison if both operators can be converted to numbers
1951  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1952  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1953  return compare( fL - fR ) ? TVL_True : TVL_False;
1954  }
1955  else
1956  {
1957  // do string comparison otherwise
1958  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1959  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1960  int diff = QString::compare( sL, sR );
1961  return compare( diff ) ? TVL_True : TVL_False;
1962  }
1963 
1964  case boIs:
1965  case boIsNot:
1966  if ( isNull( vL ) && isNull( vR ) ) // both operators null
1967  return ( mOp == boIs ? TVL_True : TVL_False );
1968  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
1969  return ( mOp == boIs ? TVL_False : TVL_True );
1970  else // both operators non-null
1971  {
1972  bool equal = false;
1973  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
1974  {
1975  double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1976  double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1977  equal = fL == fR;
1978  }
1979  else
1980  {
1981  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
1982  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
1983  equal = QString::compare( sL, sR ) == 0;
1984  }
1985  if ( equal )
1986  return mOp == boIs ? TVL_True : TVL_False;
1987  else
1988  return mOp == boIs ? TVL_False : TVL_True;
1989  }
1990 
1991  case boRegexp:
1992  case boLike:
1993  case boNotLike:
1994  case boILike:
1995  case boNotILike:
1996  if ( isNull( vL ) || isNull( vR ) )
1997  return TVL_Unknown;
1998  else
1999  {
2000  QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2001  QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2002  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
2003  bool matches;
2004  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
2005  {
2006  QString esc_regexp = QRegExp::escape( regexp );
2007  // XXX escape % and _ ???
2008  esc_regexp.replace( "%", ".*" );
2009  esc_regexp.replace( "_", "." );
2010  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
2011  }
2012  else
2013  {
2014  matches = QRegExp( regexp ).indexIn( str ) != -1;
2015  }
2016 
2017  if ( mOp == boNotLike || mOp == boNotILike )
2018  {
2019  matches = !matches;
2020  }
2021 
2022  return matches ? TVL_True : TVL_False;
2023  }
2024 
2025  case boConcat:
2026  if ( isNull( vL ) || isNull( vR ) )
2027  return QVariant();
2028  else
2029  {
2030  QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
2031  QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
2032  return QVariant( sL + sR );
2033  }
2034 
2035  default: break;
2036  }
2037  Q_ASSERT( false );
2038  return QVariant();
2039 }
2040 
2042 {
2043  switch ( mOp )
2044  {
2045  case boEQ: return diff == 0;
2046  case boNE: return diff != 0;
2047  case boLT: return diff < 0;
2048  case boGT: return diff > 0;
2049  case boLE: return diff <= 0;
2050  case boGE: return diff >= 0;
2051  default: Q_ASSERT( false ); return false;
2052  }
2053 }
2054 
2056 {
2057  switch ( mOp )
2058  {
2059  case boPlus: return x+y;
2060  case boMinus: return x-y;
2061  case boMul: return x*y;
2062  case boDiv: return x/y;
2063  case boMod: return x%y;
2064  default: Q_ASSERT( false ); return 0;
2065  }
2066 }
2067 
2069 {
2070  switch ( mOp )
2071  {
2072  case boPlus: return d.addSecs( i->seconds() );
2073  case boMinus: return d.addSecs( -i->seconds() );
2074  default: Q_ASSERT( false ); return QDateTime();
2075  }
2076 }
2077 
2079 {
2080  switch ( mOp )
2081  {
2082  case boPlus: return x+y;
2083  case boMinus: return x-y;
2084  case boMul: return x*y;
2085  case boDiv: return x/y;
2086  case boMod: return fmod( x,y );
2087  default: Q_ASSERT( false ); return 0;
2088  }
2089 }
2090 
2091 
2093 {
2094  bool resL = mOpLeft->prepare( parent, fields );
2095  bool resR = mOpRight->prepare( parent, fields );
2096  return resL && resR;
2097 }
2098 
2100 {
2101  return QString( "%1 %2 %3" ).arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
2102 }
2103 
2104 //
2105 
2107 {
2108  if ( mList->count() == 0 )
2109  return mNotIn ? TVL_True : TVL_False;
2110  QVariant v1 = mNode->eval( parent, f );
2112  if ( isNull( v1 ) )
2113  return TVL_Unknown;
2114 
2115  bool listHasNull = false;
2116 
2117  foreach ( Node* n, mList->list() )
2118  {
2119  QVariant v2 = n->eval( parent, f );
2121  if ( isNull( v2 ) )
2122  listHasNull = true;
2123  else
2124  {
2125  bool equal = false;
2126  // check whether they are equal
2127  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
2128  {
2129  double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2130  double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2131  equal = f1 == f2;
2132  }
2133  else
2134  {
2135  QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
2136  QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
2137  equal = QString::compare( s1, s2 ) == 0;
2138  }
2139 
2140  if ( equal ) // we know the result
2141  return mNotIn ? TVL_False : TVL_True;
2142  }
2143  }
2144 
2145  // item not found
2146  if ( listHasNull )
2147  return TVL_Unknown;
2148  else
2149  return mNotIn ? TVL_True : TVL_False;
2150 }
2151 
2153 {
2154  bool res = mNode->prepare( parent, fields );
2155  foreach ( Node* n, mList->list() )
2156  {
2157  res = res && n->prepare( parent, fields );
2158  }
2159  return res;
2160 }
2161 
2163 {
2164  return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
2165 }
2166 
2167 //
2168 
2170 {
2171  Function* fd = Functions()[mFnIndex];
2172 
2173  // evaluate arguments
2174  QVariantList argValues;
2175  if ( mArgs )
2176  {
2177  foreach ( Node* n, mArgs->list() )
2178  {
2179  QVariant v = n->eval( parent, f );
2181  if ( isNull( v ) && fd->name() != "coalesce" )
2182  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
2183  argValues.append( v );
2184  }
2185  }
2186 
2187  // run the function
2188  QVariant res = fd->func( argValues, f, parent );
2190 
2191  // everything went fine
2192  return res;
2193 }
2194 
2196 {
2197  bool res = true;
2198  if ( mArgs )
2199  {
2200  foreach ( Node* n, mArgs->list() )
2201  {
2202  res = res && n->prepare( parent, fields );
2203  }
2204  }
2205  return res;
2206 }
2207 
2209 {
2210  Function* fd = Functions()[mFnIndex];
2211  if ( fd->params() == 0 )
2212  return fd->name(); // special column
2213  else
2214  return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
2215 }
2216 
2217 //
2218 
2220 {
2221  return mValue;
2222 }
2223 
2224 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ )
2225 {
2226  return true;
2227 }
2228 
2229 
2231 {
2232  if ( mValue.isNull() )
2233  return "NULL";
2234 
2235  switch ( mValue.type() )
2236  {
2237  case QVariant::Int: return QString::number( mValue.toInt() );
2238  case QVariant::Double: return QString::number( mValue.toDouble() );
2239  case QVariant::String: return QString( "'%1'" ).arg( mValue.toString() );
2240  default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
2241  }
2242 }
2243 
2244 //
2245 
2247 {
2248  if ( f )
2249  {
2250  if ( mIndex >= 0 )
2251  return f->attribute( mIndex );
2252  else
2253  return f->attribute( mName );
2254  }
2255  return QVariant( "[" + mName + "]" );
2256 }
2257 
2259 {
2260  for ( int i = 0; i < fields.count(); ++i )
2261  {
2262  if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
2263  {
2264  mIndex = i;
2265  return true;
2266  }
2267  }
2268  parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName );
2269  mIndex = -1;
2270  return false;
2271 }
2272 
2274 {
2275  return mName;
2276 }
2277 
2278 //
2279 
2281 {
2282  foreach ( WhenThen* cond, mConditions )
2283  {
2284  QVariant vWhen = cond->mWhenExp->eval( parent, f );
2285  TVL tvl = getTVLValue( vWhen, parent );
2287  if ( tvl == True )
2288  {
2289  QVariant vRes = cond->mThenExp->eval( parent, f );
2291  return vRes;
2292  }
2293  }
2294 
2295  if ( mElseExp )
2296  {
2297  QVariant vElse = mElseExp->eval( parent, f );
2299  return vElse;
2300  }
2301 
2302  // return NULL if no condition is matching
2303  return QVariant();
2304 }
2305 
2307 {
2308  bool res;
2309  foreach ( WhenThen* cond, mConditions )
2310  {
2311  res = cond->mWhenExp->prepare( parent, fields )
2312  & cond->mThenExp->prepare( parent, fields );
2313  if ( !res ) return false;
2314  }
2315 
2316  if ( mElseExp )
2317  return mElseExp->prepare( parent, fields );
2318 
2319  return true;
2320 }
2321 
2323 {
2324  QString msg = "CONDITION:\n";
2325  foreach ( WhenThen* cond, mConditions )
2326  {
2327  msg += QString( "- WHEN %1 THEN %2\n" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
2328  }
2329  if ( mElseExp )
2330  msg += QString( "- ELSE %1" ).arg( mElseExp->dump() );
2331  return msg;
2332 }
2333 
2335 {
2336  QStringList lst;
2337  foreach ( WhenThen* cond, mConditions )
2338  {
2339  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
2340  }
2341 
2342  if ( mElseExp )
2343  lst += mElseExp->referencedColumns();
2344 
2345  return lst;
2346 }
2347 
2349 {
2350  foreach ( WhenThen* cond, mConditions )
2351  {
2352  if ( cond->mWhenExp->needsGeometry() ||
2353  cond->mThenExp->needsGeometry() )
2354  return true;
2355  }
2356 
2357  if ( mElseExp && mElseExp->needsGeometry() )
2358  return true;
2359 
2360  return false;
2361 }
2362 
2363 QString QgsExpression::helptext( QString name )
2364 {
2366  return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) );
2367 }
2368 
2369 QHash<QString, QString> QgsExpression::gGroups;
2370 
2371 QString QgsExpression::group( QString name )
2372 {
2373  if ( gGroups.isEmpty() )
2374  {
2375  gGroups.insert( "Operators", QObject::tr( "Operators" ) );
2376  gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) );
2377  gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) );
2378  gGroups.insert( "Math", QObject::tr( "Math" ) );
2379  gGroups.insert( "Conversions", QObject::tr( "Conversions" ) );
2380  gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) );
2381  gGroups.insert( "String", QObject::tr( "String" ) );
2382  gGroups.insert( "Color", QObject::tr( "Color" ) );
2383  gGroups.insert( "Geometry", QObject::tr( "Geometry" ) );
2384  gGroups.insert( "Record", QObject::tr( "Record" ) );
2385  }
2386 
2387  //return the translated name for this group. If group does not
2388  //have a translated name in the gGroups hash, return the name
2389  //unchanged
2390  return gGroups.value( name, name );
2391 }