Skip to content

Commit 6593754

Browse files
committedMay 1, 2017
Explicitly tag static variables
1 parent b9ec373 commit 6593754

File tree

5 files changed

+66
-34
lines changed

5 files changed

+66
-34
lines changed
 

‎python/core/qgsexpressioncontext.sip

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class QgsExpressionContextScope
7676
* @param value initial variable value
7777
* @param readOnly true if variable should not be editable by users
7878
*/
79-
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false );
79+
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false );
8080

8181
/** Variable name */
8282
QString name;
@@ -86,6 +86,9 @@ class QgsExpressionContextScope
8686

8787
/** True if variable should not be editable by users */
8888
bool readOnly;
89+
90+
//! A static variable can be cached for the lifetime of a context
91+
bool isStatic;
8992
};
9093

9194
/** Constructor for QgsExpressionContextScope
@@ -109,7 +112,7 @@ class QgsExpressionContextScope
109112
* @param value variable value
110113
* @see addVariable()
111114
*/
112-
void setVariable( const QString &name, const QVariant &value );
115+
void setVariable( const QString &name, const QVariant &value, bool isStatic = false );
113116

114117
/** Adds a variable into the context scope. If a variable with the same name is already set then its
115118
* value is overwritten, otherwise a new variable is added to the scope.
@@ -162,6 +165,14 @@ class QgsExpressionContextScope
162165
*/
163166
bool isReadOnly( const QString &name ) const;
164167

168+
/**
169+
* Tests whether the variable with the specified \a name is static and can
170+
* be cached.
171+
*
172+
* \note Added in QGIS 3.0
173+
*/
174+
bool isStatic( const QString &name ) const;
175+
165176
/** Returns the count of variables contained within the scope.
166177
*/
167178
int variableCount() const;

‎src/core/qgsexpression.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4322,9 +4322,10 @@ const QList<QgsExpression::Function *> &QgsExpression::Functions()
43224322
varFunction->setIsStaticFunction(
43234323
[]( const NodeFunction * node, QgsExpression * parent, const QgsExpressionContext * context )
43244324
{
4325-
/* A variable node is static if it has a static name and the name is defined at prepare time
4326-
* (e.g. global or layer variables)
4327-
* It is not static if a variable is set during iteration (e.g. geom_part variable)
4325+
/* A variable node is static if it has a static name and the name can be found at prepare
4326+
* time and is tagged with isStatic.
4327+
* It is not static if a variable is set during iteration or not tagged isStatic.
4328+
* (e.g. geom_part variable)
43284329
*/
43294330
if ( node->args()->count() > 0 )
43304331
{
@@ -4333,8 +4334,10 @@ const QList<QgsExpression::Function *> &QgsExpression::Functions()
43334334
if ( !argNode->isStatic( parent, context ) )
43344335
return false;
43354336

4336-
if ( fcnGetVariable( QVariantList() << argNode->eval( parent, context ), context, parent ).isValid() )
4337-
return true;
4337+
QString varName = argNode->eval( parent, context ).toString();
4338+
4339+
const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
4340+
return scope ? scope->isStatic( varName ) : false;
43384341
}
43394342
return false;
43404343
}

‎src/core/qgsexpressioncontext.cpp

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,18 @@ QgsExpressionContextScope::~QgsExpressionContextScope()
9090
qDeleteAll( mFunctions );
9191
}
9292

93-
void QgsExpressionContextScope::setVariable( const QString &name, const QVariant &value )
93+
void QgsExpressionContextScope::setVariable( const QString &name, const QVariant &value, bool isStatic )
9494
{
9595
if ( mVariables.contains( name ) )
9696
{
9797
StaticVariable existing = mVariables.value( name );
9898
existing.value = value;
99+
existing.isStatic = isStatic;
99100
addVariable( existing );
100101
}
101102
else
102103
{
103-
addVariable( QgsExpressionContextScope::StaticVariable( name, value ) );
104+
addVariable( QgsExpressionContextScope::StaticVariable( name, value, false, isStatic ) );
104105
}
105106
}
106107

@@ -179,6 +180,11 @@ bool QgsExpressionContextScope::isReadOnly( const QString &name ) const
179180
return hasVariable( name ) ? mVariables.value( name ).readOnly : false;
180181
}
181182

183+
bool QgsExpressionContextScope::isStatic( const QString &name ) const
184+
{
185+
return hasVariable( name ) ? mVariables.value( name ).isStatic : false;
186+
}
187+
182188
bool QgsExpressionContextScope::hasFunction( const QString &name ) const
183189
{
184190
return mFunctions.contains( name );
@@ -545,19 +551,19 @@ QgsExpressionContextScope *QgsExpressionContextUtils::globalScope()
545551

546552
for ( QVariantMap::const_iterator it = customVariables.constBegin(); it != customVariables.constEnd(); ++it )
547553
{
548-
scope->setVariable( it.key(), it.value() );
554+
scope->setVariable( it.key(), it.value(), true );
549555
}
550556

551557
//add some extra global variables
552-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version" ), Qgis::QGIS_VERSION, true ) );
553-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version_no" ), Qgis::QGIS_VERSION_INT, true ) );
554-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_short_version" ), QStringLiteral( "%1.%2" ).arg( Qgis::QGIS_VERSION_INT / 10000 ).arg( Qgis::QGIS_VERSION_INT / 100 % 100 ), true ) );
555-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_release_name" ), Qgis::QGIS_RELEASE_NAME, true ) );
556-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_platform" ), QgsApplication::platform(), true ) );
557-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_os_name" ), QgsApplication::osName(), true ) );
558-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_locale" ), QgsApplication::locale(), true ) );
559-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_account_name" ), QgsApplication::userLoginName(), true ) );
560-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_full_name" ), QgsApplication::userFullName(), true ) );
558+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version" ), Qgis::QGIS_VERSION, true, true ) );
559+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_version_no" ), Qgis::QGIS_VERSION_INT, true, true ) );
560+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_short_version" ), QStringLiteral( "%1.%2" ).arg( Qgis::QGIS_VERSION_INT / 10000 ).arg( Qgis::QGIS_VERSION_INT / 100 % 100 ), true, true ) );
561+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_release_name" ), Qgis::QGIS_RELEASE_NAME, true, true ) );
562+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_platform" ), QgsApplication::platform(), true, true ) );
563+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_os_name" ), QgsApplication::osName(), true, true ) );
564+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "qgis_locale" ), QgsApplication::locale(), true, true ) );
565+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_account_name" ), QgsApplication::userLoginName(), true, true ) );
566+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "user_full_name" ), QgsApplication::userFullName(), true, true ) );
561567

562568
return scope;
563569
}
@@ -715,17 +721,17 @@ QgsExpressionContextScope *QgsExpressionContextUtils::projectScope( const QgsPro
715721

716722
for ( ; it != vars.constEnd(); ++it )
717723
{
718-
scope->setVariable( it.key(), it.value() );
724+
scope->setVariable( it.key(), it.value(), true );
719725
}
720726

721727
//add other known project variables
722-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), project->title(), true ) );
723-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_path" ), project->fileInfo().filePath(), true ) );
724-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_folder" ), project->fileInfo().dir().path(), true ) );
725-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_filename" ), project->fileInfo().fileName(), true ) );
728+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), project->title(), true, true ) );
729+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_path" ), project->fileInfo().filePath(), true, true ) );
730+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_folder" ), project->fileInfo().dir().path(), true, true ) );
731+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_filename" ), project->fileInfo().fileName(), true, true ) );
726732
QgsCoordinateReferenceSystem projectCrs = project->crs();
727-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs" ), projectCrs.authid(), true ) );
728-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs_definition" ), projectCrs.toProj4(), true ) );
733+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs" ), projectCrs.authid(), true, true ) );
734+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_crs_definition" ), projectCrs.toProj4(), true, true ) );
729735

730736
scope->addFunction( QStringLiteral( "project_color" ), new GetNamedProjectColor( project ) );
731737
return scope;
@@ -772,14 +778,14 @@ QgsExpressionContextScope *QgsExpressionContextUtils::layerScope( const QgsMapLa
772778

773779
QVariant varValue = variableValues.at( varIndex );
774780
varIndex++;
775-
scope->setVariable( variableName, varValue );
781+
scope->setVariable( variableName, varValue, true );
776782
}
777783

778-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_name" ), layer->name(), true ) );
779-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_id" ), layer->id(), true ) );
780-
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer >( QgsWeakMapLayerPointer( const_cast<QgsMapLayer *>( layer ) ) ), true ) );
784+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_name" ), layer->name(), true, true ) );
785+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer_id" ), layer->id(), true, true ) );
786+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer >( QgsWeakMapLayerPointer( const_cast<QgsMapLayer *>( layer ) ) ), true, true ) );
781787

782-
const QgsVectorLayer *vLayer = dynamic_cast< const QgsVectorLayer * >( layer );
788+
const QgsVectorLayer *vLayer = qobject_cast< const QgsVectorLayer * >( layer );
783789
if ( vLayer )
784790
{
785791
scope->setFields( vLayer->fields() );

‎src/core/qgsexpressioncontext.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,11 @@ class CORE_EXPORT QgsExpressionContextScope
127127
* \param value initial variable value
128128
* \param readOnly true if variable should not be editable by users
129129
*/
130-
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false )
130+
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false )
131131
: name( name )
132132
, value( value )
133133
, readOnly( readOnly )
134+
, isStatic( isStatic )
134135
{}
135136

136137
//! Variable name
@@ -141,6 +142,9 @@ class CORE_EXPORT QgsExpressionContextScope
141142

142143
//! True if variable should not be editable by users
143144
bool readOnly;
145+
146+
//! A static variable can be cached for the lifetime of a context
147+
bool isStatic;
144148
};
145149

146150
/** Constructor for QgsExpressionContextScope
@@ -166,7 +170,7 @@ class CORE_EXPORT QgsExpressionContextScope
166170
* \param value variable value
167171
* \see addVariable()
168172
*/
169-
void setVariable( const QString &name, const QVariant &value );
173+
void setVariable( const QString &name, const QVariant &value, bool isStatic = false );
170174

171175
/** Adds a variable into the context scope. If a variable with the same name is already set then its
172176
* value is overwritten, otherwise a new variable is added to the scope.
@@ -219,6 +223,14 @@ class CORE_EXPORT QgsExpressionContextScope
219223
*/
220224
bool isReadOnly( const QString &name ) const;
221225

226+
/**
227+
* Tests whether the variable with the specified \a name is static and can
228+
* be cached.
229+
*
230+
* \note Added in QGIS 3.0
231+
*/
232+
bool isStatic( const QString &name ) const;
233+
222234
/** Returns the count of variables contained within the scope.
223235
*/
224236
int variableCount() const { return mVariables.count(); }

‎tests/src/python/test_qgsatlascomposition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def filename_test(self):
122122
for i in range(0, self.mAtlas.numFeatures()):
123123
self.mAtlas.prepareForFeature(i)
124124
expected = "output_%d" % (i + 1)
125-
assert self.mAtlas.currentFilename() == expected
125+
self.assertEqual(self.mAtlas.currentFilename(), expected)
126126
self.mAtlas.endRender()
127127

128128
def autoscale_render_test(self):

0 commit comments

Comments
 (0)
Please sign in to comment.