QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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"
25 #include <QLabel>
26 #include <QHBoxLayout>
27 
28 //
29 // QgsProcessingParameterWidgetContext
30 //
31 
33 {
34  mMapCanvas = canvas;
35 }
36 
38 {
39  return mMapCanvas;
40 }
41 
43 {
44  return mModelChildAlgorithmId;
45 }
46 
48 {
49  mModelChildAlgorithmId = modelChildAlgorithmId;
50 }
51 
52 QgsProcessingModelAlgorithm *QgsProcessingParameterWidgetContext::model() const
53 {
54  return mModel;
55 }
56 
57 void QgsProcessingParameterWidgetContext::setModel( QgsProcessingModelAlgorithm *model )
58 {
59  mModel = model;
60 }
61 
62 
63 //
64 // QgsAbstractProcessingParameterWidgetWrapper
65 //
66 
68  : QObject( parent )
69  , mType( type )
70  , mParameterDefinition( parameter )
71 {
72 }
73 
75 {
76  return mType;
77 }
78 
80 {
81  mWidgetContext = context;
82 }
83 
85 {
86  return mWidgetContext;
87 }
88 
90 {
91  if ( mWidget )
92  return mWidget;
93 
94  mWidget = createWidget();
95  QWidget *wrappedWidget = mWidget;
96  if ( mType != QgsProcessingGui::Batch && mParameterDefinition->isDynamic() )
97  {
98  QHBoxLayout *hLayout = new QHBoxLayout();
99  hLayout->setMargin( 0 );
100  hLayout->setContentsMargins( 0, 0, 0, 0 );
101  hLayout->addWidget( mWidget, 1 );
102  mPropertyButton = new QgsPropertyOverrideButton();
103  hLayout->addWidget( mPropertyButton );
104  mPropertyButton->init( 0, QgsProperty(), mParameterDefinition->dynamicPropertyDefinition() );
105  mPropertyButton->registerEnabledWidget( mWidget, false );
106  mPropertyButton->registerExpressionContextGenerator( this );
107 
108  wrappedWidget = new QWidget();
109  wrappedWidget->setLayout( hLayout );
110  }
111 
112  setWidgetValue( mParameterDefinition->defaultValue(), context );
113 
114  return wrappedWidget;
115 }
116 
118 {
119  if ( mLabel )
120  return mLabel;
121 
122  mLabel = createLabel();
123  return mLabel;
124 }
125 
127 {
128  return mWidget;
129 }
130 
132 {
133  return mLabel;
134 }
135 
137 {
138  return mParameterDefinition;
139 }
140 
142 {
143  if ( mPropertyButton && value.canConvert< QgsProperty >() )
144  {
145  mPropertyButton->setToProperty( value.value< QgsProperty >() );
146  }
147  else
148  {
149  if ( mPropertyButton )
150  mPropertyButton->setToProperty( QgsProperty() );
151 
152  setWidgetValue( value, context );
153  }
154 }
155 
157 {
158  if ( mPropertyButton && mPropertyButton->isActive() )
159  return mPropertyButton->toProperty();
160  else
161  return widgetValue();
162 }
163 
165 {
166  mProcessingContextGenerator = generator;
167 }
168 
170 {
171  switch ( mType )
172  {
174  return nullptr;
175 
178  {
179  QString description = mParameterDefinition->description();
181  description = QObject::tr( "%1 [optional]" ).arg( description );
182  std::unique_ptr< QLabel > label = qgis::make_unique< QLabel >( description );
183  label->setToolTip( mParameterDefinition->toolTip() );
184  return label.release();
185  }
186  }
187  return nullptr;
188 }
189 
191 {
192  if ( mPropertyButton )
193  return mPropertyButton->vectorLayer();
194  return nullptr;
195 }
196 
197 void QgsAbstractProcessingParameterWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
198 {
199  switch ( mType )
200  {
203  {
204  if ( parameterDefinition()->isDynamic() )
205  {
206  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
207  {
208  if ( wrapper->parameterDefinition()->name() == parameterDefinition()->dynamicLayerParameterName() )
209  {
210  setDynamicParentLayerParameter( wrapper );
211  connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, &QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged );
212  break;
213  }
214  }
215  }
216  break;
217  }
218 
220  break;
221  }
222 }
223 
225 {
226  // Get a processing context to start with
227  QgsProcessingContext *context = nullptr;
228  std::unique_ptr< QgsProcessingContext > tmpContext;
231 
232  if ( !context )
233  {
234  tmpContext = qgis::make_unique< QgsProcessingContext >();
235  context = tmpContext.get();
236  }
237 
239 
240  if ( mWidgetContext.model() )
241  {
242  const QgsProcessingAlgorithm *alg = nullptr;
243  if ( mWidgetContext.model()->childAlgorithms().contains( mWidgetContext.modelChildAlgorithmId() ) )
244  alg = mWidgetContext.model()->childAlgorithm( mWidgetContext.modelChildAlgorithmId() ).algorithm();
245 
246  QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg ? alg : mParameterDefinition->algorithm(), QVariantMap(), *context );
247  c << algorithmScope;
248  QgsExpressionContextScope *childScope = mWidgetContext.model()->createExpressionContextScopeForChildAlgorithm( mWidgetContext.modelChildAlgorithmId(), *context, QVariantMap(), QVariantMap() );
249  c << childScope;
250 
251  QStringList highlightedVariables = childScope->variableNames();
252  QStringList highlightedFunctions = childScope->functionNames();
253  highlightedVariables += algorithmScope->variableNames();
254  highlightedFunctions += algorithmScope->functionNames();
255  c.setHighlightedVariables( highlightedVariables );
256  c.setHighlightedFunctions( highlightedFunctions );
257  }
258  else
259  {
260  if ( mParameterDefinition->algorithm() )
261  c << QgsExpressionContextUtils::processingAlgorithmScope( mParameterDefinition->algorithm(), QVariantMap(), *context );
262  }
263 
264  if ( linkedVectorLayer() )
266 
267  return c;
268 }
269 
270 void QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper )
271 {
272  if ( wrapper )
273  {
274  setDynamicParentLayerParameter( wrapper );
275  }
276 }
277 
278 void QgsAbstractProcessingParameterWidgetWrapper::setDynamicParentLayerParameter( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
279 {
280  if ( mPropertyButton )
281  {
282  // evaluate value to layer
283  QgsProcessingContext *context = nullptr;
284  std::unique_ptr< QgsProcessingContext > tmpContext;
287 
288  if ( !context )
289  {
290  tmpContext = qgis::make_unique< QgsProcessingContext >();
291  context = tmpContext.get();
292  }
293 
294  QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), parentWrapper->parameterValue(), *context );
295  if ( !layer )
296  {
297  mPropertyButton->setVectorLayer( nullptr );
298  return;
299  }
300 
301  // need to grab ownership of layer if required - otherwise layer may be deleted when context
302  // goes out of scope
303  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
304  if ( ownedLayer && ownedLayer->type() == QgsMapLayer::VectorLayer )
305  {
306  mDynamicLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
307  layer = mDynamicLayer.get();
308  }
309  else
310  {
311  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
312  }
313 
314  mPropertyButton->setVectorLayer( layer );
315  }
316 }
317 
319 {
320  std::unique_ptr< QgsProcessingModelerParameterWidget > widget = qgis::make_unique< QgsProcessingModelerParameterWidget >( model, childId, parameter, context );
321  widget->populateSources( compatibleParameterTypes(), compatibleOutputTypes(), compatibleDataTypes() );
322  widget->setExpressionHelpText( modelerExpressionFormatString() );
323  return widget.release();
324 }
325 
327 {
328  return QString();
329 }
330 
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...
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...
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.
QgsProcessingGui::WidgetType type() const
Returns the dialog type for which widgets and labels will be created by this wrapper.
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.
const QgsProcessingParameterWidgetContext & widgetContext() const
Returns the context in which the Processing parameter widget is shown, e.g., the parent model algorit...
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
QWidget * createWrappedWidget(QgsProcessingContext &context)
Creates and return a new wrapped widget which allows customization of the parameter&#39;s value...
QVariant parameterValue() const
Returns the current value of the parameter.
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:74
QgsProcessingContextGenerator * mProcessingContextGenerator
void setHighlightedFunctions(const QStringList &names)
Sets the list of function names intended to be highlighted to the user.
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 QString modelerExpressionFormatString() const
Returns the expected expression format string for expression results for the parameter within model c...
A button for controlling property overrides which may apply to a widget.
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
bool isDynamic() const
Returns true if the parameter supports is dynamic, and can support data-defined values (i...
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.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
void registerProcessingContextGenerator(QgsProcessingContextGenerator *generator)
Registers a Processing context generator class that will be used to retrieve a Processing context for...
QgsProcessingAlgorithm * algorithm() const
Returns a pointer to the algorithm which owns this parameter.
QString description() const
Returns the description for the parameter.
Single scope for storing variables and functions for use within a QgsExpressionContext.
A store for object properties.
Definition: qgsproperty.h:229
QgsProcessingParameterWidgetContext mWidgetContext
QgsExpressionContext & expressionContext()
Returns the expression context.
QgsProcessingModelAlgorithm * model() const
Returns the model which the parameter widget is associated with.
QLabel * wrappedLabel()
Returns the current wrapped label, if any.
virtual QVariant widgetValue() const =0
Returns the current value of the parameter.
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...
QgsPropertyDefinition dynamicPropertyDefinition() const
Returns the property definition for dynamic properties.
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
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.
virtual QString toolTip() const
Returns a formatted tooltip for use with the parameter, which gives helpful information like paramete...
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.
QVariant defaultValue() const
Returns the default value for the parameter.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
virtual const QgsVectorLayer * linkedVectorLayer() const
Returns the optional vector layer associated with this widget wrapper, or nullptr if no vector layer ...
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
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 dynamicLayerParameterName() const
Returns the name of the parameter for a layer linked to a dynamic parameter, or an empty string if th...
QStringList variableNames() const
Returns a list of variable names contained within the scope.
QString modelChildAlgorithmId() const
Returns the child algorithm ID within the model which the parameter widget is associated with...
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.