Skip to content

Commit 35e16b2

Browse files
committed
Add method for specifying variable description when adding to contexts
And use this description in expression builders when it's set.
1 parent 534844f commit 35e16b2

File tree

9 files changed

+126
-9
lines changed

9 files changed

+126
-9
lines changed

doc/api_break.dox

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,8 @@ version instead.
11161116
- QgsExpression::Node::referencedColumns() returns QSet<QString> instead of QStringList
11171117
- `QgsExpression::Node` was renamed to `QgsExpressionNode`
11181118
- `QgsExpression::Function` was renamed to `QgsExpressionFunction`
1119+
- variableHelpText() no longer returns a formatted HTML string. It now just returns the plain text help string. Use formatVariableHelp()
1120+
to obtain the formatted version.
11191121

11201122

11211123
QgsExpression::Function {#qgis_api_break_3_0_QgsExpression_Function}

python/core/expression/qgsexpression.sip

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,11 @@ return index of the function in Functions array
464464
Returns the help text for a specified function.
465465
\param name function name
466466
.. seealso:: variableHelpText()
467+
.. seealso:: formatVariableHelp()
467468
:rtype: str
468469
%End
469470

470-
static QString variableHelpText( const QString &variableName, bool showValue = true, const QVariant &value = QVariant() );
471+
static QString variableHelpText( const QString &variableName );
471472
%Docstring
472473
Returns the help text for a specified variable.
473474
\param variableName name of variable
@@ -478,6 +479,18 @@ return index of the function in Functions array
478479
:rtype: str
479480
%End
480481

482+
static QString formatVariableHelp( const QString &description, bool showValue = true, const QVariant &value = QVariant() );
483+
%Docstring
484+
Returns formatted help text for a variable.
485+
\param description translated description of variable
486+
\param showValue set to true to include current value of variable in help text
487+
\param value current value of variable to show in help text
488+
.. seealso:: helpText()
489+
.. seealso:: variableHelpText()
490+
.. versionadded:: 3.0
491+
:rtype: str
492+
%End
493+
481494
static QString group( const QString &group );
482495
%Docstring
483496
Returns the translated name for a function group.

python/core/qgsexpressioncontext.sip

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,14 @@ class QgsExpressionContextScope
9292
struct StaticVariable
9393
{
9494

95-
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false );
95+
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false, const QString &description = QString() );
9696
%Docstring
9797
Constructor for StaticVariable.
9898
\param name variable name (should be unique within the QgsExpressionContextScope)
9999
\param value initial variable value
100100
\param readOnly true if variable should not be editable by users
101101
\param isStatic true if the variable will not change during the lifteime of an iterator.
102+
\param description optional translated description of variable, for use in expression builder widgets
102103
%End
103104

104105
QString name;
@@ -119,6 +120,11 @@ True if variable should not be editable by users
119120
bool isStatic;
120121
%Docstring
121122
A static variable can be cached for the lifetime of a context
123+
%End
124+
125+
QString description;
126+
%Docstring
127+
Translated description of variable, for use within expression builder widgets.
122128
%End
123129
};
124130

@@ -224,6 +230,15 @@ A static variable can be cached for the lifetime of a context
224230
:rtype: bool
225231
%End
226232

233+
QString description( const QString &name ) const;
234+
%Docstring
235+
Returns the translated description for the variable with the specified ``name``
236+
(if set).
237+
238+
.. versionadded:: 3.0
239+
:rtype: str
240+
%End
241+
227242
int variableCount() const;
228243
%Docstring
229244
Returns the count of variables contained within the scope.
@@ -475,6 +490,17 @@ class QgsExpressionContext
475490
:rtype: bool
476491
%End
477492

493+
QString description( const QString &name ) const;
494+
%Docstring
495+
Returns a translated description string for the variable with specified ``name``.
496+
497+
If no specific description has been provided for the variable, the value from
498+
QgsExpression.variableHelpText() will be returned.
499+
500+
.. versionadded:: 3.0
501+
:rtype: str
502+
%End
503+
478504
bool hasFunction( const QString &name ) const;
479505
%Docstring
480506
Checks whether a specified function is contained in the context.

src/core/expression/qgsexpression.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,15 @@ void QgsExpression::initVariableHelp()
690690
sVariableHelpTexts.insert( QStringLiteral( "algorithm_id" ), QCoreApplication::translate( "algorithm_id", "Unique ID for algorithm." ) );
691691
}
692692

693-
QString QgsExpression::variableHelpText( const QString &variableName, bool showValue, const QVariant &value )
693+
QString QgsExpression::variableHelpText( const QString &variableName )
694694
{
695695
QgsExpression::initVariableHelp();
696-
QString text = sVariableHelpTexts.contains( variableName ) ? QStringLiteral( "<p>%1</p>" ).arg( sVariableHelpTexts.value( variableName ) ) : QString();
696+
return sVariableHelpTexts.value( variableName, QString() );
697+
}
698+
699+
QString QgsExpression::formatVariableHelp( const QString &description, bool showValue, const QVariant &value )
700+
{
701+
QString text = !description.isEmpty() ? QStringLiteral( "<p>%1</p>" ).arg( description ) : QString();
697702
if ( showValue )
698703
{
699704
QString valueString;

src/core/expression/qgsexpression.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ class CORE_EXPORT QgsExpression
424424
/** Returns the help text for a specified function.
425425
* \param name function name
426426
* \see variableHelpText()
427+
* \see formatVariableHelp()
427428
*/
428429
static QString helpText( QString name );
429430

@@ -434,7 +435,18 @@ class CORE_EXPORT QgsExpression
434435
* \see helpText()
435436
* \since QGIS 2.12
436437
*/
437-
static QString variableHelpText( const QString &variableName, bool showValue = true, const QVariant &value = QVariant() );
438+
static QString variableHelpText( const QString &variableName );
439+
440+
/**
441+
* Returns formatted help text for a variable.
442+
* \param description translated description of variable
443+
* \param showValue set to true to include current value of variable in help text
444+
* \param value current value of variable to show in help text
445+
* \see helpText()
446+
* \see variableHelpText()
447+
* \since QGIS 3.0
448+
*/
449+
static QString formatVariableHelp( const QString &description, bool showValue = true, const QVariant &value = QVariant() );
438450

439451
/** Returns the translated name for a function group.
440452
* \param group untranslated group name

src/core/qgsexpressioncontext.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ bool QgsExpressionContextScope::isStatic( const QString &name ) const
188188
return hasVariable( name ) ? mVariables.value( name ).isStatic : false;
189189
}
190190

191+
QString QgsExpressionContextScope::description( const QString &name ) const
192+
{
193+
return hasVariable( name ) ? mVariables.value( name ).description : QString();
194+
}
195+
191196
bool QgsExpressionContextScope::hasFunction( const QString &name ) const
192197
{
193198
return mFunctions.contains( name );
@@ -404,6 +409,12 @@ bool QgsExpressionContext::isReadOnly( const QString &name ) const
404409
return false;
405410
}
406411

412+
QString QgsExpressionContext::description( const QString &name ) const
413+
{
414+
const QgsExpressionContextScope *scope = activeScopeForVariable( name );
415+
return ( scope && !scope->description( name ).isEmpty() ) ? scope->description( name ) : QgsExpression::variableHelpText( name );
416+
}
417+
407418
bool QgsExpressionContext::hasFunction( const QString &name ) const
408419
{
409420
Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )

src/core/qgsexpressioncontext.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ class CORE_EXPORT QgsExpressionContextScope
133133
* \param value initial variable value
134134
* \param readOnly true if variable should not be editable by users
135135
* \param isStatic true if the variable will not change during the lifteime of an iterator.
136+
* \param description optional translated description of variable, for use in expression builder widgets
136137
*/
137-
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false )
138+
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false, const QString &description = QString() )
138139
: name( name )
139140
, value( value )
140141
, readOnly( readOnly )
141142
, isStatic( isStatic )
143+
, description( description )
142144
{}
143145

144146
//! Variable name
@@ -152,6 +154,9 @@ class CORE_EXPORT QgsExpressionContextScope
152154

153155
//! A static variable can be cached for the lifetime of a context
154156
bool isStatic;
157+
158+
//! Translated description of variable, for use within expression builder widgets.
159+
QString description;
155160
};
156161

157162
/** Constructor for QgsExpressionContextScope
@@ -238,6 +243,14 @@ class CORE_EXPORT QgsExpressionContextScope
238243
*/
239244
bool isStatic( const QString &name ) const;
240245

246+
/**
247+
* Returns the translated description for the variable with the specified \a name
248+
* (if set).
249+
*
250+
* \since QGIS 3.0
251+
*/
252+
QString description( const QString &name ) const;
253+
241254
/** Returns the count of variables contained within the scope.
242255
*/
243256
int variableCount() const { return mVariables.count(); }
@@ -463,6 +476,16 @@ class CORE_EXPORT QgsExpressionContext
463476
*/
464477
bool isReadOnly( const QString &name ) const;
465478

479+
/**
480+
* Returns a translated description string for the variable with specified \a name.
481+
*
482+
* If no specific description has been provided for the variable, the value from
483+
* QgsExpression::variableHelpText() will be returned.
484+
*
485+
* \since QGIS 3.0
486+
*/
487+
QString description( const QString &name ) const;
488+
466489
/** Checks whether a specified function is contained in the context.
467490
* \param name function name
468491
* \returns true if context provides a matching function

src/gui/qgsexpressionbuilderwidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
587587
Q_FOREACH ( const QString &variable, variableNames )
588588
{
589589
registerItem( QStringLiteral( "Variables" ), variable, " @" + variable + ' ',
590-
QgsExpression::variableHelpText( variable, true, mExpressionContext.variable( variable ) ),
590+
QgsExpression::formatVariableHelp( mExpressionContext.description( variable ), true, mExpressionContext.variable( variable ) ),
591591
QgsExpressionItem::ExpressionNode,
592592
mExpressionContext.isHighlightedVariable( variable ) );
593593
}

tests/src/core/testqgsexpressioncontext.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class TestQgsExpressionContext : public QObject
5252
void cache();
5353

5454
void valuesAsMap();
55+
void description();
5556

5657
private:
5758

@@ -163,6 +164,7 @@ void TestQgsExpressionContext::contextScope()
163164
QVERIFY( !scope.variable( "test" ).isValid() );
164165
QCOMPARE( scope.variableNames().length(), 0 );
165166
QCOMPARE( scope.variableCount(), 0 );
167+
QVERIFY( scope.description( "test" ).isEmpty() );
166168

167169
scope.setVariable( QStringLiteral( "test" ), 5 );
168170
QVERIFY( scope.hasVariable( "test" ) );
@@ -171,15 +173,19 @@ void TestQgsExpressionContext::contextScope()
171173
QCOMPARE( scope.variableNames().length(), 1 );
172174
QCOMPARE( scope.variableCount(), 1 );
173175
QCOMPARE( scope.variableNames().at( 0 ), QString( "test" ) );
176+
QVERIFY( scope.description( "test" ).isEmpty() );
174177

175-
scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), QStringLiteral( "readonly_test" ), true ) );
178+
scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), QStringLiteral( "readonly_test" ), true, false, QStringLiteral( "readonly variable" ) ) );
176179
QVERIFY( scope.isReadOnly( "readonly" ) );
180+
QCOMPARE( scope.description( "readonly" ), QStringLiteral( "readonly variable" ) );
177181
scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "notreadonly" ), QStringLiteral( "not_readonly_test" ), false ) );
178182
QVERIFY( !scope.isReadOnly( "notreadonly" ) );
179183

180184
//updating a read only variable should remain read only
181185
scope.setVariable( QStringLiteral( "readonly" ), "newvalue" );
182186
QVERIFY( scope.isReadOnly( "readonly" ) );
187+
// and keep its description
188+
QCOMPARE( scope.description( "readonly" ), QStringLiteral( "readonly variable" ) );
183189

184190
//test retrieving filtered variable names
185191
scope.setVariable( QStringLiteral( "_hidden_" ), "hidden" );
@@ -245,6 +251,7 @@ void TestQgsExpressionContext::contextStack()
245251
QCOMPARE( context.scopeCount(), 0 );
246252
QVERIFY( !context.scope( 0 ) );
247253
QVERIFY( !context.lastScope() );
254+
QVERIFY( context.description( "test" ).isEmpty() );
248255

249256
//add a scope to the context
250257
QgsExpressionContextScope *testScope = new QgsExpressionContextScope();
@@ -305,10 +312,13 @@ void TestQgsExpressionContext::contextStack()
305312
QCOMPARE( scopes.at( 0 ), scope1 );
306313
QCOMPARE( scopes.at( 1 ), scope2 );
307314

315+
QVERIFY( context.description( "readonly" ).isEmpty() );
316+
308317
//check isReadOnly
309-
scope2->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), 5, true ) );
318+
scope2->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), 5, true, false, QStringLiteral( "readonly variable" ) ) );
310319
QVERIFY( context.isReadOnly( "readonly" ) );
311320
QVERIFY( !context.isReadOnly( "test" ) );
321+
QCOMPARE( context.description( "readonly" ), QStringLiteral( "readonly variable" ) );
312322

313323
// Check scopes can be popped
314324
delete context.popScope();
@@ -735,5 +745,20 @@ void TestQgsExpressionContext::valuesAsMap()
735745
QCOMPARE( m.value( "v3" ).toString(), QString( "t3" ) );
736746
}
737747

748+
void TestQgsExpressionContext::description()
749+
{
750+
// test that description falls back to default values if not set
751+
QgsExpressionContext context;
752+
QgsExpressionContextScope *scope = new QgsExpressionContextScope();
753+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ) ) );
754+
context << scope;
755+
QCOMPARE( context.description( "project_title" ), QgsExpression::variableHelpText( "project_title" ) );
756+
// but if set, use that
757+
scope = new QgsExpressionContextScope();
758+
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), QVariant(), true, true, QStringLiteral( "my desc" ) ) );
759+
context << scope;
760+
QCOMPARE( context.description( "project_title" ), QStringLiteral( "my desc" ) );
761+
}
762+
738763
QGSTEST_MAIN( TestQgsExpressionContext )
739764
#include "testqgsexpressioncontext.moc"

0 commit comments

Comments
 (0)