Skip to content
Permalink
Browse files

[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.
  • Loading branch information
nyalldawson committed Sep 21, 2018
1 parent 8f9f975 commit 4a0a48fe471097eb93df59163f2fbb833496824a
@@ -64,6 +64,12 @@ parent model algorithm and other relevant information which allows the widget
to fine-tune its behavior.

.. seealso:: :py:func:`widgetContext`
%End

void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
%Docstring
Register a Processing context ``generator`` class that will be used to retrieve
a Processing context for the widget when required.
%End

void populateSources( const QStringList &compatibleParameterTypes,
@@ -109,7 +109,7 @@ Sets the child algorithm ``id`` within the model which the parameter widget is a

};

class QgsAbstractProcessingParameterWidgetWrapper : QObject
class QgsAbstractProcessingParameterWidgetWrapper : QObject, QgsExpressionContextGenerator
{
%Docstring

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

void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );
%Docstring
Register a Processing context generator class that will be used to retrieve
Register a Processing context ``generator`` class that will be used to retrieve
a Processing context for the wrapper when required.
%End

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

virtual QgsExpressionContext createExpressionContext() const;


signals:


@@ -36,7 +36,6 @@
QHBoxLayout, QWidget)

from qgis.core import (Qgis,
QgsApplication,
QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterExtent,
@@ -58,6 +57,7 @@
QgsScrollArea,
QgsFilterLineEdit,
QgsHelp,
QgsProcessingContextGenerator,
QgsProcessingModelerParameterWidget,
QgsProcessingParameterWidgetContext)
from qgis.utils import iface
@@ -83,8 +83,20 @@ def __init__(self, alg, model, algName=None, configuration=None):

self.widget_labels = {}

class ContextGenerator(QgsProcessingContextGenerator):

def __init__(self, context):
super().__init__()
self.processing_context = context

def processingContext(self):
return self.processing_context

self.context_generator = ContextGenerator(self.context)

self.setupUi()
self.params = None

settings = QgsSettings()
self.restoreGeometry(settings.value("/Processing/modelParametersDialogGeometry", QByteArray()))

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

widget_context = QgsProcessingParameterWidgetContext()
widget_context.setMapCanvas(iface.mapCanvas())
widget_context.setModel(self.model)
widget_context.setModelChildAlgorithmId(self.childId)

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

if issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget):
wrapper.setWidgetContext(widget_context)
wrapper.registerProcessingContextGenerator(self.context_generator)
widget = wrapper
else:
widget = wrapper.widget
@@ -121,6 +121,12 @@ void QgsProcessingModelerParameterWidget::setWidgetContext( const QgsProcessingP
mStaticWidgetWrapper->setWidgetContext( context );
}

void QgsProcessingModelerParameterWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
{
if ( mStaticWidgetWrapper )
mStaticWidgetWrapper->registerProcessingContextGenerator( generator );
}

const QgsProcessingParameterDefinition *QgsProcessingModelerParameterWidget::parameterDefinition() const
{
return mParameterDefinition;
@@ -176,7 +182,10 @@ QgsExpressionContext QgsProcessingModelerParameterWidget::createExpressionContex
QgsExpressionContext c = mContext.expressionContext();
if ( mModel )
{
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( mModel->childAlgorithm( mChildId ).algorithm(), QVariantMap(), mContext );
const QgsProcessingAlgorithm *alg = nullptr;
if ( mModel->childAlgorithms().contains( mChildId ) )
alg = mModel->childAlgorithm( mChildId ).algorithm();
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), mContext );
c << algorithmScope;
QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
c << childScope;
@@ -305,6 +314,9 @@ void QgsProcessingModelerParameterWidget::populateSources( const QStringList &co

case QgsProcessingModelChildParameterSource::ChildOutput:
{
if ( !mModel->childAlgorithms().contains( source.outputChildId() ) )
continue;

const QgsProcessingModelChildAlgorithm &alg = mModel->childAlgorithm( source.outputChildId() );
if ( !alg.algorithm() )
continue;
@@ -31,6 +31,7 @@ class QgsAbstractProcessingParameterWidgetWrapper;
class QgsExpressionLineEdit;
class QgsProcessingModelAlgorithm;
class QgsProcessingParameterWidgetContext;
class QgsProcessingContextGenerator;

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

/**
* Register a Processing context \a generator class that will be used to retrieve
* a Processing context for the widget when required.
*/
void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator );

/**
* Populates the widget with available sources for the parameter's value, e.g.
* adding the available child algorithm outputs and model input parameter
@@ -20,6 +20,8 @@
#include "qgsprocessingparameters.h"
#include "qgsprocessingmodelerparameterwidget.h"
#include "qgspropertyoverridebutton.h"
#include "qgsexpressioncontext.h"
#include "models/qgsprocessingmodelalgorithm.h"
#include <QLabel>
#include <QHBoxLayout>

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

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

QgsExpressionContext QgsAbstractProcessingParameterWidgetWrapper::createExpressionContext() const
{
// Get a processing context to start with
QgsProcessingContext *context = nullptr;
std::unique_ptr< QgsProcessingContext > tmpContext;
if ( mProcessingContextGenerator )
context = mProcessingContextGenerator->processingContext();

if ( !context )
{
tmpContext = qgis::make_unique< QgsProcessingContext >();
context = tmpContext.get();
}

QgsExpressionContext c = context->expressionContext();

if ( mPropertyButton->vectorLayer() )
c << QgsExpressionContextUtils::layerScope( mPropertyButton->vectorLayer() );

if ( mWidgetContext.model() )
{
const QgsProcessingAlgorithm *alg = nullptr;
if ( mWidgetContext.model()->childAlgorithms().contains( mWidgetContext.modelChildAlgorithmId() ) )
alg = mWidgetContext.model()->childAlgorithm( mWidgetContext.modelChildAlgorithmId() ).algorithm();

QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), *context );
c << algorithmScope;
QgsExpressionContextScope *childScope = mWidgetContext.model()->createExpressionContextScopeForChildAlgorithm( mWidgetContext.modelChildAlgorithmId(), *context, QVariantMap(), QVariantMap() );
c << childScope;

QStringList highlightedVariables = childScope->variableNames();
QStringList highlightedFunctions = childScope->functionNames();
highlightedVariables += algorithmScope->variableNames();
highlightedFunctions += algorithmScope->functionNames();
c.setHighlightedVariables( highlightedVariables );
c.setHighlightedFunctions( highlightedFunctions );
}

return c;
}

void QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper )
{
if ( wrapper )
@@ -153,7 +153,7 @@ class GUI_EXPORT QgsProcessingParameterWidgetContext
* \ingroup gui
* \since QGIS 3.4
*/
class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject, public QgsExpressionContextGenerator
{
Q_OBJECT

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

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

QgsExpressionContext createExpressionContext() const override;

signals:

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

0 comments on commit 4a0a48f

Please sign in to comment.
You can’t perform that action at this time.