Add method for specifying variable description when adding to contexts

And use this description in expression builders when it's set.
This commit is contained in:
Nyall Dawson 2017-07-04 08:53:30 +10:00
parent 534844f999
commit 35e16b2f31
9 changed files with 126 additions and 9 deletions

View File

@ -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}

View File

@ -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
@ -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.

View File

@ -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;
@ -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
};
@ -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.
@ -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.

View File

@ -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;

View File

@ -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 );
@ -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

View File

@ -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 );
@ -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 )

View File

@ -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
@ -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
@ -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(); }
@ -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

View File

@ -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 ) );
}

View File

@ -52,6 +52,7 @@ class TestQgsExpressionContext : public QObject
void cache();
void valuesAsMap();
void description();
private:
@ -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" ) );
@ -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" );
@ -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();
@ -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();
@ -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"