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