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