|
QGIS API Documentation
master-6164ace
|
00001 /*************************************************************************** 00002 qgsexpression.cpp 00003 ------------------- 00004 begin : August 2011 00005 copyright : (C) 2011 Martin Dobias 00006 email : wonder.sk at gmail dot com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "qgsexpression.h" 00017 00018 #include <QtDebug> 00019 #include <QDomDocument> 00020 #include <QSettings> 00021 #include <QDate> 00022 #include <QRegExp> 00023 #include <QColor> 00024 00025 #include <math.h> 00026 #include <limits> 00027 00028 #include "qgsdistancearea.h" 00029 #include "qgsfeature.h" 00030 #include "qgsgeometry.h" 00031 #include "qgslogger.h" 00032 #include "qgsogcutils.h" 00033 #include "qgsvectorlayer.h" 00034 #include "qgssymbollayerv2utils.h" 00035 #include "qgsvectorcolorrampv2.h" 00036 #include "qgsstylev2.h" 00037 00038 // from parser 00039 extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg ); 00040 00041 QgsExpression::Interval::~Interval() {} 00042 00043 QgsExpression::Interval QgsExpression::Interval::invalidInterVal() 00044 { 00045 QgsExpression::Interval inter = QgsExpression::Interval(); 00046 inter.setValid( false ); 00047 return inter; 00048 } 00049 00050 QgsExpression::Interval QgsExpression::Interval::fromString( QString string ) 00051 { 00052 int seconds = 0; 00053 QRegExp rx( "(\\d?\\.?\\d+\\s+[a-z]+)", Qt::CaseInsensitive ); 00054 QStringList list; 00055 int pos = 0; 00056 00057 while (( pos = rx.indexIn( string, pos ) ) != -1 ) 00058 { 00059 list << rx.cap( 1 ); 00060 pos += rx.matchedLength(); 00061 } 00062 00063 foreach ( QString match, list ) 00064 { 00065 QStringList split = match.split( QRegExp( "\\s+" ) ); 00066 bool ok; 00067 int value = split.at( 0 ).toInt( &ok ); 00068 if ( !ok ) 00069 { 00070 continue; 00071 } 00072 00073 if ( match.contains( "day", Qt::CaseInsensitive ) || 00074 match.contains( QObject::tr( "day", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00075 match.contains( QObject::tr( "days", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00076 seconds += value * QgsExpression::Interval::DAY; 00077 if ( match.contains( "week", Qt::CaseInsensitive ) || 00078 match.contains( QObject::tr( "week", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00079 match.contains( QObject::tr( "weeks", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00080 seconds += value * QgsExpression::Interval::WEEKS; 00081 if ( match.contains( "month", Qt::CaseInsensitive ) || 00082 match.contains( QObject::tr( "month", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00083 match.contains( QObject::tr( "months", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00084 seconds += value * QgsExpression::Interval::MONTHS; 00085 if ( match.contains( "year", Qt::CaseInsensitive ) || 00086 match.contains( QObject::tr( "year", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00087 match.contains( QObject::tr( "years", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00088 seconds += value * QgsExpression::Interval::YEARS; 00089 if ( match.contains( "second", Qt::CaseInsensitive ) || 00090 match.contains( QObject::tr( "second", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00091 match.contains( QObject::tr( "seconds", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00092 seconds += value; 00093 if ( match.contains( "minute", Qt::CaseInsensitive ) || 00094 match.contains( QObject::tr( "minute", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00095 match.contains( QObject::tr( "minutes", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00096 seconds += value * QgsExpression::Interval::MINUTE; 00097 if ( match.contains( "hour", Qt::CaseInsensitive ) || 00098 match.contains( QObject::tr( "hour", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) || 00099 match.contains( QObject::tr( "hours", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ) 00100 seconds += value * QgsExpression::Interval::HOUR; 00101 } 00102 00103 // If we can't parse the string at all then we just return invalid 00104 if ( seconds == 0 ) 00105 return QgsExpression::Interval::invalidInterVal(); 00106 00107 return QgsExpression::Interval( seconds ); 00108 } 00109 00110 bool QgsExpression::Interval::operator==( const QgsExpression::Interval& other ) const 00111 { 00112 return ( mSeconds == other.mSeconds ); 00113 } 00114 00116 // three-value logic 00117 00118 enum TVL 00119 { 00120 False, 00121 True, 00122 Unknown 00123 }; 00124 00125 static TVL AND[3][3] = 00126 { 00127 // false true unknown 00128 { False, False, False }, // false 00129 { False, True, Unknown }, // true 00130 { False, Unknown, Unknown } // unknown 00131 }; 00132 00133 static TVL OR[3][3] = 00134 { 00135 { False, True, Unknown }, // false 00136 { True, True, True }, // true 00137 { Unknown, True, Unknown } // unknown 00138 }; 00139 00140 static TVL NOT[3] = { True, False, Unknown }; 00141 00142 static QVariant tvl2variant( TVL v ) 00143 { 00144 switch ( v ) 00145 { 00146 case False: return 0; 00147 case True: return 1; 00148 case Unknown: 00149 default: 00150 return QVariant(); 00151 } 00152 } 00153 00154 #define TVL_True QVariant(1) 00155 #define TVL_False QVariant(0) 00156 #define TVL_Unknown QVariant() 00157 00159 // QVariant checks and conversions 00160 00161 inline bool isIntSafe( const QVariant& v ) 00162 { 00163 if ( v.type() == QVariant::Int ) return true; 00164 if ( v.type() == QVariant::Double ) return false; 00165 if ( v.type() == QVariant::String ) { bool ok; v.toString().toInt( &ok ); return ok; } 00166 return false; 00167 } 00168 inline bool isDoubleSafe( const QVariant& v ) 00169 { 00170 if ( v.type() == QVariant::Double || v.type() == QVariant::Int ) return true; 00171 if ( v.type() == QVariant::String ) { bool ok; v.toString().toDouble( &ok ); return ok; } 00172 return false; 00173 } 00174 00175 inline bool isDateTimeSafe( const QVariant& v ) 00176 { 00177 return v.type() == QVariant::DateTime || v.type() == QVariant::Date || 00178 v.type() == QVariant::Time; 00179 } 00180 00181 inline bool isIntervalSafe( const QVariant& v ) 00182 { 00183 if ( v.canConvert<QgsExpression::Interval>() ) 00184 { 00185 return true; 00186 } 00187 00188 if ( v.type() == QVariant::String ) 00189 { 00190 return QgsExpression::Interval::fromString( v.toString() ).isValid(); 00191 } 00192 return false; 00193 } 00194 00195 inline bool isNull( const QVariant& v ) { return v.isNull(); } 00196 00198 // evaluation error macros 00199 00200 #define ENSURE_NO_EVAL_ERROR { if (parent->hasEvalError()) return QVariant(); } 00201 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString(x); return QVariant(); } 00202 00204 // operators 00205 00206 const char* QgsExpression::BinaryOperatorText[] = 00207 { 00208 "OR", "AND", 00209 "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT", 00210 "+", "-", "*", "/", "%", "^", 00211 "||" 00212 }; 00213 00214 const char* QgsExpression::UnaryOperatorText[] = 00215 { 00216 "NOT", "-" 00217 }; 00218 00220 // functions 00221 00222 // implicit conversion to string 00223 static QString getStringValue( const QVariant& value, QgsExpression* ) 00224 { 00225 return value.toString(); 00226 } 00227 00228 static double getDoubleValue( const QVariant& value, QgsExpression* parent ) 00229 { 00230 bool ok; 00231 double x = value.toDouble( &ok ); 00232 if ( !ok ) 00233 { 00234 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) ); 00235 return 0; 00236 } 00237 return x; 00238 } 00239 00240 static int getIntValue( const QVariant& value, QgsExpression* parent ) 00241 { 00242 bool ok; 00243 qint64 x = value.toLongLong( &ok ); 00244 if ( ok && x >= std::numeric_limits<int>::min() && x <= std::numeric_limits<int>::max() ) 00245 { 00246 return x; 00247 } 00248 else 00249 { 00250 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) ); 00251 return 0; 00252 } 00253 } 00254 00255 static QDateTime getDateTimeValue( const QVariant& value, QgsExpression* parent ) 00256 { 00257 QDateTime d = value.toDateTime(); 00258 if ( d.isValid() ) 00259 { 00260 return d; 00261 } 00262 else 00263 { 00264 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) ); 00265 return QDateTime(); 00266 } 00267 } 00268 00269 static QDate getDateValue( const QVariant& value, QgsExpression* parent ) 00270 { 00271 QDate d = value.toDate(); 00272 if ( d.isValid() ) 00273 { 00274 return d; 00275 } 00276 else 00277 { 00278 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) ); 00279 return QDate(); 00280 } 00281 } 00282 00283 static QTime getTimeValue( const QVariant& value, QgsExpression* parent ) 00284 { 00285 QTime t = value.toTime(); 00286 if ( t.isValid() ) 00287 { 00288 return t; 00289 } 00290 else 00291 { 00292 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) ); 00293 return QTime(); 00294 } 00295 } 00296 00297 static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false ) 00298 { 00299 if ( value.canConvert<QgsExpression::Interval>() ) 00300 return value.value<QgsExpression::Interval>(); 00301 00302 QgsExpression::Interval inter = QgsExpression::Interval::fromString( value.toString() ); 00303 if ( inter.isValid() ) 00304 { 00305 return inter; 00306 } 00307 // If we get here then we can't convert so we just error and return invalid. 00308 if ( report_error ) 00309 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) ); 00310 00311 return QgsExpression::Interval::invalidInterVal(); 00312 } 00313 static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent ) 00314 { 00315 if ( value.canConvert<QgsGeometry>() ) 00316 return value.value<QgsGeometry>(); 00317 00318 parent->setEvalErrorString( "Cannot convert to QgsGeometry" ); 00319 return QgsGeometry(); 00320 } 00321 00322 00323 // this handles also NULL values 00324 static TVL getTVLValue( const QVariant& value, QgsExpression* parent ) 00325 { 00326 // we need to convert to TVL 00327 if ( value.isNull() ) 00328 return Unknown; 00329 00330 if ( value.type() == QVariant::Int ) 00331 return value.toInt() != 0 ? True : False; 00332 00333 bool ok; 00334 double x = value.toDouble( &ok ); 00335 if ( !ok ) 00336 { 00337 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) ); 00338 return Unknown; 00339 } 00340 return x != 0 ? True : False; 00341 } 00342 00344 00345 static QVariant fcnSqrt( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent ) 00346 { 00347 double x = getDoubleValue( values.at( 0 ), parent ); 00348 return QVariant( sqrt( x ) ); 00349 } 00350 00351 static QVariant fcnAbs( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 00352 { 00353 double val = getDoubleValue( values.at( 0 ), parent ); 00354 return QVariant( fabs( val ) ); 00355 } 00356 00357 static QVariant fcnSin( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00358 { 00359 double x = getDoubleValue( values.at( 0 ), parent ); 00360 return QVariant( sin( x ) ); 00361 } 00362 static QVariant fcnCos( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00363 { 00364 double x = getDoubleValue( values.at( 0 ), parent ); 00365 return QVariant( cos( x ) ); 00366 } 00367 static QVariant fcnTan( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00368 { 00369 double x = getDoubleValue( values.at( 0 ), parent ); 00370 return QVariant( tan( x ) ); 00371 } 00372 static QVariant fcnAsin( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00373 { 00374 double x = getDoubleValue( values.at( 0 ), parent ); 00375 return QVariant( asin( x ) ); 00376 } 00377 static QVariant fcnAcos( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00378 { 00379 double x = getDoubleValue( values.at( 0 ), parent ); 00380 return QVariant( acos( x ) ); 00381 } 00382 static QVariant fcnAtan( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00383 { 00384 double x = getDoubleValue( values.at( 0 ), parent ); 00385 return QVariant( atan( x ) ); 00386 } 00387 static QVariant fcnAtan2( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00388 { 00389 double y = getDoubleValue( values.at( 0 ), parent ); 00390 double x = getDoubleValue( values.at( 1 ), parent ); 00391 return QVariant( atan2( y, x ) ); 00392 } 00393 static QVariant fcnExp( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00394 { 00395 double x = getDoubleValue( values.at( 0 ), parent ); 00396 return QVariant( exp( x ) ); 00397 } 00398 static QVariant fcnLn( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00399 { 00400 double x = getDoubleValue( values.at( 0 ), parent ); 00401 if ( x <= 0 ) 00402 return QVariant(); 00403 return QVariant( log( x ) ); 00404 } 00405 static QVariant fcnLog10( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00406 { 00407 double x = getDoubleValue( values.at( 0 ), parent ); 00408 if ( x <= 0 ) 00409 return QVariant(); 00410 return QVariant( log10( x ) ); 00411 } 00412 static QVariant fcnLog( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00413 { 00414 double b = getDoubleValue( values.at( 0 ), parent ); 00415 double x = getDoubleValue( values.at( 1 ), parent ); 00416 if ( x <= 0 || b <= 0 ) 00417 return QVariant(); 00418 return QVariant( log( x ) / log( b ) ); 00419 } 00420 static QVariant fcnRndF( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00421 { 00422 double min = getDoubleValue( values.at( 0 ), parent ); 00423 double max = getDoubleValue( values.at( 1 ), parent ); 00424 if ( max < min ) 00425 return QVariant(); 00426 00427 // Return a random double in the range [min, max] (inclusive) 00428 double f = ( double )rand() / RAND_MAX; 00429 return QVariant( min + f * ( max - min ) ) ; 00430 } 00431 static QVariant fcnRnd( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00432 { 00433 int min = getIntValue( values.at( 0 ), parent ); 00434 int max = getIntValue( values.at( 1 ), parent ); 00435 if ( max < min ) 00436 return QVariant(); 00437 00438 // Return a random integer in the range [min, max] (inclusive) 00439 return QVariant( min + ( rand() % ( int )( max - min + 1 ) ) ); 00440 } 00441 00442 static QVariant fcnLinearScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00443 { 00444 double val = getDoubleValue( values.at( 0 ), parent ); 00445 double domainMin = getDoubleValue( values.at( 1 ), parent ); 00446 double domainMax = getDoubleValue( values.at( 2 ), parent ); 00447 double rangeMin = getDoubleValue( values.at( 3 ), parent ); 00448 double rangeMax = getDoubleValue( values.at( 4 ), parent ); 00449 00450 if ( domainMin >= domainMax ) 00451 { 00452 parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) ); 00453 return QVariant(); 00454 } 00455 00456 // outside of domain? 00457 if ( val >= domainMax ) 00458 { 00459 return rangeMax; 00460 } 00461 else if ( val <= domainMin ) 00462 { 00463 return rangeMin; 00464 } 00465 00466 // calculate linear scale 00467 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin ); 00468 double c = rangeMin - ( domainMin * m ); 00469 00470 // Return linearly scaled value 00471 return QVariant( m * val + c ); 00472 } 00473 00474 static QVariant fcnExpScale( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00475 { 00476 double val = getDoubleValue( values.at( 0 ), parent ); 00477 double domainMin = getDoubleValue( values.at( 1 ), parent ); 00478 double domainMax = getDoubleValue( values.at( 2 ), parent ); 00479 double rangeMin = getDoubleValue( values.at( 3 ), parent ); 00480 double rangeMax = getDoubleValue( values.at( 4 ), parent ); 00481 double exponent = getDoubleValue( values.at( 5 ), parent ); 00482 00483 if ( domainMin >= domainMax ) 00484 { 00485 parent->setEvalErrorString( QObject::tr( "Domain max must be greater than domain min" ) ); 00486 return QVariant(); 00487 } 00488 if ( exponent <= 0 ) 00489 { 00490 parent->setEvalErrorString( QObject::tr( "Exponent must be greater than 0" ) ); 00491 return QVariant(); 00492 } 00493 00494 // outside of domain? 00495 if ( val >= domainMax ) 00496 { 00497 return rangeMax; 00498 } 00499 else if ( val <= domainMin ) 00500 { 00501 return rangeMin; 00502 } 00503 00504 // Return exponentially scaled value 00505 return QVariant((( rangeMax - rangeMin ) / pow( domainMax - domainMin, exponent ) ) * pow( val - domainMin, exponent ) + rangeMin ); 00506 } 00507 00508 static QVariant fcnMax( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00509 { 00510 //initially set max as first value 00511 double maxVal = getDoubleValue( values.at( 0 ), parent ); 00512 00513 //check against all other values 00514 for ( int i = 1; i < values.length(); ++i ) 00515 { 00516 double testVal = getDoubleValue( values[i], parent ); 00517 if ( testVal > maxVal ) 00518 { 00519 maxVal = testVal; 00520 } 00521 } 00522 00523 return QVariant( maxVal ); 00524 } 00525 00526 static QVariant fcnMin( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00527 { 00528 //initially set min as first value 00529 double minVal = getDoubleValue( values.at( 0 ), parent ); 00530 00531 //check against all other values 00532 for ( int i = 1; i < values.length(); ++i ) 00533 { 00534 double testVal = getDoubleValue( values[i], parent ); 00535 if ( testVal < minVal ) 00536 { 00537 minVal = testVal; 00538 } 00539 } 00540 00541 return QVariant( minVal ); 00542 } 00543 00544 static QVariant fcnClamp( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00545 { 00546 double minValue = getDoubleValue( values.at( 0 ), parent ); 00547 double testValue = getDoubleValue( values.at( 1 ), parent ); 00548 double maxValue = getDoubleValue( values.at( 2 ), parent ); 00549 00550 // force testValue to sit inside the range specified by the min and max value 00551 if ( testValue <= minValue ) 00552 { 00553 return QVariant( minValue ); 00554 } 00555 else if ( testValue >= maxValue ) 00556 { 00557 return QVariant( maxValue ); 00558 } 00559 else 00560 { 00561 return QVariant( testValue ); 00562 } 00563 } 00564 00565 static QVariant fcnFloor( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00566 { 00567 double x = getDoubleValue( values.at( 0 ), parent ); 00568 return QVariant( floor( x ) ); 00569 } 00570 00571 static QVariant fcnCeil( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00572 { 00573 double x = getDoubleValue( values.at( 0 ), parent ); 00574 return QVariant( ceil( x ) ); 00575 } 00576 00577 static QVariant fcnToInt( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00578 { 00579 return QVariant( getIntValue( values.at( 0 ), parent ) ); 00580 } 00581 static QVariant fcnToReal( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00582 { 00583 return QVariant( getDoubleValue( values.at( 0 ), parent ) ); 00584 } 00585 static QVariant fcnToString( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00586 { 00587 return QVariant( getStringValue( values.at( 0 ), parent ) ); 00588 } 00589 00590 static QVariant fcnToDateTime( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00591 { 00592 return QVariant( getDateTimeValue( values.at( 0 ), parent ) ); 00593 } 00594 00595 static QVariant fcnCoalesce( const QVariantList& values, const QgsFeature* , QgsExpression* ) 00596 { 00597 foreach ( const QVariant &value, values ) 00598 { 00599 if ( value.isNull() ) 00600 continue; 00601 return value; 00602 } 00603 return QVariant(); 00604 } 00605 static QVariant fcnLower( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00606 { 00607 QString str = getStringValue( values.at( 0 ), parent ); 00608 return QVariant( str.toLower() ); 00609 } 00610 static QVariant fcnUpper( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00611 { 00612 QString str = getStringValue( values.at( 0 ), parent ); 00613 return QVariant( str.toUpper() ); 00614 } 00615 static QVariant fcnTitle( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00616 { 00617 QString str = getStringValue( values.at( 0 ), parent ); 00618 QStringList elems = str.split( " " ); 00619 for ( int i = 0; i < elems.size(); i++ ) 00620 { 00621 if ( elems[i].size() > 1 ) 00622 elems[i] = elems[i].left( 1 ).toUpper() + elems[i].mid( 1 ).toLower(); 00623 } 00624 return QVariant( elems.join( " " ) ); 00625 } 00626 00627 static QVariant fcnTrim( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00628 { 00629 QString str = getStringValue( values.at( 0 ), parent ); 00630 return QVariant( str.trimmed() ); 00631 } 00632 00633 static QVariant fcnLength( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00634 { 00635 QString str = getStringValue( values.at( 0 ), parent ); 00636 return QVariant( str.length() ); 00637 } 00638 static QVariant fcnReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00639 { 00640 QString str = getStringValue( values.at( 0 ), parent ); 00641 QString before = getStringValue( values.at( 1 ), parent ); 00642 QString after = getStringValue( values.at( 2 ), parent ); 00643 return QVariant( str.replace( before, after ) ); 00644 } 00645 static QVariant fcnRegexpReplace( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00646 { 00647 QString str = getStringValue( values.at( 0 ), parent ); 00648 QString regexp = getStringValue( values.at( 1 ), parent ); 00649 QString after = getStringValue( values.at( 2 ), parent ); 00650 00651 QRegExp re( regexp ); 00652 if ( !re.isValid() ) 00653 { 00654 parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) ); 00655 return QVariant(); 00656 } 00657 return QVariant( str.replace( re, after ) ); 00658 } 00659 00660 static QVariant fcnRegexpMatch( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00661 { 00662 QString str = getStringValue( values.at( 0 ), parent ); 00663 QString regexp = getStringValue( values.at( 1 ), parent ); 00664 00665 QRegExp re( regexp ); 00666 if ( !re.isValid() ) 00667 { 00668 parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) ); 00669 return QVariant(); 00670 } 00671 return QVariant( str.contains( re ) ? 1 : 0 ); 00672 } 00673 00674 static QVariant fcnRegexpSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00675 { 00676 QString str = getStringValue( values.at( 0 ), parent ); 00677 QString regexp = getStringValue( values.at( 1 ), parent ); 00678 00679 QRegExp re( regexp ); 00680 if ( !re.isValid() ) 00681 { 00682 parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) ); 00683 return QVariant(); 00684 } 00685 00686 // extract substring 00687 re.indexIn( str ); 00688 if ( re.captureCount() > 0 ) 00689 { 00690 // return first capture 00691 return QVariant( re.capturedTexts()[0] ); 00692 } 00693 else 00694 { 00695 return QVariant( "" ); 00696 } 00697 } 00698 00699 static QVariant fcnSubstr( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 00700 { 00701 QString str = getStringValue( values.at( 0 ), parent ); 00702 int from = getIntValue( values.at( 1 ), parent ); 00703 int len = getIntValue( values.at( 2 ), parent ); 00704 return QVariant( str.mid( from -1, len ) ); 00705 } 00706 00707 static QVariant fcnRowNumber( const QVariantList& , const QgsFeature* , QgsExpression* parent ) 00708 { 00709 return QVariant( parent->currentRowNumber() ); 00710 } 00711 00712 static QVariant fcnFeatureId( const QVariantList& , const QgsFeature* f, QgsExpression* ) 00713 { 00714 // TODO: handling of 64-bit feature ids? 00715 return f ? QVariant(( int )f->id() ) : QVariant(); 00716 } 00717 00718 static QVariant fcnConcat( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00719 { 00720 QString concat; 00721 foreach ( const QVariant &value, values ) 00722 { 00723 concat += getStringValue( value, parent ); 00724 } 00725 return concat; 00726 } 00727 00728 static QVariant fcnStrpos( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00729 { 00730 QString string = getStringValue( values.at( 0 ), parent ); 00731 return string.indexOf( QRegExp( getStringValue( values.at( 1 ), parent ) ) ); 00732 } 00733 00734 static QVariant fcnRight( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00735 { 00736 QString string = getStringValue( values.at( 0 ), parent ); 00737 int pos = getIntValue( values.at( 1 ), parent ); 00738 return string.right( pos ); 00739 } 00740 00741 static QVariant fcnLeft( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00742 { 00743 QString string = getStringValue( values.at( 0 ), parent ); 00744 int pos = getIntValue( values.at( 1 ), parent ); 00745 return string.left( pos ); 00746 } 00747 00748 static QVariant fcnRPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00749 { 00750 QString string = getStringValue( values.at( 0 ), parent ); 00751 int length = getIntValue( values.at( 1 ), parent ); 00752 QString fill = getStringValue( values.at( 2 ), parent ); 00753 return string.rightJustified( length, fill.at( 0 ), true ); 00754 } 00755 00756 static QVariant fcnLPad( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00757 { 00758 QString string = getStringValue( values.at( 0 ), parent ); 00759 int length = getIntValue( values.at( 1 ), parent ); 00760 QString fill = getStringValue( values.at( 2 ), parent ); 00761 return string.leftJustified( length, fill.at( 0 ), true ); 00762 } 00763 00764 static QVariant fcnFormatString( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00765 { 00766 QString string = getStringValue( values.at( 0 ), parent ); 00767 for ( int n = 1; n < values.length(); n++ ) 00768 { 00769 string = string.arg( getStringValue( values.at( n ), parent ) ); 00770 } 00771 return string; 00772 } 00773 00774 00775 static QVariant fcnNow( const QVariantList&, const QgsFeature* , QgsExpression * ) 00776 { 00777 return QVariant( QDateTime::currentDateTime() ); 00778 } 00779 00780 static QVariant fcnToDate( const QVariantList& values, const QgsFeature* , QgsExpression * parent ) 00781 { 00782 return QVariant( getDateValue( values.at( 0 ), parent ) ); 00783 } 00784 00785 static QVariant fcnToTime( const QVariantList& values, const QgsFeature* , QgsExpression * parent ) 00786 { 00787 return QVariant( getTimeValue( values.at( 0 ), parent ) ); 00788 } 00789 00790 static QVariant fcnToInterval( const QVariantList& values, const QgsFeature* , QgsExpression * parent ) 00791 { 00792 return QVariant::fromValue( getInterval( values.at( 0 ), parent ) ); 00793 } 00794 00795 static QVariant fcnAge( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00796 { 00797 QDateTime d1 = getDateTimeValue( values.at( 0 ), parent ); 00798 QDateTime d2 = getDateTimeValue( values.at( 1 ), parent ); 00799 int seconds = d2.secsTo( d1 ); 00800 return QVariant::fromValue( QgsExpression::Interval( seconds ) ); 00801 } 00802 00803 static QVariant fcnDay( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00804 { 00805 QVariant value = values.at( 0 ); 00806 QgsExpression::Interval inter = getInterval( value, parent, false ); 00807 if ( inter.isValid() ) 00808 { 00809 return QVariant( inter.days() ); 00810 } 00811 else 00812 { 00813 QDateTime d1 = getDateTimeValue( value, parent ); 00814 return QVariant( d1.date().day() ); 00815 } 00816 } 00817 00818 static QVariant fcnYear( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00819 { 00820 QVariant value = values.at( 0 ); 00821 QgsExpression::Interval inter = getInterval( value, parent, false ); 00822 if ( inter.isValid() ) 00823 { 00824 return QVariant( inter.years() ); 00825 } 00826 else 00827 { 00828 QDateTime d1 = getDateTimeValue( value, parent ); 00829 return QVariant( d1.date().year() ); 00830 } 00831 } 00832 00833 static QVariant fcnMonth( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00834 { 00835 QVariant value = values.at( 0 ); 00836 QgsExpression::Interval inter = getInterval( value, parent, false ); 00837 if ( inter.isValid() ) 00838 { 00839 return QVariant( inter.months() ); 00840 } 00841 else 00842 { 00843 QDateTime d1 = getDateTimeValue( value, parent ); 00844 return QVariant( d1.date().month() ); 00845 } 00846 } 00847 00848 static QVariant fcnWeek( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00849 { 00850 QVariant value = values.at( 0 ); 00851 QgsExpression::Interval inter = getInterval( value, parent, false ); 00852 if ( inter.isValid() ) 00853 { 00854 return QVariant( inter.weeks() ); 00855 } 00856 else 00857 { 00858 QDateTime d1 = getDateTimeValue( value, parent ); 00859 return QVariant( d1.date().weekNumber() ); 00860 } 00861 } 00862 00863 static QVariant fcnHour( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00864 { 00865 QVariant value = values.at( 0 ); 00866 QgsExpression::Interval inter = getInterval( value, parent, false ); 00867 if ( inter.isValid() ) 00868 { 00869 return QVariant( inter.hours() ); 00870 } 00871 else 00872 { 00873 QDateTime d1 = getDateTimeValue( value, parent ); 00874 return QVariant( d1.time().hour() ); 00875 } 00876 } 00877 00878 static QVariant fcnMinute( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00879 { 00880 QVariant value = values.at( 0 ); 00881 QgsExpression::Interval inter = getInterval( value, parent, false ); 00882 if ( inter.isValid() ) 00883 { 00884 return QVariant( inter.minutes() ); 00885 } 00886 else 00887 { 00888 QDateTime d1 = getDateTimeValue( value, parent ); 00889 return QVariant( d1.time().minute() ); 00890 } 00891 } 00892 00893 static QVariant fcnSeconds( const QVariantList& values, const QgsFeature* , QgsExpression *parent ) 00894 { 00895 QVariant value = values.at( 0 ); 00896 QgsExpression::Interval inter = getInterval( value, parent, false ); 00897 if ( inter.isValid() ) 00898 { 00899 return QVariant( inter.seconds() ); 00900 } 00901 else 00902 { 00903 QDateTime d1 = getDateTimeValue( value, parent ); 00904 return QVariant( d1.time().second() ); 00905 } 00906 } 00907 00908 00909 #define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \ 00910 QgsGeometry* g = f->geometry(); \ 00911 if (!g || g->type() != geomtype) return QVariant(); 00912 00913 00914 static QVariant fcnX( const QVariantList& , const QgsFeature* f, QgsExpression* ) 00915 { 00916 ENSURE_GEOM_TYPE( f, g, QGis::Point ); 00917 if ( g->isMultipart() ) 00918 { 00919 return g->asMultiPoint()[ 0 ].x(); 00920 } 00921 else 00922 { 00923 return g->asPoint().x(); 00924 } 00925 } 00926 static QVariant fcnY( const QVariantList& , const QgsFeature* f, QgsExpression* ) 00927 { 00928 ENSURE_GEOM_TYPE( f, g, QGis::Point ); 00929 if ( g->isMultipart() ) 00930 { 00931 return g->asMultiPoint()[ 0 ].y(); 00932 } 00933 else 00934 { 00935 return g->asPoint().y(); 00936 } 00937 } 00938 00939 static QVariant pointAt( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) // helper function 00940 { 00941 int idx = getIntValue( values.at( 0 ), parent ); 00942 ENSURE_GEOM_TYPE( f, g, QGis::Line ); 00943 QgsPolyline polyline = g->asPolyline(); 00944 if ( idx < 0 ) 00945 idx += polyline.count(); 00946 00947 if ( idx < 0 || idx >= polyline.count() ) 00948 { 00949 parent->setEvalErrorString( QObject::tr( "Index is out of range" ) ); 00950 return QVariant(); 00951 } 00952 return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) ); 00953 } 00954 00955 static QVariant fcnXat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) 00956 { 00957 QVariant v = pointAt( values, f, parent ); 00958 if ( v.type() == QVariant::PointF ) 00959 return QVariant( v.toPointF().x() ); 00960 else 00961 return QVariant(); 00962 } 00963 static QVariant fcnYat( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) 00964 { 00965 QVariant v = pointAt( values, f, parent ); 00966 if ( v.type() == QVariant::PointF ) 00967 return QVariant( v.toPointF().y() ); 00968 else 00969 return QVariant(); 00970 } 00971 static QVariant fcnGeometry( const QVariantList& , const QgsFeature* f, QgsExpression* ) 00972 { 00973 QgsGeometry* geom = f->geometry(); 00974 if ( geom ) 00975 return QVariant::fromValue( *geom ); 00976 else 00977 return QVariant(); 00978 } 00979 static QVariant fcnGeomFromWKT( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 00980 { 00981 QString wkt = getStringValue( values.at( 0 ), parent ); 00982 QgsGeometry* geom = QgsGeometry::fromWkt( wkt ); 00983 if ( geom ) 00984 return QVariant::fromValue( *geom ); 00985 else 00986 return QVariant(); 00987 } 00988 static QVariant fcnGeomFromGML( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 00989 { 00990 QString gml = getStringValue( values.at( 0 ), parent ); 00991 QgsGeometry* geom = QgsOgcUtils::geometryFromGML( gml ); 00992 00993 if ( geom ) 00994 return QVariant::fromValue( *geom ); 00995 else 00996 return QVariant(); 00997 } 00998 00999 static QVariant fcnGeomArea( const QVariantList& , const QgsFeature* f, QgsExpression* parent ) 01000 { 01001 ENSURE_GEOM_TYPE( f, g, QGis::Polygon ); 01002 QgsDistanceArea* calc = parent->geomCalculator(); 01003 return QVariant( calc->measure( f->geometry() ) ); 01004 } 01005 static QVariant fcnGeomLength( const QVariantList& , const QgsFeature* f, QgsExpression* parent ) 01006 { 01007 ENSURE_GEOM_TYPE( f, g, QGis::Line ); 01008 QgsDistanceArea* calc = parent->geomCalculator(); 01009 return QVariant( calc->measure( f->geometry() ) ); 01010 } 01011 static QVariant fcnGeomPerimeter( const QVariantList& , const QgsFeature* f, QgsExpression* parent ) 01012 { 01013 ENSURE_GEOM_TYPE( f, g, QGis::Polygon ); 01014 QgsDistanceArea* calc = parent->geomCalculator(); 01015 return QVariant( calc->measurePerimeter( f->geometry() ) ); 01016 } 01017 01018 static QVariant fcnBbox( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01019 { 01020 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01021 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01022 return fGeom.intersects( sGeom.boundingBox() ) ? TVL_True : TVL_False; 01023 } 01024 static QVariant fcnDisjoint( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01025 { 01026 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01027 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01028 return fGeom.disjoint( &sGeom ) ? TVL_True : TVL_False; 01029 } 01030 static QVariant fcnIntersects( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01031 { 01032 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01033 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01034 return fGeom.intersects( &sGeom ) ? TVL_True : TVL_False; 01035 } 01036 static QVariant fcnTouches( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01037 { 01038 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01039 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01040 return fGeom.touches( &sGeom ) ? TVL_True : TVL_False; 01041 } 01042 static QVariant fcnCrosses( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01043 { 01044 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01045 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01046 return fGeom.crosses( &sGeom ) ? TVL_True : TVL_False; 01047 } 01048 static QVariant fcnContains( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01049 { 01050 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01051 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01052 return fGeom.contains( &sGeom ) ? TVL_True : TVL_False; 01053 } 01054 static QVariant fcnOverlaps( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01055 { 01056 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01057 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01058 return fGeom.overlaps( &sGeom ) ? TVL_True : TVL_False; 01059 } 01060 static QVariant fcnWithin( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01061 { 01062 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01063 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01064 return fGeom.within( &sGeom ) ? TVL_True : TVL_False; 01065 } 01066 static QVariant fcnBuffer( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 01067 { 01068 if ( values.length() < 2 || values.length() > 3 ) 01069 return QVariant(); 01070 01071 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01072 double dist = getDoubleValue( values.at( 1 ), parent ); 01073 int seg = 8; 01074 if ( values.length() == 3 ) 01075 seg = getIntValue( values.at( 2 ), parent ); 01076 01077 QgsGeometry* geom = fGeom.buffer( dist, seg ); 01078 if ( geom ) 01079 return QVariant::fromValue( *geom ); 01080 return QVariant(); 01081 } 01082 static QVariant fcnCentroid( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 01083 { 01084 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01085 QgsGeometry* geom = fGeom.centroid(); 01086 if ( geom ) 01087 return QVariant::fromValue( *geom ); 01088 return QVariant(); 01089 } 01090 static QVariant fcnConvexHull( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 01091 { 01092 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01093 QgsGeometry* geom = fGeom.convexHull(); 01094 if ( geom ) 01095 return QVariant::fromValue( *geom ); 01096 return QVariant(); 01097 } 01098 static QVariant fcnDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01099 { 01100 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01101 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01102 QgsGeometry* geom = fGeom.difference( &sGeom ); 01103 if ( geom ) 01104 return QVariant::fromValue( *geom ); 01105 return QVariant(); 01106 } 01107 static QVariant fcnDistance( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01108 { 01109 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01110 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01111 return QVariant( fGeom.distance( sGeom ) ); 01112 } 01113 static QVariant fcnIntersection( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01114 { 01115 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01116 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01117 QgsGeometry* geom = fGeom.intersection( &sGeom ); 01118 if ( geom ) 01119 return QVariant::fromValue( *geom ); 01120 return QVariant(); 01121 } 01122 static QVariant fcnSymDifference( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01123 { 01124 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01125 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01126 QgsGeometry* geom = fGeom.symDifference( &sGeom ); 01127 if ( geom ) 01128 return QVariant::fromValue( *geom ); 01129 return QVariant(); 01130 } 01131 static QVariant fcnCombine( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01132 { 01133 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01134 QgsGeometry sGeom = getGeometry( values.at( 1 ), parent ); 01135 QgsGeometry* geom = fGeom.combine( &sGeom ); 01136 if ( geom ) 01137 return QVariant::fromValue( *geom ); 01138 return QVariant(); 01139 } 01140 static QVariant fcnGeomToWKT( const QVariantList& values, const QgsFeature* , QgsExpression* parent ) 01141 { 01142 QgsGeometry fGeom = getGeometry( values.at( 0 ), parent ); 01143 QString wkt = fGeom.exportToWkt(); 01144 return QVariant( wkt ); 01145 } 01146 01147 static QVariant fcnRound( const QVariantList& values , const QgsFeature *f, QgsExpression* parent ) 01148 { 01149 Q_UNUSED( f ); 01150 if ( values.length() == 2 ) 01151 { 01152 double number = getDoubleValue( values.at( 0 ), parent ); 01153 double scaler = pow( 10.0, getIntValue( values.at( 1 ), parent ) ); 01154 return QVariant( qRound( number * scaler ) / scaler ); 01155 } 01156 01157 if ( values.length() == 1 ) 01158 { 01159 double number = getIntValue( values.at( 0 ), parent ); 01160 return QVariant( qRound( number ) ).toInt(); 01161 } 01162 01163 return QVariant(); 01164 } 01165 01166 static QVariant fcnPi( const QVariantList& values , const QgsFeature *f, QgsExpression* parent ) 01167 { 01168 Q_UNUSED( values ); 01169 Q_UNUSED( f ); 01170 Q_UNUSED( parent ); 01171 return M_PI; 01172 } 01173 01174 static QVariant fcnScale( const QVariantList&, const QgsFeature*, QgsExpression* parent ) 01175 { 01176 return QVariant( parent->scale() ); 01177 } 01178 01179 static QVariant fcnFormatNumber( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 01180 { 01181 double value = getDoubleValue( values.at( 0 ), parent ); 01182 int places = getIntValue( values.at( 1 ), parent ); 01183 return QString( "%L1" ).arg( value, 0, 'f', places ); 01184 } 01185 01186 static QVariant fcnFormatDate( const QVariantList& values, const QgsFeature*, QgsExpression* parent ) 01187 { 01188 QDateTime dt = getDateTimeValue( values.at( 0 ), parent ); 01189 QString format = getStringValue( values.at( 1 ), parent ); 01190 return dt.toString( format ); 01191 } 01192 01193 static QVariant fcnColorRgb( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01194 { 01195 int red = getIntValue( values.at( 0 ), parent ); 01196 int green = getIntValue( values.at( 1 ), parent ); 01197 int blue = getIntValue( values.at( 2 ), parent ); 01198 QColor color = QColor( red, green, blue ); 01199 if ( ! color.isValid() ) 01200 { 01201 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) ); 01202 color = QColor( 0, 0, 0 ); 01203 } 01204 01205 return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ); 01206 } 01207 01208 static QVariant fncColorRgba( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01209 { 01210 int red = getIntValue( values.at( 0 ), parent ); 01211 int green = getIntValue( values.at( 1 ), parent ); 01212 int blue = getIntValue( values.at( 2 ), parent ); 01213 int alpha = getIntValue( values.at( 3 ), parent ); 01214 QColor color = QColor( red, green, blue, alpha ); 01215 if ( ! color.isValid() ) 01216 { 01217 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) ); 01218 color = QColor( 0, 0, 0 ); 01219 } 01220 return QgsSymbolLayerV2Utils::encodeColor( color ); 01221 } 01222 01223 QVariant fcnRampColor( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01224 { 01225 QString rampName = getStringValue( values.at( 0 ), parent ); 01226 const QgsVectorColorRampV2 *mRamp = QgsStyleV2::defaultStyle()->colorRampRef( rampName ); 01227 if ( ! mRamp ) 01228 { 01229 parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) ); 01230 return QColor( 0, 0, 0 ).name(); 01231 } 01232 double value = getDoubleValue( values.at( 1 ), parent ); 01233 QColor color = mRamp->color( value ); 01234 return QgsSymbolLayerV2Utils::encodeColor( color ); 01235 } 01236 01237 static QVariant fcnColorHsl( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01238 { 01239 // Hue ranges from 0 - 360 01240 double hue = getIntValue( values.at( 0 ), parent ) / 360.0; 01241 // Saturation ranges from 0 - 100 01242 double saturation = getIntValue( values.at( 1 ), parent ) / 100.0; 01243 // Lightness ranges from 0 - 100 01244 double lightness = getIntValue( values.at( 2 ), parent ) / 100.0; 01245 01246 QColor color = QColor::fromHslF( hue, saturation, lightness ); 01247 01248 if ( ! color.isValid() ) 01249 { 01250 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) ); 01251 color = QColor( 0, 0, 0 ); 01252 } 01253 01254 return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ); 01255 } 01256 01257 static QVariant fncColorHsla( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01258 { 01259 // Hue ranges from 0 - 360 01260 double hue = getIntValue( values.at( 0 ), parent ) / 360.0; 01261 // Saturation ranges from 0 - 100 01262 double saturation = getIntValue( values.at( 1 ), parent ) / 100.0; 01263 // Lightness ranges from 0 - 100 01264 double lightness = getIntValue( values.at( 2 ), parent ) / 100.0; 01265 // Alpha ranges from 0 - 255 01266 double alpha = getIntValue( values.at( 3 ), parent ) / 255.0; 01267 01268 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha ); 01269 if ( ! color.isValid() ) 01270 { 01271 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) ); 01272 color = QColor( 0, 0, 0 ); 01273 } 01274 return QgsSymbolLayerV2Utils::encodeColor( color ); 01275 } 01276 01277 static QVariant fcnColorHsv( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01278 { 01279 // Hue ranges from 0 - 360 01280 double hue = getIntValue( values.at( 0 ), parent ) / 360.0; 01281 // Saturation ranges from 0 - 100 01282 double saturation = getIntValue( values.at( 1 ), parent ) / 100.0; 01283 // Value ranges from 0 - 100 01284 double value = getIntValue( values.at( 2 ), parent ) / 100.0; 01285 01286 QColor color = QColor::fromHsvF( hue, saturation, value ); 01287 01288 if ( ! color.isValid() ) 01289 { 01290 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) ); 01291 color = QColor( 0, 0, 0 ); 01292 } 01293 01294 return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ); 01295 } 01296 01297 static QVariant fncColorHsva( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01298 { 01299 // Hue ranges from 0 - 360 01300 double hue = getIntValue( values.at( 0 ), parent ) / 360.0; 01301 // Saturation ranges from 0 - 100 01302 double saturation = getIntValue( values.at( 1 ), parent ) / 100.0; 01303 // Value ranges from 0 - 100 01304 double value = getIntValue( values.at( 2 ), parent ) / 100.0; 01305 // Alpha ranges from 0 - 255 01306 double alpha = getIntValue( values.at( 3 ), parent ) / 255.0; 01307 01308 QColor color = QColor::fromHsvF( hue, saturation, value, alpha ); 01309 if ( ! color.isValid() ) 01310 { 01311 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) ); 01312 color = QColor( 0, 0, 0 ); 01313 } 01314 return QgsSymbolLayerV2Utils::encodeColor( color ); 01315 } 01316 01317 static QVariant fcnColorCmyk( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01318 { 01319 // Cyan ranges from 0 - 100 01320 double cyan = getIntValue( values.at( 0 ), parent ) / 100.0; 01321 // Magenta ranges from 0 - 100 01322 double magenta = getIntValue( values.at( 1 ), parent ) / 100.0; 01323 // Yellow ranges from 0 - 100 01324 double yellow = getIntValue( values.at( 2 ), parent ) / 100.0; 01325 // Black ranges from 0 - 100 01326 double black = getIntValue( values.at( 3 ), parent ) / 100.0; 01327 01328 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black ); 01329 01330 if ( ! color.isValid() ) 01331 { 01332 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) ); 01333 color = QColor( 0, 0, 0 ); 01334 } 01335 01336 return QString( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ); 01337 } 01338 01339 static QVariant fncColorCmyka( const QVariantList &values, const QgsFeature *, QgsExpression *parent ) 01340 { 01341 // Cyan ranges from 0 - 100 01342 double cyan = getIntValue( values.at( 0 ), parent ) / 100.0; 01343 // Magenta ranges from 0 - 100 01344 double magenta = getIntValue( values.at( 1 ), parent ) / 100.0; 01345 // Yellow ranges from 0 - 100 01346 double yellow = getIntValue( values.at( 2 ), parent ) / 100.0; 01347 // Black ranges from 0 - 100 01348 double black = getIntValue( values.at( 3 ), parent ) / 100.0; 01349 // Alpha ranges from 0 - 255 01350 double alpha = getIntValue( values.at( 4 ), parent ) / 255.0; 01351 01352 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha ); 01353 if ( ! color.isValid() ) 01354 { 01355 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) ); 01356 color = QColor( 0, 0, 0 ); 01357 } 01358 return QgsSymbolLayerV2Utils::encodeColor( color ); 01359 } 01360 01361 static QVariant fcnSpecialColumn( const QVariantList& values, const QgsFeature* /*f*/, QgsExpression* parent ) 01362 { 01363 QString varName = getStringValue( values.at( 0 ), parent ); 01364 return QgsExpression::specialColumn( varName ); 01365 } 01366 01367 bool QgsExpression::registerFunction( QgsExpression::Function* function ) 01368 { 01369 int fnIdx = functionIndex( function->name() ); 01370 if ( fnIdx != -1 ) 01371 { 01372 return false; 01373 } 01374 QgsExpression::gmFunctions.append( function ); 01375 return true; 01376 } 01377 01378 bool QgsExpression::unregisterFunction( QString name ) 01379 { 01380 // You can never override the built in functions. 01381 if ( QgsExpression::BuiltinFunctions().contains( name ) ) 01382 { 01383 return false; 01384 } 01385 int fnIdx = functionIndex( name ); 01386 if ( fnIdx != -1 ) 01387 { 01388 QgsExpression::gmFunctions.removeAt( fnIdx ); 01389 return true; 01390 } 01391 return false; 01392 } 01393 01394 01395 01396 QStringList QgsExpression::gmBuiltinFunctions; 01397 01398 const QStringList &QgsExpression::BuiltinFunctions() 01399 { 01400 if ( gmBuiltinFunctions.isEmpty() ) 01401 { 01402 gmBuiltinFunctions 01403 << "abs" << "sqrt" << "cos" << "sin" << "tan" 01404 << "asin" << "acos" << "atan" << "atan2" 01405 << "exp" << "ln" << "log10" << "log" 01406 << "round" << "rand" << "randf" << "max" << "min" << "clamp" 01407 << "scale_linear" << "scale_exp" << "floor" << "ceil" 01408 << "toint" << "toreal" << "tostring" 01409 << "todatetime" << "todate" << "totime" << "tointerval" 01410 << "coalesce" << "regexp_match" << "$now" << "age" << "year" 01411 << "month" << "week" << "day" << "hour" 01412 << "minute" << "second" << "lower" << "upper" 01413 << "title" << "length" << "replace" << "trim" 01414 << "regexp_replace" << "regexp_substr" 01415 << "substr" << "concat" << "strpos" << "left" 01416 << "right" << "rpad" << "lpad" 01417 << "format_number" << "format_date" 01418 << "color_rgb" << "color_rgba" << "ramp_color" 01419 << "color_hsl" << "color_hsla" << "color_hsv" << "color_hsva" 01420 << "color_cymk" << "color_cymka" 01421 << "xat" << "yat" << "$area" 01422 << "$length" << "$perimeter" << "$x" << "$y" 01423 << "$rownum" << "$id" << "$scale" << "_specialcol_"; 01424 } 01425 return gmBuiltinFunctions; 01426 } 01427 01428 QList<QgsExpression::Function*> QgsExpression::gmFunctions; 01429 01430 const QList<QgsExpression::Function*> &QgsExpression::Functions() 01431 { 01432 if ( gmFunctions.isEmpty() ) 01433 { 01434 gmFunctions 01435 << new StaticFunction( "sqrt", 1, fcnSqrt, "Math" ) 01436 << new StaticFunction( "abs", 1, fcnAbs, "Math" ) 01437 << new StaticFunction( "cos", 1, fcnCos, "Math" ) 01438 << new StaticFunction( "sin", 1, fcnSin, "Math" ) 01439 << new StaticFunction( "tan", 1, fcnTan, "Math" ) 01440 << new StaticFunction( "asin", 1, fcnAsin, "Math" ) 01441 << new StaticFunction( "acos", 1, fcnAcos, "Math" ) 01442 << new StaticFunction( "atan", 1, fcnAtan, "Math" ) 01443 << new StaticFunction( "atan2", 2, fcnAtan2, "Math" ) 01444 << new StaticFunction( "exp", 1, fcnExp, "Math" ) 01445 << new StaticFunction( "ln", 1, fcnLn, "Math" ) 01446 << new StaticFunction( "log10", 1, fcnLog10, "Math" ) 01447 << new StaticFunction( "log", 2, fcnLog, "Math" ) 01448 << new StaticFunction( "round", -1, fcnRound, "Math" ) 01449 << new StaticFunction( "rand", 2, fcnRnd, "Math" ) 01450 << new StaticFunction( "randf", 2, fcnRndF, "Math" ) 01451 << new StaticFunction( "max", -1, fcnMax, "Math" ) 01452 << new StaticFunction( "min", -1, fcnMin, "Math" ) 01453 << new StaticFunction( "clamp", 3, fcnClamp, "Math" ) 01454 << new StaticFunction( "scale_linear", 5, fcnLinearScale, "Math" ) 01455 << new StaticFunction( "scale_exp", 6, fcnExpScale, "Math" ) 01456 << new StaticFunction( "floor", 1, fcnFloor, "Math" ) 01457 << new StaticFunction( "ceil", 1, fcnCeil, "Math" ) 01458 << new StaticFunction( "$pi", 0, fcnPi, "Math" ) 01459 << new StaticFunction( "toint", 1, fcnToInt, "Conversions" ) 01460 << new StaticFunction( "toreal", 1, fcnToReal, "Conversions" ) 01461 << new StaticFunction( "tostring", 1, fcnToString, "Conversions" ) 01462 << new StaticFunction( "todatetime", 1, fcnToDateTime, "Conversions" ) 01463 << new StaticFunction( "todate", 1, fcnToDate, "Conversions" ) 01464 << new StaticFunction( "totime", 1, fcnToTime, "Conversions" ) 01465 << new StaticFunction( "tointerval", 1, fcnToInterval, "Conversions" ) 01466 << new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" ) 01467 << new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" ) 01468 << new StaticFunction( "$now", 0, fcnNow, "Date and Time" ) 01469 << new StaticFunction( "age", 2, fcnAge, "Date and Time" ) 01470 << new StaticFunction( "year", 1, fcnYear, "Date and Time" ) 01471 << new StaticFunction( "month", 1, fcnMonth, "Date and Time" ) 01472 << new StaticFunction( "week", 1, fcnWeek, "Date and Time" ) 01473 << new StaticFunction( "day", 1, fcnDay, "Date and Time" ) 01474 << new StaticFunction( "hour", 1, fcnHour, "Date and Time" ) 01475 << new StaticFunction( "minute", 1, fcnMinute, "Date and Time" ) 01476 << new StaticFunction( "second", 1, fcnSeconds, "Date and Time" ) 01477 << new StaticFunction( "lower", 1, fcnLower, "String" ) 01478 << new StaticFunction( "upper", 1, fcnUpper, "String" ) 01479 << new StaticFunction( "title", 1, fcnTitle, "String" ) 01480 << new StaticFunction( "trim", 1, fcnTrim, "String" ) 01481 << new StaticFunction( "length", 1, fcnLength, "String" ) 01482 << new StaticFunction( "replace", 3, fcnReplace, "String" ) 01483 << new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" ) 01484 << new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" ) 01485 << new StaticFunction( "substr", 3, fcnSubstr, "String" ) 01486 << new StaticFunction( "concat", -1, fcnConcat, "String" ) 01487 << new StaticFunction( "strpos", 2, fcnStrpos, "String" ) 01488 << new StaticFunction( "left", 2, fcnLeft, "String" ) 01489 << new StaticFunction( "right", 2, fcnRight, "String" ) 01490 << new StaticFunction( "rpad", 3, fcnRPad, "String" ) 01491 << new StaticFunction( "lpad", 3, fcnLPad, "String" ) 01492 << new StaticFunction( "format", -1, fcnFormatString, "String" ) 01493 << new StaticFunction( "format_number", 2, fcnFormatNumber, "String" ) 01494 << new StaticFunction( "format_date", 2, fcnFormatDate, "String" ) 01495 << new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" ) 01496 << new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" ) 01497 << new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" ) 01498 << new StaticFunction( "color_hsl", 3, fcnColorHsl, "Color" ) 01499 << new StaticFunction( "color_hsla", 4, fncColorHsla, "Color" ) 01500 << new StaticFunction( "color_hsv", 3, fcnColorHsv, "Color" ) 01501 << new StaticFunction( "color_hsva", 4, fncColorHsva, "Color" ) 01502 << new StaticFunction( "color_cmyk", 4, fcnColorCmyk, "Color" ) 01503 << new StaticFunction( "color_cmyka", 5, fncColorCmyka, "Color" ) 01504 << new StaticFunction( "xat", 1, fcnXat, "Geometry", "", true ) 01505 << new StaticFunction( "yat", 1, fcnYat, "Geometry", "", true ) 01506 << new StaticFunction( "$area", 0, fcnGeomArea, "Geometry", "", true ) 01507 << new StaticFunction( "$length", 0, fcnGeomLength, "Geometry", "", true ) 01508 << new StaticFunction( "$perimeter", 0, fcnGeomPerimeter, "Geometry", "", true ) 01509 << new StaticFunction( "$x", 0, fcnX, "Geometry", "", true ) 01510 << new StaticFunction( "$y", 0, fcnY, "Geometry", "" , true ) 01511 << new StaticFunction( "$geometry", 0, fcnGeometry, "Geometry", "" , true ) 01512 << new StaticFunction( "geomFromWKT", 1, fcnGeomFromWKT, "Geometry" ) 01513 << new StaticFunction( "geomFromGML", 1, fcnGeomFromGML, "Geometry" ) 01514 << new StaticFunction( "bbox", 2, fcnBbox, "Geometry" ) 01515 << new StaticFunction( "disjoint", 2, fcnDisjoint, "Geometry" ) 01516 << new StaticFunction( "intersects", 2, fcnIntersects, "Geometry" ) 01517 << new StaticFunction( "touches", 2, fcnTouches, "Geometry" ) 01518 << new StaticFunction( "crosses", 2, fcnCrosses, "Geometry" ) 01519 << new StaticFunction( "contains", 2, fcnContains, "Geometry" ) 01520 << new StaticFunction( "overlaps", 2, fcnOverlaps, "Geometry" ) 01521 << new StaticFunction( "within", 2, fcnWithin, "Geometry" ) 01522 << new StaticFunction( "buffer", -1, fcnBuffer, "Geometry" ) 01523 << new StaticFunction( "centroid", 1, fcnCentroid, "Geometry" ) 01524 << new StaticFunction( "convexHull", 1, fcnConvexHull, "Geometry" ) 01525 << new StaticFunction( "difference", 2, fcnDifference, "Geometry" ) 01526 << new StaticFunction( "distance", 2, fcnDistance, "Geometry" ) 01527 << new StaticFunction( "intersection", 2, fcnIntersection, "Geometry" ) 01528 << new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" ) 01529 << new StaticFunction( "combine", 2, fcnCombine, "Geometry" ) 01530 << new StaticFunction( "union", 2, fcnCombine, "Geometry" ) 01531 << new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" ) 01532 << new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" ) 01533 << new StaticFunction( "$id", 0, fcnFeatureId, "Record" ) 01534 << new StaticFunction( "$scale", 0, fcnScale, "Record" ) 01535 << new StaticFunction( "_specialcol_", 1, fcnSpecialColumn, "Special" ) 01536 ; 01537 } 01538 return gmFunctions; 01539 } 01540 01541 QMap<QString, QVariant> QgsExpression::gmSpecialColumns; 01542 01543 void QgsExpression::setSpecialColumn( const QString& name, QVariant variant ) 01544 { 01545 int fnIdx = functionIndex( name ); 01546 if ( fnIdx != -1 ) 01547 { 01548 // function of the same name already exists 01549 return; 01550 } 01551 gmSpecialColumns[ name ] = variant; 01552 } 01553 01554 void QgsExpression::unsetSpecialColumn( const QString& name ) 01555 { 01556 QMap<QString, QVariant>::iterator fit = gmSpecialColumns.find( name ); 01557 if ( fit != gmSpecialColumns.end() ) 01558 { 01559 gmSpecialColumns.erase( fit ); 01560 } 01561 } 01562 01563 QVariant QgsExpression::specialColumn( const QString& name ) 01564 { 01565 int fnIdx = functionIndex( name ); 01566 if ( fnIdx != -1 ) 01567 { 01568 // function of the same name already exists 01569 return QVariant(); 01570 } 01571 QMap<QString, QVariant>::iterator it = gmSpecialColumns.find( name ); 01572 if ( it == gmSpecialColumns.end() ) 01573 { 01574 return QVariant(); 01575 } 01576 return it.value(); 01577 } 01578 01579 QList<QgsExpression::Function*> QgsExpression::specialColumns() 01580 { 01581 QList<Function*> defs; 01582 for ( QMap<QString, QVariant>::const_iterator it = gmSpecialColumns.begin(); it != gmSpecialColumns.end(); ++it ) 01583 { 01584 defs << new StaticFunction( it.key(), 0, 0, "Record" ); 01585 } 01586 return defs; 01587 } 01588 01589 bool QgsExpression::isFunctionName( QString name ) 01590 { 01591 return functionIndex( name ) != -1; 01592 } 01593 01594 int QgsExpression::functionIndex( QString name ) 01595 { 01596 int count = functionCount(); 01597 for ( int i = 0; i < count; i++ ) 01598 { 01599 if ( QString::compare( name, Functions()[i]->name(), Qt::CaseInsensitive ) == 0 ) 01600 return i; 01601 } 01602 return -1; 01603 } 01604 01605 int QgsExpression::functionCount() 01606 { 01607 return Functions().size(); 01608 } 01609 01610 01611 QgsExpression::QgsExpression( const QString& expr ) 01612 : mExpression( expr ) 01613 , mRowNumber( 0 ) 01614 , mScale( 0 ) 01615 01616 { 01617 initGeomCalculator(); 01618 01619 mRootNode = ::parseExpression( mExpression, mParserErrorString ); 01620 01621 if ( mParserErrorString.isNull() ) 01622 { 01623 Q_ASSERT( mRootNode != NULL ); 01624 } 01625 } 01626 01627 QgsExpression::~QgsExpression() 01628 { 01629 delete mRootNode; 01630 } 01631 01632 QStringList QgsExpression::referencedColumns() 01633 { 01634 if ( !mRootNode ) 01635 return QStringList(); 01636 QStringList columns = mRootNode->referencedColumns(); 01637 01638 // filter out duplicates 01639 for ( int i = 0; i < columns.count(); i++ ) 01640 { 01641 QString col = columns.at( i ); 01642 for ( int j = i + 1; j < columns.count(); j++ ) 01643 { 01644 if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 ) 01645 { 01646 // this column is repeated: remove it! 01647 columns.removeAt( j-- ); 01648 } 01649 } 01650 } 01651 01652 return columns; 01653 } 01654 01655 bool QgsExpression::needsGeometry() 01656 { 01657 if ( !mRootNode ) 01658 return false; 01659 return mRootNode->needsGeometry(); 01660 } 01661 01662 void QgsExpression::initGeomCalculator() 01663 { 01664 // Use planimetric as default 01665 mCalc.setEllipsoidalMode( false ); 01666 } 01667 01668 void QgsExpression::setGeomCalculator( QgsDistanceArea& calc ) 01669 { 01670 // Copy from supplied calculator 01671 mCalc.setEllipsoid( calc.ellipsoid() ); 01672 mCalc.setEllipsoidalMode( calc.ellipsoidalEnabled() ); 01673 mCalc.setSourceCrs( calc.sourceCrs() ); 01674 } 01675 01676 bool QgsExpression::prepare( const QgsFields& fields ) 01677 { 01678 mEvalErrorString = QString(); 01679 if ( !mRootNode ) 01680 { 01681 mEvalErrorString = QObject::tr( "No root node! Parsing failed?" ); 01682 return false; 01683 } 01684 01685 return mRootNode->prepare( this, fields ); 01686 } 01687 01688 QVariant QgsExpression::evaluate( const QgsFeature* f ) 01689 { 01690 mEvalErrorString = QString(); 01691 if ( !mRootNode ) 01692 { 01693 mEvalErrorString = QObject::tr( "No root node! Parsing failed?" ); 01694 return QVariant(); 01695 } 01696 01697 return mRootNode->eval( this, f ); 01698 } 01699 01700 QVariant QgsExpression::evaluate( const QgsFeature* f, const QgsFields& fields ) 01701 { 01702 // first prepare 01703 bool res = prepare( fields ); 01704 if ( !res ) 01705 return QVariant(); 01706 01707 // then evaluate 01708 return evaluate( f ); 01709 } 01710 01711 QString QgsExpression::dump() const 01712 { 01713 if ( !mRootNode ) 01714 return QObject::tr( "(no root)" ); 01715 01716 return mRootNode->dump(); 01717 } 01718 01719 void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const 01720 { 01721 if ( mRootNode ) 01722 mRootNode->accept( v ); 01723 } 01724 01725 QString QgsExpression::replaceExpressionText( QString action, QgsFeature* feat, 01726 QgsVectorLayer* layer, 01727 const QMap<QString, QVariant> *substitutionMap ) 01728 { 01729 QString expr_action; 01730 01731 QMap<QString, QVariant> savedValues; 01732 if ( substitutionMap ) 01733 { 01734 // variables with a local scope (must be restored after evaluation) 01735 for ( QMap<QString, QVariant>::const_iterator sit = substitutionMap->begin(); sit != substitutionMap->end(); ++sit ) 01736 { 01737 QVariant oldValue = QgsExpression::specialColumn( sit.key() ); 01738 if ( !oldValue.isNull() ) 01739 savedValues.insert( sit.key(), oldValue ); 01740 01741 // set the new value 01742 QgsExpression::setSpecialColumn( sit.key(), sit.value() ); 01743 } 01744 } 01745 01746 int index = 0; 01747 while ( index < action.size() ) 01748 { 01749 QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" ); 01750 01751 int pos = rx.indexIn( action, index ); 01752 if ( pos < 0 ) 01753 break; 01754 01755 int start = index; 01756 index = pos + rx.matchedLength(); 01757 QString to_replace = rx.cap( 1 ).trimmed(); 01758 QgsDebugMsg( "Found expression: " + to_replace ); 01759 01760 QgsExpression exp( to_replace ); 01761 if ( exp.hasParserError() ) 01762 { 01763 QgsDebugMsg( "Expression parser error: " + exp.parserErrorString() ); 01764 expr_action += action.mid( start, index - start ); 01765 continue; 01766 } 01767 01768 QVariant result; 01769 if ( layer ) 01770 { 01771 result = exp.evaluate( feat, layer->pendingFields() ); 01772 } 01773 else 01774 { 01775 result = exp.evaluate( feat ); 01776 } 01777 if ( exp.hasEvalError() ) 01778 { 01779 QgsDebugMsg( "Expression parser eval error: " + exp.evalErrorString() ); 01780 expr_action += action.mid( start, index - start ); 01781 continue; 01782 } 01783 01784 QgsDebugMsg( "Expression result is: " + result.toString() ); 01785 expr_action += action.mid( start, pos - start ) + result.toString(); 01786 } 01787 01788 expr_action += action.mid( index ); 01789 01790 // restore overwritten local values 01791 for ( QMap<QString, QVariant>::const_iterator sit = savedValues.begin(); sit != savedValues.end(); ++sit ) 01792 { 01793 QgsExpression::setSpecialColumn( sit.key(), sit.value() ); 01794 } 01795 01796 return expr_action; 01797 } 01798 01799 01800 QString QgsExpression::replaceExpressionText( QString action, QgsFeature& feat, 01801 QgsVectorLayer* layer, 01802 const QMap<QString, QVariant> *substitutionMap ) 01803 { 01804 return replaceExpressionText( action, &feat, layer, substitutionMap ); 01805 } 01806 01807 01809 // nodes 01810 01811 QString QgsExpression::NodeList::dump() const 01812 { 01813 QString msg; bool first = true; 01814 foreach ( Node* n, mList ) 01815 { 01816 if ( !first ) msg += ", "; else first = false; 01817 msg += n->dump(); 01818 } 01819 return msg; 01820 } 01821 01822 01823 // 01824 01825 QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression* parent, const QgsFeature* f ) 01826 { 01827 QVariant val = mOperand->eval( parent, f ); 01828 ENSURE_NO_EVAL_ERROR; 01829 01830 switch ( mOp ) 01831 { 01832 case uoNot: 01833 { 01834 TVL tvl = getTVLValue( val, parent ); 01835 ENSURE_NO_EVAL_ERROR; 01836 return tvl2variant( NOT[tvl] ); 01837 } 01838 01839 case uoMinus: 01840 if ( isIntSafe( val ) ) 01841 return QVariant( - getIntValue( val, parent ) ); 01842 else if ( isDoubleSafe( val ) ) 01843 return QVariant( - getDoubleValue( val, parent ) ); 01844 else 01845 SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) ); 01846 break; 01847 default: 01848 Q_ASSERT( 0 && "unknown unary operation" ); 01849 } 01850 return QVariant(); 01851 } 01852 01853 bool QgsExpression::NodeUnaryOperator::prepare( QgsExpression* parent, const QgsFields& fields ) 01854 { 01855 return mOperand->prepare( parent, fields ); 01856 } 01857 01858 QString QgsExpression::NodeUnaryOperator::dump() const 01859 { 01860 return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() ); 01861 } 01862 01863 // 01864 01865 QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression* parent, const QgsFeature* f ) 01866 { 01867 QVariant vL = mOpLeft->eval( parent, f ); 01868 ENSURE_NO_EVAL_ERROR; 01869 QVariant vR = mOpRight->eval( parent, f ); 01870 ENSURE_NO_EVAL_ERROR; 01871 01872 switch ( mOp ) 01873 { 01874 case boPlus: 01875 case boMinus: 01876 case boMul: 01877 case boDiv: 01878 case boMod: 01879 if ( isNull( vL ) || isNull( vR ) ) 01880 return QVariant(); 01881 else if ( isIntSafe( vL ) && isIntSafe( vR ) ) 01882 { 01883 // both are integers - let's use integer arithmetics 01884 int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01885 int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01886 if ( mOp == boDiv && iR == 0 ) return QVariant(); // silently handle division by zero and return NULL 01887 return QVariant( computeInt( iL, iR ) ); 01888 } 01889 else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) ) 01890 { 01891 QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01892 QgsExpression::Interval iL = getInterval( vR, parent ); ENSURE_NO_EVAL_ERROR; 01893 if ( mOp == boDiv || mOp == boMul || mOp == boMod ) 01894 { 01895 parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) ); 01896 return QVariant(); 01897 } 01898 return QVariant( computeDateTimeFromInterval( dL, &iL ) ); 01899 } 01900 else 01901 { 01902 // general floating point arithmetic 01903 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01904 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01905 if ( mOp == boDiv && fR == 0 ) 01906 return QVariant(); // silently handle division by zero and return NULL 01907 return QVariant( computeDouble( fL, fR ) ); 01908 } 01909 01910 case boPow: 01911 if ( isNull( vL ) || isNull( vR ) ) 01912 return QVariant(); 01913 else 01914 { 01915 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01916 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01917 return QVariant( pow( fL, fR ) ); 01918 } 01919 01920 case boAnd: 01921 { 01922 TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent ); 01923 ENSURE_NO_EVAL_ERROR; 01924 return tvl2variant( AND[tvlL][tvlR] ); 01925 } 01926 01927 case boOr: 01928 { 01929 TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent ); 01930 ENSURE_NO_EVAL_ERROR; 01931 return tvl2variant( OR[tvlL][tvlR] ); 01932 } 01933 01934 case boEQ: 01935 case boNE: 01936 case boLT: 01937 case boGT: 01938 case boLE: 01939 case boGE: 01940 if ( isNull( vL ) || isNull( vR ) ) 01941 { 01942 return TVL_Unknown; 01943 } 01944 else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) ) 01945 { 01946 // do numeric comparison if both operators can be converted to numbers 01947 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01948 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01949 return compare( fL - fR ) ? TVL_True : TVL_False; 01950 } 01951 else 01952 { 01953 // do string comparison otherwise 01954 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01955 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01956 int diff = QString::compare( sL, sR ); 01957 return compare( diff ) ? TVL_True : TVL_False; 01958 } 01959 01960 case boIs: 01961 case boIsNot: 01962 if ( isNull( vL ) && isNull( vR ) ) // both operators null 01963 return ( mOp == boIs ? TVL_True : TVL_False ); 01964 else if ( isNull( vL ) || isNull( vR ) ) // one operator null 01965 return ( mOp == boIs ? TVL_False : TVL_True ); 01966 else // both operators non-null 01967 { 01968 bool equal = false; 01969 if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) ) 01970 { 01971 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01972 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01973 equal = fL == fR; 01974 } 01975 else 01976 { 01977 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01978 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01979 equal = QString::compare( sL, sR ) == 0; 01980 } 01981 if ( equal ) 01982 return mOp == boIs ? TVL_True : TVL_False; 01983 else 01984 return mOp == boIs ? TVL_False : TVL_True; 01985 } 01986 01987 case boRegexp: 01988 case boLike: 01989 case boNotLike: 01990 case boILike: 01991 case boNotILike: 01992 if ( isNull( vL ) || isNull( vR ) ) 01993 return TVL_Unknown; 01994 else 01995 { 01996 QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 01997 QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 01998 // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant) 01999 bool matches; 02000 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp 02001 { 02002 QString esc_regexp = QRegExp::escape( regexp ); 02003 // XXX escape % and _ ??? 02004 esc_regexp.replace( "%", ".*" ); 02005 esc_regexp.replace( "_", "." ); 02006 matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str ); 02007 } 02008 else 02009 { 02010 matches = QRegExp( regexp ).indexIn( str ) != -1; 02011 } 02012 02013 if ( mOp == boNotLike || mOp == boNotILike ) 02014 { 02015 matches = !matches; 02016 } 02017 02018 return matches ? TVL_True : TVL_False; 02019 } 02020 02021 case boConcat: 02022 if ( isNull( vL ) || isNull( vR ) ) 02023 return QVariant(); 02024 else 02025 { 02026 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR; 02027 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR; 02028 return QVariant( sL + sR ); 02029 } 02030 02031 default: break; 02032 } 02033 Q_ASSERT( false ); 02034 return QVariant(); 02035 } 02036 02037 bool QgsExpression::NodeBinaryOperator::compare( double diff ) 02038 { 02039 switch ( mOp ) 02040 { 02041 case boEQ: return diff == 0; 02042 case boNE: return diff != 0; 02043 case boLT: return diff < 0; 02044 case boGT: return diff > 0; 02045 case boLE: return diff <= 0; 02046 case boGE: return diff >= 0; 02047 default: Q_ASSERT( false ); return false; 02048 } 02049 } 02050 02051 int QgsExpression::NodeBinaryOperator::computeInt( int x, int y ) 02052 { 02053 switch ( mOp ) 02054 { 02055 case boPlus: return x+y; 02056 case boMinus: return x-y; 02057 case boMul: return x*y; 02058 case boDiv: return x/y; 02059 case boMod: return x%y; 02060 default: Q_ASSERT( false ); return 0; 02061 } 02062 } 02063 02064 QDateTime QgsExpression::NodeBinaryOperator::computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i ) 02065 { 02066 switch ( mOp ) 02067 { 02068 case boPlus: return d.addSecs( i->seconds() ); 02069 case boMinus: return d.addSecs( -i->seconds() ); 02070 default: Q_ASSERT( false ); return QDateTime(); 02071 } 02072 } 02073 02074 double QgsExpression::NodeBinaryOperator::computeDouble( double x, double y ) 02075 { 02076 switch ( mOp ) 02077 { 02078 case boPlus: return x+y; 02079 case boMinus: return x-y; 02080 case boMul: return x*y; 02081 case boDiv: return x/y; 02082 case boMod: return fmod( x,y ); 02083 default: Q_ASSERT( false ); return 0; 02084 } 02085 } 02086 02087 02088 bool QgsExpression::NodeBinaryOperator::prepare( QgsExpression* parent, const QgsFields& fields ) 02089 { 02090 bool resL = mOpLeft->prepare( parent, fields ); 02091 bool resR = mOpRight->prepare( parent, fields ); 02092 return resL && resR; 02093 } 02094 02095 QString QgsExpression::NodeBinaryOperator::dump() const 02096 { 02097 return QString( "%1 %2 %3" ).arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() ); 02098 } 02099 02100 // 02101 02102 QVariant QgsExpression::NodeInOperator::eval( QgsExpression* parent, const QgsFeature* f ) 02103 { 02104 if ( mList->count() == 0 ) 02105 return mNotIn ? TVL_True : TVL_False; 02106 QVariant v1 = mNode->eval( parent, f ); 02107 ENSURE_NO_EVAL_ERROR; 02108 if ( isNull( v1 ) ) 02109 return TVL_Unknown; 02110 02111 bool listHasNull = false; 02112 02113 foreach ( Node* n, mList->list() ) 02114 { 02115 QVariant v2 = n->eval( parent, f ); 02116 ENSURE_NO_EVAL_ERROR; 02117 if ( isNull( v2 ) ) 02118 listHasNull = true; 02119 else 02120 { 02121 bool equal = false; 02122 // check whether they are equal 02123 if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) ) 02124 { 02125 double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR; 02126 double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR; 02127 equal = f1 == f2; 02128 } 02129 else 02130 { 02131 QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR; 02132 QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR; 02133 equal = QString::compare( s1, s2 ) == 0; 02134 } 02135 02136 if ( equal ) // we know the result 02137 return mNotIn ? TVL_False : TVL_True; 02138 } 02139 } 02140 02141 // item not found 02142 if ( listHasNull ) 02143 return TVL_Unknown; 02144 else 02145 return mNotIn ? TVL_True : TVL_False; 02146 } 02147 02148 bool QgsExpression::NodeInOperator::prepare( QgsExpression* parent, const QgsFields& fields ) 02149 { 02150 bool res = mNode->prepare( parent, fields ); 02151 foreach ( Node* n, mList->list() ) 02152 { 02153 res = res && n->prepare( parent, fields ); 02154 } 02155 return res; 02156 } 02157 02158 QString QgsExpression::NodeInOperator::dump() const 02159 { 02160 return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() ); 02161 } 02162 02163 // 02164 02165 QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, const QgsFeature* f ) 02166 { 02167 Function* fd = Functions()[mFnIndex]; 02168 02169 // evaluate arguments 02170 QVariantList argValues; 02171 if ( mArgs ) 02172 { 02173 foreach ( Node* n, mArgs->list() ) 02174 { 02175 QVariant v = n->eval( parent, f ); 02176 ENSURE_NO_EVAL_ERROR; 02177 if ( isNull( v ) && fd->name() != "coalesce" ) 02178 return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal) 02179 argValues.append( v ); 02180 } 02181 } 02182 02183 // run the function 02184 QVariant res = fd->func( argValues, f, parent ); 02185 ENSURE_NO_EVAL_ERROR; 02186 02187 // everything went fine 02188 return res; 02189 } 02190 02191 bool QgsExpression::NodeFunction::prepare( QgsExpression* parent, const QgsFields& fields ) 02192 { 02193 bool res = true; 02194 if ( mArgs ) 02195 { 02196 foreach ( Node* n, mArgs->list() ) 02197 { 02198 res = res && n->prepare( parent, fields ); 02199 } 02200 } 02201 return res; 02202 } 02203 02204 QString QgsExpression::NodeFunction::dump() const 02205 { 02206 Function* fd = Functions()[mFnIndex]; 02207 if ( fd->params() == 0 ) 02208 return fd->name(); // special column 02209 else 02210 return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function 02211 } 02212 02213 // 02214 02215 QVariant QgsExpression::NodeLiteral::eval( QgsExpression* , const QgsFeature* ) 02216 { 02217 return mValue; 02218 } 02219 02220 bool QgsExpression::NodeLiteral::prepare( QgsExpression* /*parent*/, const QgsFields& /*fields*/ ) 02221 { 02222 return true; 02223 } 02224 02225 02226 QString QgsExpression::NodeLiteral::dump() const 02227 { 02228 if ( mValue.isNull() ) 02229 return "NULL"; 02230 02231 switch ( mValue.type() ) 02232 { 02233 case QVariant::Int: return QString::number( mValue.toInt() ); 02234 case QVariant::Double: return QString::number( mValue.toDouble() ); 02235 case QVariant::String: return QString( "'%1'" ).arg( mValue.toString() ); 02236 default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() ); 02237 } 02238 } 02239 02240 // 02241 02242 QVariant QgsExpression::NodeColumnRef::eval( QgsExpression* /*parent*/, const QgsFeature* f ) 02243 { 02244 if ( f ) 02245 { 02246 if ( mIndex >= 0 ) 02247 return f->attribute( mIndex ); 02248 else 02249 return f->attribute( mName ); 02250 } 02251 return QVariant( "[" + mName + "]" ); 02252 } 02253 02254 bool QgsExpression::NodeColumnRef::prepare( QgsExpression* parent, const QgsFields& fields ) 02255 { 02256 for ( int i = 0; i < fields.count(); ++i ) 02257 { 02258 if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 ) 02259 { 02260 mIndex = i; 02261 return true; 02262 } 02263 } 02264 parent->mEvalErrorString = QObject::tr( "Column '%1' not found" ).arg( mName ); 02265 mIndex = -1; 02266 return false; 02267 } 02268 02269 QString QgsExpression::NodeColumnRef::dump() const 02270 { 02271 return mName; 02272 } 02273 02274 // 02275 02276 QVariant QgsExpression::NodeCondition::eval( QgsExpression* parent, const QgsFeature* f ) 02277 { 02278 foreach ( WhenThen* cond, mConditions ) 02279 { 02280 QVariant vWhen = cond->mWhenExp->eval( parent, f ); 02281 TVL tvl = getTVLValue( vWhen, parent ); 02282 ENSURE_NO_EVAL_ERROR; 02283 if ( tvl == True ) 02284 { 02285 QVariant vRes = cond->mThenExp->eval( parent, f ); 02286 ENSURE_NO_EVAL_ERROR; 02287 return vRes; 02288 } 02289 } 02290 02291 if ( mElseExp ) 02292 { 02293 QVariant vElse = mElseExp->eval( parent, f ); 02294 ENSURE_NO_EVAL_ERROR; 02295 return vElse; 02296 } 02297 02298 // return NULL if no condition is matching 02299 return QVariant(); 02300 } 02301 02302 bool QgsExpression::NodeCondition::prepare( QgsExpression* parent, const QgsFields& fields ) 02303 { 02304 bool res; 02305 foreach ( WhenThen* cond, mConditions ) 02306 { 02307 res = cond->mWhenExp->prepare( parent, fields ) 02308 & cond->mThenExp->prepare( parent, fields ); 02309 if ( !res ) return false; 02310 } 02311 02312 if ( mElseExp ) 02313 return mElseExp->prepare( parent, fields ); 02314 02315 return true; 02316 } 02317 02318 QString QgsExpression::NodeCondition::dump() const 02319 { 02320 QString msg = "CONDITION:\n"; 02321 foreach ( WhenThen* cond, mConditions ) 02322 { 02323 msg += QString( "- WHEN %1 THEN %2\n" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() ); 02324 } 02325 if ( mElseExp ) 02326 msg += QString( "- ELSE %1" ).arg( mElseExp->dump() ); 02327 return msg; 02328 } 02329 02330 QStringList QgsExpression::NodeCondition::referencedColumns() const 02331 { 02332 QStringList lst; 02333 foreach ( WhenThen* cond, mConditions ) 02334 { 02335 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns(); 02336 } 02337 02338 if ( mElseExp ) 02339 lst += mElseExp->referencedColumns(); 02340 02341 return lst; 02342 } 02343 02344 bool QgsExpression::NodeCondition::needsGeometry() const 02345 { 02346 foreach ( WhenThen* cond, mConditions ) 02347 { 02348 if ( cond->mWhenExp->needsGeometry() || 02349 cond->mThenExp->needsGeometry() ) 02350 return true; 02351 } 02352 02353 if ( mElseExp && mElseExp->needsGeometry() ) 02354 return true; 02355 02356 return false; 02357 } 02358 02359 QString QgsExpression::helptext( QString name ) 02360 { 02361 QgsExpression::initFunctionHelp(); 02362 return gFunctionHelpTexts.value( name, QObject::tr( "function help for %1 missing" ).arg( name ) ); 02363 } 02364 02365 QHash<QString, QString> QgsExpression::gGroups; 02366 02367 QString QgsExpression::group( QString name ) 02368 { 02369 if ( gGroups.isEmpty() ) 02370 { 02371 gGroups.insert( "Operators", QObject::tr( "Operators" ) ); 02372 gGroups.insert( "Conditionals", QObject::tr( "Conditionals" ) ); 02373 gGroups.insert( "Fields and Values", QObject::tr( "Fields and Values" ) ); 02374 gGroups.insert( "Math", QObject::tr( "Math" ) ); 02375 gGroups.insert( "Conversions", QObject::tr( "Conversions" ) ); 02376 gGroups.insert( "Date and Time", QObject::tr( "Date and Time" ) ); 02377 gGroups.insert( "String", QObject::tr( "String" ) ); 02378 gGroups.insert( "Color", QObject::tr( "Color" ) ); 02379 gGroups.insert( "Geometry", QObject::tr( "Geometry" ) ); 02380 gGroups.insert( "Record", QObject::tr( "Record" ) ); 02381 } 02382 02383 return gGroups.value( name, QObject::tr( "Missing group %1" ).arg( name ) ); 02384 }