Skip to content

Commit bfc8f56

Browse files
committedAug 22, 2015
Display variables and functions from contexts in expression builder
1 parent c9c12bc commit bfc8f56

18 files changed

+245
-30
lines changed
 

‎python/core/composer/qgscomposition.sip

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,12 @@ class QgsComposition : QGraphicsScene
678678
*/
679679
void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );
680680

681+
/** Creates an expression context relating to the compositions's current state. The context includes
682+
* scopes for global, project, composition and atlas properties.
683+
* @note added in QGIS 2.12
684+
*/
685+
QgsExpressionContext* createExpressionContext() const;
686+
681687
protected:
682688
void init();
683689

‎python/core/qgsexpressioncontext.sip

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class QgsExpressionContextScope
121121
QVariant variable( const QString& name ) const;
122122

123123
/** Returns a list of variable names contained within the scope.
124+
* @see functionNames()
124125
*/
125126
QStringList variableNames() const;
126127

@@ -147,10 +148,17 @@ class QgsExpressionContextScope
147148
* @param name function name
148149
* @returns function, or null if matching function could not be found
149150
* @see hasFunction()
151+
* @see functionNames()
150152
* @see variable()
151153
*/
152154
QgsExpression::Function* function( const QString &name ) const;
153155

156+
/** Retrieves a list of names of functions contained in the scope.
157+
* @see function()
158+
* @see variableNames()
159+
*/
160+
QStringList functionNames() const;
161+
154162
/** Adds a function to the scope.
155163
* @param name function name
156164
* @param function function to insert. Ownership is transferred to the scope.
@@ -163,7 +171,7 @@ class QgsExpressionContextScope
163171
* @param feature feature for scope
164172
*/
165173
void setFeature( const QgsFeature& feature );
166-
174+
167175
/** Convenience function for setting a fields for the scope. Any existing
168176
* fields set by the scope will be overwritten.
169177
* @param fields fields for scope
@@ -253,11 +261,20 @@ class QgsExpressionContext
253261

254262
/** Returns a list of variables names set by all scopes in the context.
255263
* @returns list of unique variable names
264+
* @see filteredVariableNames
265+
* @see functionNames
256266
* @see hasVariable
257267
* @see variable
258268
*/
259269
QStringList variableNames() const;
260270

271+
/** Returns a filtered list of variables names set by all scopes in the context. The included
272+
* variables are those which should be seen by users.
273+
* @returns filtered list of unique variable names
274+
* @see variableNames
275+
*/
276+
QStringList filteredVariableNames() const;
277+
261278
/** Returns whether a variable is read only, and should not be modifiable by users.
262279
* @param name variable name
263280
* @returns true if variable is read only. Read only status will be taken from last
@@ -272,6 +289,12 @@ class QgsExpressionContext
272289
*/
273290
bool hasFunction( const QString& name ) const;
274291

292+
/** Retrieves a list of function names contained in the context.
293+
* @see function()
294+
* @see variableNames()
295+
*/
296+
QStringList functionNames() const;
297+
275298
/** Fetches a matching function from the context. The function will be fetched
276299
* from the last scope contained within the context which has a matching
277300
* function set.
@@ -297,21 +320,21 @@ class QgsExpressionContext
297320
* context. Ownership of the scope is transferred to the stack.
298321
*/
299322
QgsExpressionContext& operator<< ( QgsExpressionContextScope* scope /Transfer/ );
300-
323+
301324
/** Convenience function for setting a feature for the context. The feature
302325
* will be set within the last scope of the context, so will override any
303326
* existing features within the context.
304327
* @param feature feature for context
305328
*/
306-
void setFeature( const QgsFeature& feature );
329+
void setFeature( const QgsFeature& feature );
307330

308331
/** Convenience function for setting a fields for the context. The fields
309332
* will be set within the last scope of the context, so will override any
310333
* existing fields within the context.
311334
* @param fields fields for context
312335
*/
313336
void setFields( const QgsFields& fields );
314-
337+
315338
};
316339

317340
/** \ingroup core
@@ -378,12 +401,12 @@ class QgsExpressionContextUtils
378401
* For instance, layer name, id and fields.
379402
*/
380403
static QgsExpressionContextScope* layerScope( QgsMapLayer* layer ) /Factory/;
381-
404+
382405
/** Helper function for creating an expression context which contains just a feature and fields
383406
* collection. Generally this method should not be used as the created context does not include
384407
* standard scopes such as the global and project scopes.
385408
*/
386-
static QgsExpressionContext createFeatureBasedContext( const QgsFeature& feature, const QgsFields& fields );
409+
static QgsExpressionContext createFeatureBasedContext( const QgsFeature& feature, const QgsFields& fields );
387410

388411
/** Sets a layer context variable. This variable will be contained within scopes retrieved via
389412
* layerScope().

‎python/gui/qgsexpressionbuilderdialog.sip

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class QgsExpressionBuilderDialog : QDialog
88
%End
99

1010
public:
11-
QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText = QString(), QWidget* parent /TransferThis/ = NULL, QString key = "generic" );
11+
QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText = QString(), QWidget* parent /TransferThis/ = NULL, QString key = "generic",
12+
const QgsExpressionContext& context = QgsExpressionContext() );
1213

1314
/** The builder widget that is used by the dialog */
1415
QgsExpressionBuilderWidget* expressionBuilder();
@@ -17,6 +18,21 @@ class QgsExpressionBuilderDialog : QDialog
1718

1819
QString expressionText();
1920

21+
/** Returns the expression context for the dialog. The context is used for the expression
22+
* preview result and for populating the list of available functions and variables.
23+
* @see setExpressionContext
24+
* @note added in QGIS 2.12
25+
*/
26+
QgsExpressionContext expressionContext() const;
27+
28+
/** Sets the expression context for the dialog. The context is used for the expression
29+
* preview result and for populating the list of available functions and variables.
30+
* @param context expression context
31+
* @see expressionContext
32+
* @note added in QGIS 2.12
33+
*/
34+
void setExpressionContext( const QgsExpressionContext& context );
35+
2036
/** Sets geometry calculator used in distance/area calculations. */
2137
void setGeomCalculator( const QgsDistanceArea & da );
2238

‎python/gui/qgsexpressionbuilderwidget.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,21 @@ class QgsExpressionBuilderWidget : QWidget
100100
/** Sets the expression string for the widget */
101101
void setExpressionText( const QString& expression );
102102

103+
/** Returns the expression context for the widget. The context is used for the expression
104+
* preview result and for populating the list of available functions and variables.
105+
* @see setExpressionContext
106+
* @note added in QGIS 2.12
107+
*/
108+
QgsExpressionContext expressionContext() const;
109+
110+
/** Sets the expression context for the widget. The context is used for the expression
111+
* preview result and for populating the list of available functions and variables.
112+
* @param context expression context
113+
* @see expressionContext
114+
* @note added in QGIS 2.12
115+
*/
116+
void setExpressionContext( const QgsExpressionContext& context );
117+
103118
/** Registers a node item for the expression builder.
104119
* @param group The group the item will be show in the tree view. If the group doesn't exsit it will be created.
105120
* @param label The label that is show to the user for the item in the tree.

‎src/app/composer/qgsatlascompositionwidget.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,10 @@ void QgsAtlasCompositionWidget::on_mAtlasFilenameExpressionButton_clicked()
9494
return;
9595
}
9696

97-
QgsExpressionBuilderDialog exprDlg( atlasMap->coverageLayer(), mAtlasFilenamePatternEdit->text(), this );
97+
QScopedPointer<QgsExpressionContext> context( mComposition->createExpressionContext() );
98+
QgsExpressionBuilderDialog exprDlg( atlasMap->coverageLayer(), mAtlasFilenamePatternEdit->text(), this, "generic", *context );
9899
exprDlg.setWindowTitle( tr( "Expression based filename" ) );
100+
99101
if ( exprDlg.exec() == QDialog::Accepted )
100102
{
101103
QString expression = exprDlg.expressionText();
@@ -233,8 +235,10 @@ void QgsAtlasCompositionWidget::on_mAtlasFeatureFilterButton_clicked()
233235
return;
234236
}
235237

236-
QgsExpressionBuilderDialog exprDlg( vl, mAtlasFeatureFilterEdit->text(), this );
238+
QScopedPointer<QgsExpressionContext> context( mComposition->createExpressionContext() );
239+
QgsExpressionBuilderDialog exprDlg( vl, mAtlasFeatureFilterEdit->text(), this, "generic", *context );
237240
exprDlg.setWindowTitle( tr( "Expression based filter" ) );
241+
238242
if ( exprDlg.exec() == QDialog::Accepted )
239243
{
240244
QString expression = exprDlg.expressionText();

‎src/app/composer/qgscomposerattributetablewidget.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,8 @@ void QgsComposerAttributeTableWidget::on_mFeatureFilterButton_clicked()
798798
return;
799799
}
800800

801-
QgsExpressionBuilderDialog exprDlg( mComposerTable->sourceLayer(), mFeatureFilterEdit->text(), this );
801+
QScopedPointer<QgsExpressionContext> context( mComposerTable->createExpressionContext() );
802+
QgsExpressionBuilderDialog exprDlg( mComposerTable->sourceLayer(), mFeatureFilterEdit->text(), this, "generic", *context );
802803
exprDlg.setWindowTitle( tr( "Expression based filter" ) );
803804
if ( exprDlg.exec() == QDialog::Accepted )
804805
{

‎src/app/composer/qgscomposerhtmlwidget.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ void QgsComposerHtmlWidget::on_mInsertExpressionButton_clicked()
369369

370370
// use the atlas coverage layer, if any
371371
QgsVectorLayer* coverageLayer = atlasCoverageLayer();
372-
QgsExpressionBuilderDialog exprDlg( coverageLayer, selText, this );
372+
QScopedPointer<QgsExpressionContext> context( mHtml->createExpressionContext() );
373+
QgsExpressionBuilderDialog exprDlg( coverageLayer, selText, this, "generic", *context );
373374
exprDlg.setWindowTitle( tr( "Insert expression" ) );
374375
if ( exprDlg.exec() == QDialog::Accepted )
375376
{

‎src/app/composer/qgscomposerlabelwidget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ void QgsComposerLabelWidget::on_mInsertExpressionButton_clicked()
152152

153153
// use the atlas coverage layer, if any
154154
QgsVectorLayer* coverageLayer = atlasCoverageLayer();
155-
QgsExpressionBuilderDialog exprDlg( coverageLayer, selText, this );
155+
QScopedPointer<QgsExpressionContext> context( mComposerLabel->createExpressionContext() );
156+
QgsExpressionBuilderDialog exprDlg( coverageLayer, selText, this, "generic", *context );
157+
156158
exprDlg.setWindowTitle( tr( "Insert expression" ) );
157159
if ( exprDlg.exec() == QDialog::Accepted )
158160
{

‎src/app/composer/qgscomposertablewidget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,9 @@ void QgsComposerTableWidget::on_mFeatureFilterButton_clicked()
464464
return;
465465
}
466466

467-
QgsExpressionBuilderDialog exprDlg( mComposerTable->vectorLayer(), mFeatureFilterEdit->text(), this );
467+
QScopedPointer<QgsExpressionContext> context( mComposerTable->createExpressionContext() );
468+
QgsExpressionBuilderDialog exprDlg( mComposerTable->vectorLayer(), mFeatureFilterEdit->text(), this, "generic", *context );
469+
468470
exprDlg.setWindowTitle( tr( "Expression based filter" ) );
469471
if ( exprDlg.exec() == QDialog::Accepted )
470472
{

‎src/core/composer/qgscomposition.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,12 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
741741
*/
742742
void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );
743743

744+
/** Creates an expression context relating to the compositions's current state. The context includes
745+
* scopes for global, project, composition and atlas properties.
746+
* @note added in QGIS 2.12
747+
*/
748+
QgsExpressionContext* createExpressionContext() const;
749+
744750
protected:
745751
void init();
746752

@@ -900,12 +906,6 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
900906
*/
901907
void prepareDataDefinedExpression( QgsDataDefined *dd, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >* dataDefinedProperties, const QgsExpressionContext& context ) const;
902908

903-
/** Creates an expression context relating to the compositions's current state. The context includes
904-
* scopes for global, project, composition and atlas properties.
905-
* @note added in QGIS 2.12
906-
*/
907-
QgsExpressionContext* createExpressionContext() const;
908-
909909
/** Check whether any data defined page settings are active.
910910
* @returns true if any data defined page settings are active.
911911
* @note this method was added in version 2.5

‎src/core/qgsexpression.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,7 @@ QString QgsExpression::group( QString name )
30413041
gGroups.insert( "Color", QObject::tr( "Color" ) );
30423042
gGroups.insert( "GeometryGroup", QObject::tr( "Geometry" ) );
30433043
gGroups.insert( "Record", QObject::tr( "Record" ) );
3044+
gGroups.insert( "Variables", QObject::tr( "Variables" ) );
30443045
}
30453046

30463047
//return the translated name for this group. If group does not

‎src/core/qgsexpressioncontext.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ QgsExpression::Function* QgsExpressionContextScope::function( const QString& nam
127127
return mFunctions.contains( name ) ? mFunctions.value( name ) : 0;
128128
}
129129

130+
QStringList QgsExpressionContextScope::functionNames() const
131+
{
132+
return mFunctions.keys();
133+
}
134+
130135
void QgsExpressionContextScope::addFunction( const QString& name, QgsScopedExpressionFunction* function )
131136
{
132137
mFunctions.insert( name, function );
@@ -248,6 +253,22 @@ QStringList QgsExpressionContext::variableNames() const
248253
return names.toSet().toList();
249254
}
250255

256+
QStringList QgsExpressionContext::filteredVariableNames() const
257+
{
258+
QStringList allVariables = variableNames();
259+
QStringList filtered;
260+
Q_FOREACH ( QString variable, allVariables )
261+
{
262+
if ( variable.startsWith( "_" ) )
263+
continue;
264+
265+
filtered << variable;
266+
}
267+
268+
filtered.sort();
269+
return filtered;
270+
}
271+
251272
bool QgsExpressionContext::isReadOnly( const QString& name ) const { Q_UNUSED( name ); return true; }
252273

253274
bool QgsExpressionContext::hasFunction( const QString &name ) const
@@ -260,6 +281,18 @@ bool QgsExpressionContext::hasFunction( const QString &name ) const
260281
return false;
261282
}
262283

284+
QStringList QgsExpressionContext::functionNames() const
285+
{
286+
QStringList result;
287+
Q_FOREACH ( const QgsExpressionContextScope* scope, mStack )
288+
{
289+
result << scope->functionNames();
290+
}
291+
result = result.toSet().toList();
292+
result.sort();
293+
return result;
294+
}
295+
263296
QgsExpression::Function *QgsExpressionContext::function( const QString &name ) const
264297
{
265298
//iterate through stack backwards, so that higher priority variables take precedence

‎src/core/qgsexpressioncontext.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class CORE_EXPORT QgsExpressionContextScope
150150
QVariant variable( const QString& name ) const;
151151

152152
/** Returns a list of variable names contained within the scope.
153+
* @see functionNames()
153154
*/
154155
QStringList variableNames() const;
155156

@@ -176,10 +177,17 @@ class CORE_EXPORT QgsExpressionContextScope
176177
* @param name function name
177178
* @returns function, or null if matching function could not be found
178179
* @see hasFunction()
180+
* @see functionNames()
179181
* @see variable()
180182
*/
181183
QgsExpression::Function* function( const QString &name ) const;
182184

185+
/** Retrieves a list of names of functions contained in the scope.
186+
* @see function()
187+
* @see variableNames()
188+
*/
189+
QStringList functionNames() const;
190+
183191
/** Adds a function to the scope.
184192
* @param name function name
185193
* @param function function to insert. Ownership is transferred to the scope.
@@ -284,11 +292,20 @@ class CORE_EXPORT QgsExpressionContext
284292

285293
/** Returns a list of variables names set by all scopes in the context.
286294
* @returns list of unique variable names
295+
* @see filteredVariableNames
296+
* @see functionNames
287297
* @see hasVariable
288298
* @see variable
289299
*/
290300
QStringList variableNames() const;
291301

302+
/** Returns a filtered list of variables names set by all scopes in the context. The included
303+
* variables are those which should be seen by users.
304+
* @returns filtered list of unique variable names
305+
* @see variableNames
306+
*/
307+
QStringList filteredVariableNames() const;
308+
292309
/** Returns whether a variable is read only, and should not be modifiable by users.
293310
* @param name variable name
294311
* @returns true if variable is read only. Read only status will be taken from last
@@ -303,6 +320,12 @@ class CORE_EXPORT QgsExpressionContext
303320
*/
304321
bool hasFunction( const QString& name ) const;
305322

323+
/** Retrieves a list of function names contained in the context.
324+
* @see function()
325+
* @see variableNames()
326+
*/
327+
QStringList functionNames() const;
328+
306329
/** Fetches a matching function from the context. The function will be fetched
307330
* from the last scope contained within the context which has a matching
308331
* function set.

‎src/gui/qgsexpressionbuilderdialog.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
#include "qgsexpressionbuilderdialog.h"
1717
#include <QSettings>
1818

19-
QgsExpressionBuilderDialog::QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText, QWidget* parent, QString key )
19+
QgsExpressionBuilderDialog::QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText, QWidget* parent, QString key, const QgsExpressionContext &context )
2020
: QDialog( parent ), mRecentKey( key )
2121
{
2222
setupUi( this );
2323

2424
QPushButton* okButton = buttonBox->button( QDialogButtonBox::Ok );
2525
connect( builder, SIGNAL( expressionParsed( bool ) ), okButton, SLOT( setEnabled( bool ) ) );
2626

27+
builder->setExpressionContext( context );
2728
builder->setLayer( layer );
2829
builder->setExpressionText( startText );
2930
builder->loadFieldNames();
@@ -48,6 +49,16 @@ QString QgsExpressionBuilderDialog::expressionText()
4849
return builder->expressionText();
4950
}
5051

52+
QgsExpressionContext QgsExpressionBuilderDialog::expressionContext() const
53+
{
54+
return builder->expressionContext();
55+
}
56+
57+
void QgsExpressionBuilderDialog::setExpressionContext( const QgsExpressionContext &context )
58+
{
59+
builder->setExpressionContext( context );
60+
}
61+
5162
void QgsExpressionBuilderDialog::done( int r )
5263
{
5364
QDialog::done( r );

‎src/gui/qgsexpressionbuilderdialog.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
class GUI_EXPORT QgsExpressionBuilderDialog : public QDialog, private Ui::QgsExpressionBuilderDialogBase
2727
{
2828
public:
29-
QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText = QString(), QWidget* parent = NULL, QString key = "generic" );
29+
QgsExpressionBuilderDialog( QgsVectorLayer* layer, QString startText = QString(), QWidget* parent = NULL, QString key = "generic",
30+
const QgsExpressionContext& context = QgsExpressionContext() );
3031

3132
/** The builder widget that is used by the dialog */
3233
QgsExpressionBuilderWidget* expressionBuilder();
@@ -35,6 +36,21 @@ class GUI_EXPORT QgsExpressionBuilderDialog : public QDialog, private Ui::QgsExp
3536

3637
QString expressionText();
3738

39+
/** Returns the expression context for the dialog. The context is used for the expression
40+
* preview result and for populating the list of available functions and variables.
41+
* @see setExpressionContext
42+
* @note added in QGIS 2.12
43+
*/
44+
QgsExpressionContext expressionContext() const;
45+
46+
/** Sets the expression context for the dialog. The context is used for the expression
47+
* preview result and for populating the list of available functions and variables.
48+
* @param context expression context
49+
* @see expressionContext
50+
* @note added in QGIS 2.12
51+
*/
52+
void setExpressionContext( const QgsExpressionContext& context );
53+
3854
/** Sets geometry calculator used in distance/area calculations. */
3955
void setGeomCalculator( const QgsDistanceArea & da );
4056

‎src/gui/qgsexpressionbuilderwidget.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
3535
{
3636
setupUi( this );
3737

38-
//TODO - allow setting context for widget, so that preview has access to full context for expression
39-
//and variables etc can be shown in builder widget
40-
mExpressionContext << QgsExpressionContextUtils::globalScope()
41-
<< QgsExpressionContextUtils::projectScope();
42-
4338
mValueGroupBox->hide();
4439
mLoadGroupBox->hide();
4540
// highlighter = new QgsExpressionHighlighter( txtExpressionString->document() );
@@ -104,9 +99,8 @@ void QgsExpressionBuilderWidget::setLayer( QgsVectorLayer *layer )
10499
{
105100
mLayer = layer;
106101

107-
mExpressionContext = QgsExpressionContext();
108-
mExpressionContext << QgsExpressionContextUtils::globalScope()
109-
<< QgsExpressionContextUtils::projectScope();
102+
//TODO - remove existing layer scope from context
103+
110104
if ( mLayer )
111105
mExpressionContext << QgsExpressionContextUtils::layerScope( mLayer );
112106
}
@@ -464,6 +458,8 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
464458
QString name = specials[i]->name();
465459
registerItem( specials[i]->group(), name, " " + name + " " );
466460
}
461+
462+
loadExpressionContext();
467463
}
468464

469465
void QgsExpressionBuilderWidget::setGeomCalculator( const QgsDistanceArea & da )
@@ -481,6 +477,13 @@ void QgsExpressionBuilderWidget::setExpressionText( const QString& expression )
481477
txtExpressionString->setText( expression );
482478
}
483479

480+
void QgsExpressionBuilderWidget::setExpressionContext( const QgsExpressionContext &context )
481+
{
482+
mExpressionContext = context;
483+
484+
loadExpressionContext();
485+
}
486+
484487
void QgsExpressionBuilderWidget::on_txtExpressionString_textChanged()
485488
{
486489
QString text = expressionText();
@@ -498,7 +501,6 @@ void QgsExpressionBuilderWidget::on_txtExpressionString_textChanged()
498501
}
499502

500503
QgsExpression exp( text );
501-
mExpressionContext.setFeature( QgsFeature() );
502504

503505
if ( mLayer )
504506
{
@@ -568,6 +570,28 @@ QString QgsExpressionBuilderWidget::formatPreviewString( const QString& previewS
568570
}
569571
}
570572

573+
void QgsExpressionBuilderWidget::loadExpressionContext()
574+
{
575+
QStringList variableNames = mExpressionContext.filteredVariableNames();
576+
Q_FOREACH ( QString variable, variableNames )
577+
{
578+
registerItem( "Variables", variable, " @" + variable + " " );
579+
}
580+
581+
// Load the functions from the expression context
582+
QStringList contextFunctions = mExpressionContext.functionNames();
583+
Q_FOREACH ( QString functionName, contextFunctions )
584+
{
585+
QgsExpression::Function* func = mExpressionContext.function( functionName );
586+
QString name = func->name();
587+
if ( name.startsWith( "_" ) ) // do not display private functions
588+
continue;
589+
if ( func->params() != 0 )
590+
name += "(";
591+
registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
592+
}
593+
}
594+
571595
void QgsExpressionBuilderWidget::on_txtSearchEdit_textChanged()
572596
{
573597
mProxyModel->setFilterWildcard( txtSearchEdit->text() );

‎src/gui/qgsexpressionbuilderwidget.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,21 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
142142
/** Sets the expression string for the widget */
143143
void setExpressionText( const QString& expression );
144144

145+
/** Returns the expression context for the widget. The context is used for the expression
146+
* preview result and for populating the list of available functions and variables.
147+
* @see setExpressionContext
148+
* @note added in QGIS 2.12
149+
*/
150+
QgsExpressionContext expressionContext() const { return mExpressionContext; }
151+
152+
/** Sets the expression context for the widget. The context is used for the expression
153+
* preview result and for populating the list of available functions and variables.
154+
* @param context expression context
155+
* @see expressionContext
156+
* @note added in QGIS 2.12
157+
*/
158+
void setExpressionContext( const QgsExpressionContext& context );
159+
145160
/** Registers a node item for the expression builder.
146161
* @param group The group the item will be show in the tree view. If the group doesn't exsit it will be created.
147162
* @param label The label that is show to the user for the item in the tree.
@@ -218,6 +233,8 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
218233
*/
219234
QString formatPreviewString( const QString &previewString ) const;
220235

236+
void loadExpressionContext();
237+
221238
QString mFunctionsPath;
222239
QgsVectorLayer *mLayer;
223240
QStandardItemModel *mModel;

‎tests/src/core/testqgsexpressioncontext.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ void TestQgsExpressionContext::contextScopeFunctions()
203203
QVERIFY( scope.function( "get_test_value" ) );
204204
QgsExpressionContext temp;
205205
QCOMPARE( scope.function( "get_test_value" )->func( QVariantList(), &temp, 0 ).toInt(), 42 );
206+
207+
//test functionNames
208+
scope.addFunction( "get_test_value2", new GetTestValueFunction() );
209+
QStringList functionNames = scope.functionNames();
210+
QCOMPARE( functionNames.count(), 2 );
211+
QVERIFY( functionNames.contains( "get_test_value" ) );
212+
QVERIFY( functionNames.contains( "get_test_value2" ) );
206213
}
207214

208215
void TestQgsExpressionContext::contextStack()
@@ -262,6 +269,13 @@ void TestQgsExpressionContext::contextStack()
262269
QCOMPARE( context.variable( "test2" ).toInt(), 11 );
263270
QCOMPARE( context.variableNames().length(), 2 );
264271

272+
//check filteredVariableNames method
273+
scope2->setVariable( "_hidden", 5 );
274+
QStringList filteredNames = context.filteredVariableNames();
275+
QCOMPARE( filteredNames.count(), 2 );
276+
QCOMPARE( filteredNames.at( 0 ), QString( "test" ) );
277+
QCOMPARE( filteredNames.at( 1 ), QString( "test2" ) );
278+
265279
//test scopes method
266280
QList< QgsExpressionContextScope*> scopes = context.scopes();
267281
QCOMPARE( scopes.length(), 2 );
@@ -325,6 +339,12 @@ void TestQgsExpressionContext::contextStackFunctions()
325339
QVERIFY( context.hasFunction( "get_test_value2" ) );
326340
QVERIFY( context.function( "get_test_value2" ) );
327341
QCOMPARE( context.function( "get_test_value2" )->func( QVariantList(), &temp, 0 ).toInt(), 42 );
342+
343+
//test functionNames
344+
QStringList names = context.functionNames();
345+
QCOMPARE( names.count(), 2 );
346+
QCOMPARE( names.at( 0 ), QString( "get_test_value" ) );
347+
QCOMPARE( names.at( 1 ), QString( "get_test_value2" ) );
328348
}
329349

330350
void TestQgsExpressionContext::evaluate()

0 commit comments

Comments
 (0)
Please sign in to comment.