Skip to content

Commit

Permalink
Add method for specifying variable description when adding to contexts
Browse files Browse the repository at this point in the history
And use this description in expression builders when it's set.
  • Loading branch information
nyalldawson committed Jul 7, 2017
1 parent 534844f commit 35e16b2
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 9 deletions.
2 changes: 2 additions & 0 deletions doc/api_break.dox
Expand Up @@ -1116,6 +1116,8 @@ version instead.
- QgsExpression::Node::referencedColumns() returns QSet<QString> instead of QStringList
- `QgsExpression::Node` was renamed to `QgsExpressionNode`
- `QgsExpression::Function` was renamed to `QgsExpressionFunction`
- variableHelpText() no longer returns a formatted HTML string. It now just returns the plain text help string. Use formatVariableHelp()
to obtain the formatted version.


QgsExpression::Function {#qgis_api_break_3_0_QgsExpression_Function}
Expand Down
15 changes: 14 additions & 1 deletion python/core/expression/qgsexpression.sip
Expand Up @@ -464,10 +464,11 @@ return index of the function in Functions array
Returns the help text for a specified function.
\param name function name
.. seealso:: variableHelpText()
.. seealso:: formatVariableHelp()
:rtype: str
%End

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

static QString formatVariableHelp( const QString &description, bool showValue = true, const QVariant &value = QVariant() );
%Docstring
Returns formatted help text for a variable.
\param description translated description of variable
\param showValue set to true to include current value of variable in help text
\param value current value of variable to show in help text
.. seealso:: helpText()
.. seealso:: variableHelpText()
.. versionadded:: 3.0
:rtype: str
%End

static QString group( const QString &group );
%Docstring
Returns the translated name for a function group.
Expand Down
28 changes: 27 additions & 1 deletion python/core/qgsexpressioncontext.sip
Expand Up @@ -92,13 +92,14 @@ class QgsExpressionContextScope
struct StaticVariable
{

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

QString name;
Expand All @@ -119,6 +120,11 @@ True if variable should not be editable by users
bool isStatic;
%Docstring
A static variable can be cached for the lifetime of a context
%End

QString description;
%Docstring
Translated description of variable, for use within expression builder widgets.
%End
};

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

QString description( const QString &name ) const;
%Docstring
Returns the translated description for the variable with the specified ``name``
(if set).

.. versionadded:: 3.0
:rtype: str
%End

int variableCount() const;
%Docstring
Returns the count of variables contained within the scope.
Expand Down Expand Up @@ -475,6 +490,17 @@ class QgsExpressionContext
:rtype: bool
%End

QString description( const QString &name ) const;
%Docstring
Returns a translated description string for the variable with specified ``name``.

If no specific description has been provided for the variable, the value from
QgsExpression.variableHelpText() will be returned.

.. versionadded:: 3.0
:rtype: str
%End

bool hasFunction( const QString &name ) const;
%Docstring
Checks whether a specified function is contained in the context.
Expand Down
9 changes: 7 additions & 2 deletions src/core/expression/qgsexpression.cpp
Expand Up @@ -690,10 +690,15 @@ void QgsExpression::initVariableHelp()
sVariableHelpTexts.insert( QStringLiteral( "algorithm_id" ), QCoreApplication::translate( "algorithm_id", "Unique ID for algorithm." ) );
}

QString QgsExpression::variableHelpText( const QString &variableName, bool showValue, const QVariant &value )
QString QgsExpression::variableHelpText( const QString &variableName )
{
QgsExpression::initVariableHelp();
QString text = sVariableHelpTexts.contains( variableName ) ? QStringLiteral( "<p>%1</p>" ).arg( sVariableHelpTexts.value( variableName ) ) : QString();
return sVariableHelpTexts.value( variableName, QString() );
}

QString QgsExpression::formatVariableHelp( const QString &description, bool showValue, const QVariant &value )
{
QString text = !description.isEmpty() ? QStringLiteral( "<p>%1</p>" ).arg( description ) : QString();
if ( showValue )
{
QString valueString;
Expand Down
14 changes: 13 additions & 1 deletion src/core/expression/qgsexpression.h
Expand Up @@ -424,6 +424,7 @@ class CORE_EXPORT QgsExpression
/** Returns the help text for a specified function.
* \param name function name
* \see variableHelpText()
* \see formatVariableHelp()
*/
static QString helpText( QString name );

Expand All @@ -434,7 +435,18 @@ class CORE_EXPORT QgsExpression
* \see helpText()
* \since QGIS 2.12
*/
static QString variableHelpText( const QString &variableName, bool showValue = true, const QVariant &value = QVariant() );
static QString variableHelpText( const QString &variableName );

/**
* Returns formatted help text for a variable.
* \param description translated description of variable
* \param showValue set to true to include current value of variable in help text
* \param value current value of variable to show in help text
* \see helpText()
* \see variableHelpText()
* \since QGIS 3.0
*/
static QString formatVariableHelp( const QString &description, bool showValue = true, const QVariant &value = QVariant() );

/** Returns the translated name for a function group.
* \param group untranslated group name
Expand Down
11 changes: 11 additions & 0 deletions src/core/qgsexpressioncontext.cpp
Expand Up @@ -188,6 +188,11 @@ bool QgsExpressionContextScope::isStatic( const QString &name ) const
return hasVariable( name ) ? mVariables.value( name ).isStatic : false;
}

QString QgsExpressionContextScope::description( const QString &name ) const
{
return hasVariable( name ) ? mVariables.value( name ).description : QString();
}

bool QgsExpressionContextScope::hasFunction( const QString &name ) const
{
return mFunctions.contains( name );
Expand Down Expand Up @@ -404,6 +409,12 @@ bool QgsExpressionContext::isReadOnly( const QString &name ) const
return false;
}

QString QgsExpressionContext::description( const QString &name ) const
{
const QgsExpressionContextScope *scope = activeScopeForVariable( name );
return ( scope && !scope->description( name ).isEmpty() ) ? scope->description( name ) : QgsExpression::variableHelpText( name );
}

bool QgsExpressionContext::hasFunction( const QString &name ) const
{
Q_FOREACH ( const QgsExpressionContextScope *scope, mStack )
Expand Down
25 changes: 24 additions & 1 deletion src/core/qgsexpressioncontext.h
Expand Up @@ -133,12 +133,14 @@ class CORE_EXPORT QgsExpressionContextScope
* \param value initial variable value
* \param readOnly true if variable should not be editable by users
* \param isStatic true if the variable will not change during the lifteime of an iterator.
* \param description optional translated description of variable, for use in expression builder widgets
*/
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false )
StaticVariable( const QString &name = QString(), const QVariant &value = QVariant(), bool readOnly = false, bool isStatic = false, const QString &description = QString() )
: name( name )
, value( value )
, readOnly( readOnly )
, isStatic( isStatic )
, description( description )
{}

//! Variable name
Expand All @@ -152,6 +154,9 @@ class CORE_EXPORT QgsExpressionContextScope

//! A static variable can be cached for the lifetime of a context
bool isStatic;

//! Translated description of variable, for use within expression builder widgets.
QString description;
};

/** Constructor for QgsExpressionContextScope
Expand Down Expand Up @@ -238,6 +243,14 @@ class CORE_EXPORT QgsExpressionContextScope
*/
bool isStatic( const QString &name ) const;

/**
* Returns the translated description for the variable with the specified \a name
* (if set).
*
* \since QGIS 3.0
*/
QString description( const QString &name ) const;

/** Returns the count of variables contained within the scope.
*/
int variableCount() const { return mVariables.count(); }
Expand Down Expand Up @@ -463,6 +476,16 @@ class CORE_EXPORT QgsExpressionContext
*/
bool isReadOnly( const QString &name ) const;

/**
* Returns a translated description string for the variable with specified \a name.
*
* If no specific description has been provided for the variable, the value from
* QgsExpression::variableHelpText() will be returned.
*
* \since QGIS 3.0
*/
QString description( const QString &name ) const;

/** Checks whether a specified function is contained in the context.
* \param name function name
* \returns true if context provides a matching function
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsexpressionbuilderwidget.cpp
Expand Up @@ -587,7 +587,7 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
Q_FOREACH ( const QString &variable, variableNames )
{
registerItem( QStringLiteral( "Variables" ), variable, " @" + variable + ' ',
QgsExpression::variableHelpText( variable, true, mExpressionContext.variable( variable ) ),
QgsExpression::formatVariableHelp( mExpressionContext.description( variable ), true, mExpressionContext.variable( variable ) ),
QgsExpressionItem::ExpressionNode,
mExpressionContext.isHighlightedVariable( variable ) );
}
Expand Down
29 changes: 27 additions & 2 deletions tests/src/core/testqgsexpressioncontext.cpp
Expand Up @@ -52,6 +52,7 @@ class TestQgsExpressionContext : public QObject
void cache();

void valuesAsMap();
void description();

private:

Expand Down Expand Up @@ -163,6 +164,7 @@ void TestQgsExpressionContext::contextScope()
QVERIFY( !scope.variable( "test" ).isValid() );
QCOMPARE( scope.variableNames().length(), 0 );
QCOMPARE( scope.variableCount(), 0 );
QVERIFY( scope.description( "test" ).isEmpty() );

scope.setVariable( QStringLiteral( "test" ), 5 );
QVERIFY( scope.hasVariable( "test" ) );
Expand All @@ -171,15 +173,19 @@ void TestQgsExpressionContext::contextScope()
QCOMPARE( scope.variableNames().length(), 1 );
QCOMPARE( scope.variableCount(), 1 );
QCOMPARE( scope.variableNames().at( 0 ), QString( "test" ) );
QVERIFY( scope.description( "test" ).isEmpty() );

scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), QStringLiteral( "readonly_test" ), true ) );
scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), QStringLiteral( "readonly_test" ), true, false, QStringLiteral( "readonly variable" ) ) );
QVERIFY( scope.isReadOnly( "readonly" ) );
QCOMPARE( scope.description( "readonly" ), QStringLiteral( "readonly variable" ) );
scope.addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "notreadonly" ), QStringLiteral( "not_readonly_test" ), false ) );
QVERIFY( !scope.isReadOnly( "notreadonly" ) );

//updating a read only variable should remain read only
scope.setVariable( QStringLiteral( "readonly" ), "newvalue" );
QVERIFY( scope.isReadOnly( "readonly" ) );
// and keep its description
QCOMPARE( scope.description( "readonly" ), QStringLiteral( "readonly variable" ) );

//test retrieving filtered variable names
scope.setVariable( QStringLiteral( "_hidden_" ), "hidden" );
Expand Down Expand Up @@ -245,6 +251,7 @@ void TestQgsExpressionContext::contextStack()
QCOMPARE( context.scopeCount(), 0 );
QVERIFY( !context.scope( 0 ) );
QVERIFY( !context.lastScope() );
QVERIFY( context.description( "test" ).isEmpty() );

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

QVERIFY( context.description( "readonly" ).isEmpty() );

//check isReadOnly
scope2->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), 5, true ) );
scope2->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "readonly" ), 5, true, false, QStringLiteral( "readonly variable" ) ) );
QVERIFY( context.isReadOnly( "readonly" ) );
QVERIFY( !context.isReadOnly( "test" ) );
QCOMPARE( context.description( "readonly" ), QStringLiteral( "readonly variable" ) );

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

void TestQgsExpressionContext::description()
{
// test that description falls back to default values if not set
QgsExpressionContext context;
QgsExpressionContextScope *scope = new QgsExpressionContextScope();
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ) ) );
context << scope;
QCOMPARE( context.description( "project_title" ), QgsExpression::variableHelpText( "project_title" ) );
// but if set, use that
scope = new QgsExpressionContextScope();
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "project_title" ), QVariant(), true, true, QStringLiteral( "my desc" ) ) );
context << scope;
QCOMPARE( context.description( "project_title" ), QStringLiteral( "my desc" ) );
}

QGSTEST_MAIN( TestQgsExpressionContext )
#include "testqgsexpressioncontext.moc"

0 comments on commit 35e16b2

Please sign in to comment.