QGIS API Documentation  2.13.0-Master
qgsexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.cpp
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsexpression.h"
17 
18 #include <QtDebug>
19 #include <QDomDocument>
20 #include <QDate>
21 #include <QRegExp>
22 #include <QColor>
23 #include <QUuid>
24 
25 #include <math.h>
26 #include <limits>
27 
28 #include "qgsdistancearea.h"
29 #include "qgsfeature.h"
30 #include "qgsgeometry.h"
31 #include "qgsgeometryengine.h"
32 #include "qgsgeometryutils.h"
33 #include "qgslogger.h"
34 #include "qgsmaplayerregistry.h"
35 #include "qgsogcutils.h"
36 #include "qgsvectorlayer.h"
37 #include "qgssymbollayerv2utils.h"
38 #include "qgsvectorcolorrampv2.h"
39 #include "qgsstylev2.h"
40 #include "qgsexpressioncontext.h"
41 #include "qgsproject.h"
42 #include "qgsstringutils.h"
44 #include "qgspointv2.h"
45 #include "qgspolygonv2.h"
46 #include "qgsmultipointv2.h"
47 #include "qgsmultilinestringv2.h"
48 #include "qgscurvepolygonv2.h"
49 #include "qgsexpressionprivate.h"
50 #include "qgsexpressionsorter.h"
51 
52 #if QT_VERSION < 0x050000
53 #include <qtextdocument.h>
54 #endif
55 
56 // from parser
57 extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
58 
60 {
62  inter.setValid( false );
63  return inter;
64 }
65 
67 {
68  int seconds = 0;
69  QRegExp rx( "([-+]?\\d?\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
70  QStringList list;
71  int pos = 0;
72 
73  while (( pos = rx.indexIn( string, pos ) ) != -1 )
74  {
75  list << rx.cap( 1 );
76  pos += rx.matchedLength();
77  }
78 
80  map.insert( 1, QStringList() << "second" << "seconds" << tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) );
81  map.insert( 0 + MINUTE, QStringList() << "minute" << "minutes" << tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) );
82  map.insert( 0 + HOUR, QStringList() << "hour" << "hours" << tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) );
83  map.insert( 0 + DAY, QStringList() << "day" << "days" << tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) );
84  map.insert( 0 + WEEKS, QStringList() << "week" << "weeks" << tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) );
85  map.insert( 0 + MONTHS, QStringList() << "month" << "months" << tr( "month|months", "list of words separated by | which reference months" ).split( '|' ) );
86  map.insert( 0 + YEARS, QStringList() << "year" << "years" << tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) );
87 
88  Q_FOREACH ( const QString& match, list )
89  {
90  QStringList split = match.split( QRegExp( "\\s+" ) );
91  bool ok;
92  double value = split.at( 0 ).toDouble( &ok );
93  if ( !ok )
94  {
95  continue;
96  }
97 
98  bool matched = false;
100  for ( ; it != map.constEnd(); ++it )
101  {
102  int duration = it.key();
103  Q_FOREACH ( const QString& name, it.value() )
104  {
105  if ( match.contains( name, Qt::CaseInsensitive ) )
106  {
107  matched = true;
108  break;
109  }
110  }
111 
112  if ( matched )
113  {
114  seconds += value * duration;
115  break;
116  }
117  }
118  }
119 
120  // If we can't parse the string at all then we just return invalid
121  if ( seconds == 0 )
123 
124  return QgsExpression::Interval( seconds );
125 }
126 
128 {
129  return qgsDoubleNear( mSeconds, other.mSeconds );
130 }
131 
133 // three-value logic
134 
135 enum TVL
136 {
140 };
141 
142 static TVL AND[3][3] =
143 {
144  // false true unknown
145  { False, False, False }, // false
146  { False, True, Unknown }, // true
147  { False, Unknown, Unknown } // unknown
148 };
149 
150 static TVL OR[3][3] =
151 {
152  { False, True, Unknown }, // false
153  { True, True, True }, // true
154  { Unknown, True, Unknown } // unknown
155 };
156 
157 static TVL NOT[3] = { True, False, Unknown };
158 
160 {
161  switch ( v )
162  {
163  case False:
164  return 0;
165  case True:
166  return 1;
167  case Unknown:
168  default:
169  return QVariant();
170  }
171 }
172 
173 #define TVL_True QVariant(1)
174 #define TVL_False QVariant(0)
175 #define TVL_Unknown QVariant()
176 
178 // QVariant checks and conversions
179 
180 inline bool isIntSafe( const QVariant& v )
181 {
182  if ( v.type() == QVariant::Int ) return true;
183  if ( v.type() == QVariant::UInt ) return true;
184  if ( v.type() == QVariant::LongLong ) return true;
185  if ( v.type() == QVariant::ULongLong ) return true;
186  if ( v.type() == QVariant::Double ) return false;
187  if ( v.type() == QVariant::String ) { bool ok; v.toString().toInt( &ok ); return ok; }
188  return false;
189 }
190 inline bool isDoubleSafe( const QVariant& v )
191 {
192  if ( v.type() == QVariant::Double ) return true;
193  if ( v.type() == QVariant::Int ) return true;
194  if ( v.type() == QVariant::UInt ) return true;
195  if ( v.type() == QVariant::LongLong ) return true;
196  if ( v.type() == QVariant::ULongLong ) return true;
197  if ( v.type() == QVariant::String )
198  {
199  bool ok;
200  double val = v.toString().toDouble( &ok );
201  ok = ok && qIsFinite( val ) && !qIsNaN( val );
202  return ok;
203  }
204  return false;
205 }
206 
207 inline bool isDateTimeSafe( const QVariant& v )
208 {
209  return v.type() == QVariant::DateTime || v.type() == QVariant::Date ||
210  v.type() == QVariant::Time;
211 }
212 
213 inline bool isIntervalSafe( const QVariant& v )
214 {
216  {
217  return true;
218  }
219 
220  if ( v.type() == QVariant::String )
221  {
223  }
224  return false;
225 }
226 
227 inline bool isNull( const QVariant& v ) { return v.isNull(); }
228 
230 // evaluation error macros
231 
232 #define ENSURE_NO_EVAL_ERROR { if (parent->hasEvalError()) return QVariant(); }
233 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString(x); return QVariant(); }
234 
236 // operators
237 
238 const char* QgsExpression::BinaryOperatorText[] =
239 {
240  // this must correspond (number and order of element) to the declaration of the enum BinaryOperator
241  "OR", "AND",
242  "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
243  "+", "-", "*", "/", "//", "%", "^",
244  "||"
245 };
246 
247 const char* QgsExpression::UnaryOperatorText[] =
248 {
249  // this must correspond (number and order of element) to the declaration of the enum UnaryOperator
250  "NOT", "-"
251 };
252 
254 // functions
255 
256 // implicit conversion to string
258 {
259  return value.toString();
260 }
261 
262 static double getDoubleValue( const QVariant& value, QgsExpression* parent )
263 {
264  bool ok;
265  double x = value.toDouble( &ok );
266  if ( !ok || qIsNaN( x ) || !qIsFinite( x ) )
267  {
268  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) );
269  return 0;
270  }
271  return x;
272 }
273 
274 static int getIntValue( const QVariant& value, QgsExpression* parent )
275 {
276  bool ok;
277  qint64 x = value.toLongLong( &ok );
279  {
280  return x;
281  }
282  else
283  {
284  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) );
285  return 0;
286  }
287 }
288 
289 static QDateTime getDateTimeValue( const QVariant& value, QgsExpression* parent )
290 {
291  QDateTime d = value.toDateTime();
292  if ( d.isValid() )
293  {
294  return d;
295  }
296  else
297  {
298  QTime t = value.toTime();
299  if ( t.isValid() )
300  {
301  return QDateTime( QDate( 1, 1, 1 ), t );
302  }
303 
304  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
305  return QDateTime();
306  }
307 }
308 
309 static QDate getDateValue( const QVariant& value, QgsExpression* parent )
310 {
311  QDate d = value.toDate();
312  if ( d.isValid() )
313  {
314  return d;
315  }
316  else
317  {
318  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) );
319  return QDate();
320  }
321 }
322 
323 static QTime getTimeValue( const QVariant& value, QgsExpression* parent )
324 {
325  QTime t = value.toTime();
326  if ( t.isValid() )
327  {
328  return t;
329  }
330  else
331  {
332  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) );
333  return QTime();
334  }
335 }
336 
337 static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
338 {
339  if ( value.canConvert<QgsExpression::Interval>() )
340  return value.value<QgsExpression::Interval>();
341 
343  if ( inter.isValid() )
344  {
345  return inter;
346  }
347  // If we get here then we can't convert so we just error and return invalid.
348  if ( report_error )
349  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
350 
352 }
353 
354 static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent )
355 {
356  if ( value.canConvert<QgsGeometry>() )
357  return value.value<QgsGeometry>();
358 
359  parent->setEvalErrorString( "Cannot convert to QgsGeometry" );
360  return QgsGeometry();
361 }
362 
363 static QgsFeature getFeature( const QVariant& value, QgsExpression* parent )
364 {
365  if ( value.canConvert<QgsFeature>() )
366  return value.value<QgsFeature>();
367 
368  parent->setEvalErrorString( "Cannot convert to QgsFeature" );
369  return 0;
370 }
371 
372 static QgsExpression::Node* getNode( const QVariant& value, QgsExpression* parent )
373 {
374  if ( value.canConvert<QgsExpression::Node*>() )
375  return value.value<QgsExpression::Node*>();
376 
377  parent->setEvalErrorString( "Cannot convert to Node" );
378  return nullptr;
379 }
380 
381 // this handles also NULL values
382 static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
383 {
384  // we need to convert to TVL
385  if ( value.isNull() )
386  return Unknown;
387 
388  //handle some special cases
389  if ( value.canConvert<QgsGeometry>() )
390  {
391  //geom is false if empty
392  QgsGeometry geom = value.value<QgsGeometry>();
393  return geom.isEmpty() ? False : True;
394  }
395  else if ( value.canConvert<QgsFeature>() )
396  {
397  //feat is false if non-valid
398  QgsFeature feat = value.value<QgsFeature>();
399  return feat.isValid() ? True : False;
400  }
401 
402  if ( value.type() == QVariant::Int )
403  return value.toInt() != 0 ? True : False;
404 
405  bool ok;
406  double x = value.toDouble( &ok );
407  if ( !ok )
408  {
409  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) );
410  return Unknown;
411  }
412  return !qgsDoubleNear( x, 0.0 ) ? True : False;
413 }
414 
416 
417 static QVariant fcnGetVariable( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent )
418 {
419  if ( !context )
420  return QVariant();
421 
422  QString name = getStringValue( values.at( 0 ), parent );
423  return context->variable( name );
424 }
425 
426 static QVariant fcnEval( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent )
427 {
428  if ( !context )
429  return QVariant();
430 
431  QString expString = getStringValue( values.at( 0 ), parent );
432  QgsExpression expression( expString );
433  return expression.evaluate( context );
434 }
435 
436 static QVariant fcnSqrt( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
437 {
438  double x = getDoubleValue( values.at( 0 ), parent );
439  return QVariant( sqrt( x ) );
440 }
441 
442 static QVariant fcnAbs( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
443 {
444  double val = getDoubleValue( values.at( 0 ), parent );
445  return QVariant( fabs( val ) );
446 }
447 
448 static QVariant fcnRadians( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
449 {
450  double deg = getDoubleValue( values.at( 0 ), parent );
451  return ( deg * M_PI ) / 180;
452 }
453 static QVariant fcnDegrees( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
454 {
455  double rad = getDoubleValue( values.at( 0 ), parent );
456  return ( 180 * rad ) / M_PI;
457 }
458 static QVariant fcnSin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
459 {
460  double x = getDoubleValue( values.at( 0 ), parent );
461  return QVariant( sin( x ) );
462 }
463 static QVariant fcnCos( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
464 {
465  double x = getDoubleValue( values.at( 0 ), parent );
466  return QVariant( cos( x ) );
467 }
468 static QVariant fcnTan( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
469 {
470  double x = getDoubleValue( values.at( 0 ), parent );
471  return QVariant( tan( x ) );
472 }
473 static QVariant fcnAsin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
474 {
475  double x = getDoubleValue( values.at( 0 ), parent );
476  return QVariant( asin( x ) );
477 }
478 static QVariant fcnAcos( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
479 {
480  double x = getDoubleValue( values.at( 0 ), parent );
481  return QVariant( acos( x ) );
482 }
483 static QVariant fcnAtan( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
484 {
485  double x = getDoubleValue( values.at( 0 ), parent );
486  return QVariant( atan( x ) );
487 }
488 static QVariant fcnAtan2( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
489 {
490  double y = getDoubleValue( values.at( 0 ), parent );
491  double x = getDoubleValue( values.at( 1 ), parent );
492  return QVariant( atan2( y, x ) );
493 }
494 static QVariant fcnExp( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
495 {
496  double x = getDoubleValue( values.at( 0 ), parent );
497  return QVariant( exp( x ) );
498 }
499 static QVariant fcnLn( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
500 {
501  double x = getDoubleValue( values.at( 0 ), parent );
502  if ( x <= 0 )
503  return QVariant();
504  return QVariant( log( x ) );
505 }
506 static QVariant fcnLog10( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
507 {
508  double x = getDoubleValue( values.at( 0 ), parent );
509  if ( x <= 0 )
510  return QVariant();
511  return QVariant( log10( x ) );
512 }
513 static QVariant fcnLog( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
514 {
515  double b = getDoubleValue( values.at( 0 ), parent );
516  double x = getDoubleValue( values.at( 1 ), parent );
517  if ( x <= 0 || b <= 0 )
518  return QVariant();
519  return QVariant( log( x ) / log( b ) );
520 }
521 static QVariant fcnRndF( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
522 {
523  double min = getDoubleValue( values.at( 0 ), parent );
524  double max = getDoubleValue( values.at( 1 ), parent );
525  if ( max < min )
526  return QVariant();
527 
528  // Return a random double in the range [min, max] (inclusive)
529  double f = static_cast< double >( qrand() ) / RAND_MAX;
530  return QVariant( min + f * ( max - min ) );
531 }
532 static QVariant fcnRnd( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
533 {
534  int min = getIntValue( values.at( 0 ), parent );
535  int max = getIntValue( values.at( 1 ), parent );
536  if ( max < min )
537  return QVariant();
538 
539  // Return a random integer in the range [min, max] (inclusive)
540  return QVariant( min + ( qrand() % static_cast< int >( max - min + 1 ) ) );
541 }
542 
543 static QVariant fcnLinearScale( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
544 {
545  double val = getDoubleValue( values.at( 0 ), parent );
546  double domainMin = getDoubleValue( values.at( 1 ), parent );
547  double domainMax = getDoubleValue( values.at( 2 ), parent );
548  double rangeMin = getDoubleValue( values.at( 3 ), parent );
549  double rangeMax = getDoubleValue( values.at( 4 ), parent );
550 
551  if ( domainMin >= domainMax )
552  {
553  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
554  return QVariant();
555  }
556 
557  // outside of domain?
558  if ( val >= domainMax )
559  {
560  return rangeMax;
561  }
562  else if ( val <= domainMin )
563  {
564  return rangeMin;
565  }
566 
567  // calculate linear scale
568  double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
569  double c = rangeMin - ( domainMin * m );
570 
571  // Return linearly scaled value
572  return QVariant( m * val + c );
573 }
574 
575 static QVariant fcnExpScale( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
576 {
577  double val = getDoubleValue( values.at( 0 ), parent );
578  double domainMin = getDoubleValue( values.at( 1 ), parent );
579  double domainMax = getDoubleValue( values.at( 2 ), parent );
580  double rangeMin = getDoubleValue( values.at( 3 ), parent );
581  double rangeMax = getDoubleValue( values.at( 4 ), parent );
582  double exponent = getDoubleValue( values.at( 5 ), parent );
583 
584  if ( domainMin >= domainMax )
585  {
586  parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) );
587  return QVariant();
588  }
589  if ( exponent <= 0 )
590  {
591  parent->setEvalErrorString( QObject::tr( "Exponent must be greater than 0" ) );
592  return QVariant();
593  }
594 
595  // outside of domain?
596  if ( val >= domainMax )
597  {
598  return rangeMax;
599  }
600  else if ( val <= domainMin )
601  {
602  return rangeMin;
603  }
604 
605  // Return exponentially scaled value
606  return QVariant((( rangeMax - rangeMin ) / pow( domainMax - domainMin, exponent ) ) * pow( val - domainMin, exponent ) + rangeMin );
607 }
608 
609 static QVariant fcnMax( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
610 {
611  //initially set max as first value
612  double maxVal = getDoubleValue( values.at( 0 ), parent );
613 
614  //check against all other values
615  for ( int i = 1; i < values.length(); ++i )
616  {
617  double testVal = getDoubleValue( values[i], parent );
618  if ( testVal > maxVal )
619  {
620  maxVal = testVal;
621  }
622  }
623 
624  return QVariant( maxVal );
625 }
626 
627 static QVariant fcnMin( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
628 {
629  //initially set min as first value
630  double minVal = getDoubleValue( values.at( 0 ), parent );
631 
632  //check against all other values
633  for ( int i = 1; i < values.length(); ++i )
634  {
635  double testVal = getDoubleValue( values[i], parent );
636  if ( testVal < minVal )
637  {
638  minVal = testVal;
639  }
640  }
641 
642  return QVariant( minVal );
643 }
644 
645 static QVariant fcnClamp( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
646 {
647  double minValue = getDoubleValue( values.at( 0 ), parent );
648  double testValue = getDoubleValue( values.at( 1 ), parent );
649  double maxValue = getDoubleValue( values.at( 2 ), parent );
650 
651  // force testValue to sit inside the range specified by the min and max value
652  if ( testValue <= minValue )
653  {
654  return QVariant( minValue );
655  }
656  else if ( testValue >= maxValue )
657  {
658  return QVariant( maxValue );
659  }
660  else
661  {
662  return QVariant( testValue );
663  }
664 }
665 
666 static QVariant fcnFloor( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
667 {
668  double x = getDoubleValue( values.at( 0 ), parent );
669  return QVariant( floor( x ) );
670 }
671 
672 static QVariant fcnCeil( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
673 {
674  double x = getDoubleValue( values.at( 0 ), parent );
675  return QVariant( ceil( x ) );
676 }
677 
678 static QVariant fcnToInt( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
679 {
680  return QVariant( getIntValue( values.at( 0 ), parent ) );
681 }
682 static QVariant fcnToReal( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
683 {
684  return QVariant( getDoubleValue( values.at( 0 ), parent ) );
685 }
686 static QVariant fcnToString( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
687 {
688  return QVariant( getStringValue( values.at( 0 ), parent ) );
689 }
690 
691 static QVariant fcnToDateTime( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
692 {
693  return QVariant( getDateTimeValue( values.at( 0 ), parent ) );
694 }
695 
696 static QVariant fcnCoalesce( const QVariantList& values, const QgsExpressionContext*, QgsExpression* )
697 {
698  Q_FOREACH ( const QVariant &value, values )
699  {
700  if ( value.isNull() )
701  continue;
702  return value;
703  }
704  return QVariant();
705 }
706 static QVariant fcnLower( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
707 {
708  QString str = getStringValue( values.at( 0 ), parent );
709  return QVariant( str.toLower() );
710 }
711 static QVariant fcnUpper( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
712 {
713  QString str = getStringValue( values.at( 0 ), parent );
714  return QVariant( str.toUpper() );
715 }
716 static QVariant fcnTitle( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
717 {
718  QString str = getStringValue( values.at( 0 ), parent );
719  QStringList elems = str.split( ' ' );
720  for ( int i = 0; i < elems.size(); i++ )
721  {
722  if ( elems[i].size() > 1 )
723  elems[i] = elems[i].left( 1 ).toUpper() + elems[i].mid( 1 ).toLower();
724  }
725  return QVariant( elems.join( " " ) );
726 }
727 
728 static QVariant fcnTrim( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
729 {
730  QString str = getStringValue( values.at( 0 ), parent );
731  return QVariant( str.trimmed() );
732 }
733 
734 static QVariant fcnLevenshtein( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
735 {
736  QString string1 = getStringValue( values.at( 0 ), parent );
737  QString string2 = getStringValue( values.at( 1 ), parent );
738  return QVariant( QgsStringUtils::levenshteinDistance( string1, string2, true ) );
739 }
740 
741 static QVariant fcnLCS( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
742 {
743  QString string1 = getStringValue( values.at( 0 ), parent );
744  QString string2 = getStringValue( values.at( 1 ), parent );
745  return QVariant( QgsStringUtils::longestCommonSubstring( string1, string2, true ) );
746 }
747 
748 static QVariant fcnHamming( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
749 {
750  QString string1 = getStringValue( values.at( 0 ), parent );
751  QString string2 = getStringValue( values.at( 1 ), parent );
752  int dist = QgsStringUtils::hammingDistance( string1, string2 );
753  return ( dist < 0 ? QVariant() : QVariant( QgsStringUtils::hammingDistance( string1, string2, true ) ) );
754 }
755 
756 static QVariant fcnSoundex( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
757 {
758  QString string = getStringValue( values.at( 0 ), parent );
759  return QVariant( QgsStringUtils::soundex( string ) );
760 }
761 
762 static QVariant fcnWordwrap( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
763 {
764  if ( values.length() == 2 || values.length() == 3 )
765  {
766  QString str = getStringValue( values.at( 0 ), parent );
767  int wrap = getIntValue( values.at( 1 ), parent );
768 
769  if ( !str.isEmpty() && wrap != 0 )
770  {
771  QString newstr;
772  QString delimiterstr;
773  if ( values.length() == 3 ) delimiterstr = getStringValue( values.at( 2 ), parent );
774  if ( delimiterstr.isEmpty() ) delimiterstr = ' ';
775  int delimiterlength = delimiterstr.length();
776 
777  QStringList lines = str.split( '\n' );
778  int strlength, strcurrent, strhit, lasthit;
779 
780  for ( int i = 0; i < lines.size(); i++ )
781  {
782  strlength = lines[i].length();
783  strcurrent = 0;
784  strhit = 0;
785  lasthit = 0;
786 
787  while ( strcurrent < strlength )
788  {
789  // positive wrap value = desired maximum line width to wrap
790  // negative wrap value = desired minimum line width before wrap
791  if ( wrap > 0 )
792  {
793  //first try to locate delimiter backwards
794  strhit = lines[i].lastIndexOf( delimiterstr, strcurrent + wrap );
795  if ( strhit == lasthit || strhit == -1 )
796  {
797  //if no new backward delimiter found, try to locate forward
798  strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
799  }
800  lasthit = strhit;
801  }
802  else
803  {
804  strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
805  }
806  if ( strhit > -1 )
807  {
808  newstr.append( lines[i].midRef( strcurrent, strhit - strcurrent ) );
809  newstr.append( '\n' );
810  strcurrent = strhit + delimiterlength;
811  }
812  else
813  {
814  newstr.append( lines[i].midRef( strcurrent ) );
815  strcurrent = strlength;
816  }
817  }
818  if ( i < lines.size() - 1 ) newstr.append( '\n' );
819  }
820 
821  return QVariant( newstr );
822  }
823  }
824 
825  return QVariant();
826 }
827 
828 static QVariant fcnLength( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
829 {
830  // two variants, one for geometry, one for string
831  if ( values.at( 0 ).canConvert<QgsGeometry>() )
832  {
833  //geometry variant
834  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
835  if ( geom.type() != QGis::Line )
836  return QVariant();
837 
838  return QVariant( geom.length() );
839  }
840 
841  //otherwise fall back to string variant
842  QString str = getStringValue( values.at( 0 ), parent );
843  return QVariant( str.length() );
844 }
845 
846 static QVariant fcnReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
847 {
848  QString str = getStringValue( values.at( 0 ), parent );
849  QString before = getStringValue( values.at( 1 ), parent );
850  QString after = getStringValue( values.at( 2 ), parent );
851  return QVariant( str.replace( before, after ) );
852 }
853 static QVariant fcnRegexpReplace( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
854 {
855  QString str = getStringValue( values.at( 0 ), parent );
856  QString regexp = getStringValue( values.at( 1 ), parent );
857  QString after = getStringValue( values.at( 2 ), parent );
858 
859  QRegExp re( regexp );
860  if ( !re.isValid() )
861  {
862  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
863  return QVariant();
864  }
865  return QVariant( str.replace( re, after ) );
866 }
867 
868 static QVariant fcnRegexpMatch( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
869 {
870  QString str = getStringValue( values.at( 0 ), parent );
871  QString regexp = getStringValue( values.at( 1 ), parent );
872 
873  QRegExp re( regexp );
874  if ( !re.isValid() )
875  {
876  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
877  return QVariant();
878  }
879  return QVariant( str.contains( re ) ? 1 : 0 );
880 }
881 
882 static QVariant fcnRegexpSubstr( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
883 {
884  QString str = getStringValue( values.at( 0 ), parent );
885  QString regexp = getStringValue( values.at( 1 ), parent );
886 
887  QRegExp re( regexp );
888  if ( !re.isValid() )
889  {
890  parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
891  return QVariant();
892  }
893 
894  // extract substring
895  ( void )re.indexIn( str );
896  if ( re.captureCount() > 0 )
897  {
898  // return first capture
899  return QVariant( re.capturedTexts().at( 1 ) );
900  }
901  else
902  {
903  return QVariant( "" );
904  }
905 }
906 
907 static QVariant fcnUuid( const QVariantList&, const QgsExpressionContext*, QgsExpression* )
908 {
909  return QUuid::createUuid().toString();
910 }
911 
912 static QVariant fcnSubstr( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
913 {
914  QString str = getStringValue( values.at( 0 ), parent );
915  int from = getIntValue( values.at( 1 ), parent );
916  int len = getIntValue( values.at( 2 ), parent );
917  return QVariant( str.mid( from -1, len ) );
918 }
919 
920 static QVariant fcnRowNumber( const QVariantList&, const QgsExpressionContext* context, QgsExpression* parent )
921 {
922  if ( context && context->hasVariable( "row_number" ) )
923  return context->variable( "row_number" );
924 
926  return QVariant( parent->currentRowNumber() );
928  //when above is removed - return QVariant()
929 }
930 
931 static QVariant fcnMapId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
932 {
933  if ( context && context->hasVariable( "map_id" ) )
934  return context->variable( "map_id" );
935 
937  return QgsExpression::specialColumn( "$map" );
939 }
940 
941 static QVariant fcnComposerNumPages( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
942 {
943  if ( context && context->hasVariable( "layout_numpages" ) )
944  return context->variable( "layout_numpages" );
945 
947  return QgsExpression::specialColumn( "$numpages" );
949 }
950 
951 static QVariant fcnComposerPage( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
952 {
953  if ( context && context->hasVariable( "layout_page" ) )
954  return context->variable( "layout_page" );
955 
957  return QgsExpression::specialColumn( "$page" );
959 }
960 
961 static QVariant fcnAtlasFeature( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
962 {
963  if ( context && context->hasVariable( "atlas_featurenumber" ) )
964  return context->variable( "atlas_featurenumber" );
965 
967  return QgsExpression::specialColumn( "$feature" );
969 }
970 
971 static QVariant fcnAtlasFeatureId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
972 {
973  if ( context && context->hasVariable( "atlas_featureid" ) )
974  return context->variable( "atlas_featureid" );
975 
977  return QgsExpression::specialColumn( "$atlasfeatureid" );
979 }
980 
981 
982 static QVariant fcnAtlasCurrentFeature( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
983 {
984  if ( context && context->hasVariable( "atlas_feature" ) )
985  return context->variable( "atlas_feature" );
986 
988  return QgsExpression::specialColumn( "$atlasfeature" );
990 }
991 
992 static QVariant fcnAtlasCurrentGeometry( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
993 {
994  if ( context && context->hasVariable( "atlas_geometry" ) )
995  return context->variable( "atlas_geometry" );
996 
998  return QgsExpression::specialColumn( "$atlasgeometry" );
1000 }
1001 
1002 static QVariant fcnAtlasNumFeatures( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1003 {
1004  if ( context && context->hasVariable( "atlas_totalfeatures" ) )
1005  return context->variable( "atlas_totalfeatures" );
1006 
1008  return QgsExpression::specialColumn( "$numfeatures" );
1010 }
1011 
1012 #define FEAT_FROM_CONTEXT(c, f) if (!c || !c->hasVariable(QgsExpressionContext::EXPR_FEATURE)) return QVariant(); \
1013  QgsFeature f = qvariant_cast<QgsFeature>( c->variable( QgsExpressionContext::EXPR_FEATURE ) );
1014 
1015 static QVariant fcnFeatureId( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1016 {
1017  FEAT_FROM_CONTEXT( context, f );
1018  // TODO: handling of 64-bit feature ids?
1019  return QVariant( static_cast< int >( f.id() ) );
1020 }
1021 
1022 static QVariant fcnFeature( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1023 {
1024  if ( !context )
1025  return QVariant();
1026 
1027  return context->variable( QgsExpressionContext::EXPR_FEATURE );
1028 }
1029 static QVariant fcnAttribute( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1030 {
1031  QgsFeature feat = getFeature( values.at( 0 ), parent );
1032  QString attr = getStringValue( values.at( 1 ), parent );
1033 
1034  return feat.attribute( attr );
1035 }
1036 static QVariant fcnConcat( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1037 {
1038  QString concat;
1039  Q_FOREACH ( const QVariant &value, values )
1040  {
1041  concat += getStringValue( value, parent );
1042  }
1043  return concat;
1044 }
1045 
1046 static QVariant fcnStrpos( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1047 {
1048  QString string = getStringValue( values.at( 0 ), parent );
1049  return string.indexOf( QRegExp( getStringValue( values.at( 1 ), parent ) ) ) + 1;
1050 }
1051 
1052 static QVariant fcnRight( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1053 {
1054  QString string = getStringValue( values.at( 0 ), parent );
1055  int pos = getIntValue( values.at( 1 ), parent );
1056  return string.right( pos );
1057 }
1058 
1059 static QVariant fcnLeft( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1060 {
1061  QString string = getStringValue( values.at( 0 ), parent );
1062  int pos = getIntValue( values.at( 1 ), parent );
1063  return string.left( pos );
1064 }
1065 
1066 static QVariant fcnRPad( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1067 {
1068  QString string = getStringValue( values.at( 0 ), parent );
1069  int length = getIntValue( values.at( 1 ), parent );
1070  QString fill = getStringValue( values.at( 2 ), parent );
1071  return string.leftJustified( length, fill.at( 0 ), true );
1072 }
1073 
1074 static QVariant fcnLPad( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1075 {
1076  QString string = getStringValue( values.at( 0 ), parent );
1077  int length = getIntValue( values.at( 1 ), parent );
1078  QString fill = getStringValue( values.at( 2 ), parent );
1079  return string.rightJustified( length, fill.at( 0 ), true );
1080 }
1081 
1082 static QVariant fcnFormatString( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1083 {
1084  QString string = getStringValue( values.at( 0 ), parent );
1085  for ( int n = 1; n < values.length(); n++ )
1086  {
1087  string = string.arg( getStringValue( values.at( n ), parent ) );
1088  }
1089  return string;
1090 }
1091 
1092 
1093 static QVariant fcnNow( const QVariantList&, const QgsExpressionContext*, QgsExpression * )
1094 {
1096 }
1097 
1098 static QVariant fcnToDate( const QVariantList& values, const QgsExpressionContext*, QgsExpression * parent )
1099 {
1100  return QVariant( getDateValue( values.at( 0 ), parent ) );
1101 }
1102 
1103 static QVariant fcnToTime( const QVariantList& values, const QgsExpressionContext*, QgsExpression * parent )
1104 {
1105  return QVariant( getTimeValue( values.at( 0 ), parent ) );
1106 }
1107 
1108 static QVariant fcnToInterval( const QVariantList& values, const QgsExpressionContext*, QgsExpression * parent )
1109 {
1110  return QVariant::fromValue( getInterval( values.at( 0 ), parent ) );
1111 }
1112 
1113 static QVariant fcnAge( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1114 {
1115  QDateTime d1 = getDateTimeValue( values.at( 0 ), parent );
1116  QDateTime d2 = getDateTimeValue( values.at( 1 ), parent );
1117  int seconds = d2.secsTo( d1 );
1118  return QVariant::fromValue( QgsExpression::Interval( seconds ) );
1119 }
1120 
1121 static QVariant fcnDayOfWeek( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1122 {
1123  if ( !values.at( 0 ).canConvert<QDate>() )
1124  return QVariant();
1125 
1126  QDate date = getDateValue( values.at( 0 ), parent );
1127  if ( !date.isValid() )
1128  return QVariant();
1129 
1130  // return dayOfWeek() % 7 so that values range from 0 (sun) to 6 (sat)
1131  // (to match PostgreSQL behaviour)
1132  return date.dayOfWeek() % 7;
1133 }
1134 
1135 static QVariant fcnDay( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1136 {
1137  QVariant value = values.at( 0 );
1138  QgsExpression::Interval inter = getInterval( value, parent, false );
1139  if ( inter.isValid() )
1140  {
1141  return QVariant( inter.days() );
1142  }
1143  else
1144  {
1145  QDateTime d1 = getDateTimeValue( value, parent );
1146  return QVariant( d1.date().day() );
1147  }
1148 }
1149 
1150 static QVariant fcnYear( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1151 {
1152  QVariant value = values.at( 0 );
1153  QgsExpression::Interval inter = getInterval( value, parent, false );
1154  if ( inter.isValid() )
1155  {
1156  return QVariant( inter.years() );
1157  }
1158  else
1159  {
1160  QDateTime d1 = getDateTimeValue( value, parent );
1161  return QVariant( d1.date().year() );
1162  }
1163 }
1164 
1165 static QVariant fcnMonth( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1166 {
1167  QVariant value = values.at( 0 );
1168  QgsExpression::Interval inter = getInterval( value, parent, false );
1169  if ( inter.isValid() )
1170  {
1171  return QVariant( inter.months() );
1172  }
1173  else
1174  {
1175  QDateTime d1 = getDateTimeValue( value, parent );
1176  return QVariant( d1.date().month() );
1177  }
1178 }
1179 
1180 static QVariant fcnWeek( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1181 {
1182  QVariant value = values.at( 0 );
1183  QgsExpression::Interval inter = getInterval( value, parent, false );
1184  if ( inter.isValid() )
1185  {
1186  return QVariant( inter.weeks() );
1187  }
1188  else
1189  {
1190  QDateTime d1 = getDateTimeValue( value, parent );
1191  return QVariant( d1.date().weekNumber() );
1192  }
1193 }
1194 
1195 static QVariant fcnHour( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1196 {
1197  QVariant value = values.at( 0 );
1198  QgsExpression::Interval inter = getInterval( value, parent, false );
1199  if ( inter.isValid() )
1200  {
1201  return QVariant( inter.hours() );
1202  }
1203  else
1204  {
1205  QTime t1 = getTimeValue( value, parent );
1206  return QVariant( t1.hour() );
1207  }
1208 }
1209 
1210 static QVariant fcnMinute( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1211 {
1212  QVariant value = values.at( 0 );
1213  QgsExpression::Interval inter = getInterval( value, parent, false );
1214  if ( inter.isValid() )
1215  {
1216  return QVariant( inter.minutes() );
1217  }
1218  else
1219  {
1220  QTime t1 = getTimeValue( value, parent );
1221  return QVariant( t1.minute() );
1222  }
1223 }
1224 
1225 static QVariant fcnSeconds( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
1226 {
1227  QVariant value = values.at( 0 );
1228  QgsExpression::Interval inter = getInterval( value, parent, false );
1229  if ( inter.isValid() )
1230  {
1231  return QVariant( inter.seconds() );
1232  }
1233  else
1234  {
1235  QTime t1 = getTimeValue( value, parent );
1236  return QVariant( t1.second() );
1237  }
1238 }
1239 
1240 
1241 #define ENSURE_GEOM_TYPE(f, g, geomtype) const QgsGeometry* g = f.constGeometry(); \
1242  if (!g || g->type() != geomtype) return QVariant();
1243 
1244 static QVariant fcnX( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1245 {
1246  FEAT_FROM_CONTEXT( context, f );
1247  ENSURE_GEOM_TYPE( f, g, QGis::Point );
1248  if ( g->isMultipart() )
1249  {
1250  return g->asMultiPoint().at( 0 ).x();
1251  }
1252  else
1253  {
1254  return g->asPoint().x();
1255  }
1256 }
1257 
1258 static QVariant fcnY( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1259 {
1260  FEAT_FROM_CONTEXT( context, f );
1261  ENSURE_GEOM_TYPE( f, g, QGis::Point );
1262  if ( g->isMultipart() )
1263  {
1264  return g->asMultiPoint().at( 0 ).y();
1265  }
1266  else
1267  {
1268  return g->asPoint().y();
1269  }
1270 }
1271 
1272 static QVariant fcnGeomX( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1273 {
1274  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1275  if ( geom.isEmpty() )
1276  return QVariant();
1277 
1278  //if single point, return the point's x coordinate
1279  if ( geom.type() == QGis::Point && !geom.isMultipart() )
1280  {
1281  return geom.asPoint().x();
1282  }
1283 
1284  //otherwise return centroid x
1285  QgsGeometry* centroid = geom.centroid();
1286  QVariant result( centroid->asPoint().x() );
1287  delete centroid;
1288  return result;
1289 }
1290 
1291 static QVariant fcnGeomY( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1292 {
1293  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1294  if ( geom.isEmpty() )
1295  return QVariant();
1296 
1297  //if single point, return the point's y coordinate
1298  if ( geom.type() == QGis::Point && !geom.isMultipart() )
1299  {
1300  return geom.asPoint().y();
1301  }
1302 
1303  //otherwise return centroid y
1304  QgsGeometry* centroid = geom.centroid();
1305  QVariant result( centroid->asPoint().y() );
1306  delete centroid;
1307  return result;
1308 }
1309 
1310 static QVariant fcnGeomZ( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1311 {
1312  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1313  if ( geom.isEmpty() )
1314  return QVariant(); //or 0?
1315 
1316  //if single point, return the point's z coordinate
1317  if ( geom.type() == QGis::Point && !geom.isMultipart() )
1318  {
1319  QgsPointV2* point = dynamic_cast< QgsPointV2* >( geom.geometry() );
1320  if ( point )
1321  return point->z();
1322  }
1323 
1324  return QVariant();
1325 }
1326 
1327 static QVariant fcnGeomM( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1328 {
1329  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1330  if ( geom.isEmpty() )
1331  return QVariant(); //or 0?
1332 
1333  //if single point, return the point's m value
1334  if ( geom.type() == QGis::Point && !geom.isMultipart() )
1335  {
1336  QgsPointV2* point = dynamic_cast< QgsPointV2* >( geom.geometry() );
1337  if ( point )
1338  return point->m();
1339  }
1340 
1341  return QVariant();
1342 }
1343 
1344 static QVariant fcnPointN( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1345 {
1346  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1347 
1348  if ( geom.isEmpty() )
1349  return QVariant();
1350 
1351  //idx is 1 based
1352  int idx = getIntValue( values.at( 1 ), parent ) - 1;
1353 
1354  QgsVertexId vId;
1355  if ( idx < 0 || !geom.vertexIdFromVertexNr( idx, vId ) )
1356  {
1357  parent->setEvalErrorString( QObject::tr( "Point index is out of range" ) );
1358  return QVariant();
1359  }
1360 
1361  QgsPointV2 point = geom.geometry()->vertexAt( vId );
1362  return QVariant::fromValue( QgsGeometry( new QgsPointV2( point ) ) );
1363 }
1364 
1365 static QVariant fcnStartPoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1366 {
1367  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1368 
1369  if ( geom.isEmpty() )
1370  return QVariant();
1371 
1372  QgsVertexId vId;
1373  if ( !geom.vertexIdFromVertexNr( 0, vId ) )
1374  {
1375  return QVariant();
1376  }
1377 
1378  QgsPointV2 point = geom.geometry()->vertexAt( vId );
1379  return QVariant::fromValue( QgsGeometry( new QgsPointV2( point ) ) );
1380 }
1381 
1382 static QVariant fcnEndPoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1383 {
1384  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1385 
1386  if ( geom.isEmpty() )
1387  return QVariant();
1388 
1389  QgsVertexId vId;
1390  if ( !geom.vertexIdFromVertexNr( geom.geometry()->nCoordinates() - 1, vId ) )
1391  {
1392  return QVariant();
1393  }
1394 
1395  QgsPointV2 point = geom.geometry()->vertexAt( vId );
1396  return QVariant::fromValue( QgsGeometry( new QgsPointV2( point ) ) );
1397 }
1398 
1399 static QVariant fcnNodesToPoints( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1400 {
1401  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1402 
1403  if ( geom.isEmpty() )
1404  return QVariant();
1405 
1406  bool ignoreClosing = false;
1407  if ( values.length() > 1 )
1408  {
1409  ignoreClosing = getIntValue( values.at( 1 ), parent );
1410  }
1411 
1412  QgsMultiPointV2* mp = new QgsMultiPointV2();
1413 
1415  geom.geometry()->coordinateSequence( coords );
1416 
1417  Q_FOREACH ( const QList< QList< QgsPointV2 > >& part, coords )
1418  {
1419  Q_FOREACH ( const QList< QgsPointV2 >& ring, part )
1420  {
1421  bool skipLast = false;
1422  if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
1423  {
1424  skipLast = true;
1425  }
1426 
1427  for ( int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
1428  {
1429  mp->addGeometry( ring.at( i ).clone() );
1430  }
1431  }
1432  }
1433 
1434  return QVariant::fromValue( QgsGeometry( mp ) );
1435 }
1436 
1437 static QVariant fcnSegmentsToLines( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1438 {
1439  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1440 
1441  if ( geom.isEmpty() )
1442  return QVariant();
1443 
1445 
1446  //ok, now we have a complete list of segmentized lines from the geometry
1448  Q_FOREACH ( QgsLineStringV2* line, linesToProcess )
1449  {
1450  for ( int i = 0; i < line->numPoints() - 1; ++i )
1451  {
1452  QgsLineStringV2* segment = new QgsLineStringV2();
1453  segment->setPoints( QList<QgsPointV2>()
1454  << line->pointN( i )
1455  << line->pointN( i + 1 ) );
1456  ml->addGeometry( segment );
1457  }
1458  delete line;
1459  }
1460 
1461  return QVariant::fromValue( QgsGeometry( ml ) );
1462 }
1463 
1464 static QVariant fcnInteriorRingN( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1465 {
1466  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1467 
1468  if ( geom.isEmpty() )
1469  return QVariant();
1470 
1471  QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() );
1472  if ( !curvePolygon )
1473  return QVariant();
1474 
1475  //idx is 1 based
1476  int idx = getIntValue( values.at( 1 ), parent ) - 1;
1477 
1478  if ( idx >= curvePolygon->numInteriorRings() || idx < 0 )
1479  return QVariant();
1480 
1481  QgsCurveV2* curve = static_cast< QgsCurveV2* >( curvePolygon->interiorRing( idx )->clone() );
1482  QVariant result = curve ? QVariant::fromValue( QgsGeometry( curve ) ) : QVariant();
1483  return result;
1484 }
1485 
1486 static QVariant fcnGeometryN( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1487 {
1488  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1489 
1490  if ( geom.isEmpty() )
1491  return QVariant();
1492 
1493  QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() );
1494  if ( !collection )
1495  return QVariant();
1496 
1497  //idx is 1 based
1498  int idx = getIntValue( values.at( 1 ), parent ) - 1;
1499 
1500  if ( idx < 0 || idx >= collection->numGeometries() )
1501  return QVariant();
1502 
1503  QgsAbstractGeometryV2* part = collection->geometryN( idx )->clone();
1504  QVariant result = part ? QVariant::fromValue( QgsGeometry( part ) ) : QVariant();
1505  return result;
1506 }
1507 
1508 static QVariant fcnMakePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1509 {
1510  if ( values.count() < 2 || values.count() > 4 )
1511  {
1512  parent->setEvalErrorString( QObject::tr( "Function make_point requires 2-4 arguments" ) );
1513  return QVariant();
1514  }
1515 
1516  double x = getDoubleValue( values.at( 0 ), parent );
1517  double y = getDoubleValue( values.at( 1 ), parent );
1518  double z = values.count() >= 3 ? getDoubleValue( values.at( 2 ), parent ) : 0.0;
1519  double m = values.count() >= 4 ? getDoubleValue( values.at( 3 ), parent ) : 0.0;
1520  switch ( values.count() )
1521  {
1522  case 2:
1523  return QVariant::fromValue( QgsGeometry( new QgsPointV2( x, y ) ) );
1524  case 3:
1525  return QVariant::fromValue( QgsGeometry( new QgsPointV2( QgsWKBTypes::PointZ, x, y, z ) ) );
1526  case 4:
1527  return QVariant::fromValue( QgsGeometry( new QgsPointV2( QgsWKBTypes::PointZM, x, y, z, m ) ) );
1528  }
1529  return QVariant(); //avoid warning
1530 }
1531 
1532 static QVariant fcnMakePointM( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1533 {
1534  double x = getDoubleValue( values.at( 0 ), parent );
1535  double y = getDoubleValue( values.at( 1 ), parent );
1536  double m = getDoubleValue( values.at( 2 ), parent );
1537  return QVariant::fromValue( QgsGeometry( new QgsPointV2( QgsWKBTypes::PointM, x, y, 0.0, m ) ) );
1538 }
1539 
1540 static QVariant fcnMakeLine( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1541 {
1542  if ( values.count() < 2 )
1543  {
1544  return QVariant();
1545  }
1546 
1547  QgsLineStringV2* lineString = new QgsLineStringV2();
1548  lineString->clear();
1549 
1550  Q_FOREACH ( const QVariant& value, values )
1551  {
1552  QgsGeometry geom = getGeometry( value, parent );
1553  if ( geom.isEmpty() )
1554  continue;
1555 
1556  if ( geom.type() != QGis::Point || geom.isMultipart() )
1557  continue;
1558 
1559  QgsPointV2* point = dynamic_cast< QgsPointV2* >( geom.geometry() );
1560  if ( !point )
1561  continue;
1562 
1563  lineString->addVertex( *point );
1564  }
1565 
1566  return QVariant::fromValue( QgsGeometry( lineString ) );
1567 }
1568 
1569 static QVariant fcnMakePolygon( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1570 {
1571  if ( values.count() < 1 )
1572  {
1573  parent->setEvalErrorString( QObject::tr( "Function make_polygon requires an argument" ) );
1574  return QVariant();
1575  }
1576 
1577  QgsGeometry outerRing = getGeometry( values.at( 0 ), parent );
1578  if ( outerRing.type() != QGis::Line || outerRing.isMultipart() || outerRing.isEmpty() )
1579  return QVariant();
1580 
1581  QgsPolygonV2* polygon = new QgsPolygonV2();
1582  polygon->setExteriorRing( dynamic_cast< QgsCurveV2* >( outerRing.geometry()->clone() ) );
1583 
1584  for ( int i = 1; i < values.count(); ++i )
1585  {
1586  QgsGeometry ringGeom = getGeometry( values.at( i ), parent );
1587  if ( ringGeom.isEmpty() )
1588  continue;
1589 
1590  if ( ringGeom.type() != QGis::Line || ringGeom.isMultipart() || ringGeom.isEmpty() )
1591  continue;
1592 
1593  polygon->addInteriorRing( dynamic_cast< QgsCurveV2* >( ringGeom.geometry()->clone() ) );
1594  }
1595 
1596  return QVariant::fromValue( QgsGeometry( polygon ) );
1597 }
1598 
1599 static QVariant pointAt( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) // helper function
1600 {
1601  FEAT_FROM_CONTEXT( context, f );
1602  int idx = getIntValue( values.at( 0 ), parent );
1603  ENSURE_GEOM_TYPE( f, g, QGis::Line );
1604  QgsPolyline polyline = g->asPolyline();
1605  if ( idx < 0 )
1606  idx += polyline.count();
1607 
1608  if ( idx < 0 || idx >= polyline.count() )
1609  {
1610  parent->setEvalErrorString( QObject::tr( "Index is out of range" ) );
1611  return QVariant();
1612  }
1613  return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) );
1614 }
1615 
1616 static QVariant fcnXat( const QVariantList& values, const QgsExpressionContext* f, QgsExpression* parent )
1617 {
1618  QVariant v = pointAt( values, f, parent );
1619  if ( v.type() == QVariant::PointF )
1620  return QVariant( v.toPointF().x() );
1621  else
1622  return QVariant();
1623 }
1624 static QVariant fcnYat( const QVariantList& values, const QgsExpressionContext* f, QgsExpression* parent )
1625 {
1626  QVariant v = pointAt( values, f, parent );
1627  if ( v.type() == QVariant::PointF )
1628  return QVariant( v.toPointF().y() );
1629  else
1630  return QVariant();
1631 }
1632 static QVariant fcnGeometry( const QVariantList&, const QgsExpressionContext* context, QgsExpression* )
1633 {
1634  FEAT_FROM_CONTEXT( context, f );
1635  const QgsGeometry* geom = f.constGeometry();
1636  if ( geom )
1637  return QVariant::fromValue( *geom );
1638  else
1639  return QVariant();
1640 }
1641 static QVariant fcnGeomFromWKT( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1642 {
1643  QString wkt = getStringValue( values.at( 0 ), parent );
1644  QgsGeometry* geom = QgsGeometry::fromWkt( wkt );
1645  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1646  delete geom;
1647  return result;
1648 }
1649 static QVariant fcnGeomFromGML( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1650 {
1651  QString gml = getStringValue( values.at( 0 ), parent );
1653  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1654  delete geom;
1655  return result;
1656 }
1657 
1658 static QVariant fcnGeomArea( const QVariantList&, const QgsExpressionContext* context, QgsExpression* parent )
1659 {
1660  FEAT_FROM_CONTEXT( context, f );
1662  QgsDistanceArea* calc = parent->geomCalculator();
1663  if ( calc )
1664  {
1665  return QVariant( calc->measureArea( f.constGeometry() ) );
1666  }
1667  else
1668  {
1669  return QVariant( f.constGeometry()->area() );
1670  }
1671 }
1672 
1673 static QVariant fcnArea( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1674 {
1675  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1676 
1677  if ( geom.type() != QGis::Polygon )
1678  return QVariant();
1679 
1680  return QVariant( geom.area() );
1681 }
1682 
1683 static QVariant fcnGeomLength( const QVariantList&, const QgsExpressionContext* context, QgsExpression* parent )
1684 {
1685  FEAT_FROM_CONTEXT( context, f );
1686  ENSURE_GEOM_TYPE( f, g, QGis::Line );
1687  QgsDistanceArea* calc = parent->geomCalculator();
1688  if ( calc )
1689  {
1690  double len = calc->measureLength( f.constGeometry() );
1691  len = calc->convertLengthMeasurement( len, parent->distanceUnits() );
1692  return QVariant( len );
1693  }
1694  else
1695  {
1696  return QVariant( f.constGeometry()->length() );
1697  }
1698 }
1699 
1700 static QVariant fcnGeomPerimeter( const QVariantList&, const QgsExpressionContext* context, QgsExpression* parent )
1701 {
1702  FEAT_FROM_CONTEXT( context, f );
1704  QgsDistanceArea* calc = parent->geomCalculator();
1705  if ( calc )
1706  {
1707  double len = calc->measurePerimeter( f.constGeometry() );
1708  len = calc->convertLengthMeasurement( len, parent->distanceUnits() );
1709  return QVariant( len );
1710  }
1711  else
1712  {
1713  return f.constGeometry()->isEmpty() ? QVariant( 0 ) : QVariant( f.constGeometry()->geometry()->perimeter() );
1714  }
1715 }
1716 
1717 static QVariant fcnPerimeter( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1718 {
1719  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1720 
1721  if ( geom.type() != QGis::Polygon )
1722  return QVariant();
1723 
1724  //length for polygons = perimeter
1725  return QVariant( geom.length() );
1726 }
1727 
1728 static QVariant fcnGeomNumPoints( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1729 {
1730  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1731  return QVariant( geom.isEmpty() ? 0 : geom.geometry()->nCoordinates() );
1732 }
1733 
1734 static QVariant fcnGeomNumGeometries( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1735 {
1736  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1737  if ( geom.isEmpty() )
1738  return QVariant();
1739 
1740  return QVariant( geom.geometry()->partCount() );
1741 }
1742 
1743 static QVariant fcnGeomNumInteriorRings( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1744 {
1745  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1746 
1747  if ( geom.isEmpty() )
1748  return QVariant();
1749 
1750  QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() );
1751  if ( curvePolygon )
1752  return QVariant( curvePolygon->numInteriorRings() );
1753 
1754  QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() );
1755  if ( collection )
1756  {
1757  //find first CurvePolygon in collection
1758  for ( int i = 0; i < collection->numGeometries(); ++i )
1759  {
1760  curvePolygon = dynamic_cast< QgsCurvePolygonV2*>( collection->geometryN( i ) );
1761  if ( !curvePolygon )
1762  continue;
1763 
1764  return QVariant( curvePolygon->isEmpty() ? 0 : curvePolygon->numInteriorRings() );
1765  }
1766  }
1767 
1768  return QVariant();
1769 }
1770 
1771 static QVariant fcnGeomNumRings( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1772 {
1773  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1774 
1775  if ( geom.isEmpty() )
1776  return QVariant();
1777 
1778  QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( geom.geometry() );
1779  if ( curvePolygon )
1780  return QVariant( curvePolygon->ringCount() );
1781 
1782  bool foundPoly = false;
1783  int ringCount = 0;
1784  QgsGeometryCollectionV2* collection = dynamic_cast< QgsGeometryCollectionV2* >( geom.geometry() );
1785  if ( collection )
1786  {
1787  //find CurvePolygons in collection
1788  for ( int i = 0; i < collection->numGeometries(); ++i )
1789  {
1790  curvePolygon = dynamic_cast< QgsCurvePolygonV2*>( collection->geometryN( i ) );
1791  if ( !curvePolygon )
1792  continue;
1793 
1794  foundPoly = true;
1795  ringCount += curvePolygon->ringCount();
1796  }
1797  }
1798 
1799  if ( !foundPoly )
1800  return QVariant();
1801 
1802  return QVariant( ringCount );
1803 }
1804 
1805 static QVariant fcnBounds( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1806 {
1807  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1808  QgsGeometry* geomBounds = QgsGeometry::fromRect( geom.boundingBox() );
1809  QVariant result = geomBounds ? QVariant::fromValue( *geomBounds ) : QVariant();
1810  delete geomBounds;
1811  return result;
1812 }
1813 
1814 static QVariant fcnBoundsWidth( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1815 {
1816  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1817  return QVariant::fromValue( geom.boundingBox().width() );
1818 }
1819 
1820 static QVariant fcnBoundsHeight( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1821 {
1822  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1823  return QVariant::fromValue( geom.boundingBox().height() );
1824 }
1825 
1826 static QVariant fcnXMin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1827 {
1828  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1829  return QVariant::fromValue( geom.boundingBox().xMinimum() );
1830 }
1831 
1832 static QVariant fcnXMax( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1833 {
1834  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1835  return QVariant::fromValue( geom.boundingBox().xMaximum() );
1836 }
1837 
1838 static QVariant fcnYMin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1839 {
1840  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1841  return QVariant::fromValue( geom.boundingBox().yMinimum() );
1842 }
1843 
1844 static QVariant fcnYMax( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1845 {
1846  QgsGeometry geom = getGeometry( values.at( 0 ), parent );
1847  return QVariant::fromValue( geom.boundingBox().yMaximum() );
1848 }
1849 
1850 static QVariant fcnIsClosed( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1851 {
1852  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1853  if ( fGeom.isEmpty() )
1854  return QVariant();
1855 
1856  QgsCurveV2* curve = dynamic_cast< QgsCurveV2* >( fGeom.geometry() );
1857  if ( !curve )
1858  return QVariant();
1859 
1860  return QVariant::fromValue( curve->isClosed() );
1861 }
1862 
1863 static QVariant fcnRelate( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1864 {
1865  if ( values.length() < 2 || values.length() > 3 )
1866  return QVariant();
1867 
1868  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1869  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1870 
1871  if ( fGeom.isEmpty() || sGeom.isEmpty() )
1872  return QVariant();
1873 
1875 
1876  if ( values.length() == 2 )
1877  {
1878  //two geometry arguments, return relation
1879  QString result = engine->relate( *sGeom.geometry() );
1880  return QVariant::fromValue( result );
1881  }
1882  else
1883  {
1884  //three arguments, test pattern
1885  QString pattern = getStringValue( values.at( 2 ), parent );
1886  bool result = engine->relatePattern( *sGeom.geometry(), pattern );
1887  return QVariant::fromValue( result );
1888  }
1889 }
1890 
1891 static QVariant fcnBbox( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1892 {
1893  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1894  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1895  return fGeom.intersects( sGeom.boundingBox() ) ? TVL_True : TVL_False;
1896 }
1897 static QVariant fcnDisjoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1898 {
1899  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1900  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1901  return fGeom.disjoint( &sGeom ) ? TVL_True : TVL_False;
1902 }
1903 static QVariant fcnIntersects( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1904 {
1905  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1906  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1907  return fGeom.intersects( &sGeom ) ? TVL_True : TVL_False;
1908 }
1909 static QVariant fcnTouches( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1910 {
1911  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1912  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1913  return fGeom.touches( &sGeom ) ? TVL_True : TVL_False;
1914 }
1915 static QVariant fcnCrosses( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1916 {
1917  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1918  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1919  return fGeom.crosses( &sGeom ) ? TVL_True : TVL_False;
1920 }
1921 static QVariant fcnContains( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1922 {
1923  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1924  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1925  return fGeom.contains( &sGeom ) ? TVL_True : TVL_False;
1926 }
1927 static QVariant fcnOverlaps( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1928 {
1929  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1930  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1931  return fGeom.overlaps( &sGeom ) ? TVL_True : TVL_False;
1932 }
1933 static QVariant fcnWithin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1934 {
1935  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1936  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1937  return fGeom.within( &sGeom ) ? TVL_True : TVL_False;
1938 }
1939 static QVariant fcnBuffer( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1940 {
1941  if ( values.length() < 2 || values.length() > 3 )
1942  return QVariant();
1943 
1944  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1945  double dist = getDoubleValue( values.at( 1 ), parent );
1946  int seg = 8;
1947  if ( values.length() == 3 )
1948  seg = getIntValue( values.at( 2 ), parent );
1949 
1950  QgsGeometry* geom = fGeom.buffer( dist, seg );
1951  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1952  delete geom;
1953  return result;
1954 }
1955 static QVariant fcnTranslate( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1956 {
1957  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1958  double dx = getDoubleValue( values.at( 1 ), parent );
1959  double dy = getDoubleValue( values.at( 2 ), parent );
1960  fGeom.translate( dx, dy );
1961  return QVariant::fromValue( fGeom );
1962 }
1963 static QVariant fcnCentroid( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1964 {
1965  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1966  QgsGeometry* geom = fGeom.centroid();
1967  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1968  delete geom;
1969  return result;
1970 }
1971 static QVariant fcnPointOnSurface( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1972 {
1973  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1974  QgsGeometry* geom = fGeom.pointOnSurface();
1975  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1976  delete geom;
1977  return result;
1978 }
1979 static QVariant fcnConvexHull( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1980 {
1981  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1982  QgsGeometry* geom = fGeom.convexHull();
1983  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1984  delete geom;
1985  return result;
1986 }
1987 static QVariant fcnDifference( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1988 {
1989  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1990  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
1991  QgsGeometry* geom = fGeom.difference( &sGeom );
1992  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
1993  delete geom;
1994  return result;
1995 }
1996 
1997 static QVariant fcnReverse( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1998 {
1999  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2000  if ( fGeom.isEmpty() )
2001  return QVariant();
2002 
2003  QgsCurveV2* curve = dynamic_cast< QgsCurveV2* >( fGeom.geometry() );
2004  if ( !curve )
2005  return QVariant();
2006 
2007  QgsCurveV2* reversed = curve->reversed();
2008  QVariant result = reversed ? QVariant::fromValue( QgsGeometry( reversed ) ) : QVariant();
2009  return result;
2010 }
2011 
2012 static QVariant fcnExteriorRing( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2013 {
2014  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2015  if ( fGeom.isEmpty() )
2016  return QVariant();
2017 
2018  QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( fGeom.geometry() );
2019  if ( !curvePolygon || !curvePolygon->exteriorRing() )
2020  return QVariant();
2021 
2022  QgsCurveV2* exterior = static_cast< QgsCurveV2* >( curvePolygon->exteriorRing()->clone() );
2023  QVariant result = exterior ? QVariant::fromValue( QgsGeometry( exterior ) ) : QVariant();
2024  return result;
2025 }
2026 
2027 static QVariant fcnDistance( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2028 {
2029  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2030  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
2031  return QVariant( fGeom.distance( sGeom ) );
2032 }
2033 static QVariant fcnIntersection( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2034 {
2035  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2036  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
2037  QgsGeometry* geom = fGeom.intersection( &sGeom );
2038  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
2039  delete geom;
2040  return result;
2041 }
2042 static QVariant fcnSymDifference( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2043 {
2044  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2045  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
2046  QgsGeometry* geom = fGeom.symDifference( &sGeom );
2047  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
2048  delete geom;
2049  return result;
2050 }
2051 static QVariant fcnCombine( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2052 {
2053  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2054  QgsGeometry sGeom = getGeometry( values.at( 1 ), parent );
2055  QgsGeometry* geom = fGeom.combine( &sGeom );
2056  QVariant result = geom ? QVariant::fromValue( *geom ) : QVariant();
2057  delete geom;
2058  return result;
2059 }
2060 static QVariant fcnGeomToWKT( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2061 {
2062  if ( values.length() < 1 || values.length() > 2 )
2063  return QVariant();
2064 
2065  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2066  int prec = 8;
2067  if ( values.length() == 2 )
2068  prec = getIntValue( values.at( 1 ), parent );
2069  QString wkt = fGeom.exportToWkt( prec );
2070  return QVariant( wkt );
2071 }
2072 
2073 static QVariant fcnAzimuth( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
2074 {
2075  if ( values.length() != 2 )
2076  {
2077  parent->setEvalErrorString( QObject::tr( "Function `azimuth` requires exactly two parameters. %1 given." ).arg( values.length() ) );
2078  return QVariant();
2079  }
2080 
2081  QgsGeometry fGeom1 = getGeometry( values.at( 0 ), parent );
2082  QgsGeometry fGeom2 = getGeometry( values.at( 1 ), parent );
2083 
2084  const QgsPointV2* pt1 = dynamic_cast<const QgsPointV2*>( fGeom1.geometry() );
2085  const QgsPointV2* pt2 = dynamic_cast<const QgsPointV2*>( fGeom2.geometry() );
2086 
2087  if ( !pt1 || !pt2 )
2088  {
2089  parent->setEvalErrorString( QObject::tr( "Function `azimuth` requires two points as arguments." ) );
2090  return QVariant();
2091  }
2092 
2093  // Code from postgis
2094  if ( pt1->x() == pt2->x() )
2095  {
2096  if ( pt1->y() < pt2->y() )
2097  return 0.0;
2098  else if ( pt1->y() > pt2->y() )
2099  return M_PI;
2100  else
2101  return 0;
2102  }
2103 
2104  if ( pt1->y() == pt2->y() )
2105  {
2106  if ( pt1->x() < pt2->x() )
2107  return M_PI / 2;
2108  else if ( pt1->x() > pt2->x() )
2109  return M_PI + ( M_PI / 2 );
2110  else
2111  return 0;
2112  }
2113 
2114  if ( pt1->x() < pt2->x() )
2115  {
2116  if ( pt1->y() < pt2->y() )
2117  {
2118  return atan( fabs( pt1->x() - pt2->x() ) / fabs( pt1->y() - pt2->y() ) );
2119  }
2120  else /* ( pt1->y() > pt2->y() ) - equality case handled above */
2121  {
2122  return atan( fabs( pt1->y() - pt2->y() ) / fabs( pt1->x() - pt2->x() ) )
2123  + ( M_PI / 2 );
2124  }
2125  }
2126 
2127  else /* ( pt1->x() > pt2->x() ) - equality case handled above */
2128  {
2129  if ( pt1->y() > pt2->y() )
2130  {
2131  return atan( fabs( pt1->x() - pt2->x() ) / fabs( pt1->y() - pt2->y() ) )
2132  + M_PI;
2133  }
2134  else /* ( pt1->y() < pt2->y() ) - equality case handled above */
2135  {
2136  return atan( fabs( pt1->y() - pt2->y() ) / fabs( pt1->x() - pt2->x() ) )
2137  + ( M_PI + ( M_PI / 2 ) );
2138  }
2139  }
2140 }
2141 
2142 static QVariant fcnExtrude( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2143 {
2144  if ( values.length() != 3 )
2145  return QVariant();
2146 
2147  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2148  double x = getDoubleValue( values.at( 1 ), parent );
2149  double y = getDoubleValue( values.at( 2 ), parent );
2150 
2151  QgsGeometry geom = fGeom.extrude( x, y );
2152 
2153  QVariant result = geom.geometry() ? QVariant::fromValue( geom ) : QVariant();
2154  return result;
2155 }
2156 
2157 static QVariant fcnOrderParts( const QVariantList& values, const QgsExpressionContext* ctx, QgsExpression* parent )
2158 {
2159  if ( values.length() < 2 )
2160  return QVariant();
2161 
2162  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2163 
2164  if ( !fGeom.isMultipart() )
2165  return values.at( 0 );
2166 
2167  QString expString = getStringValue( values.at( 1 ), parent );
2168  bool asc = values.value( 2 ).toBool();
2169 
2170  QgsExpressionContext* unconstedContext;
2171  QgsFeature f;
2172  if ( ctx )
2173  {
2174  // ExpressionSorter wants a modifiable expression context, but it will return it in the same shape after
2175  // so no reason to worry
2176  unconstedContext = const_cast<QgsExpressionContext*>( ctx );
2177  f = ctx->feature();
2178  }
2179  else
2180  {
2181  // If there's no context provided, create a fake one
2182  unconstedContext = new QgsExpressionContext();
2183  }
2184 
2185  QgsGeometryCollectionV2* collection = dynamic_cast<QgsGeometryCollectionV2*>( fGeom.geometry() );
2186  Q_ASSERT( collection ); // Should have failed the multipart check above
2187 
2189  orderBy.append( QgsFeatureRequest::OrderByClause( expString, asc ) );
2190  QgsExpressionSorter sorter( orderBy );
2191 
2192  QList<QgsFeature> partFeatures;
2193  for ( int i = 0; i < collection->partCount(); ++i )
2194  {
2195  f.setGeometry( QgsGeometry( collection->geometryN( i )->clone() ) );
2196  partFeatures << f;
2197  }
2198 
2199  sorter.sortFeatures( partFeatures, unconstedContext );
2200 
2201  QgsGeometryCollectionV2* orderedGeom = dynamic_cast<QgsGeometryCollectionV2*>( fGeom.geometry()->clone() );
2202 
2203  Q_ASSERT( orderedGeom );
2204 
2205  while ( orderedGeom->partCount() )
2206  orderedGeom->removeGeometry( 0 );
2207 
2208  Q_FOREACH ( const QgsFeature& feature, partFeatures )
2209  {
2210  orderedGeom->addGeometry( feature.constGeometry()->geometry()->clone() );
2211  }
2212 
2213  QVariant result = QVariant::fromValue( QgsGeometry( orderedGeom ) );
2214 
2215  if ( !ctx )
2216  delete unconstedContext;
2217 
2218  return result;
2219 }
2220 
2221 static QVariant fcnClosestPoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2222 {
2223  QgsGeometry fromGeom = getGeometry( values.at( 0 ), parent );
2224  QgsGeometry toGeom = getGeometry( values.at( 1 ), parent );
2225 
2226  QgsGeometry geom = fromGeom.nearestPoint( toGeom );
2227 
2228  QVariant result = !geom.isEmpty() ? QVariant::fromValue( geom ) : QVariant();
2229  return result;
2230 }
2231 
2232 static QVariant fcnShortestLine( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2233 {
2234  QgsGeometry fromGeom = getGeometry( values.at( 0 ), parent );
2235  QgsGeometry toGeom = getGeometry( values.at( 1 ), parent );
2236 
2237  QgsGeometry geom = fromGeom.shortestLine( toGeom );
2238 
2239  QVariant result = !geom.isEmpty() ? QVariant::fromValue( geom ) : QVariant();
2240  return result;
2241 }
2242 
2243 static QVariant fcnRound( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
2244 {
2245  if ( values.length() == 2 )
2246  {
2247  double number = getDoubleValue( values.at( 0 ), parent );
2248  double scaler = pow( 10.0, getIntValue( values.at( 1 ), parent ) );
2249  return QVariant( qRound( number * scaler ) / scaler );
2250  }
2251 
2252  if ( values.length() == 1 )
2253  {
2254  double number = getIntValue( values.at( 0 ), parent );
2255  return QVariant( qRound( number ) ).toInt();
2256  }
2257 
2258  return QVariant();
2259 }
2260 
2261 static QVariant fcnPi( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
2262 {
2263  Q_UNUSED( values );
2264  Q_UNUSED( parent );
2265  return M_PI;
2266 }
2267 
2268 static QVariant fcnScale( const QVariantList&, const QgsExpressionContext*, QgsExpression* parent )
2269 {
2270  return QVariant( parent->scale() );
2271 }
2272 
2273 static QVariant fcnFormatNumber( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2274 {
2275  double value = getDoubleValue( values.at( 0 ), parent );
2276  int places = getIntValue( values.at( 1 ), parent );
2277  if ( places < 0 )
2278  {
2279  parent->setEvalErrorString( QObject::tr( "Number of places must be positive" ) );
2280  return QVariant();
2281  }
2282  return QString( "%L1" ).arg( value, 0, 'f', places );
2283 }
2284 
2285 static QVariant fcnFormatDate( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2286 {
2287  QDateTime dt = getDateTimeValue( values.at( 0 ), parent );
2288  QString format = getStringValue( values.at( 1 ), parent );
2289  return dt.toString( format );
2290 }
2291 
2292 static QVariant fcnColorRgb( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent )
2293 {
2294  int red = getIntValue( values.at( 0 ), parent );
2295  int green = getIntValue( values.at( 1 ), parent );
2296  int blue = getIntValue( values.at( 2 ), parent );
2297  QColor color = QColor( red, green, blue );
2298  if ( ! color.isValid() )
2299  {
2300  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
2301  color = QColor( 0, 0, 0 );
2302  }
2303 
2304  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
2305 }
2306 
2307 static QVariant fcnIf( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent )
2308 {
2309  QgsExpression::Node* node = getNode( values.at( 0 ), parent );
2311  QVariant value = node->eval( parent, context );
2313  if ( value.toBool() )
2314  {
2315  node = getNode( values.at( 1 ), parent );
2317  value = node->eval( parent, context );
2319  }
2320  else
2321  {
2322  node = getNode( values.at( 2 ), parent );
2324  value = node->eval( parent, context );
2326  }
2327  return value;
2328 }
2329 
2330 static QVariant fncColorRgba( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent )
2331 {
2332  int red = getIntValue( values.at( 0 ), parent );
2333  int green = getIntValue( values.at( 1 ), parent );
2334  int blue = getIntValue( values.at( 2 ), parent );
2335  int alpha = getIntValue( values.at( 3 ), parent );
2336  QColor color = QColor( red, green, blue, alpha );
2337  if ( ! color.isValid() )
2338  {
2339  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
2340  color = QColor( 0, 0, 0 );
2341  }
2342  return QgsSymbolLayerV2Utils::encodeColor( color );
2343 }
2344 
2345 QVariant fcnRampColor( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent )
2346 {
2347  QString rampName = getStringValue( values.at( 0 ), parent );
2348  const QgsVectorColorRampV2 *mRamp = QgsStyleV2::defaultStyle()->colorRampRef( rampName );
2349  if ( ! mRamp )
2350  {
2351  parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) );
2352  return QColor( 0, 0, 0 ).name();
2353  }
2354  double value = getDoubleValue( values.at( 1 ), parent );
2355  QColor color = mRamp->color( value );
2356  return QgsSymbolLayerV2Utils::encodeColor( color );
2357 }
2358 
2359 static QVariant fcnColorHsl( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent )
2360 {
2361  // Hue ranges from 0 - 360
2362  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
2363  // Saturation ranges from 0 - 100
2364  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
2365  // Lightness ranges from 0 - 100
2366  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
2367 
2368  QColor color = QColor::fromHslF( hue, saturation, lightness );
2369 
2370  if ( ! color.isValid() )
2371  {
2372  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
2373  color = QColor( 0, 0, 0 );
2374  }
2375 
2376  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
2377 }
2378 
2379 static QVariant fncColorHsla( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2380 {
2381  // Hue ranges from 0 - 360
2382  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
2383  // Saturation ranges from 0 - 100
2384  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
2385  // Lightness ranges from 0 - 100
2386  double lightness = getIntValue( values.at( 2 ), parent ) / 100.0;
2387  // Alpha ranges from 0 - 255
2388  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
2389 
2390  QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
2391  if ( ! color.isValid() )
2392  {
2393  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
2394  color = QColor( 0, 0, 0 );
2395  }
2396  return QgsSymbolLayerV2Utils::encodeColor( color );
2397 }
2398 
2399 static QVariant fcnColorHsv( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2400 {
2401  // Hue ranges from 0 - 360
2402  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
2403  // Saturation ranges from 0 - 100
2404  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
2405  // Value ranges from 0 - 100
2406  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
2407 
2408  QColor color = QColor::fromHsvF( hue, saturation, value );
2409 
2410  if ( ! color.isValid() )
2411  {
2412  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
2413  color = QColor( 0, 0, 0 );
2414  }
2415 
2416  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
2417 }
2418 
2419 static QVariant fncColorHsva( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2420 {
2421  // Hue ranges from 0 - 360
2422  double hue = getIntValue( values.at( 0 ), parent ) / 360.0;
2423  // Saturation ranges from 0 - 100
2424  double saturation = getIntValue( values.at( 1 ), parent ) / 100.0;
2425  // Value ranges from 0 - 100
2426  double value = getIntValue( values.at( 2 ), parent ) / 100.0;
2427  // Alpha ranges from 0 - 255
2428  double alpha = getIntValue( values.at( 3 ), parent ) / 255.0;
2429 
2430  QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
2431  if ( ! color.isValid() )
2432  {
2433  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
2434  color = QColor( 0, 0, 0 );
2435  }
2436  return QgsSymbolLayerV2Utils::encodeColor( color );
2437 }
2438 
2439 static QVariant fcnColorCmyk( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2440 {
2441  // Cyan ranges from 0 - 100
2442  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
2443  // Magenta ranges from 0 - 100
2444  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
2445  // Yellow ranges from 0 - 100
2446  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
2447  // Black ranges from 0 - 100
2448  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
2449 
2450  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
2451 
2452  if ( ! color.isValid() )
2453  {
2454  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
2455  color = QColor( 0, 0, 0 );
2456  }
2457 
2458  return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
2459 }
2460 
2461 static QVariant fncColorCmyka( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2462 {
2463  // Cyan ranges from 0 - 100
2464  double cyan = getIntValue( values.at( 0 ), parent ) / 100.0;
2465  // Magenta ranges from 0 - 100
2466  double magenta = getIntValue( values.at( 1 ), parent ) / 100.0;
2467  // Yellow ranges from 0 - 100
2468  double yellow = getIntValue( values.at( 2 ), parent ) / 100.0;
2469  // Black ranges from 0 - 100
2470  double black = getIntValue( values.at( 3 ), parent ) / 100.0;
2471  // Alpha ranges from 0 - 255
2472  double alpha = getIntValue( values.at( 4 ), parent ) / 255.0;
2473 
2474  QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
2475  if ( ! color.isValid() )
2476  {
2477  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
2478  color = QColor( 0, 0, 0 );
2479  }
2480  return QgsSymbolLayerV2Utils::encodeColor( color );
2481 }
2482 
2483 static QVariant fncColorPart( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2484 {
2485  QColor color = QgsSymbolLayerV2Utils::decodeColor( values.at( 0 ).toString() );
2486  if ( ! color.isValid() )
2487  {
2488  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
2489  return QVariant();
2490  }
2491 
2492  QString part = getStringValue( values.at( 1 ), parent );
2493  if ( part.compare( QLatin1String( "red" ), Qt::CaseInsensitive ) == 0 )
2494  return color.red();
2495  else if ( part.compare( QLatin1String( "green" ), Qt::CaseInsensitive ) == 0 )
2496  return color.green();
2497  else if ( part.compare( QLatin1String( "blue" ), Qt::CaseInsensitive ) == 0 )
2498  return color.blue();
2499  else if ( part.compare( QLatin1String( "alpha" ), Qt::CaseInsensitive ) == 0 )
2500  return color.alpha();
2501  else if ( part.compare( QLatin1String( "hue" ), Qt::CaseInsensitive ) == 0 )
2502  return color.hsvHueF() * 360;
2503  else if ( part.compare( QLatin1String( "saturation" ), Qt::CaseInsensitive ) == 0 )
2504  return color.hsvSaturationF() * 100;
2505  else if ( part.compare( QLatin1String( "value" ), Qt::CaseInsensitive ) == 0 )
2506  return color.valueF() * 100;
2507  else if ( part.compare( QLatin1String( "hsl_hue" ), Qt::CaseInsensitive ) == 0 )
2508  return color.hslHueF() * 360;
2509  else if ( part.compare( QLatin1String( "hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
2510  return color.hslSaturationF() * 100;
2511  else if ( part.compare( QLatin1String( "lightness" ), Qt::CaseInsensitive ) == 0 )
2512  return color.lightnessF() * 100;
2513  else if ( part.compare( QLatin1String( "cyan" ), Qt::CaseInsensitive ) == 0 )
2514  return color.cyanF() * 100;
2515  else if ( part.compare( QLatin1String( "magenta" ), Qt::CaseInsensitive ) == 0 )
2516  return color.magentaF() * 100;
2517  else if ( part.compare( QLatin1String( "yellow" ), Qt::CaseInsensitive ) == 0 )
2518  return color.yellowF() * 100;
2519  else if ( part.compare( QLatin1String( "black" ), Qt::CaseInsensitive ) == 0 )
2520  return color.blackF() * 100;
2521 
2522  parent->setEvalErrorString( QObject::tr( "Unknown color component '%1'" ).arg( part ) );
2523  return QVariant();
2524 }
2525 
2526 static QVariant fncSetColorPart( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2527 {
2528  QColor color = QgsSymbolLayerV2Utils::decodeColor( values.at( 0 ).toString() );
2529  if ( ! color.isValid() )
2530  {
2531  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
2532  return QVariant();
2533  }
2534 
2535  QString part = getStringValue( values.at( 1 ), parent );
2536  int value = getIntValue( values.at( 2 ), parent );
2537  if ( part.compare( QLatin1String( "red" ), Qt::CaseInsensitive ) == 0 )
2538  color.setRed( value );
2539  else if ( part.compare( QLatin1String( "green" ), Qt::CaseInsensitive ) == 0 )
2540  color.setGreen( value );
2541  else if ( part.compare( QLatin1String( "blue" ), Qt::CaseInsensitive ) == 0 )
2542  color.setBlue( value );
2543  else if ( part.compare( QLatin1String( "alpha" ), Qt::CaseInsensitive ) == 0 )
2544  color.setAlpha( value );
2545  else if ( part.compare( QLatin1String( "hue" ), Qt::CaseInsensitive ) == 0 )
2546  color.setHsv( value, color.hsvSaturation(), color.value(), color.alpha() );
2547  else if ( part.compare( QLatin1String( "saturation" ), Qt::CaseInsensitive ) == 0 )
2548  color.setHsvF( color.hsvHueF(), value / 100.0, color.valueF(), color.alphaF() );
2549  else if ( part.compare( QLatin1String( "value" ), Qt::CaseInsensitive ) == 0 )
2550  color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), value / 100.0, color.alphaF() );
2551  else if ( part.compare( QLatin1String( "hsl_hue" ), Qt::CaseInsensitive ) == 0 )
2552  color.setHsl( value, color.hslSaturation(), color.lightness(), color.alpha() );
2553  else if ( part.compare( QLatin1String( "hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
2554  color.setHslF( color.hslHueF(), value / 100.0, color.lightnessF(), color.alphaF() );
2555  else if ( part.compare( QLatin1String( "lightness" ), Qt::CaseInsensitive ) == 0 )
2556  color.setHslF( color.hslHueF(), color.hslSaturationF(), value / 100.0, color.alphaF() );
2557  else if ( part.compare( QLatin1String( "cyan" ), Qt::CaseInsensitive ) == 0 )
2558  color.setCmykF( value / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
2559  else if ( part.compare( QLatin1String( "magenta" ), Qt::CaseInsensitive ) == 0 )
2560  color.setCmykF( color.cyanF(), value / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
2561  else if ( part.compare( QLatin1String( "yellow" ), Qt::CaseInsensitive ) == 0 )
2562  color.setCmykF( color.cyanF(), color.magentaF(), value / 100.0, color.blackF(), color.alphaF() );
2563  else if ( part.compare( QLatin1String( "black" ), Qt::CaseInsensitive ) == 0 )
2564  color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), value / 100.0, color.alphaF() );
2565  else
2566  {
2567  parent->setEvalErrorString( QObject::tr( "Unknown color component '%1'" ).arg( part ) );
2568  return QVariant();
2569  }
2570  return QgsSymbolLayerV2Utils::encodeColor( color );
2571 }
2572 
2573 static QVariant fncDarker( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2574 {
2575  QColor color = QgsSymbolLayerV2Utils::decodeColor( values.at( 0 ).toString() );
2576  if ( ! color.isValid() )
2577  {
2578  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
2579  return QVariant();
2580  }
2581 
2582  color = color.darker( getIntValue( values.at( 1 ), parent ) );
2583 
2584  return QgsSymbolLayerV2Utils::encodeColor( color );
2585 }
2586 
2587 static QVariant fncLighter( const QVariantList &values, const QgsExpressionContext*, QgsExpression *parent )
2588 {
2589  QColor color = QgsSymbolLayerV2Utils::decodeColor( values.at( 0 ).toString() );
2590  if ( ! color.isValid() )
2591  {
2592  parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
2593  return QVariant();
2594  }
2595 
2596  color = color.lighter( getIntValue( values.at( 1 ), parent ) );
2597 
2598  return QgsSymbolLayerV2Utils::encodeColor( color );
2599 }
2600 
2601 static QVariant fcnSpecialColumn( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2602 {
2603  QString varName = getStringValue( values.at( 0 ), parent );
2605  return QgsExpression::specialColumn( varName );
2607 }
2608 
2609 static QVariant fcnGetGeometry( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2610 {
2611  QgsFeature feat = getFeature( values.at( 0 ), parent );
2612  const QgsGeometry* geom = feat.constGeometry();
2613  if ( geom )
2614  return QVariant::fromValue( *geom );
2615  return QVariant();
2616 }
2617 
2618 static QVariant fcnTransformGeometry( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2619 {
2620  QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
2621  QString sAuthId = getStringValue( values.at( 1 ), parent );
2622  QString dAuthId = getStringValue( values.at( 2 ), parent );
2623 
2625  if ( ! s.createFromOgcWmsCrs( sAuthId ) )
2626  return QVariant::fromValue( fGeom );
2628  if ( ! d.createFromOgcWmsCrs( dAuthId ) )
2629  return QVariant::fromValue( fGeom );
2630 
2631  QgsCoordinateTransform t( s, d );
2632  if ( fGeom.transform( t ) == 0 )
2633  return QVariant::fromValue( fGeom );
2634  return QVariant();
2635 }
2636 
2637 static QVariant fcnGetFeature( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2638 {
2639  //arguments: 1. layer id / name, 2. key attribute, 3. eq value
2640  QString layerString = getStringValue( values.at( 0 ), parent );
2641  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerString ) ); //search by id first
2642  if ( !vl )
2643  {
2644  QList<QgsMapLayer *> layersByName = QgsMapLayerRegistry::instance()->mapLayersByName( layerString );
2645  if ( !layersByName.isEmpty() )
2646  {
2647  vl = qobject_cast<QgsVectorLayer*>( layersByName.at( 0 ) );
2648  }
2649  }
2650 
2651  //no layer found
2652  if ( !vl )
2653  {
2654  return QVariant();
2655  }
2656 
2657  QString attribute = getStringValue( values.at( 1 ), parent );
2658  int attributeId = vl->fieldNameIndex( attribute );
2659  if ( attributeId == -1 )
2660  {
2661  return QVariant();
2662  }
2663 
2664  const QVariant& attVal = values.at( 2 );
2665  QgsFeatureRequest req;
2666  req.setFilterExpression( QString( "%1=%2" ).arg( QgsExpression::quotedColumnRef( attribute ),
2667  QgsExpression::quotedString( attVal.toString() ) ) );
2668  req.setLimit( 1 );
2669  if ( !parent->needsGeometry() )
2670  {
2672  }
2673  QgsFeatureIterator fIt = vl->getFeatures( req );
2674 
2675  QgsFeature fet;
2676  if ( fIt.nextFeature( fet ) )
2677  return QVariant::fromValue( fet );
2678 
2679  return QVariant();
2680 }
2681 
2682 static QVariant fcnGetLayerProperty( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2683 {
2684  QString layerIdOrName = getStringValue( values.at( 0 ), parent );
2685 
2686  //try to find a matching layer by name
2687  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerIdOrName ); //search by id first
2688  if ( !layer )
2689  {
2690  QList<QgsMapLayer *> layersByName = QgsMapLayerRegistry::instance()->mapLayersByName( layerIdOrName );
2691  if ( !layersByName.isEmpty() )
2692  {
2693  layer = layersByName.at( 0 );
2694  }
2695  }
2696 
2697  if ( !layer )
2698  return QVariant();
2699 
2700  QString layerProperty = getStringValue( values.at( 1 ), parent );
2701  if ( QString::compare( layerProperty, QString( "name" ), Qt::CaseInsensitive ) == 0 )
2702  return layer->name();
2703  else if ( QString::compare( layerProperty, QString( "id" ), Qt::CaseInsensitive ) == 0 )
2704  return layer->id();
2705  else if ( QString::compare( layerProperty, QString( "title" ), Qt::CaseInsensitive ) == 0 )
2706  return layer->title();
2707  else if ( QString::compare( layerProperty, QString( "abstract" ), Qt::CaseInsensitive ) == 0 )
2708  return layer->abstract();
2709  else if ( QString::compare( layerProperty, QString( "keywords" ), Qt::CaseInsensitive ) == 0 )
2710  return layer->keywordList();
2711  else if ( QString::compare( layerProperty, QString( "data_url" ), Qt::CaseInsensitive ) == 0 )
2712  return layer->dataUrl();
2713  else if ( QString::compare( layerProperty, QString( "attribution" ), Qt::CaseInsensitive ) == 0 )
2714  return layer->attribution();
2715  else if ( QString::compare( layerProperty, QString( "attribution_url" ), Qt::CaseInsensitive ) == 0 )
2716  return layer->attributionUrl();
2717  else if ( QString::compare( layerProperty, QString( "source" ), Qt::CaseInsensitive ) == 0 )
2718  return layer->publicSource();
2719  else if ( QString::compare( layerProperty, QString( "min_scale" ), Qt::CaseInsensitive ) == 0 )
2720  return static_cast< double >( layer->minimumScale() );
2721  else if ( QString::compare( layerProperty, QString( "max_scale" ), Qt::CaseInsensitive ) == 0 )
2722  return static_cast< double >( layer->maximumScale() );
2723  else if ( QString::compare( layerProperty, QString( "crs" ), Qt::CaseInsensitive ) == 0 )
2724  return layer->crs().authid();
2725  else if ( QString::compare( layerProperty, QString( "crs_definition" ), Qt::CaseInsensitive ) == 0 )
2726  return layer->crs().toProj4();
2727  else if ( QString::compare( layerProperty, QString( "extent" ), Qt::CaseInsensitive ) == 0 )
2728  {
2729  QgsGeometry* extentGeom = QgsGeometry::fromRect( layer->extent() );
2730  QVariant result = QVariant::fromValue( *extentGeom );
2731  delete extentGeom;
2732  return result;
2733  }
2734  else if ( QString::compare( layerProperty, QString( "type" ), Qt::CaseInsensitive ) == 0 )
2735  {
2736  switch ( layer->type() )
2737  {
2739  return QCoreApplication::translate( "expressions", "Vector" );
2741  return QCoreApplication::translate( "expressions", "Raster" );
2743  return QCoreApplication::translate( "expressions", "Plugin" );
2744  }
2745  }
2746  else
2747  {
2748  //vector layer methods
2749  QgsVectorLayer* vLayer = dynamic_cast< QgsVectorLayer* >( layer );
2750  if ( vLayer )
2751  {
2752  if ( QString::compare( layerProperty, QString( "storage_type" ), Qt::CaseInsensitive ) == 0 )
2753  return vLayer->storageType();
2754  else if ( QString::compare( layerProperty, QString( "geometry_type" ), Qt::CaseInsensitive ) == 0 )
2755  return QGis::vectorGeometryType( vLayer->geometryType() );
2756  else if ( QString::compare( layerProperty, QString( "feature_count" ), Qt::CaseInsensitive ) == 0 )
2757  return QVariant::fromValue( vLayer->featureCount() );
2758  }
2759  }
2760 
2761  return QVariant();
2762 }
2763 
2764 bool QgsExpression::registerFunction( QgsExpression::Function* function, bool transferOwnership )
2765 {
2766  int fnIdx = functionIndex( function->name() );
2767  if ( fnIdx != -1 )
2768  {
2769  return false;
2770  }
2771  QgsExpression::gmFunctions.append( function );
2772  if ( transferOwnership )
2773  QgsExpression::gmOwnedFunctions.append( function );
2774  return true;
2775 }
2776 
2778 {
2779  // You can never override the built in functions.
2780  if ( QgsExpression::BuiltinFunctions().contains( name ) )
2781  {
2782  return false;
2783  }
2784  int fnIdx = functionIndex( name );
2785  if ( fnIdx != -1 )
2786  {
2787  QgsExpression::gmFunctions.removeAt( fnIdx );
2788  return true;
2789  }
2790  return false;
2791 }
2792 
2794 {
2795  qDeleteAll( QgsExpression::gmOwnedFunctions );
2797 }
2798 
2800 
2802 {
2803  if ( gmBuiltinFunctions.isEmpty() )
2804  {
2806  << "abs" << "sqrt" << "cos" << "sin" << "tan"
2807  << "asin" << "acos" << "atan" << "atan2"
2808  << "exp" << "ln" << "log10" << "log"
2809  << "round" << "rand" << "randf" << "max" << "min" << "clamp"
2810  << "scale_linear" << "scale_exp" << "floor" << "ceil" << "$pi"
2811  << "toint" << "to_int" << "toreal" << "to_real" << "tostring" << "to_string"
2812  << "todatetime" << "to_datetime" << "todate" << "to_date"
2813  << "totime" << "to_time" << "tointerval" << "to_interval"
2814  << "coalesce" << "if" << "regexp_match" << "age" << "year"
2815  << "month" << "week" << "day" << "hour" << "day_of_week"
2816  << "minute" << "second" << "lower" << "upper"
2817  << "title" << "length" << "replace" << "trim" << "wordwrap"
2818  << "regexp_replace" << "regexp_substr"
2819  << "substr" << "concat" << "strpos" << "left"
2820  << "right" << "rpad" << "lpad" << "format"
2821  << "format_number" << "format_date"
2822  << "color_rgb" << "color_rgba" << "ramp_color"
2823  << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva"
2824  << "color_cmyk" << "color_cmyka" << "color_part" << "set_color_part"
2825  << "xat" << "yat" << "$area" << "area" << "perimeter"
2826  << "$length" << "$perimeter" << "x" << "y" << "$x" << "$y" << "z" << "m" << "num_points"
2827  << "num_interior_rings" << "num_rings" << "num_geometries"
2828  << "geometry_n" << "interior_ring_n"
2829  << "point_n" << "start_point" << "end_point" << "make_point" << "make_point_m"
2830  << "nodes_to_points" << "segments_to_lines"
2831  << "make_line" << "make_polygon"
2832  << "$x_at" << "x_at" << "xat" << "$y_at" << "y_at" << "yat" << "x_min" << "xmin" << "x_max" << "xmax"
2833  << "y_min" << "ymin" << "y_max" << "ymax" << "geom_from_wkt" << "geomFromWKT"
2834  << "geom_from_gml" << "geomFromGML" << "intersects_bbox" << "bbox"
2835  << "disjoint" << "intersects" << "touches" << "crosses" << "contains"
2836  << "relate"
2837  << "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse" << "exterior_ring"
2838  << "bounds_width" << "bounds_height" << "is_closed" << "convex_hull" << "difference"
2839  << "distance" << "intersection" << "sym_difference" << "combine"
2840  << "extrude" << "azimuth" << "closest_point" << "shortest_line"
2841  << "union" << "geom_to_wkt" << "geomToWKT" << "geometry"
2842  << "transform" << "get_feature" << "getFeature"
2843  << "levenshtein" << "longest_common_substring" << "hamming_distance"
2844  << "soundex"
2845  << "attribute" << "var" << "layer_property"
2846  << "$id" << "$scale" << "_specialcol_";
2847  }
2848  return gmBuiltinFunctions;
2849 }
2850 
2853 
2855 {
2856  if ( gmFunctions.isEmpty() )
2857  {
2858  gmFunctions
2859  << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
2860  << new StaticFunction( "radians", 1, fcnRadians, "Math" )
2861  << new StaticFunction( "degrees", 1, fcnDegrees, "Math" )
2862  << new StaticFunction( "azimuth", 2, fcnAzimuth, "Math" )
2863  << new StaticFunction( "abs", 1, fcnAbs, "Math" )
2864  << new StaticFunction( "cos", 1, fcnCos, "Math" )
2865  << new StaticFunction( "sin", 1, fcnSin, "Math" )
2866  << new StaticFunction( "tan", 1, fcnTan, "Math" )
2867  << new StaticFunction( "asin", 1, fcnAsin, "Math" )
2868  << new StaticFunction( "acos", 1, fcnAcos, "Math" )
2869  << new StaticFunction( "atan", 1, fcnAtan, "Math" )
2870  << new StaticFunction( "atan2", 2, fcnAtan2, "Math" )
2871  << new StaticFunction( "exp", 1, fcnExp, "Math" )
2872  << new StaticFunction( "ln", 1, fcnLn, "Math" )
2873  << new StaticFunction( "log10", 1, fcnLog10, "Math" )
2874  << new StaticFunction( "log", 2, fcnLog, "Math" )
2875  << new StaticFunction( "round", -1, fcnRound, "Math" )
2876  << new StaticFunction( "rand", 2, fcnRnd, "Math" )
2877  << new StaticFunction( "randf", 2, fcnRndF, "Math" )
2878  << new StaticFunction( "max", -1, fcnMax, "Math" )
2879  << new StaticFunction( "min", -1, fcnMin, "Math" )
2880  << new StaticFunction( "clamp", 3, fcnClamp, "Math" )
2881  << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" )
2882  << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" )
2883  << new StaticFunction( "floor", 1, fcnFloor, "Math" )
2884  << new StaticFunction( "ceil", 1, fcnCeil, "Math" )
2885  << new StaticFunction( "pi", 0, fcnPi, "Math", QString(), false, QStringList(), false, QStringList() << "$pi" )
2886  << new StaticFunction( "to_int", 1, fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
2887  << new StaticFunction( "to_real", 1, fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
2888  << new StaticFunction( "to_string", 1, fcnToString, "Conversions", QString(), false, QStringList(), false, QStringList() << "tostring" )
2889  << new StaticFunction( "to_datetime", 1, fcnToDateTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "todatetime" )
2890  << new StaticFunction( "to_date", 1, fcnToDate, "Conversions", QString(), false, QStringList(), false, QStringList() << "todate" )
2891  << new StaticFunction( "to_time", 1, fcnToTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "totime" )
2892  << new StaticFunction( "to_interval", 1, fcnToInterval, "Conversions", QString(), false, QStringList(), false, QStringList() << "tointerval" )
2893  << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals", QString(), false, QStringList(), false, QStringList(), true )
2894  << new StaticFunction( "if", 3, fcnIf, "Conditionals", QString(), False, QStringList(), true )
2895  << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
2896  << new StaticFunction( "now", 0, fcnNow, "Date and Time", QString(), false, QStringList(), false, QStringList() << "$now" )
2897  << new StaticFunction( "age", 2, fcnAge, "Date and Time" )
2898  << new StaticFunction( "year", 1, fcnYear, "Date and Time" )
2899  << new StaticFunction( "month", 1, fcnMonth, "Date and Time" )
2900  << new StaticFunction( "week", 1, fcnWeek, "Date and Time" )
2901  << new StaticFunction( "day", 1, fcnDay, "Date and Time" )
2902  << new StaticFunction( "hour", 1, fcnHour, "Date and Time" )
2903  << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" )
2904  << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" )
2905  << new StaticFunction( "day_of_week", 1, fcnDayOfWeek, "Date and Time" )
2906  << new StaticFunction( "lower", 1, fcnLower, "String" )
2907  << new StaticFunction( "upper", 1, fcnUpper, "String" )
2908  << new StaticFunction( "title", 1, fcnTitle, "String" )
2909  << new StaticFunction( "trim", 1, fcnTrim, "String" )
2910  << new StaticFunction( "levenshtein", 2, fcnLevenshtein, "Fuzzy Matching" )
2911  << new StaticFunction( "longest_common_substring", 2, fcnLCS, "Fuzzy Matching" )
2912  << new StaticFunction( "hamming_distance", 2, fcnHamming, "Fuzzy Matching" )
2913  << new StaticFunction( "soundex", 1, fcnSoundex, "Fuzzy Matching" )
2914  << new StaticFunction( "wordwrap", -1, fcnWordwrap, "String" )
2915  << new StaticFunction( "length", 1, fcnLength, "String" )
2916  << new StaticFunction( "replace", 3, fcnReplace, "String" )
2917  << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
2918  << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
2919  << new StaticFunction( "substr", 3, fcnSubstr, "String" )
2920  << new StaticFunction( "concat", -1, fcnConcat, "String", QString(), false, QStringList(), false, QStringList(), true )
2921  << new StaticFunction( "strpos", 2, fcnStrpos, "String" )
2922  << new StaticFunction( "left", 2, fcnLeft, "String" )
2923  << new StaticFunction( "right", 2, fcnRight, "String" )
2924  << new StaticFunction( "rpad", 3, fcnRPad, "String" )
2925  << new StaticFunction( "lpad", 3, fcnLPad, "String" )
2926  << new StaticFunction( "format", -1, fcnFormatString, "String" )
2927  << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
2928  << new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
2929  << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
2930  << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
2931  << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )
2932  << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" )
2933  << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" )
2934  << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" )
2935  << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" )
2936  << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" )
2937  << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" )
2938  << new StaticFunction( "color_part", 2, fncColorPart, "Color" )
2939  << new StaticFunction( "darker", 2, fncDarker, "Color" )
2940  << new StaticFunction( "lighter", 2, fncLighter, "Color" )
2941  << new StaticFunction( "set_color_part", 3, fncSetColorPart, "Color" )
2942  << new StaticFunction( "$geometry", 0, fcnGeometry, "GeometryGroup", QString(), true )
2943  << new StaticFunction( "$area", 0, fcnGeomArea, "GeometryGroup", QString(), true )
2944  << new StaticFunction( "area", 1, fcnArea, "GeometryGroup" )
2945  << new StaticFunction( "$length", 0, fcnGeomLength, "GeometryGroup", QString(), true )
2946  << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "GeometryGroup", QString(), true )
2947  << new StaticFunction( "perimeter", 1, fcnPerimeter, "GeometryGroup" )
2948  << new StaticFunction( "$x", 0, fcnX, "GeometryGroup", QString(), true )
2949  << new StaticFunction( "$y", 0, fcnY, "GeometryGroup", QString(), true )
2950  << new StaticFunction( "x", 1, fcnGeomX, "GeometryGroup" )
2951  << new StaticFunction( "y", 1, fcnGeomY, "GeometryGroup" )
2952  << new StaticFunction( "z", 1, fcnGeomZ, "GeometryGroup" )
2953  << new StaticFunction( "m", 1, fcnGeomM, "GeometryGroup" )
2954  << new StaticFunction( "point_n", 2, fcnPointN, "GeometryGroup" )
2955  << new StaticFunction( "start_point", 1, fcnStartPoint, "GeometryGroup" )
2956  << new StaticFunction( "end_point", 1, fcnEndPoint, "GeometryGroup" )
2957  << new StaticFunction( "nodes_to_points", -1, fcnNodesToPoints, "GeometryGroup" )
2958  << new StaticFunction( "segments_to_lines", 1, fcnSegmentsToLines, "GeometryGroup" )
2959  << new StaticFunction( "make_point", -1, fcnMakePoint, "GeometryGroup" )
2960  << new StaticFunction( "make_point_m", 3, fcnMakePointM, "GeometryGroup" )
2961  << new StaticFunction( "make_line", -1, fcnMakeLine, "GeometryGroup" )
2962  << new StaticFunction( "make_polygon", -1, fcnMakePolygon, "GeometryGroup" )
2963  << new StaticFunction( "$x_at", 1, fcnXat, "GeometryGroup", QString(), true, QStringList(), false, QStringList() << "xat" << "x_at" )
2964  << new StaticFunction( "$y_at", 1, fcnYat, "GeometryGroup", QString(), true, QStringList(), false, QStringList() << "yat" << "y_at" )
2965  << new StaticFunction( "x_min", 1, fcnXMin, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "xmin" )
2966  << new StaticFunction( "x_max", 1, fcnXMax, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "xmax" )
2967  << new StaticFunction( "y_min", 1, fcnYMin, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "ymin" )
2968  << new StaticFunction( "y_max", 1, fcnYMax, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "ymax" )
2969  << new StaticFunction( "geom_from_wkt", 1, fcnGeomFromWKT, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "geomFromWKT" )
2970  << new StaticFunction( "geom_from_gml", 1, fcnGeomFromGML, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "geomFromGML" )
2971  << new StaticFunction( "relate", -1, fcnRelate, "GeometryGroup" )
2972  << new StaticFunction( "intersects_bbox", 2, fcnBbox, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "bbox" )
2973  << new StaticFunction( "disjoint", 2, fcnDisjoint, "GeometryGroup" )
2974  << new StaticFunction( "intersects", 2, fcnIntersects, "GeometryGroup" )
2975  << new StaticFunction( "touches", 2, fcnTouches, "GeometryGroup" )
2976  << new StaticFunction( "crosses", 2, fcnCrosses, "GeometryGroup" )
2977  << new StaticFunction( "contains", 2, fcnContains, "GeometryGroup" )
2978  << new StaticFunction( "overlaps", 2, fcnOverlaps, "GeometryGroup" )
2979  << new StaticFunction( "within", 2, fcnWithin, "GeometryGroup" )
2980  << new StaticFunction( "translate", 3, fcnTranslate, "GeometryGroup" )
2981  << new StaticFunction( "buffer", -1, fcnBuffer, "GeometryGroup" )
2982  << new StaticFunction( "centroid", 1, fcnCentroid, "GeometryGroup" )
2983  << new StaticFunction( "point_on_surface", 1, fcnPointOnSurface, "GeometryGroup" )
2984  << new StaticFunction( "reverse", 1, fcnReverse, "GeometryGroup" )
2985  << new StaticFunction( "exterior_ring", 1, fcnExteriorRing, "GeometryGroup" )
2986  << new StaticFunction( "interior_ring_n", 2, fcnInteriorRingN, "GeometryGroup" )
2987  << new StaticFunction( "geometry_n", 2, fcnGeometryN, "GeometryGroup" )
2988  << new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" )
2989  << new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" )
2990  << new StaticFunction( "num_interior_rings", 1, fcnGeomNumInteriorRings, "GeometryGroup" )
2991  << new StaticFunction( "num_rings", 1, fcnGeomNumRings, "GeometryGroup" )
2992  << new StaticFunction( "num_geometries", 1, fcnGeomNumGeometries, "GeometryGroup" )
2993  << new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "GeometryGroup" )
2994  << new StaticFunction( "bounds_height", 1, fcnBoundsHeight, "GeometryGroup" )
2995  << new StaticFunction( "is_closed", 1, fcnIsClosed, "GeometryGroup" )
2996  << new StaticFunction( "convex_hull", 1, fcnConvexHull, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "convexHull" )
2997  << new StaticFunction( "difference", 2, fcnDifference, "GeometryGroup" )
2998  << new StaticFunction( "distance", 2, fcnDistance, "GeometryGroup" )
2999  << new StaticFunction( "intersection", 2, fcnIntersection, "GeometryGroup" )
3000  << new StaticFunction( "sym_difference", 2, fcnSymDifference, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "symDifference" )
3001  << new StaticFunction( "combine", 2, fcnCombine, "GeometryGroup" )
3002  << new StaticFunction( "union", 2, fcnCombine, "GeometryGroup" )
3003  << new StaticFunction( "geom_to_wkt", -1, fcnGeomToWKT, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "geomToWKT" )
3004  << new StaticFunction( "geometry", 1, fcnGetGeometry, "GeometryGroup", QString(), true )
3005  << new StaticFunction( "transform", 3, fcnTransformGeometry, "GeometryGroup" )
3006  << new StaticFunction( "extrude", 3, fcnExtrude, "GeometryGroup", QString() )
3007  << new StaticFunction( "order_parts", 3, fcnOrderParts, "GeometryGroup", QString() )
3008  << new StaticFunction( "closest_point", 2, fcnClosestPoint, "GeometryGroup" )
3009  << new StaticFunction( "shortest_line", 2, fcnShortestLine, "GeometryGroup" )
3010  << new StaticFunction( "$rownum", 0, fcnRowNumber, "deprecated" )
3011  << new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
3012  << new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
3013  << new StaticFunction( "$scale", 0, fcnScale, "Record" )
3014  << new StaticFunction( "$map", 0, fcnMapId, "deprecated" )
3015  << new StaticFunction( "$numpages", 0, fcnComposerNumPages, "deprecated" )
3016  << new StaticFunction( "$page", 0, fcnComposerPage, "deprecated" )
3017  << new StaticFunction( "$feature", 0, fcnAtlasFeature, "deprecated" )
3018  << new StaticFunction( "$atlasfeatureid", 0, fcnAtlasFeatureId, "deprecated" )
3019  << new StaticFunction( "$atlasfeature", 0, fcnAtlasCurrentFeature, "deprecated" )
3020  << new StaticFunction( "$atlasgeometry", 0, fcnAtlasCurrentGeometry, "deprecated" )
3021  << new StaticFunction( "$numfeatures", 0, fcnAtlasNumFeatures, "deprecated" )
3022  << new StaticFunction( "uuid", 0, fcnUuid, "Record", QString(), false, QStringList(), false, QStringList() << "$uuid" )
3023  << new StaticFunction( "get_feature", 3, fcnGetFeature, "Record", QString(), false, QStringList(), false, QStringList() << "getFeature" )
3024  << new StaticFunction( "layer_property", 2, fcnGetLayerProperty, "General" )
3025  << new StaticFunction( "var", 1, fcnGetVariable, "General" )
3026 
3027  //return all attributes string for referencedColumns - this is caught by
3028  // QgsFeatureRequest::setSubsetOfAttributes and causes all attributes to be fetched by the
3029  // feature request
3030  << new StaticFunction( "eval", 1, fcnEval, "General", QString(), true, QStringList( QgsFeatureRequest::AllAttributes ) )
3031  << new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
3032 
3033  << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" )
3034  ;
3035 
3037 
3038  //QgsExpression has ownership of all built-in functions
3039  Q_FOREACH ( QgsExpression::Function* func, gmFunctions )
3040  {
3041  gmOwnedFunctions << func;
3042  }
3043  }
3044  return gmFunctions;
3045 }
3046 
3049 
3050 void QgsExpression::setSpecialColumn( const QString& name, const QVariant& variant )
3051 {
3052  int fnIdx = functionIndex( name );
3053  if ( fnIdx != -1 )
3054  {
3055  // function of the same name already exists
3056  return;
3057  }
3058  gmSpecialColumns[ name ] = variant;
3059 }
3060 
3062 {
3064  if ( fit != gmSpecialColumns.end() )
3065  {
3066  gmSpecialColumns.erase( fit );
3067  }
3068 }
3069 
3071 {
3072  int fnIdx = functionIndex( name );
3073  if ( fnIdx != -1 )
3074  {
3075  // function of the same name already exists
3076  return QVariant();
3077  }
3079  if ( it == gmSpecialColumns.constEnd() )
3080  {
3081  return QVariant();
3082  }
3083  return it.value();
3084 }
3085 
3087 {
3088  if ( functionIndex( name ) != -1 )
3089  return false;
3090  return gmSpecialColumns.contains( name );
3091 }
3092 
3093 bool QgsExpression::isValid( const QString &text, const QgsFields &fields, QString &errorMessage )
3094 {
3096  return isValid( text, &context, errorMessage );
3097 }
3098 
3099 bool QgsExpression::isValid( const QString &text, const QgsExpressionContext *context, QString &errorMessage )
3100 {
3101  QgsExpression exp( text );
3102  exp.prepare( context );
3103  errorMessage = exp.parserErrorString();
3104  return !exp.hasParserError();
3105 }
3106 
3107 void QgsExpression::setScale( double scale ) { d->mScale = scale; }
3108 
3109 double QgsExpression::scale() { return d->mScale; }
3110 
3112 {
3113  if ( !d->mExp.isNull() )
3114  return d->mExp;
3115  else
3116  return dump();
3117 }
3118 
3120 {
3121  QList<Function*> defs;
3123  {
3124  //check for special column group name
3125  QString group = gmSpecialColumnGroups.value( it.key(), "Record" );
3126  defs << new StaticFunction( it.key(), 0, static_cast< FcnEvalContext >( nullptr ), group );
3127  }
3128  return defs;
3129 }
3130 
3132 {
3133  return QString( "\"%1\"" ).arg( name.replace( '\"', "\"\"" ) );
3134 }
3135 
3137 {
3138  text.replace( '\'', "''" );
3139  text.replace( '\\', "\\\\" );
3140  text.replace( '\n', "\\n" );
3141  text.replace( '\t', "\\t" );
3142  return QString( "'%1'" ).arg( text );
3143 }
3144 
3146 {
3147  return quotedValue( value, value.type() );
3148 }
3149 
3150 QString QgsExpression::quotedValue( const QVariant& value, QVariant::Type type )
3151 {
3152  if ( value.isNull() )
3153  return "NULL";
3154 
3155  switch ( type )
3156  {
3157  case QVariant::Int:
3158  case QVariant::LongLong:
3159  case QVariant::Double:
3160  return value.toString();
3161 
3162  case QVariant::Bool:
3163  return value.toBool() ? "TRUE" : "FALSE";
3164 
3165  default:
3166  case QVariant::String:
3167  return quotedString( value.toString() );
3168  }
3169 
3170 }
3171 
3173 {
3174  return functionIndex( name ) != -1;
3175 }
3176 
3178 {
3179  int count = functionCount();
3180  for ( int i = 0; i < count; i++ )
3181  {
3182  if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 )
3183  return i;
3184  Q_FOREACH ( const QString& alias, Functions()[i]->aliases() )
3185  {
3186  if ( QString::compare( name, alias, Qt::CaseInsensitive ) == 0 )
3187  return i;
3188  }
3189  }
3190  return -1;
3191 }
3192 
3194 {
3195  return Functions().size();
3196 }
3197 
3198 
3200  : d( new QgsExpressionPrivate )
3201 {
3202  d->mRootNode = ::parseExpression( expr, d->mParserErrorString );
3203  d->mExp = expr;
3204  Q_ASSERT( !d->mParserErrorString.isNull() || d->mRootNode );
3205 }
3206 
3208  : d( other.d )
3209 {
3210  d->ref.ref();
3211 }
3212 
3214 {
3215  d = other.d;
3216  d->ref.ref();
3217  return *this;
3218 }
3219 
3221  : d( new QgsExpressionPrivate )
3222 {
3223 }
3224 
3226 {
3227  Q_ASSERT( d );
3228  if ( !d->ref.deref() )
3229  delete d;
3230 }
3231 
3232 bool QgsExpression::hasParserError() const { return !d->mParserErrorString.isNull(); }
3233 
3234 QString QgsExpression::parserErrorString() const { return d->mParserErrorString; }
3235 
3237 {
3238  if ( !d->mRootNode )
3239  return QStringList();
3240 
3241  QStringList columns = d->mRootNode->referencedColumns();
3242 
3243  // filter out duplicates
3244  for ( int i = 0; i < columns.count(); i++ )
3245  {
3246  QString col = columns.at( i );
3247  for ( int j = i + 1; j < columns.count(); j++ )
3248  {
3249  if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
3250  {
3251  // this column is repeated: remove it!
3252  columns.removeAt( j-- );
3253  }
3254  }
3255  }
3256 
3257  return columns;
3258 }
3259 
3261 {
3262  if ( !d->mRootNode )
3263  return false;
3264  return d->mRootNode->needsGeometry();
3265 }
3266 
3268 {
3269  if ( d->mCalc.data() )
3270  return;
3271 
3272  // Use planimetric as default
3274  d->mCalc->setEllipsoidalMode( false );
3275 }
3276 
3278 {
3279  Q_ASSERT( d );
3280 
3281  if ( d->ref > 1 )
3282  {
3283  ( void )d->ref.deref();
3284 
3285  d = new QgsExpressionPrivate( *d );
3286  }
3287 }
3288 
3290 {
3291  d->mCalc = QSharedPointer<QgsDistanceArea>( new QgsDistanceArea( calc ) );
3292 }
3293 
3294 bool QgsExpression::prepare( const QgsFields& fields )
3295 {
3296  detach();
3298  return prepare( &fc );
3299 }
3300 
3302 {
3303  detach();
3304  d->mEvalErrorString = QString();
3305  if ( !d->mRootNode )
3306  {
3307  //re-parse expression. Creation of QgsExpressionContexts may have added extra
3308  //known functions since this expression was created, so we have another try
3309  //at re-parsing it now that the context must have been created
3310  d->mRootNode = ::parseExpression( d->mExp, d->mParserErrorString );
3311  }
3312 
3313  if ( !d->mRootNode )
3314  {
3315  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
3316  return false;
3317  }
3318 
3319  return d->mRootNode->prepare( this, context );
3320 }
3321 
3323 {
3324  d->mEvalErrorString = QString();
3325  if ( !d->mRootNode )
3326  {
3327  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
3328  return QVariant();
3329  }
3330 
3332  return d->mRootNode->eval( this, &context );
3333 }
3334 
3336 {
3338  return evaluate( &f );
3340 }
3341 
3343 {
3344  // first prepare
3346  bool res = prepare( &context );
3347  if ( !res )
3348  return QVariant();
3349 
3350  // then evaluate
3351  return evaluate( &context );
3352 }
3353 
3354 inline QVariant QgsExpression::evaluate( const QgsFeature& f, const QgsFields& fields )
3355 {
3357  return evaluate( &f, fields );
3359 }
3360 
3362 {
3363  d->mEvalErrorString = QString();
3364  if ( !d->mRootNode )
3365  {
3366  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
3367  return QVariant();
3368  }
3369 
3370  return d->mRootNode->eval( this, static_cast<const QgsExpressionContext*>( nullptr ) );
3371 }
3372 
3374 {
3375  d->mEvalErrorString = QString();
3376  if ( !d->mRootNode )
3377  {
3378  d->mEvalErrorString = tr( "No root node! Parsing failed?" );
3379  return QVariant();
3380  }
3381 
3382  return d->mRootNode->eval( this, context );
3383 }
3384 
3386 {
3387  return !d->mEvalErrorString.isNull();
3388 }
3389 
3391 {
3392  return d->mEvalErrorString;
3393 }
3394 
3396 {
3397  d->mEvalErrorString = str;
3398 }
3399 
3401 {
3402  d->mRowNumber = rowNumber;
3403 }
3404 
3405 int QgsExpression::currentRowNumber() { return d->mRowNumber; }
3406 
3408 {
3409  if ( !d->mRootNode )
3410  return tr( "(no root)" );
3411 
3412  return d->mRootNode->dump();
3413 }
3414 
3416 {
3417  return d->mCalc.data();
3418 }
3419 
3421 {
3422  return d->mDistanceUnit;
3423 }
3424 
3426 {
3427  d->mDistanceUnit = unit;
3428 }
3429 
3431 {
3432  if ( d->mRootNode )
3433  d->mRootNode->accept( v );
3434 }
3435 
3437  QgsVectorLayer *layer,
3438  const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
3439 {
3440  QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( feat ? *feat : QgsFeature(), layer ? layer->fields() : QgsFields() );
3441  return replaceExpressionText( action, &context, substitutionMap, distanceArea );
3442 }
3443 
3444 QString QgsExpression::replaceExpressionText( const QString &action, const QgsExpressionContext *context, const QMap<QString, QVariant> *substitutionMap, const QgsDistanceArea *distanceArea )
3445 {
3446  QString expr_action;
3447 
3448  QMap<QString, QVariant> savedValues;
3449  if ( substitutionMap )
3450  {
3451  // variables with a local scope (must be restored after evaluation)
3452  for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit )
3453  {
3455  QVariant oldValue = QgsExpression::specialColumn( sit.key() );
3456  if ( !oldValue.isNull() )
3457  savedValues.insert( sit.key(), oldValue );
3458 
3459  // set the new value
3460  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
3462  }
3463  }
3464 
3465  int index = 0;
3466  while ( index < action.size() )
3467  {
3468  QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" );
3469 
3470  int pos = rx.indexIn( action, index );
3471  if ( pos < 0 )
3472  break;
3473 
3474  int start = index;
3475  index = pos + rx.matchedLength();
3476  QString to_replace = rx.cap( 1 ).trimmed();
3477  QgsDebugMsg( "Found expression: " + to_replace );
3478 
3479  QgsExpression exp( to_replace );
3480  if ( exp.hasParserError() )
3481  {
3482  QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() );
3483  expr_action += action.midRef( start, index - start );
3484  continue;
3485  }
3486 
3487  if ( distanceArea )
3488  {
3489  //if QgsDistanceArea specified for area/distance conversion, use it
3490  exp.setGeomCalculator( *distanceArea );
3491  }
3492 
3493  QVariant result = exp.evaluate( context );
3494 
3495  if ( exp.hasEvalError() )
3496  {
3497  QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() );
3498  expr_action += action.midRef( start, index - start );
3499  continue;
3500  }
3501 
3502  QgsDebugMsg( "Expression result is: " + result.toString() );
3503  expr_action += action.mid( start, pos - start ) + result.toString();
3504  }
3505 
3506  expr_action += action.midRef( index );
3507 
3508  // restore overwritten local values
3510  for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit )
3511  {
3512  QgsExpression::setSpecialColumn( sit.key(), sit.value() );
3513  }
3515 
3516  return expr_action;
3517 }
3518 
3519 double QgsExpression::evaluateToDouble( const QString &text, const double fallbackValue )
3520 {
3521  bool ok;
3522  //first test if text is directly convertible to double
3523  double convertedValue = text.toDouble( &ok );
3524  if ( ok )
3525  {
3526  return convertedValue;
3527  }
3528 
3529  //otherwise try to evalute as expression
3530  QgsExpression expr( text );
3531 
3532  QgsExpressionContext context;
3535 
3536  QVariant result = expr.evaluate( &context );
3537  convertedValue = result.toDouble( &ok );
3538  if ( expr.hasEvalError() || !ok )
3539  {
3540  return fallbackValue;
3541  }
3542  return convertedValue;
3543 }
3544 
3545 
3547 // nodes
3548 
3550 {
3551  NodeList* nl = new NodeList;
3552  Q_FOREACH ( Node* node, mList )
3553  {
3554  nl->mList.append( node->clone() );
3555  }
3556 
3557  return nl;
3558 }
3559 
3561 {
3562  QString msg;
3563  bool first = true;
3564  Q_FOREACH ( Node* n, mList )
3565  {
3566  if ( !first ) msg += ", ";
3567  else first = false;
3568  msg += n->dump();
3569  }
3570  return msg;
3571 }
3572 
3573 
3574 //
3575 
3577 {
3578  QVariant val = mOperand->eval( parent, context );
3580 
3581  switch ( mOp )
3582  {
3583  case uoNot:
3584  {
3585  TVL tvl = getTVLValue( val, parent );
3587  return tvl2variant( NOT[tvl] );
3588  }
3589 
3590  case uoMinus:
3591  if ( isIntSafe( val ) )
3592  return QVariant( - getIntValue( val, parent ) );
3593  else if ( isDoubleSafe( val ) )
3594  return QVariant( - getDoubleValue( val, parent ) );
3595  else
3596  SET_EVAL_ERROR( tr( "Unary minus only for numeric values." ) );
3597  default:
3598  Q_ASSERT( 0 && "unknown unary operation" );
3599  }
3600  return QVariant();
3601 }
3602 
3604 {
3605  return mOperand->prepare( parent, context );
3606 }
3607 
3609 {
3610  return QString( "%1 %2" ).arg( UnaryOperatorText[mOp], mOperand->dump() );
3611 }
3612 
3614 {
3615  return new NodeUnaryOperator( mOp, mOperand->clone() );
3616 }
3617 
3618 //
3619 
3621 {
3622  QVariant vL = mOpLeft->eval( parent, context );
3624  QVariant vR = mOpRight->eval( parent, context );
3626 
3627  switch ( mOp )
3628  {
3629  case boPlus:
3630  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
3631  {
3632  QString sL = isNull( vL ) ? QString() : getStringValue( vL, parent );
3634  QString sR = isNull( vR ) ? QString() : getStringValue( vR, parent );
3636  return QVariant( sL + sR );
3637  }
3638  //intentional fall-through
3639  FALLTHROUGH;
3640  case boMinus:
3641  case boMul:
3642  case boDiv:
3643  case boMod:
3644  {
3645  if ( isNull( vL ) || isNull( vR ) )
3646  return QVariant();
3647  else if ( mOp != boDiv && isIntSafe( vL ) && isIntSafe( vR ) )
3648  {
3649  // both are integers - let's use integer arithmetics
3650  int iL = getIntValue( vL, parent );
3652  int iR = getIntValue( vR, parent );
3654 
3655  if ( mOp == boMod && iR == 0 )
3656  return QVariant();
3657 
3658  return QVariant( computeInt( iL, iR ) );
3659  }
3660  else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
3661  {
3662  QDateTime dL = getDateTimeValue( vL, parent );
3664  QgsExpression::Interval iL = getInterval( vR, parent );
3666  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
3667  {
3668  parent->setEvalErrorString( tr( "Can't preform /, *, or % on DateTime and Interval" ) );
3669  return QVariant();
3670  }
3671  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
3672  }
3673  else
3674  {
3675  // general floating point arithmetic
3676  double fL = getDoubleValue( vL, parent );
3678  double fR = getDoubleValue( vR, parent );
3680  if (( mOp == boDiv || mOp == boMod ) && fR == 0. )
3681  return QVariant(); // silently handle division by zero and return NULL
3682  return QVariant( computeDouble( fL, fR ) );
3683  }
3684  }
3685  case boIntDiv:
3686  {
3687  //integer division
3688  double fL = getDoubleValue( vL, parent );
3690  double fR = getDoubleValue( vR, parent );
3692  if ( fR == 0. )
3693  return QVariant(); // silently handle division by zero and return NULL
3694  return QVariant( qFloor( fL / fR ) );
3695  }
3696  case boPow:
3697  if ( isNull( vL ) || isNull( vR ) )
3698  return QVariant();
3699  else
3700  {
3701  double fL = getDoubleValue( vL, parent );
3703  double fR = getDoubleValue( vR, parent );
3705  return QVariant( pow( fL, fR ) );
3706  }
3707 
3708  case boAnd:
3709  {
3710  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
3712  return tvl2variant( AND[tvlL][tvlR] );
3713  }
3714 
3715  case boOr:
3716  {
3717  TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
3719  return tvl2variant( OR[tvlL][tvlR] );
3720  }
3721 
3722  case boEQ:
3723  case boNE:
3724  case boLT:
3725  case boGT:
3726  case boLE:
3727  case boGE:
3728  if ( isNull( vL ) || isNull( vR ) )
3729  {
3730  return TVL_Unknown;
3731  }
3732  else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
3733  {
3734  // do numeric comparison if both operators can be converted to numbers
3735  double fL = getDoubleValue( vL, parent );
3737  double fR = getDoubleValue( vR, parent );
3739  return compare( fL - fR ) ? TVL_True : TVL_False;
3740  }
3741  else
3742  {
3743  // do string comparison otherwise
3744  QString sL = getStringValue( vL, parent );
3746  QString sR = getStringValue( vR, parent );
3748  int diff = QString::compare( sL, sR );
3749  return compare( diff ) ? TVL_True : TVL_False;
3750  }
3751 
3752  case boIs:
3753  case boIsNot:
3754  if ( isNull( vL ) && isNull( vR ) ) // both operators null
3755  return ( mOp == boIs ? TVL_True : TVL_False );
3756  else if ( isNull( vL ) || isNull( vR ) ) // one operator null
3757  return ( mOp == boIs ? TVL_False : TVL_True );
3758  else // both operators non-null
3759  {
3760  bool equal = false;
3761  if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
3762  {
3763  double fL = getDoubleValue( vL, parent );
3765  double fR = getDoubleValue( vR, parent );
3767  equal = qgsDoubleNear( fL, fR );
3768  }
3769  else
3770  {
3771  QString sL = getStringValue( vL, parent );
3773  QString sR = getStringValue( vR, parent );
3775  equal = QString::compare( sL, sR ) == 0;
3776  }
3777  if ( equal )
3778  return mOp == boIs ? TVL_True : TVL_False;
3779  else
3780  return mOp == boIs ? TVL_False : TVL_True;
3781  }
3782 
3783  case boRegexp:
3784  case boLike:
3785  case boNotLike:
3786  case boILike:
3787  case boNotILike:
3788  if ( isNull( vL ) || isNull( vR ) )
3789  return TVL_Unknown;
3790  else
3791  {
3792  QString str = getStringValue( vL, parent );
3794  QString regexp = getStringValue( vR, parent );
3796  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
3797  bool matches;
3798  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
3799  {
3800  QString esc_regexp = QRegExp::escape( regexp );
3801  // XXX escape % and _ ???
3802  esc_regexp.replace( '%', ".*" );
3803  esc_regexp.replace( '_', '.' );
3804  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
3805  }
3806  else
3807  {
3808  matches = QRegExp( regexp ).indexIn( str ) != -1;
3809  }
3810 
3811  if ( mOp == boNotLike || mOp == boNotILike )
3812  {
3813  matches = !matches;
3814  }
3815 
3816  return matches ? TVL_True : TVL_False;
3817  }
3818 
3819  case boConcat:
3820  if ( isNull( vL ) || isNull( vR ) )
3821  return QVariant();
3822  else
3823  {
3824  QString sL = getStringValue( vL, parent );
3826  QString sR = getStringValue( vR, parent );
3828  return QVariant( sL + sR );
3829  }
3830 
3831  default:
3832  break;
3833  }
3834  Q_ASSERT( false );
3835  return QVariant();
3836 }
3837 
3839 {
3840  switch ( mOp )
3841  {
3842  case boEQ:
3843  return qgsDoubleNear( diff, 0.0 );
3844  case boNE:
3845  return !qgsDoubleNear( diff, 0.0 );
3846  case boLT:
3847  return diff < 0;
3848  case boGT:
3849  return diff > 0;
3850  case boLE:
3851  return diff <= 0;
3852  case boGE:
3853  return diff >= 0;
3854  default:
3855  Q_ASSERT( false );
3856  return false;
3857  }
3858 }
3859 
3861 {
3862  switch ( mOp )
3863  {
3864  case boPlus:
3865  return x + y;
3866  case boMinus:
3867  return x -y;
3868  case boMul:
3869  return x*y;
3870  case boDiv:
3871  return x / y;
3872  case boMod:
3873  return x % y;
3874  default:
3875  Q_ASSERT( false );
3876  return 0;
3877  }
3878 }
3879 
3881 {
3882  switch ( mOp )
3883  {
3884  case boPlus:
3885  return d.addSecs( i->seconds() );
3886  case boMinus:
3887  return d.addSecs( -i->seconds() );
3888  default:
3889  Q_ASSERT( false );
3890  return QDateTime();
3891  }
3892 }
3893 
3895 {
3896  switch ( mOp )
3897  {
3898  case boPlus:
3899  return x + y;
3900  case boMinus:
3901  return x -y;
3902  case boMul:
3903  return x*y;
3904  case boDiv:
3905  return x / y;
3906  case boMod:
3907  return fmod( x, y );
3908  default:
3909  Q_ASSERT( false );
3910  return 0;
3911  }
3912 }
3913 
3915 {
3916  bool resL = mOpLeft->prepare( parent, context );
3917  bool resR = mOpRight->prepare( parent, context );
3918  return resL && resR;
3919 }
3920 
3922 {
3923  // see left/right in qgsexpressionparser.yy
3924  switch ( mOp )
3925  {
3926  case boOr:
3927  return 1;
3928 
3929  case boAnd:
3930  return 2;
3931 
3932  case boEQ:
3933  case boNE:
3934  case boLE:
3935  case boGE:
3936  case boLT:
3937  case boGT:
3938  case boRegexp:
3939  case boLike:
3940  case boILike:
3941  case boNotLike:
3942  case boNotILike:
3943  case boIs:
3944  case boIsNot:
3945  return 3;
3946 
3947  case boPlus:
3948  case boMinus:
3949  return 4;
3950 
3951  case boMul:
3952  case boDiv:
3953  case boIntDiv:
3954  case boMod:
3955  return 5;
3956 
3957  case boPow:
3958  return 6;
3959 
3960  case boConcat:
3961  return 7;
3962  }
3963  Q_ASSERT( 0 && "unexpected binary operator" );
3964  return -1;
3965 }
3966 
3968 {
3969  // see left/right in qgsexpressionparser.yy
3970  switch ( mOp )
3971  {
3972  case boOr:
3973  case boAnd:
3974  case boEQ:
3975  case boNE:
3976  case boLE:
3977  case boGE:
3978  case boLT:
3979  case boGT:
3980  case boRegexp:
3981  case boLike:
3982  case boILike:
3983  case boNotLike:
3984  case boNotILike:
3985  case boIs:
3986  case boIsNot:
3987  case boPlus:
3988  case boMinus:
3989  case boMul:
3990  case boDiv:
3991  case boIntDiv:
3992  case boMod:
3993  case boConcat:
3994  return true;
3995 
3996  case boPow:
3997  return false;
3998  }
3999  Q_ASSERT( 0 && "unexpected binary operator" );
4000  return false;
4001 }
4002 
4004 {
4005  QgsExpression::NodeBinaryOperator *lOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpLeft );
4006  QgsExpression::NodeBinaryOperator *rOp = dynamic_cast<QgsExpression::NodeBinaryOperator *>( mOpRight );
4007 
4008  QString fmt;
4009  if ( leftAssociative() )
4010  {
4011  fmt += lOp && ( lOp->precedence() < precedence() ) ? "(%1)" : "%1";
4012  fmt += " %2 ";
4013  fmt += rOp && ( rOp->precedence() <= precedence() ) ? "(%3)" : "%3";
4014  }
4015  else
4016  {
4017  fmt += lOp && ( lOp->precedence() <= precedence() ) ? "(%1)" : "%1";
4018  fmt += " %2 ";
4019  fmt += rOp && ( rOp->precedence() < precedence() ) ? "(%3)" : "%3";
4020  }
4021 
4022  return fmt.arg( mOpLeft->dump(), BinaryOperatorText[mOp], mOpRight->dump() );
4023 }
4024 
4026 {
4027  return new NodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
4028 }
4029 
4030 //
4031 
4033 {
4034  if ( mList->count() == 0 )
4035  return mNotIn ? TVL_True : TVL_False;
4036  QVariant v1 = mNode->eval( parent, context );
4038  if ( isNull( v1 ) )
4039  return TVL_Unknown;
4040 
4041  bool listHasNull = false;
4042 
4043  Q_FOREACH ( Node* n, mList->list() )
4044  {
4045  QVariant v2 = n->eval( parent, context );
4047  if ( isNull( v2 ) )
4048  listHasNull = true;
4049  else
4050  {
4051  bool equal = false;
4052  // check whether they are equal
4053  if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
4054  {
4055  double f1 = getDoubleValue( v1, parent );
4057  double f2 = getDoubleValue( v2, parent );
4059  equal = qgsDoubleNear( f1, f2 );
4060  }
4061  else
4062  {
4063  QString s1 = getStringValue( v1, parent );
4065  QString s2 = getStringValue( v2, parent );
4067  equal = QString::compare( s1, s2 ) == 0;
4068  }
4069 
4070  if ( equal ) // we know the result
4071  return mNotIn ? TVL_False : TVL_True;
4072  }
4073  }
4074 
4075  // item not found
4076  if ( listHasNull )
4077  return TVL_Unknown;
4078  else
4079  return mNotIn ? TVL_True : TVL_False;
4080 }
4081 
4083 {
4084  bool res = mNode->prepare( parent, context );
4085  Q_FOREACH ( Node* n, mList->list() )
4086  {
4087  res = res && n->prepare( parent, context );
4088  }
4089  return res;
4090 }
4091 
4093 {
4094  return QString( "%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? "NOT" : "", mList->dump() );
4095 }
4096 
4098 {
4099  return new NodeInOperator( mNode->clone(), mList->clone(), mNotIn );
4100 }
4101 
4102 //
4103 
4105 {
4106  QString name = Functions()[mFnIndex]->name();
4107  Function* fd = context && context->hasFunction( name ) ? context->function( name ) : Functions()[mFnIndex];
4108 
4109  // evaluate arguments
4110  QVariantList argValues;
4111  if ( mArgs )
4112  {
4113  Q_FOREACH ( Node* n, mArgs->list() )
4114  {
4115  QVariant v;
4116  if ( fd->lazyEval() )
4117  {
4118  // Pass in the node for the function to eval as it needs.
4119  v = QVariant::fromValue( n );
4120  }
4121  else
4122  {
4123  v = n->eval( parent, context );
4125  if ( isNull( v ) && !fd->handlesNull() )
4126  return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
4127  }
4128  argValues.append( v );
4129  }
4130  }
4131 
4132  // run the function
4133  QVariant res = fd->func( argValues, context, parent );
4135 
4136  // everything went fine
4137  return res;
4138 }
4139 
4141 {
4142  bool res = true;
4143  if ( mArgs )
4144  {
4145  Q_FOREACH ( Node* n, mArgs->list() )
4146  {
4147  res = res && n->prepare( parent, context );
4148  }
4149  }
4150  return res;
4151 }
4152 
4154 {
4155  Function* fd = Functions()[mFnIndex];
4156  if ( fd->params() == 0 )
4157  return QString( "%1%2" ).arg( fd->name(), fd->name().startsWith( '$' ) ? "" : "()" ); // special column
4158  else
4159  return QString( "%1(%2)" ).arg( fd->name(), mArgs ? mArgs->dump() : QString() ); // function
4160 }
4161 
4163 {
4164  Function* fd = Functions()[mFnIndex];
4165  QStringList functionColumns = fd->referencedColumns();
4166 
4167  if ( !mArgs )
4168  {
4169  //no referenced columns in arguments, just return function's referenced columns
4170  return functionColumns;
4171  }
4172 
4173  Q_FOREACH ( Node* n, mArgs->list() )
4174  {
4175  functionColumns.append( n->referencedColumns() );
4176  }
4177 
4178  //remove duplicates and return
4179  return functionColumns.toSet().toList();
4180 }
4181 
4183 {
4184  return new NodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
4185 }
4186 
4187 //
4188 
4190 {
4191  Q_UNUSED( context );
4192  Q_UNUSED( parent );
4193  return mValue;
4194 }
4195 
4197 {
4198  Q_UNUSED( parent );
4199  Q_UNUSED( context );
4200  return true;
4201 }
4202 
4203 
4205 {
4206  if ( mValue.isNull() )
4207  return "NULL";
4208 
4209  switch ( mValue.type() )
4210  {
4211  case QVariant::Int:
4212  return QString::number( mValue.toInt() );
4213  case QVariant::Double:
4214  return QString::number( mValue.toDouble() );
4215  case QVariant::String:
4216  return quotedString( mValue.toString() );
4217  case QVariant::Bool:
4218  return mValue.toBool() ? "TRUE" : "FALSE";
4219  default:
4220  return tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName(), mValue.toString() );
4221  }
4222 }
4223 
4225 {
4226  return new NodeLiteral( mValue );
4227 }
4228 
4229 //
4230 
4232 {
4233  Q_UNUSED( parent );
4234  if ( context && context->hasVariable( QgsExpressionContext::EXPR_FEATURE ) )
4235  {
4236  QgsFeature feature = qvariant_cast<QgsFeature>( context->variable( QgsExpressionContext::EXPR_FEATURE ) );
4237  if ( mIndex >= 0 )
4238  return feature.attribute( mIndex );
4239  else
4240  return feature.attribute( mName );
4241  }
4242  return QVariant( '[' + mName + ']' );
4243 }
4244 
4246 {
4247  if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
4248  return false;
4249 
4250  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
4251 
4252  mIndex = fields.fieldNameIndex( mName );
4253  if ( mIndex >= 0 )
4254  {
4255  return true;
4256  }
4257  else
4258  {
4259  parent->d->mEvalErrorString = tr( "Column '%1' not found" ).arg( mName );
4260  mIndex = -1;
4261  return false;
4262  }
4263 }
4264 
4266 {
4267  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
4268 }
4269 
4271 {
4272  return new NodeColumnRef( mName );
4273 }
4274 
4275 //
4276 
4278 {
4279  Q_FOREACH ( WhenThen* cond, mConditions )
4280  {
4281  QVariant vWhen = cond->mWhenExp->eval( parent, context );
4282  TVL tvl = getTVLValue( vWhen, parent );
4284  if ( tvl == True )
4285  {
4286  QVariant vRes = cond->mThenExp->eval( parent, context );
4288  return vRes;
4289  }
4290  }
4291 
4292  if ( mElseExp )
4293  {
4294  QVariant vElse = mElseExp->eval( parent, context );
4296  return vElse;
4297  }
4298 
4299  // return NULL if no condition is matching
4300  return QVariant();
4301 }
4302 
4304 {
4305  bool res;
4306  Q_FOREACH ( WhenThen* cond, mConditions )
4307  {
4308  res = cond->mWhenExp->prepare( parent, context )
4309  & cond->mThenExp->prepare( parent, context );
4310  if ( !res ) return false;
4311  }
4312 
4313  if ( mElseExp )
4314  return mElseExp->prepare( parent, context );
4315 
4316  return true;
4317 }
4318 
4320 {
4321  QString msg( "CASE" );
4322  Q_FOREACH ( WhenThen* cond, mConditions )
4323  {
4324  msg += QString( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
4325  }
4326  if ( mElseExp )
4327  msg += QString( " ELSE %1" ).arg( mElseExp->dump() );
4328  msg += QString( " END" );
4329  return msg;
4330 }
4331 
4333 {
4334  QStringList lst;
4335  Q_FOREACH ( WhenThen* cond, mConditions )
4336  {
4337  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
4338  }
4339 
4340  if ( mElseExp )
4341  lst += mElseExp->referencedColumns();
4342 
4343  return lst;
4344 }
4345 
4347 {
4348  Q_FOREACH ( WhenThen* cond, mConditions )
4349  {
4350  if ( cond->mWhenExp->needsGeometry() ||
4351  cond->mThenExp->needsGeometry() )
4352  return true;
4353  }
4354 
4355  if ( mElseExp && mElseExp->needsGeometry() )
4356  return true;
4357 
4358  return false;
4359 }
4360 
4362 {
4363  WhenThenList conditions;
4364  Q_FOREACH ( WhenThen* wt, mConditions )
4365  conditions.append( new WhenThen( wt->mWhenExp->clone(), wt->mThenExp->clone() ) );
4366  return new NodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
4367 }
4368 
4369 
4371 {
4373 
4374  if ( !gFunctionHelpTexts.contains( name ) )
4375  return tr( "function help for %1 missing" ).arg( name );
4376 
4377  const Help &f = gFunctionHelpTexts[ name ];
4378 
4379  name = f.mName;
4380  if ( f.mType == tr( "group" ) )
4381  name = group( name );
4382 
4383 #if QT_VERSION < 0x050000
4384  name =