Skip to content

Commit 4a0a48f

Browse files
committed
[processing] Also expose complete expression context inside
data defined buttons for model child algorithms The context was not previously exposed, so users would not have been aware that they can utilise all the variables and functions available to parameters within child algorithms.
1 parent 8f9f975 commit 4a0a48f

7 files changed

+95
-6
lines changed

python/gui/auto_generated/processing/qgsprocessingmodelerparameterwidget.sip.in

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ parent model algorithm and other relevant information which allows the widget
6464
to fine-tune its behavior.
6565

6666
.. seealso:: :py:func:`widgetContext`
67+
%End
68+
69+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
70+
%Docstring
71+
Register a Processing context ``generator`` class that will be used to retrieve
72+
a Processing context for the widget when required.
6773
%End
6874

6975
void populateSources( const QStringList &compatibleParameterTypes,

python/gui/auto_generated/processing/qgsprocessingwidgetwrapper.sip.in

+5-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ Sets the child algorithm ``id`` within the model which the parameter widget is a
109109

110110
};
111111

112-
class QgsAbstractProcessingParameterWidgetWrapper : QObject
112+
class QgsAbstractProcessingParameterWidgetWrapper : QObject, QgsExpressionContextGenerator
113113
{
114114
%Docstring
115115

@@ -232,7 +232,7 @@ Returns the current value of the parameter.
232232

233233
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
234234
%Docstring
235-
Register a Processing context generator class that will be used to retrieve
235+
Register a Processing context ``generator`` class that will be used to retrieve
236236
a Processing context for the wrapper when required.
237237
%End
238238

@@ -242,6 +242,9 @@ Called after all wrappers have been created within a particular dialog or contex
242242
allowing the wrapper to connect to the wrappers of other, related parameters.
243243
%End
244244

245+
virtual QgsExpressionContext createExpressionContext() const;
246+
247+
245248
signals:
246249

247250

python/plugins/processing/modeler/ModelerParametersDialog.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
QHBoxLayout, QWidget)
3737

3838
from qgis.core import (Qgis,
39-
QgsApplication,
4039
QgsProcessingParameterDefinition,
4140
QgsProcessingParameterPoint,
4241
QgsProcessingParameterExtent,
@@ -58,6 +57,7 @@
5857
QgsScrollArea,
5958
QgsFilterLineEdit,
6059
QgsHelp,
60+
QgsProcessingContextGenerator,
6161
QgsProcessingModelerParameterWidget,
6262
QgsProcessingParameterWidgetContext)
6363
from qgis.utils import iface
@@ -83,8 +83,20 @@ def __init__(self, alg, model, algName=None, configuration=None):
8383

8484
self.widget_labels = {}
8585

86+
class ContextGenerator(QgsProcessingContextGenerator):
87+
88+
def __init__(self, context):
89+
super().__init__()
90+
self.processing_context = context
91+
92+
def processingContext(self):
93+
return self.processing_context
94+
95+
self.context_generator = ContextGenerator(self.context)
96+
8697
self.setupUi()
8798
self.params = None
99+
88100
settings = QgsSettings()
89101
self.restoreGeometry(settings.value("/Processing/modelParametersDialogGeometry", QByteArray()))
90102

@@ -135,6 +147,8 @@ def setupUi(self):
135147

136148
widget_context = QgsProcessingParameterWidgetContext()
137149
widget_context.setMapCanvas(iface.mapCanvas())
150+
widget_context.setModel(self.model)
151+
widget_context.setModelChildAlgorithmId(self.childId)
138152

139153
for param in self._alg.parameterDefinitions():
140154
if param.flags() & QgsProcessingParameterDefinition.FlagAdvanced:
@@ -156,6 +170,7 @@ def setupUi(self):
156170

157171
if issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget):
158172
wrapper.setWidgetContext(widget_context)
173+
wrapper.registerProcessingContextGenerator(self.context_generator)
159174
widget = wrapper
160175
else:
161176
widget = wrapper.widget

src/gui/processing/qgsprocessingmodelerparameterwidget.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ void QgsProcessingModelerParameterWidget::setWidgetContext( const QgsProcessingP
121121
mStaticWidgetWrapper->setWidgetContext( context );
122122
}
123123

124+
void QgsProcessingModelerParameterWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
125+
{
126+
if ( mStaticWidgetWrapper )
127+
mStaticWidgetWrapper->registerProcessingContextGenerator( generator );
128+
}
129+
124130
const QgsProcessingParameterDefinition *QgsProcessingModelerParameterWidget::parameterDefinition() const
125131
{
126132
return mParameterDefinition;
@@ -176,7 +182,10 @@ QgsExpressionContext QgsProcessingModelerParameterWidget::createExpressionContex
176182
QgsExpressionContext c = mContext.expressionContext();
177183
if ( mModel )
178184
{
179-
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( mModel->childAlgorithm( mChildId ).algorithm(), QVariantMap(), mContext );
185+
const QgsProcessingAlgorithm *alg = nullptr;
186+
if ( mModel->childAlgorithms().contains( mChildId ) )
187+
alg = mModel->childAlgorithm( mChildId ).algorithm();
188+
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), mContext );
180189
c << algorithmScope;
181190
QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
182191
c << childScope;
@@ -305,6 +314,9 @@ void QgsProcessingModelerParameterWidget::populateSources( const QStringList &co
305314

306315
case QgsProcessingModelChildParameterSource::ChildOutput:
307316
{
317+
if ( !mModel->childAlgorithms().contains( source.outputChildId() ) )
318+
continue;
319+
308320
const QgsProcessingModelChildAlgorithm &alg = mModel->childAlgorithm( source.outputChildId() );
309321
if ( !alg.algorithm() )
310322
continue;

src/gui/processing/qgsprocessingmodelerparameterwidget.h

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class QgsAbstractProcessingParameterWidgetWrapper;
3131
class QgsExpressionLineEdit;
3232
class QgsProcessingModelAlgorithm;
3333
class QgsProcessingParameterWidgetContext;
34+
class QgsProcessingContextGenerator;
3435

3536
class QLabel;
3637
class QToolButton;
@@ -92,6 +93,12 @@ class GUI_EXPORT QgsProcessingModelerParameterWidget : public QWidget, public Qg
9293
*/
9394
void setWidgetContext( const QgsProcessingParameterWidgetContext &context );
9495

96+
/**
97+
* Register a Processing context \a generator class that will be used to retrieve
98+
* a Processing context for the widget when required.
99+
*/
100+
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
101+
95102
/**
96103
* Populates the widget with available sources for the parameter's value, e.g.
97104
* adding the available child algorithm outputs and model input parameter

src/gui/processing/qgsprocessingwidgetwrapper.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "qgsprocessingparameters.h"
2121
#include "qgsprocessingmodelerparameterwidget.h"
2222
#include "qgspropertyoverridebutton.h"
23+
#include "qgsexpressioncontext.h"
24+
#include "models/qgsprocessingmodelalgorithm.h"
2325
#include <QLabel>
2426
#include <QHBoxLayout>
2527

@@ -101,6 +103,7 @@ QWidget *QgsAbstractProcessingParameterWidgetWrapper::createWrappedWidget( QgsPr
101103
hLayout->addWidget( mPropertyButton );
102104
mPropertyButton->init( 0, QgsProperty(), mParameterDefinition->dynamicPropertyDefinition() );
103105
mPropertyButton->registerEnabledWidget( mWidget, false );
106+
mPropertyButton->registerExpressionContextGenerator( this );
104107

105108
wrappedWidget = new QWidget();
106109
wrappedWidget->setLayout( hLayout );
@@ -211,6 +214,47 @@ void QgsAbstractProcessingParameterWidgetWrapper::postInitialize( const QList<Qg
211214
}
212215
}
213216

217+
QgsExpressionContext QgsAbstractProcessingParameterWidgetWrapper::createExpressionContext() const
218+
{
219+
// Get a processing context to start with
220+
QgsProcessingContext *context = nullptr;
221+
std::unique_ptr< QgsProcessingContext > tmpContext;
222+
if ( mProcessingContextGenerator )
223+
context = mProcessingContextGenerator->processingContext();
224+
225+
if ( !context )
226+
{
227+
tmpContext = qgis::make_unique< QgsProcessingContext >();
228+
context = tmpContext.get();
229+
}
230+
231+
QgsExpressionContext c = context->expressionContext();
232+
233+
if ( mPropertyButton->vectorLayer() )
234+
c << QgsExpressionContextUtils::layerScope( mPropertyButton->vectorLayer() );
235+
236+
if ( mWidgetContext.model() )
237+
{
238+
const QgsProcessingAlgorithm *alg = nullptr;
239+
if ( mWidgetContext.model()->childAlgorithms().contains( mWidgetContext.modelChildAlgorithmId() ) )
240+
alg = mWidgetContext.model()->childAlgorithm( mWidgetContext.modelChildAlgorithmId() ).algorithm();
241+
242+
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), *context );
243+
c << algorithmScope;
244+
QgsExpressionContextScope *childScope = mWidgetContext.model()->createExpressionContextScopeForChildAlgorithm( mWidgetContext.modelChildAlgorithmId(), *context, QVariantMap(), QVariantMap() );
245+
c << childScope;
246+
247+
QStringList highlightedVariables = childScope->variableNames();
248+
QStringList highlightedFunctions = childScope->functionNames();
249+
highlightedVariables += algorithmScope->variableNames();
250+
highlightedFunctions += algorithmScope->functionNames();
251+
c.setHighlightedVariables( highlightedVariables );
252+
c.setHighlightedFunctions( highlightedFunctions );
253+
}
254+
255+
return c;
256+
}
257+
214258
void QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper )
215259
{
216260
if ( wrapper )

src/gui/processing/qgsprocessingwidgetwrapper.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class GUI_EXPORT QgsProcessingParameterWidgetContext
153153
* \ingroup gui
154154
* \since QGIS 3.4
155155
*/
156-
class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
156+
class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject, public QgsExpressionContextGenerator
157157
{
158158
Q_OBJECT
159159

@@ -257,7 +257,7 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
257257
QVariant parameterValue() const;
258258

259259
/**
260-
* Register a Processing context generator class that will be used to retrieve
260+
* Register a Processing context \a generator class that will be used to retrieve
261261
* a Processing context for the wrapper when required.
262262
*/
263263
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
@@ -268,6 +268,8 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
268268
*/
269269
virtual void postInitialize( const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers );
270270

271+
QgsExpressionContext createExpressionContext() const override;
272+
271273
signals:
272274

273275
// TODO QGIS 4.0 - remove wrapper parameter - this is kept for compatibility with 3.x API,

0 commit comments

Comments
 (0)