Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsexpressioncontext.cpp 3 : : ------------------------ 4 : : Date : April 2015 5 : : Copyright : (C) 2015 by Nyall Dawson 6 : : Email : nyall dot dawson 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 "qgsexpressioncontext.h" 17 : : #include "qgslogger.h" 18 : : #include "qgsxmlutils.h" 19 : : #include "qgsexpression.h" 20 : : 21 : 10 : const QString QgsExpressionContext::EXPR_FIELDS( QStringLiteral( "_fields_" ) ); 22 : 10 : const QString QgsExpressionContext::EXPR_ORIGINAL_VALUE( QStringLiteral( "value" ) ); 23 : 10 : const QString QgsExpressionContext::EXPR_SYMBOL_COLOR( QStringLiteral( "symbol_color" ) ); 24 : 10 : const QString QgsExpressionContext::EXPR_SYMBOL_ANGLE( QStringLiteral( "symbol_angle" ) ); 25 : 10 : const QString QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT( QStringLiteral( "geometry_part_count" ) ); 26 : 10 : const QString QgsExpressionContext::EXPR_GEOMETRY_PART_NUM( QStringLiteral( "geometry_part_num" ) ); 27 : 10 : const QString QgsExpressionContext::EXPR_GEOMETRY_RING_NUM( QStringLiteral( "geometry_ring_num" ) ); 28 : 10 : const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT( QStringLiteral( "geometry_point_count" ) ); 29 : 10 : const QString QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM( QStringLiteral( "geometry_point_num" ) ); 30 : 10 : const QString QgsExpressionContext::EXPR_CLUSTER_SIZE( QStringLiteral( "cluster_size" ) ); 31 : 10 : const QString QgsExpressionContext::EXPR_CLUSTER_COLOR( QStringLiteral( "cluster_color" ) ); 32 : : 33 : : // 34 : : // QgsExpressionContextScope 35 : : // 36 : : 37 : 421 : QgsExpressionContextScope::QgsExpressionContextScope( const QString &name ) 38 : 421 : : mName( name ) 39 : : { 40 : : 41 : 421 : } 42 : : 43 : 122 : QgsExpressionContextScope::QgsExpressionContextScope( const QgsExpressionContextScope &other ) 44 : 61 : : mName( other.mName ) 45 : 61 : , mVariables( other.mVariables ) 46 : 61 : , mHasFeature( other.mHasFeature ) 47 : 61 : , mFeature( other.mFeature ) 48 : : { 49 : 61 : QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin(); 50 : 62 : for ( ; it != other.mFunctions.constEnd(); ++it ) 51 : : { 52 : 1 : mFunctions.insert( it.key(), it.value()->clone() ); 53 : 1 : } 54 : 61 : } 55 : : 56 : 199 : QgsExpressionContextScope &QgsExpressionContextScope::operator=( const QgsExpressionContextScope &other ) 57 : : { 58 : 199 : mName = other.mName; 59 : 199 : mVariables = other.mVariables; 60 : 199 : mHasFeature = other.mHasFeature; 61 : 199 : mFeature = other.mFeature; 62 : : 63 : 199 : qDeleteAll( mFunctions ); 64 : 199 : mFunctions.clear(); 65 : 199 : QHash<QString, QgsScopedExpressionFunction * >::const_iterator it = other.mFunctions.constBegin(); 66 : 199 : for ( ; it != other.mFunctions.constEnd(); ++it ) 67 : : { 68 : 0 : mFunctions.insert( it.key(), it.value()->clone() ); 69 : 0 : } 70 : : 71 : 199 : return *this; 72 : : } 73 : : 74 : 479 : QgsExpressionContextScope::~QgsExpressionContextScope() 75 : : { 76 : 479 : qDeleteAll( mFunctions ); 77 : 479 : } 78 : : 79 : 0 : void QgsExpressionContextScope::setVariable( const QString &name, const QVariant &value, bool isStatic ) 80 : : { 81 : 0 : if ( mVariables.contains( name ) ) 82 : : { 83 : 0 : StaticVariable existing = mVariables.value( name ); 84 : 0 : existing.value = value; 85 : 0 : existing.isStatic = isStatic; 86 : 0 : addVariable( existing ); 87 : 0 : } 88 : : else 89 : : { 90 : 0 : addVariable( QgsExpressionContextScope::StaticVariable( name, value, false, isStatic ) ); 91 : : } 92 : 0 : } 93 : : 94 : 1260 : void QgsExpressionContextScope::addVariable( const QgsExpressionContextScope::StaticVariable &variable ) 95 : : { 96 : 1260 : mVariables.insert( variable.name, variable ); 97 : 1260 : } 98 : : 99 : 0 : bool QgsExpressionContextScope::removeVariable( const QString &name ) 100 : : { 101 : 0 : return mVariables.remove( name ) > 0; 102 : : } 103 : : 104 : 0 : bool QgsExpressionContextScope::hasVariable( const QString &name ) const 105 : : { 106 : 0 : return mVariables.contains( name ); 107 : : } 108 : : 109 : 0 : QVariant QgsExpressionContextScope::variable( const QString &name ) const 110 : : { 111 : 0 : return hasVariable( name ) ? mVariables.value( name ).value : QVariant(); 112 : 0 : } 113 : : 114 : 20 : QStringList QgsExpressionContextScope::variableNames() const 115 : : { 116 : 20 : QStringList names = mVariables.keys(); 117 : 20 : return names; 118 : 20 : } 119 : : 120 : : /// @cond PRIVATE 121 : : class QgsExpressionContextVariableCompare 122 : : { 123 : : public: 124 : 0 : explicit QgsExpressionContextVariableCompare( const QgsExpressionContextScope &scope ) 125 : 0 : : mScope( scope ) 126 : 0 : { } 127 : : 128 : 0 : bool operator()( const QString &a, const QString &b ) const 129 : : { 130 : 0 : bool aReadOnly = mScope.isReadOnly( a ); 131 : 0 : bool bReadOnly = mScope.isReadOnly( b ); 132 : 0 : if ( aReadOnly != bReadOnly ) 133 : 0 : return aReadOnly; 134 : 0 : return QString::localeAwareCompare( a, b ) < 0; 135 : 0 : } 136 : : 137 : : private: 138 : : const QgsExpressionContextScope &mScope; 139 : : }; 140 : : /// @endcond 141 : : 142 : 0 : QStringList QgsExpressionContextScope::filteredVariableNames() const 143 : : { 144 : 0 : QStringList allVariables = mVariables.keys(); 145 : 0 : QStringList filtered; 146 : 0 : const auto constAllVariables = allVariables; 147 : 0 : for ( const QString &variable : constAllVariables ) 148 : : { 149 : 0 : if ( variable.startsWith( '_' ) ) 150 : 0 : continue; 151 : : 152 : 0 : filtered << variable; 153 : : } 154 : 0 : QgsExpressionContextVariableCompare cmp( *this ); 155 : 0 : std::sort( filtered.begin(), filtered.end(), cmp ); 156 : : 157 : 0 : return filtered; 158 : 0 : } 159 : : 160 : 0 : bool QgsExpressionContextScope::isReadOnly( const QString &name ) const 161 : : { 162 : 0 : return hasVariable( name ) ? mVariables.value( name ).readOnly : false; 163 : : } 164 : : 165 : 0 : bool QgsExpressionContextScope::isStatic( const QString &name ) const 166 : : { 167 : 0 : return hasVariable( name ) ? mVariables.value( name ).isStatic : false; 168 : : } 169 : : 170 : 0 : QString QgsExpressionContextScope::description( const QString &name ) const 171 : : { 172 : 0 : return hasVariable( name ) ? mVariables.value( name ).description : QString(); 173 : : } 174 : : 175 : 0 : bool QgsExpressionContextScope::hasFunction( const QString &name ) const 176 : : { 177 : 0 : return mFunctions.contains( name ); 178 : : } 179 : : 180 : 0 : QgsExpressionFunction *QgsExpressionContextScope::function( const QString &name ) const 181 : : { 182 : 0 : return mFunctions.contains( name ) ? mFunctions.value( name ) : nullptr; 183 : : } 184 : : 185 : 0 : QStringList QgsExpressionContextScope::functionNames() const 186 : : { 187 : 0 : return mFunctions.keys(); 188 : : } 189 : : 190 : 1 : void QgsExpressionContextScope::addFunction( const QString &name, QgsScopedExpressionFunction *function ) 191 : : { 192 : 1 : mFunctions.insert( name, function ); 193 : 1 : } 194 : : 195 : : 196 : 200 : void QgsExpressionContextScope::setFields( const QgsFields &fields ) 197 : : { 198 : 200 : addVariable( StaticVariable( QgsExpressionContext::EXPR_FIELDS, QVariant::fromValue( fields ), true ) ); 199 : 200 : } 200 : : 201 : 0 : void QgsExpressionContextScope::readXml( const QDomElement &element, const QgsReadWriteContext & ) 202 : : { 203 : 0 : const QDomNodeList variablesNodeList = element.childNodes(); 204 : 0 : for ( int i = 0; i < variablesNodeList.size(); ++i ) 205 : : { 206 : 0 : const QDomElement variableElement = variablesNodeList.at( i ).toElement(); 207 : 0 : const QString key = variableElement.attribute( QStringLiteral( "name" ) ); 208 : 0 : const QVariant value = QgsXmlUtils::readVariant( variableElement.firstChildElement( QStringLiteral( "Option" ) ) ); 209 : 0 : setVariable( key, value ); 210 : 0 : } 211 : 0 : } 212 : : 213 : 0 : bool QgsExpressionContextScope::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext & ) const 214 : : { 215 : 0 : for ( auto it = mVariables.constBegin(); it != mVariables.constEnd(); ++it ) 216 : : { 217 : 0 : QDomElement varElem = document.createElement( QStringLiteral( "Variable" ) ); 218 : 0 : varElem.setAttribute( QStringLiteral( "name" ), it.key() ); 219 : 0 : QDomElement valueElem = QgsXmlUtils::writeVariant( it.value().value, document ); 220 : 0 : varElem.appendChild( valueElem ); 221 : 0 : element.appendChild( varElem ); 222 : 0 : } 223 : 0 : return true; 224 : 0 : } 225 : : 226 : : 227 : : // 228 : : // QgsExpressionContext 229 : : // 230 : : 231 : 1 : QgsExpressionContext::QgsExpressionContext( const QList<QgsExpressionContextScope *> &scopes ) 232 : 1 : : mStack( scopes ) 233 : : { 234 : 1 : } 235 : : 236 : 0 : QgsExpressionContext::QgsExpressionContext( const QgsExpressionContext &other ) : mStack{} 237 : : { 238 : 0 : for ( const QgsExpressionContextScope *scope : std::as_const( other.mStack ) ) 239 : : { 240 : 0 : mStack << new QgsExpressionContextScope( *scope ); 241 : : } 242 : 0 : mHighlightedVariables = other.mHighlightedVariables; 243 : 0 : mHighlightedFunctions = other.mHighlightedFunctions; 244 : 0 : mCachedValues = other.mCachedValues; 245 : 0 : } 246 : : 247 : 0 : QgsExpressionContext &QgsExpressionContext::operator=( QgsExpressionContext &&other ) noexcept 248 : : { 249 : 0 : if ( this != &other ) 250 : : { 251 : 0 : qDeleteAll( mStack ); 252 : : // move the stack over 253 : 0 : mStack = other.mStack; 254 : 0 : other.mStack.clear(); 255 : : 256 : 0 : mHighlightedVariables = other.mHighlightedVariables; 257 : 0 : mHighlightedFunctions = other.mHighlightedFunctions; 258 : 0 : mCachedValues = other.mCachedValues; 259 : 0 : } 260 : 0 : return *this; 261 : : } 262 : : 263 : 533 : QgsExpressionContext &QgsExpressionContext::operator=( const QgsExpressionContext &other ) 264 : : { 265 : 533 : if ( &other == this ) 266 : 0 : return *this; 267 : : 268 : 533 : qDeleteAll( mStack ); 269 : 533 : mStack.clear(); 270 : 533 : for ( const QgsExpressionContextScope *scope : std::as_const( other.mStack ) ) 271 : : { 272 : 0 : mStack << new QgsExpressionContextScope( *scope ); 273 : : } 274 : 533 : mHighlightedVariables = other.mHighlightedVariables; 275 : 533 : mHighlightedFunctions = other.mHighlightedFunctions; 276 : 533 : mCachedValues = other.mCachedValues; 277 : 533 : return *this; 278 : 533 : } 279 : : 280 : 853 : QgsExpressionContext::~QgsExpressionContext() 281 : : { 282 : 853 : qDeleteAll( mStack ); 283 : 853 : mStack.clear(); 284 : 853 : } 285 : : 286 : 0 : bool QgsExpressionContext::hasVariable( const QString &name ) const 287 : : { 288 : 0 : const auto constMStack = mStack; 289 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 290 : : { 291 : 0 : if ( scope->hasVariable( name ) ) 292 : 0 : return true; 293 : : } 294 : 0 : return false; 295 : 0 : } 296 : : 297 : 0 : QVariant QgsExpressionContext::variable( const QString &name ) const 298 : : { 299 : 0 : const QgsExpressionContextScope *scope = activeScopeForVariable( name ); 300 : 0 : return scope ? scope->variable( name ) : QVariant(); 301 : : } 302 : : 303 : 0 : QVariantMap QgsExpressionContext::variablesToMap() const 304 : : { 305 : 0 : QStringList names = variableNames(); 306 : 0 : QVariantMap m; 307 : 0 : const auto constNames = names; 308 : 0 : for ( const QString &name : constNames ) 309 : : { 310 : 0 : m.insert( name, variable( name ) ); 311 : : } 312 : 0 : return m; 313 : 0 : } 314 : : 315 : 0 : bool QgsExpressionContext::isHighlightedVariable( const QString &name ) const 316 : : { 317 : 0 : return mHighlightedVariables.contains( name ); 318 : : } 319 : : 320 : 0 : QStringList QgsExpressionContext::highlightedVariables() const 321 : : { 322 : 0 : return mHighlightedVariables; 323 : : } 324 : : 325 : 0 : void QgsExpressionContext::setHighlightedVariables( const QStringList &variableNames ) 326 : : { 327 : 0 : mHighlightedVariables = variableNames; 328 : 0 : } 329 : : 330 : 0 : bool QgsExpressionContext::isHighlightedFunction( const QString &name ) const 331 : : { 332 : 0 : return mHighlightedFunctions.contains( name ); 333 : : } 334 : : 335 : 0 : void QgsExpressionContext::setHighlightedFunctions( const QStringList &names ) 336 : : { 337 : 0 : mHighlightedFunctions = names; 338 : 0 : } 339 : : 340 : 0 : const QgsExpressionContextScope *QgsExpressionContext::activeScopeForVariable( const QString &name ) const 341 : : { 342 : : //iterate through stack backwards, so that higher priority variables take precedence 343 : 0 : QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd(); 344 : 0 : while ( it != mStack.constBegin() ) 345 : : { 346 : 0 : --it; 347 : 0 : if ( ( *it )->hasVariable( name ) ) 348 : 0 : return ( *it ); 349 : : } 350 : 0 : return nullptr; 351 : 0 : } 352 : 421 : 353 : 0 : QgsExpressionContextScope *QgsExpressionContext::activeScopeForVariable( const QString &name ) 354 : : { 355 : : //iterate through stack backwards, so that higher priority variables take precedence 356 : 0 : QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd(); 357 : 0 : while ( it != mStack.constBegin() ) 358 : : { 359 : 0 : --it; 360 : 0 : if ( ( *it )->hasVariable( name ) ) 361 : 0 : return ( *it ); 362 : : } 363 : 0 : return nullptr; 364 : 0 : } 365 : : 366 : 0 : QgsExpressionContextScope *QgsExpressionContext::scope( int index ) 367 : : { 368 : 0 : if ( index < 0 || index >= mStack.count() ) 369 : 0 : return nullptr; 370 : : 371 : 0 : return mStack.at( index ); 372 : 0 : } 373 : : 374 : 0 : QgsExpressionContextScope *QgsExpressionContext::lastScope() 375 : : { 376 : 0 : if ( mStack.count() < 1 ) 377 : 0 : return nullptr; 378 : : 379 : 0 : return mStack.last(); 380 : 0 : } 381 : : 382 : 0 : int QgsExpressionContext::indexOfScope( QgsExpressionContextScope *scope ) const 383 : : { 384 : 0 : if ( !scope ) 385 : 0 : return -1; 386 : : 387 : 0 : return mStack.indexOf( scope ); 388 : 0 : } 389 : : 390 : 0 : int QgsExpressionContext::indexOfScope( const QString &scopeName ) const 391 : : { 392 : 0 : int index = 0; 393 : 0 : const auto constMStack = mStack; 394 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 395 : : { 396 : 0 : if ( scope->name() == scopeName ) 397 : 0 : return index; 398 : : 399 : 0 : index++; 400 : : } 401 : 0 : return -1; 402 : 0 : } 403 : : 404 : 0 : QStringList QgsExpressionContext::variableNames() const 405 : : { 406 : 0 : QStringList names; 407 : 0 : const auto constMStack = mStack; 408 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 409 : : { 410 : 0 : names << scope->variableNames(); 411 : : } 412 : 0 : return qgis::setToList( qgis::listToSet( names ) ); 413 : 0 : } 414 : : 415 : 0 : QStringList QgsExpressionContext::filteredVariableNames() const 416 : : { 417 : 0 : QStringList allVariables = variableNames(); 418 : 0 : QStringList filtered; 419 : 0 : const auto constAllVariables = allVariables; 420 : 0 : for ( const QString &variable : constAllVariables ) 421 : : { 422 : 0 : if ( variable.startsWith( '_' ) ) 423 : 0 : continue; 424 : : 425 : 0 : filtered << variable; 426 : : } 427 : : 428 : 0 : filtered.sort(); 429 : 0 : return filtered; 430 : 0 : } 431 : : 432 : 0 : bool QgsExpressionContext::isReadOnly( const QString &name ) const 433 : : { 434 : 0 : const auto constMStack = mStack; 435 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 436 : : { 437 : 0 : if ( scope->isReadOnly( name ) ) 438 : 0 : return true; 439 : : } 440 : 0 : return false; 441 : 0 : } 442 : : 443 : 0 : QString QgsExpressionContext::description( const QString &name ) const 444 : : { 445 : 0 : const QgsExpressionContextScope *scope = activeScopeForVariable( name ); 446 : 0 : return ( scope && !scope->description( name ).isEmpty() ) ? scope->description( name ) : QgsExpression::variableHelpText( name ); 447 : 0 : } 448 : : 449 : 0 : bool QgsExpressionContext::hasFunction( const QString &name ) const 450 : : { 451 : 0 : const auto constMStack = mStack; 452 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 453 : : { 454 : 0 : if ( scope->hasFunction( name ) ) 455 : 0 : return true; 456 : : } 457 : 0 : return false; 458 : 0 : } 459 : : 460 : 0 : QStringList QgsExpressionContext::functionNames() const 461 : : { 462 : 0 : QStringList result; 463 : 0 : const auto constMStack = mStack; 464 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 465 : : { 466 : 0 : result << scope->functionNames(); 467 : : } 468 : 0 : result = qgis::setToList( qgis::listToSet( result ) ); 469 : 0 : result.sort(); 470 : 0 : return result; 471 : 0 : } 472 : : 473 : 0 : QgsExpressionFunction *QgsExpressionContext::function( const QString &name ) const 474 : : { 475 : : //iterate through stack backwards, so that higher priority variables take precedence 476 : 0 : QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd(); 477 : 0 : while ( it != mStack.constBegin() ) 478 : : { 479 : 0 : --it; 480 : 0 : if ( ( *it )->hasFunction( name ) ) 481 : 0 : return ( *it )->function( name ); 482 : : } 483 : 0 : return nullptr; 484 : 0 : } 485 : : 486 : 0 : int QgsExpressionContext::scopeCount() const 487 : : { 488 : 0 : return mStack.count(); 489 : : } 490 : : 491 : 0 : void QgsExpressionContext::appendScope( QgsExpressionContextScope *scope ) 492 : : { 493 : 0 : mStack.append( scope ); 494 : 0 : } 495 : : 496 : 0 : void QgsExpressionContext::appendScopes( const QList<QgsExpressionContextScope *> &scopes ) 497 : : { 498 : 0 : mStack.append( scopes ); 499 : 0 : } 500 : : 501 : 0 : QgsExpressionContextScope *QgsExpressionContext::popScope() 502 : : { 503 : 0 : if ( !mStack.isEmpty() ) 504 : 0 : return mStack.takeLast(); 505 : : 506 : 0 : return nullptr; 507 : 0 : } 508 : : 509 : 0 : QList<QgsExpressionContextScope *> QgsExpressionContext::takeScopes() 510 : : { 511 : 0 : QList<QgsExpressionContextScope *> stack = mStack; 512 : 0 : mStack.clear(); 513 : 0 : return stack; 514 : 0 : } 515 : : 516 : 0 : QgsExpressionContext &QgsExpressionContext::operator<<( QgsExpressionContextScope *scope ) 517 : : { 518 : 0 : mStack.append( scope ); 519 : 0 : return *this; 520 : : } 521 : : 522 : 0 : void QgsExpressionContext::setFeature( const QgsFeature &feature ) 523 : : { 524 : 0 : if ( mStack.isEmpty() ) 525 : 0 : mStack.append( new QgsExpressionContextScope() ); 526 : : 527 : 0 : mStack.last()->setFeature( feature ); 528 : 0 : } 529 : : 530 : 0 : bool QgsExpressionContext::hasFeature() const 531 : : { 532 : 0 : const auto constMStack = mStack; 533 : 0 : for ( const QgsExpressionContextScope *scope : constMStack ) 534 : : { 535 : 0 : if ( scope->hasFeature() ) 536 : 0 : return true; 537 : : } 538 : 0 : return false; 539 : 0 : } 540 : : 541 : 0 : QgsFeature QgsExpressionContext::feature() const 542 : : { 543 : : //iterate through stack backwards, so that higher priority variables take precedence 544 : 0 : QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd(); 545 : 0 : while ( it != mStack.constBegin() ) 546 : : { 547 : 0 : --it; 548 : 0 : if ( ( *it )->hasFeature() ) 549 : 0 : return ( *it )->feature(); 550 : : } 551 : 0 : return QgsFeature(); 552 : 0 : } 553 : : 554 : 0 : void QgsExpressionContext::setFields( const QgsFields &fields ) 555 : : { 556 : 0 : if ( mStack.isEmpty() ) 557 : 0 : mStack.append( new QgsExpressionContextScope() ); 558 : : 559 : 0 : mStack.last()->setFields( fields ); 560 : 0 : } 561 : : 562 : 0 : QgsFields QgsExpressionContext::fields() const 563 : : { 564 : 0 : return qvariant_cast<QgsFields>( variable( QgsExpressionContext::EXPR_FIELDS ) ); 565 : 0 : } 566 : : 567 : 0 : void QgsExpressionContext::setOriginalValueVariable( const QVariant &value ) 568 : : { 569 : 0 : if ( mStack.isEmpty() ) 570 : 0 : mStack.append( new QgsExpressionContextScope() ); 571 : : 572 : 0 : mStack.last()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_ORIGINAL_VALUE, 573 : 0 : value, true ) ); 574 : 0 : } 575 : : 576 : 0 : void QgsExpressionContext::setCachedValue( const QString &key, const QVariant &value ) const 577 : : { 578 : 0 : mCachedValues.insert( key, value ); 579 : 0 : } 580 : : 581 : 0 : bool QgsExpressionContext::hasCachedValue( const QString &key ) const 582 : : { 583 : 0 : return mCachedValues.contains( key ); 584 : : } 585 : : 586 : 0 : QVariant QgsExpressionContext::cachedValue( const QString &key ) const 587 : : { 588 : 0 : return mCachedValues.value( key, QVariant() ); 589 : 0 : } 590 : : 591 : 0 : void QgsExpressionContext::clearCachedValues() const 592 : : { 593 : 0 : mCachedValues.clear(); 594 : 0 : }