Skip to content

Commit

Permalink
[processing] Also expose complete expression context inside
Browse files Browse the repository at this point in the history
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 4a0a48f
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 6 deletions.
Expand Up @@ -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,
Expand Down
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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:


Expand Down
17 changes: 16 additions & 1 deletion python/plugins/processing/modeler/ModelerParametersDialog.py
Expand Up @@ -36,7 +36,6 @@
QHBoxLayout, QWidget)

from qgis.core import (Qgis,
QgsApplication,
QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterExtent,
Expand All @@ -58,6 +57,7 @@
QgsScrollArea,
QgsFilterLineEdit,
QgsHelp,
QgsProcessingContextGenerator,
QgsProcessingModelerParameterWidget,
QgsProcessingParameterWidgetContext)
from qgis.utils import iface
Expand All @@ -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()))

Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
14 changes: 13 additions & 1 deletion src/gui/processing/qgsprocessingmodelerparameterwidget.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/gui/processing/qgsprocessingmodelerparameterwidget.h
Expand Up @@ -31,6 +31,7 @@ class QgsAbstractProcessingParameterWidgetWrapper;
class QgsExpressionLineEdit;
class QgsProcessingModelAlgorithm;
class QgsProcessingParameterWidgetContext;
class QgsProcessingContextGenerator;

class QLabel;
class QToolButton;
Expand Down Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapper.cpp
Expand Up @@ -20,6 +20,8 @@
#include "qgsprocessingparameters.h"
#include "qgsprocessingmodelerparameterwidget.h"
#include "qgspropertyoverridebutton.h"
#include "qgsexpressioncontext.h"
#include "models/qgsprocessingmodelalgorithm.h"
#include <QLabel>
#include <QHBoxLayout>

Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 )
Expand Down
6 changes: 4 additions & 2 deletions src/gui/processing/qgsprocessingwidgetwrapper.h
Expand Up @@ -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

Expand Down Expand Up @@ -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 );
Expand All @@ -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,
Expand Down

0 comments on commit 4a0a48f

Please sign in to comment.