QGIS API Documentation  3.6.0-Noosa (5873452)
qgsprocessingwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingwidgetwrapper.cpp
3  ---------------------
4  begin : August 2018
5  copyright : (C) 2018 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
23 #include "qgsexpressioncontext.h"
24 #include "models/qgsprocessingmodelalgorithm.h"
26 
27 #include <QLabel>
28 #include <QHBoxLayout>
29 
30 //
31 // QgsProcessingParameterWidgetContext
32 //
33 
35 {
36  mMapCanvas = canvas;
37 }
38 
40 {
41  return mMapCanvas;
42 }
43 
45 {
46  return mModelChildAlgorithmId;
47 }
48 
50 {
51  mModelChildAlgorithmId = modelChildAlgorithmId;
52 }
53 
54 QgsProcessingModelAlgorithm *QgsProcessingParameterWidgetContext::model() const
55 {
56  return mModel;
57 }
58 
59 void QgsProcessingParameterWidgetContext::setModel( QgsProcessingModelAlgorithm *model )
60 {
61  mModel = model;
62 }
63 
64 
65 //
66 // QgsAbstractProcessingParameterWidgetWrapper
67 //
68 
70  : QObject( parent )
71  , mType( type )
72  , mParameterDefinition( parameter )
73 {
74 }
75 
77 {
78  return mType;
79 }
80 
82 {
83  mWidgetContext = context;
84 }
85 
87 {
88  return mWidgetContext;
89 }
90 
92 {
93  if ( mWidget )
94  return mWidget;
95 
96  mWidget = createWidget();
97  QWidget *wrappedWidget = mWidget;
98  if ( mType != QgsProcessingGui::Batch && mParameterDefinition->isDynamic() )
99  {
100  QHBoxLayout *hLayout = new QHBoxLayout();
101  hLayout->setMargin( 0 );
102  hLayout->setContentsMargins( 0, 0, 0, 0 );
103  hLayout->addWidget( mWidget, 1 );
104  mPropertyButton = new QgsPropertyOverrideButton();
105  hLayout->addWidget( mPropertyButton );
106  mPropertyButton->init( 0, QgsProperty(), mParameterDefinition->dynamicPropertyDefinition() );
107  mPropertyButton->registerEnabledWidget( mWidget, false );
108  mPropertyButton->registerExpressionContextGenerator( this );
109 
110  wrappedWidget = new QWidget();
111  wrappedWidget->setLayout( hLayout );
112  }
113 
114  setWidgetValue( mParameterDefinition->defaultValue(), context );
115 
116  return wrappedWidget;
117 }
118 
120 {
121  if ( mLabel )
122  return mLabel;
123 
124  mLabel = createLabel();
125  return mLabel;
126 }
127 
129 {
130  return mWidget;
131 }
132 
134 {
135  return mLabel;
136 }
137 
139 {
140  return mParameterDefinition;
141 }
142 
144 {
145  if ( mPropertyButton && value.canConvert< QgsProperty >() )
146  {
147  mPropertyButton->setToProperty( value.value< QgsProperty >() );
148  }
149  else
150  {
151  if ( mPropertyButton )
152  mPropertyButton->setToProperty( QgsProperty() );
153 
154  setWidgetValue( value, context );
155  }
156 }
157 
159 {
160  if ( mPropertyButton && mPropertyButton->isActive() )
161  return mPropertyButton->toProperty();
162  else
163  return widgetValue();
164 }
165 
167 {
168  mProcessingContextGenerator = generator;
169 }
170 
172 {
173  switch ( mType )
174  {
176  return nullptr;
177 
180  {
181  QString description = mParameterDefinition->description();
183  description = QObject::tr( "%1 [optional]" ).arg( description );
184  std::unique_ptr< QLabel > label = qgis::make_unique< QLabel >( description );
185  label->setToolTip( mParameterDefinition->toolTip() );
186  return label.release();
187  }
188  }
189  return nullptr;
190 }
191 
193 {
194  if ( mPropertyButton )
195  return mPropertyButton->vectorLayer();
196  return nullptr;
197 }
198 
199 void QgsAbstractProcessingParameterWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
200 {
201  switch ( mType )
202  {
205  {
206  if ( parameterDefinition()->isDynamic() )
207  {
208  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
209  {
210  if ( wrapper->parameterDefinition()->name() == parameterDefinition()->dynamicLayerParameterName() )
211  {
212  setDynamicParentLayerParameter( wrapper );
213  connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, &QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged );
214  break;
215  }
216  }
217  }
218  break;
219  }
220 
222  break;
223  }
224 }
225 
227 {
228  return QgsProcessingGuiUtils::createExpressionContext( mProcessingContextGenerator, mWidgetContext, mParameterDefinition ? mParameterDefinition->algorithm() : nullptr, linkedVectorLayer() );
229 }
230 
231 void QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper )
232 {
233  if ( wrapper )
234  {
235  setDynamicParentLayerParameter( wrapper );
236  }
237 }
238 
239 void QgsAbstractProcessingParameterWidgetWrapper::setDynamicParentLayerParameter( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
240 {
241  if ( mPropertyButton )
242  {
243  // evaluate value to layer
244  QgsProcessingContext *context = nullptr;
245  std::unique_ptr< QgsProcessingContext > tmpContext;
248 
249  if ( !context )
250  {
251  tmpContext = qgis::make_unique< QgsProcessingContext >();
252  context = tmpContext.get();
253  }
254 
255  QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), parentWrapper->parameterValue(), *context );
256  if ( !layer )
257  {
258  mPropertyButton->setVectorLayer( nullptr );
259  return;
260  }
261 
262  // need to grab ownership of layer if required - otherwise layer may be deleted when context
263  // goes out of scope
264  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
265  if ( ownedLayer && ownedLayer->type() == QgsMapLayer::VectorLayer )
266  {
267  mDynamicLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
268  layer = mDynamicLayer.get();
269  }
270  else
271  {
272  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
273  }
274 
275  mPropertyButton->setVectorLayer( layer );
276  }
277 }
278 
280 {
281  std::unique_ptr< QgsProcessingModelerParameterWidget > widget = qgis::make_unique< QgsProcessingModelerParameterWidget >( model, childId, parameter, context );
282  widget->populateSources( compatibleParameterTypes(), compatibleOutputTypes(), compatibleDataTypes() );
283  widget->setExpressionHelpText( modelerExpressionFormatString() );
284  return widget.release();
285 }
286 
288 {
289  return QString();
290 }
291 
292 //
293 // QgsProcessingGuiUtils
294 //
295 
297 QgsExpressionContext QgsProcessingGuiUtils::createExpressionContext( QgsProcessingContextGenerator *processingContextGenerator, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingAlgorithm *algorithm, const QgsVectorLayer *linkedLayer )
298 {
299  // Get a processing context to start with
300  QgsProcessingContext *context = nullptr;
301  std::unique_ptr< QgsProcessingContext > tmpContext;
302  if ( processingContextGenerator )
303  context = processingContextGenerator->processingContext();
304 
305  if ( !context )
306  {
307  tmpContext = qgis::make_unique< QgsProcessingContext >();
308  context = tmpContext.get();
309  }
310 
312 
313  if ( widgetContext.model() )
314  {
315  c << QgsExpressionContextUtils::processingModelAlgorithmScope( widgetContext.model(), QVariantMap(), *context );
316 
317  const QgsProcessingAlgorithm *alg = nullptr;
318  if ( widgetContext.model()->childAlgorithms().contains( widgetContext.modelChildAlgorithmId() ) )
319  alg = widgetContext.model()->childAlgorithm( widgetContext.modelChildAlgorithmId() ).algorithm();
320 
321  QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg ? alg : algorithm, QVariantMap(), *context );
322  c << algorithmScope;
323  QgsExpressionContextScope *childScope = widgetContext.model()->createExpressionContextScopeForChildAlgorithm( widgetContext.modelChildAlgorithmId(), *context, QVariantMap(), QVariantMap() );
324  c << childScope;
325 
326  QStringList highlightedVariables = childScope->variableNames();
327  QStringList highlightedFunctions = childScope->functionNames();
328  highlightedVariables += algorithmScope->variableNames();
329  highlightedFunctions += algorithmScope->functionNames();
330  c.setHighlightedVariables( highlightedVariables );
331  c.setHighlightedFunctions( highlightedFunctions );
332  }
333  else
334  {
335  if ( algorithm )
336  c << QgsExpressionContextUtils::processingAlgorithmScope( algorithm, QVariantMap(), *context );
337  }
338 
339  if ( linkedLayer )
340  c << QgsExpressionContextUtils::layerScope( linkedLayer );
341 
342  return c;
343 }
static QgsExpressionContextScope * processingAlgorithmScope(const QgsProcessingAlgorithm *algorithm, const QVariantMap &parameters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing algorithm...
QgsPropertyDefinition dynamicPropertyDefinition() const
Returns the property definition for dynamic properties.
QgsAbstractProcessingParameterWidgetWrapper(const QgsProcessingParameterDefinition *parameter=nullptr, QgsProcessingGui::WidgetType type=QgsProcessingGui::Standard, QObject *parent=nullptr)
Constructor for QgsAbstractProcessingParameterWidgetWrapper, for the specified parameter definition a...
A widget wrapper for Processing parameter value widgets.
virtual void setWidgetContext(const QgsProcessingParameterWidgetContext &context)
Sets the context in which the Processing parameter widget is shown, e.g., the parent model algorithm...
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
void setParameterValue(const QVariant &value, QgsProcessingContext &context)
Sets the current value for the parameter.
void setModel(QgsProcessingModelAlgorithm *model)
Sets the model which the parameter widget is associated with.
WidgetType
Types of dialogs which Processing widgets can be created for.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
QgsMapLayer * takeResultLayer(const QString &id)
Takes the result map layer with matching id from the context and transfers ownership of it back to th...
A widget for customising the value of Processing algorithm parameter inside a Processing model...
virtual QLabel * createLabel()
Creates a new label to accompany widgets created by the wrapper.
QWidget * createWrappedWidget(QgsProcessingContext &context)
Creates and return a new wrapped widget which allows customization of the parameter&#39;s value...
static QgsVectorLayer * parameterAsVectorLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a vector layer.
Abstract base class for processing algorithms.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
QgsProcessingContextGenerator * mProcessingContextGenerator
void setHighlightedFunctions(const QStringList &names)
Sets the list of function names intended to be highlighted to the user.
QString modelChildAlgorithmId() const
Returns the child algorithm ID within the model which the parameter widget is associated with...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
virtual const QgsVectorLayer * linkedVectorLayer() const
Returns the optional vector layer associated with this widget wrapper, or nullptr if no vector layer ...
virtual QString toolTip() const
Returns a formatted tooltip for use with the parameter, which gives helpful information like paramete...
A button for controlling property overrides which may apply to a widget.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
QVariant parameterValue() const
Returns the current value of the parameter.
QVariant defaultValue() const
Returns the default value for the parameter.
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
An interface for objects which can create Processing contexts.
void populateSources(const QStringList &compatibleParameterTypes, const QStringList &compatibleOutputTypes, const QList< int > &compatibleDataTypes)
Populates the widget with available sources for the parameter&#39;s value, e.g.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void postInitialize(const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers)
Called after all wrappers have been created within a particular dialog or context, allowing the wrapper to connect to the wrappers of other, related parameters.
virtual void setWidgetValue(const QVariant &value, QgsProcessingContext &context)=0
Sets the current value for the parameter to show in the widget.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
QgsProcessingAlgorithm * algorithm() const
Returns a pointer to the algorithm which owns this parameter.
virtual QString modelerExpressionFormatString() const
Returns the expected expression format string for expression results for the parameter within model c...
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
void registerProcessingContextGenerator(QgsProcessingContextGenerator *generator)
Registers a Processing context generator class that will be used to retrieve a Processing context for...
Single scope for storing variables and functions for use within a QgsExpressionContext.
A store for object properties.
Definition: qgsproperty.h:229
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
QgsProcessingParameterWidgetContext mWidgetContext
QString dynamicLayerParameterName() const
Returns the name of the parameter for a layer linked to a dynamic parameter, or an empty string if th...
QgsExpressionContext & expressionContext()
Returns the expression context.
QLabel * wrappedLabel()
Returns the current wrapped label, if any.
virtual QVariant widgetValue() const =0
Returns the current value of the parameter.
static QgsExpressionContextScope * processingModelAlgorithmScope(const QgsProcessingModelAlgorithm *model, const QVariantMap &parameters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing model algorithm...
QgsProcessingModelAlgorithm * model() const
Returns the model which the parameter widget is associated with.
bool isDynamic() const
Returns true if the parameter supports is dynamic, and can support data-defined values (i...
QgsProcessingGui::WidgetType type() const
Returns the dialog type for which widgets and labels will be created by this wrapper.
virtual QgsProcessingContext * processingContext()=0
This method needs to be reimplemented in all classes which implement this interface and return a Proc...
Contains settings which reflect the context in which a Processing parameter widget is shown...
Base class for the definition of processing parameters.
virtual QgsProcessingModelerParameterWidget * createModelerWidgetWrapper(QgsProcessingModelAlgorithm *model, const QString &childId, const QgsProcessingParameterDefinition *parameter, QgsProcessingContext &context)
Creates a new modeler parameter widget for the given parameter.
const QgsProcessingParameterWidgetContext & widgetContext() const
Returns the context in which the Processing parameter widget is shown, e.g., the parent model algorit...
virtual QWidget * createWidget()=0
Creates a new widget which allows customization of the parameter&#39;s value.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user...
QLabel * createWrappedLabel()
Creates and returns a new label to accompany widgets created by the wrapper.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Represents a vector layer which manages a vector based data sets.
QWidget * wrappedWidget()
Returns the current wrapped widget, if any.
Contains information about the context in which a processing algorithm is executed.
void setModelChildAlgorithmId(const QString &id)
Sets the child algorithm id within the model which the parameter widget is associated with...
QString description() const
Returns the description for the parameter.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Standard algorithm dialog.
Batch processing dialog.