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