Skip to content

Commit 814b65b

Browse files
committedJan 14, 2021
Cleaner approach -- create expression contexts in modeler parameter
definition dialogs using expression context and processing context generators
1 parent 5a9e8c6 commit 814b65b

9 files changed

+190
-76
lines changed
 

‎python/gui/auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip.in

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313

1414

15-
class QgsProcessingAbstractParameterDefinitionWidget : QWidget
15+
16+
class QgsProcessingAbstractParameterDefinitionWidget : QWidget, QgsExpressionContextGenerator
1617
{
1718
%Docstring
1819
Abstract base class for widgets which allow users to specify the properties of a
@@ -53,6 +54,42 @@ Common properties for parameters, including the ``name``, ``description``, and p
5354
method. Subclass implementations must use these properties when crafting a parameter definition which
5455
also respects the additional properties specific to the parameter type handled by the widget subclass.
5556
%End
57+
58+
virtual void setWidgetContext( const QgsProcessingParameterWidgetContext &context );
59+
%Docstring
60+
Sets the ``context`` in which the Processing definition widget is shown, e.g., the
61+
parent model algorithm, a linked map canvas, and other relevant information which allows the widget
62+
to fine-tune its behavior.
63+
64+
Subclasses should take care to call the base class method when reimplementing this method.
65+
66+
.. seealso:: :py:func:`widgetContext`
67+
68+
.. versionadded:: 3.18
69+
%End
70+
71+
const QgsProcessingParameterWidgetContext &widgetContext() const;
72+
%Docstring
73+
Returns the context in which the Processing definition widget is shown, e.g., the
74+
parent model algorithm, a linked map canvas, and other relevant information which allows the widget
75+
to fine-tune its behavior.
76+
77+
.. seealso:: :py:func:`setWidgetContext`
78+
79+
.. versionadded:: 3.18
80+
%End
81+
82+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
83+
%Docstring
84+
Registers a Processing context ``generator`` class that will be used to retrieve
85+
a Processing context for the widget when required.
86+
87+
.. versionadded:: 3.18
88+
%End
89+
90+
virtual QgsExpressionContext createExpressionContext() const;
91+
92+
5693
};
5794

5895

@@ -96,6 +133,14 @@ associated with the parameter.
96133
Returns a new instance of a parameter definition, using the current settings defined in the dialog.
97134

98135
The ``name`` parameter specifies the name for the newly created parameter.
136+
%End
137+
138+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
139+
%Docstring
140+
Registers a Processing context ``generator`` class that will be used to retrieve
141+
a Processing context for the widget when required.
142+
143+
.. versionadded:: 3.18
99144
%End
100145

101146
};
@@ -181,6 +226,14 @@ Returns the color for the comments for the parameter.
181226
void switchToCommentTab();
182227
%Docstring
183228
Switches the dialog to the comments tab.
229+
%End
230+
231+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
232+
%Docstring
233+
Registers a Processing context ``generator`` class that will be used to retrieve
234+
a Processing context for the widget when required.
235+
236+
.. versionadded:: 3.18
184237
%End
185238

186239
public slots:

‎python/gui/auto_generated/qgsexpressionlineedit.sip.in

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,6 @@ an expression context for the widget.
127127
create an expression context when required.
128128
%End
129129

130-
void setExpressionContext( QgsExpressionContext &context );
131-
%Docstring
132-
Set a default expression context. Will be used if no QgsEcpressionContextGenerator or layer is set.
133-
134-
:param context: The QgsExpressionContext to use.
135-
136-
.. versionadded:: 3.18
137-
%End
138-
139130
signals:
140131

141132
void expressionChanged( const QString &expression );

‎python/plugins/processing/modeler/ModelerDialog.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@
4040
QgsProcessing,
4141
QgsProject,
4242
QgsProcessingModelParameter,
43-
QgsSettings
43+
QgsSettings,
4444
)
4545
from qgis.gui import (QgsProcessingParameterDefinitionDialog,
4646
QgsProcessingParameterWidgetContext,
4747
QgsModelGraphicsScene,
48-
QgsModelDesignerDialog)
48+
QgsModelDesignerDialog,
49+
QgsProcessingContextGenerator)
4950
from processing.gui.HelpEditionDialog import HelpEditionDialog
5051
from processing.gui.AlgorithmDialog import AlgorithmDialog
5152
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
@@ -105,6 +106,19 @@ def __init__(self, model=None, parent=None):
105106

106107
self.view().centerOn(0, 0)
107108

109+
self.processing_context = createContext()
110+
111+
class ContextGenerator(QgsProcessingContextGenerator):
112+
113+
def __init__(self, context):
114+
super().__init__()
115+
self.processing_context = context
116+
117+
def processingContext(self):
118+
return self.processing_context
119+
120+
self.context_generator = ContextGenerator(self.processing_context)
121+
108122
def editHelp(self):
109123
alg = self.model()
110124
dlg = HelpEditionDialog(alg)
@@ -270,6 +284,7 @@ def addInput(self, paramType, pos=None):
270284
context=context,
271285
widgetContext=widget_context,
272286
algorithm=self.model())
287+
dlg.registerProcessingContextGenerator(self.context_generator)
273288
if dlg.exec_():
274289
new_param = dlg.createParameter()
275290
self.autogenerate_parameter_name(new_param)

‎python/plugins/processing/modeler/ModelerGraphicItem.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
QgsProcessingParameterWidgetContext,
3232
QgsModelParameterGraphicItem,
3333
QgsModelChildAlgorithmGraphicItem,
34-
QgsModelOutputGraphicItem
34+
QgsModelOutputGraphicItem,
35+
QgsProcessingContextGenerator
3536
)
3637
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
3738
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
@@ -50,6 +51,19 @@ class ModelerInputGraphicItem(QgsModelParameterGraphicItem):
5051
def __init__(self, element, model):
5152
super().__init__(element, model, None)
5253

54+
self.processing_context = createContext()
55+
56+
class ContextGenerator(QgsProcessingContextGenerator):
57+
58+
def __init__(self, context):
59+
super().__init__()
60+
self.processing_context = context
61+
62+
def processingContext(self):
63+
return self.processing_context
64+
65+
self.context_generator = ContextGenerator(self.processing_context)
66+
5367
def create_widget_context(self):
5468
"""
5569
Returns a new widget context for use in the model editor
@@ -91,6 +105,8 @@ def edit(self, edit_comment=False):
91105
algorithm=self.model())
92106
dlg.setComments(comment)
93107
dlg.setCommentColor(comment_color)
108+
dlg.registerProcessingContextGenerator(self.context_generator)
109+
94110
if edit_comment:
95111
dlg.switchToCommentTab()
96112

‎src/gui/processing/qgsprocessingparameterdefinitionwidget.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,35 @@
3434
#include <QTextEdit>
3535

3636
QgsProcessingAbstractParameterDefinitionWidget::QgsProcessingAbstractParameterDefinitionWidget( QgsProcessingContext &,
37-
const QgsProcessingParameterWidgetContext &,
37+
const QgsProcessingParameterWidgetContext &context,
3838
const QgsProcessingParameterDefinition *,
3939
const QgsProcessingAlgorithm *, QWidget *parent )
4040
: QWidget( parent )
41+
, mWidgetContext( context )
4142
{
4243

4344
}
4445

46+
void QgsProcessingAbstractParameterDefinitionWidget::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
47+
{
48+
mWidgetContext = context;
49+
}
50+
51+
const QgsProcessingParameterWidgetContext &QgsProcessingAbstractParameterDefinitionWidget::widgetContext() const
52+
{
53+
return mWidgetContext;
54+
}
55+
56+
void QgsProcessingAbstractParameterDefinitionWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
57+
{
58+
mContextGenerator = generator;
59+
}
60+
61+
QgsExpressionContext QgsProcessingAbstractParameterDefinitionWidget::createExpressionContext() const
62+
{
63+
return QgsProcessingGuiUtils::createExpressionContext( mContextGenerator, mWidgetContext, nullptr, nullptr );
64+
}
65+
4566
//
4667
// QgsProcessingParameterDefinitionWidget
4768
//
@@ -120,6 +141,14 @@ QgsProcessingParameterDefinition *QgsProcessingParameterDefinitionWidget::create
120141
return param.release();
121142
}
122143

144+
void QgsProcessingParameterDefinitionWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
145+
{
146+
if ( mDefinitionWidget )
147+
{
148+
mDefinitionWidget->registerProcessingContextGenerator( generator );
149+
}
150+
}
151+
123152
//
124153
// QgsProcessingParameterDefinitionDialog
125154
//
@@ -210,6 +239,14 @@ void QgsProcessingParameterDefinitionDialog::switchToCommentTab()
210239
mCommentEdit->selectAll();
211240
}
212241

242+
void QgsProcessingParameterDefinitionDialog::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
243+
{
244+
if ( mWidget )
245+
{
246+
mWidget->registerProcessingContextGenerator( generator );
247+
}
248+
}
249+
213250
void QgsProcessingParameterDefinitionDialog::accept()
214251
{
215252
if ( mWidget->mDescriptionLineEdit->text().isEmpty() )

‎src/gui/processing/qgsprocessingparameterdefinitionwidget.h

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
#include "qgis_gui.h"
2626
#include "qgis_sip.h"
2727
#include "qgsprocessingparameters.h"
28+
#include "qgsexpressioncontextgenerator.h"
29+
#include "qgsprocessingwidgetwrapper.h"
30+
31+
class QgsProcessingContextGenerator;
2832

29-
class QgsProcessingParameterWidgetContext;
3033
class QLineEdit;
3134
class QCheckBox;
3235
class QTabWidget;
@@ -40,7 +43,7 @@ class QgsColorButton;
4043
* \ingroup gui
4144
* \since QGIS 3.10
4245
*/
43-
class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget
46+
class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget, public QgsExpressionContextGenerator
4447
{
4548
Q_OBJECT
4649

@@ -73,6 +76,43 @@ class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget
7376
* also respects the additional properties specific to the parameter type handled by the widget subclass.
7477
*/
7578
virtual QgsProcessingParameterDefinition *createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const = 0 SIP_FACTORY;
79+
80+
/**
81+
* Sets the \a context in which the Processing definition widget is shown, e.g., the
82+
* parent model algorithm, a linked map canvas, and other relevant information which allows the widget
83+
* to fine-tune its behavior.
84+
*
85+
* Subclasses should take care to call the base class method when reimplementing this method.
86+
*
87+
* \see widgetContext()
88+
* \since QGIS 3.18
89+
*/
90+
virtual void setWidgetContext( const QgsProcessingParameterWidgetContext &context );
91+
92+
/**
93+
* Returns the context in which the Processing definition widget is shown, e.g., the
94+
* parent model algorithm, a linked map canvas, and other relevant information which allows the widget
95+
* to fine-tune its behavior.
96+
*
97+
* \see setWidgetContext()
98+
* \since QGIS 3.18
99+
*/
100+
const QgsProcessingParameterWidgetContext &widgetContext() const;
101+
102+
/**
103+
* Registers a Processing context \a generator class that will be used to retrieve
104+
* a Processing context for the widget when required.
105+
*
106+
* \since QGIS 3.18
107+
*/
108+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
109+
110+
QgsExpressionContext createExpressionContext() const override;
111+
112+
private:
113+
114+
QgsProcessingContextGenerator *mContextGenerator = nullptr;
115+
QgsProcessingParameterWidgetContext mWidgetContext;
76116
};
77117

78118

@@ -117,6 +157,14 @@ class GUI_EXPORT QgsProcessingParameterDefinitionWidget: public QWidget
117157
*/
118158
QgsProcessingParameterDefinition *createParameter( const QString &name = QString() ) const SIP_FACTORY;
119159

160+
/**
161+
* Registers a Processing context \a generator class that will be used to retrieve
162+
* a Processing context for the widget when required.
163+
*
164+
* \since QGIS 3.18
165+
*/
166+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
167+
120168
private:
121169

122170
QString mType;
@@ -203,6 +251,14 @@ class GUI_EXPORT QgsProcessingParameterDefinitionDialog: public QDialog
203251
*/
204252
void switchToCommentTab();
205253

254+
/**
255+
* Registers a Processing context \a generator class that will be used to retrieve
256+
* a Processing context for the widget when required.
257+
*
258+
* \since QGIS 3.18
259+
*/
260+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
261+
206262
public slots:
207263
void accept() override;
208264

‎src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,18 +1841,13 @@ QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFileWidgetWrapper::
18411841
QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
18421842
: QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
18431843
{
1844-
mModel = widgetContext.model();
1845-
18461844
QVBoxLayout *vlayout = new QVBoxLayout();
18471845
vlayout->setContentsMargins( 0, 0, 0, 0 );
18481846
vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
18491847

18501848
mDefaultLineEdit = new QgsExpressionLineEdit();
1851-
if ( mModel )
1852-
{
1853-
QgsExpressionContext expressionContext = createExpressionContext( context, algorithm );
1854-
mDefaultLineEdit->setExpressionContext( expressionContext );
1855-
}
1849+
mDefaultLineEdit->registerExpressionContextGenerator( this );
1850+
18561851
if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
18571852
mDefaultLineEdit->setExpression( QgsProcessingParameters::parameterAsExpression( expParam, expParam->defaultValueForGui(), context ) );
18581853
vlayout->addWidget( mDefaultLineEdit );
@@ -1866,22 +1861,21 @@ QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParamet
18661861
if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
18671862
initialParent = expParam->parentLayerParameterName();
18681863

1869-
1870-
if ( mModel )
1864+
if ( QgsProcessingModelAlgorithm *model = widgetContext.model() )
18711865
{
18721866
// populate combo box with other model input choices
1873-
const QMap<QString, QgsProcessingModelParameter> components = mModel->parameterComponents();
1867+
const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
18741868
for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
18751869
{
1876-
if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( mModel->parameterDefinition( it.value().parameterName() ) ) )
1870+
if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( model->parameterDefinition( it.value().parameterName() ) ) )
18771871
{
18781872
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
18791873
if ( !initialParent.isEmpty() && initialParent == definition->name() )
18801874
{
18811875
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
18821876
}
18831877
}
1884-
else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( mModel->parameterDefinition( it.value().parameterName() ) ) )
1878+
else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( model->parameterDefinition( it.value().parameterName() ) ) )
18851879
{
18861880
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
18871881
if ( !initialParent.isEmpty() && initialParent == definition->name() )
@@ -1907,46 +1901,9 @@ QgsProcessingParameterDefinition *QgsProcessingExpressionParameterDefinitionWidg
19071901
{
19081902
auto param = qgis::make_unique< QgsProcessingParameterExpression >( name, description, mDefaultLineEdit->expression(), mParentLayerComboBox->currentData().toString() );
19091903
param->setFlags( flags );
1910-
if ( mModel )
1911-
{
1912-
QStringList extraVars = mModel->variables().keys();
1913-
param->setAdditionalExpressionContextVariables( extraVars );
1914-
}
19151904
return param.release();
19161905
}
19171906

1918-
QgsExpressionContext QgsProcessingExpressionParameterDefinitionWidget::createExpressionContext( QgsProcessingContext &context, const QgsProcessingAlgorithm *algorithm ) const
1919-
{
1920-
QgsExpressionContext finalContext = context.expressionContext();
1921-
QString childId;
1922-
1923-
QgsExpressionContextScope *algScope = QgsExpressionContextUtils::processingAlgorithmScope( algorithm, QVariantMap(), context );
1924-
finalContext.appendScope( algScope );
1925-
1926-
QgsExpressionContextScope *modelScope = QgsExpressionContextUtils::processingModelAlgorithmScope( mModel, QVariantMap(), context );
1927-
finalContext << modelScope;
1928-
const QgsProcessingAlgorithm *childAlg = nullptr;
1929-
if ( mModel->childAlgorithms().contains( childId ) )
1930-
childAlg = mModel->childAlgorithm( childId ).algorithm();
1931-
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( childAlg, QVariantMap(), context );
1932-
finalContext << algorithmScope;
1933-
1934-
QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( childId, context, QVariantMap(), QVariantMap() );
1935-
finalContext << childScope;
1936-
1937-
QStringList highlightedVariables = childScope->variableNames();
1938-
QStringList highlightedFunctions = childScope->functionNames();
1939-
highlightedVariables += algorithmScope->variableNames();
1940-
highlightedVariables += algScope->variableNames();
1941-
highlightedVariables += mModel->variables().keys();
1942-
highlightedFunctions += algScope->functionNames();
1943-
highlightedFunctions += algorithmScope->functionNames();
1944-
finalContext.setHighlightedVariables( highlightedVariables );
1945-
finalContext.setHighlightedFunctions( highlightedFunctions );
1946-
1947-
return finalContext;
1948-
}
1949-
19501907
QgsProcessingExpressionWidgetWrapper::QgsProcessingExpressionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
19511908
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
19521909
{

‎src/gui/processing/qgsprocessingwidgetwrapperimpl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ class QgsProcessingMapLayerComboBox;
6666
class QgsRasterBandComboBox;
6767
class QgsProcessingLayerOutputDestinationWidget;
6868
class QgsCheckableComboBox;
69-
class QgsProcessingModelAlgorithm;
70-
class QgsExpressionContext;
7169

7270
///@cond PRIVATE
7371

@@ -635,13 +633,11 @@ class GUI_EXPORT QgsProcessingExpressionParameterDefinitionWidget : public QgsPr
635633
const QgsProcessingParameterDefinition *definition = nullptr,
636634
const QgsProcessingAlgorithm *algorithm = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr );
637635
QgsProcessingParameterDefinition *createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const override;
638-
QgsExpressionContext createExpressionContext( QgsProcessingContext &context, const QgsProcessingAlgorithm *algorithm ) const;
639636

640637
private:
641638

642639
QComboBox *mParentLayerComboBox = nullptr;
643640
QgsExpressionLineEdit *mDefaultLineEdit = nullptr;
644-
QgsProcessingModelAlgorithm *mModel = nullptr;
645641

646642
};
647643

‎src/gui/qgsexpressionlineedit.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,6 @@ class GUI_EXPORT QgsExpressionLineEdit : public QWidget
132132
*/
133133
void registerExpressionContextGenerator( const QgsExpressionContextGenerator *generator );
134134

135-
/**
136-
* Set a default expression context. Will be used if no QgsEcpressionContextGenerator or layer is set.
137-
* \param context The QgsExpressionContext to use.
138-
* \since QGIS 3.18
139-
*/
140-
void setExpressionContext( QgsExpressionContext &context ) { mExpressionContext = context; }
141-
142135
signals:
143136

144137
/**

0 commit comments

Comments
 (0)
Please sign in to comment.