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