QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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  mMessageBar = bar;
47 }
48 
50 {
51  return mMessageBar;
52 }
53 
55 {
56  mProject = project;
57 }
58 
60 {
61  return mProject;
62 }
63 
65 {
66  return mModelChildAlgorithmId;
67 }
68 
70 {
71  mModelChildAlgorithmId = modelChildAlgorithmId;
72 }
73 
74 QgsProcessingModelAlgorithm *QgsProcessingParameterWidgetContext::model() const
75 {
76  return mModel;
77 }
78 
79 void QgsProcessingParameterWidgetContext::setModel( QgsProcessingModelAlgorithm *model )
80 {
81  mModel = model;
82 }
83 
84 
85 //
86 // QgsAbstractProcessingParameterWidgetWrapper
87 //
88 
90  : QObject( parent )
91  , mType( type )
92  , mParameterDefinition( parameter )
93 {
94 }
95 
97 {
98  return mType;
99 }
100 
102 {
103  mWidgetContext = context;
104 }
105 
107 {
108  return mWidgetContext;
109 }
110 
112 {
113  if ( mWidget )
114  return mWidget;
115 
116  mWidget = createWidget();
117  QWidget *wrappedWidget = mWidget;
118  if ( mParameterDefinition->isDynamic() )
119  {
120  QHBoxLayout *hLayout = new QHBoxLayout();
121  hLayout->setMargin( 0 );
122  hLayout->setContentsMargins( 0, 0, 0, 0 );
123  hLayout->addWidget( mWidget, 1 );
124  mPropertyButton = new QgsPropertyOverrideButton();
125  hLayout->addWidget( mPropertyButton );
126  mPropertyButton->init( 0, QgsProperty(), mParameterDefinition->dynamicPropertyDefinition() );
127  mPropertyButton->registerEnabledWidget( mWidget, false );
128  mPropertyButton->registerExpressionContextGenerator( this );
129 
130  wrappedWidget = new QWidget();
131  wrappedWidget->setLayout( hLayout );
132  }
133 
134  setWidgetValue( mParameterDefinition->defaultValue(), context );
135 
136  return wrappedWidget;
137 }
138 
140 {
141  if ( mLabel )
142  return mLabel;
143 
144  mLabel = createLabel();
145  return mLabel;
146 }
147 
149 {
150  return mWidget;
151 }
152 
154 {
155  return mLabel;
156 }
157 
159 {
160  return mParameterDefinition;
161 }
162 
164 {
165  if ( mPropertyButton && value.canConvert< QgsProperty >() )
166  {
167  mPropertyButton->setToProperty( value.value< QgsProperty >() );
168  }
169  else
170  {
171  if ( mPropertyButton )
172  mPropertyButton->setToProperty( QgsProperty() );
173 
174  setWidgetValue( value, context );
175  }
176 }
177 
179 {
180  if ( mPropertyButton && mPropertyButton->isActive() )
181  return mPropertyButton->toProperty();
182  else
183  return widgetValue();
184 }
185 
187 {
188  mProcessingContextGenerator = generator;
189 }
190 
192 {
193  switch ( mType )
194  {
196  return nullptr;
197 
200  {
201  QString description = mParameterDefinition->description();
203  description = QObject::tr( "%1 [optional]" ).arg( description );
204  std::unique_ptr< QLabel > label = qgis::make_unique< QLabel >( description );
205  label->setToolTip( mParameterDefinition->toolTip() );
206  return label.release();
207  }
208  }
209  return nullptr;
210 }
211 
213 {
214  if ( mPropertyButton )
215  return mPropertyButton->vectorLayer();
216  return nullptr;
217 }
218 
219 void QgsAbstractProcessingParameterWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
220 {
221  switch ( mType )
222  {
225  {
226  if ( parameterDefinition()->isDynamic() )
227  {
228  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
229  {
230  if ( wrapper->parameterDefinition()->name() == parameterDefinition()->dynamicLayerParameterName() )
231  {
232  setDynamicParentLayerParameter( wrapper );
233  connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, &QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged );
234  break;
235  }
236  }
237  }
238  break;
239  }
240 
242  break;
243  }
244 }
245 
247 {
248  QgsExpressionContext context = QgsProcessingGuiUtils::createExpressionContext( mProcessingContextGenerator, mWidgetContext, mParameterDefinition ? mParameterDefinition->algorithm() : nullptr, linkedVectorLayer() );
249  if ( mParameterDefinition && !mParameterDefinition->additionalExpressionContextVariables().isEmpty() )
250  {
251  std::unique_ptr< QgsExpressionContextScope > paramScope = qgis::make_unique< QgsExpressionContextScope >();
252  const QStringList additional = mParameterDefinition->additionalExpressionContextVariables();
253  for ( const QString &var : additional )
254  {
255  paramScope->setVariable( var, QVariant() );
256  }
257  context.appendScope( paramScope.release() );
258 
259  // we always highlight additional variables for visibility
260  QStringList highlighted = context.highlightedVariables();
261  highlighted.append( additional );
262  context.setHighlightedVariables( highlighted );
263  }
264  return context;
265 }
266 
268 {
269 
270 }
271 
272 void QgsAbstractProcessingParameterWidgetWrapper::parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper )
273 {
274  if ( wrapper )
275  {
276  setDynamicParentLayerParameter( wrapper );
277  }
278 }
279 
280 void QgsAbstractProcessingParameterWidgetWrapper::setDynamicParentLayerParameter( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
281 {
282  if ( mPropertyButton )
283  {
284  // evaluate value to layer
285  QgsProcessingContext *context = nullptr;
286  std::unique_ptr< QgsProcessingContext > tmpContext;
289 
290  if ( !context )
291  {
292  tmpContext = qgis::make_unique< QgsProcessingContext >();
293  context = tmpContext.get();
294  }
295 
296  QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), parentWrapper->parameterValue(), *context );
297  if ( !layer )
298  {
299  mPropertyButton->setVectorLayer( nullptr );
300  return;
301  }
302 
303  // need to grab ownership of layer if required - otherwise layer may be deleted when context
304  // goes out of scope
305  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
306  if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
307  {
308  mDynamicLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
309  layer = mDynamicLayer.get();
310  }
311  else
312  {
313  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
314  }
315 
316  mPropertyButton->setVectorLayer( layer );
317  }
318 }
319 
321 {
322  std::unique_ptr< QgsProcessingModelerParameterWidget > widget = qgis::make_unique< QgsProcessingModelerParameterWidget >( model, childId, parameter, context );
323  widget->populateSources( compatibleParameterTypes(), compatibleOutputTypes(), compatibleDataTypes() );
324  widget->setExpressionHelpText( modelerExpressionFormatString() );
325  return widget.release();
326 }
327 
330  const QgsProcessingAlgorithm * )
331 {
332  return nullptr;
333 }
334 
336 {
337  return QString();
338 }
339 
340 //
341 // QgsProcessingGuiUtils
342 //
343 
345 QgsExpressionContext QgsProcessingGuiUtils::createExpressionContext( QgsProcessingContextGenerator *processingContextGenerator, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingAlgorithm *algorithm, const QgsVectorLayer *linkedLayer )
346 {
347  // Get a processing context to start with
348  QgsProcessingContext *context = nullptr;
349  std::unique_ptr< QgsProcessingContext > tmpContext;
350  if ( processingContextGenerator )
351  context = processingContextGenerator->processingContext();
352 
353  if ( !context )
354  {
355  tmpContext = qgis::make_unique< QgsProcessingContext >();
356  context = tmpContext.get();
357  }
358 
360 
361  if ( widgetContext.model() )
362  {
363  c << QgsExpressionContextUtils::processingModelAlgorithmScope( widgetContext.model(), QVariantMap(), *context );
364 
365  const QgsProcessingAlgorithm *alg = nullptr;
366  if ( widgetContext.model()->childAlgorithms().contains( widgetContext.modelChildAlgorithmId() ) )
367  alg = widgetContext.model()->childAlgorithm( widgetContext.modelChildAlgorithmId() ).algorithm();
368 
369  QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg ? alg : algorithm, QVariantMap(), *context );
370  c << algorithmScope;
371  QgsExpressionContextScope *childScope = widgetContext.model()->createExpressionContextScopeForChildAlgorithm( widgetContext.modelChildAlgorithmId(), *context, QVariantMap(), QVariantMap() );
372  c << childScope;
373 
374  QStringList highlightedVariables = childScope->variableNames();
375  QStringList highlightedFunctions = childScope->functionNames();
376  highlightedVariables += algorithmScope->variableNames();
377  highlightedVariables += widgetContext.model()->variables().keys();
378  highlightedFunctions += algorithmScope->functionNames();
379  c.setHighlightedVariables( highlightedVariables );
380  c.setHighlightedFunctions( highlightedFunctions );
381  }
382  else
383  {
384  if ( algorithm )
385  c << QgsExpressionContextUtils::processingAlgorithmScope( algorithm, QVariantMap(), *context );
386  }
387 
388  if ( linkedLayer )
389  c << QgsExpressionContextUtils::layerScope( linkedLayer );
390 
391  return c;
392 }
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.
Abstract base class for widgets which allow users to specify the properties of a Processing parameter...
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.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
WidgetType
Types of dialogs which Processing widgets can be created for.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:45
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:75
QgsProcessingContextGenerator * mProcessingContextGenerator
virtual void setDialog(QDialog *dialog)
Sets the parent dialog in which the wrapper is shown.
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.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:91
void registerProcessingContextGenerator(QgsProcessingContextGenerator *generator)
Registers a Processing context generator class that will be used to retrieve a Processing context for...
QgsProject * project() const
Returns the project associated with the widget.
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.
QStringList highlightedVariables() const
Returns the current list of variables highlighted within the 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.
virtual QgsProcessingAbstractParameterDefinitionWidget * createParameterDefinitionWidget(QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition=nullptr, const QgsProcessingAlgorithm *algorithm=nullptr)
Creates a new parameter definition widget allowing for configuration of an instance of the parameter ...
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...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Base class for the definition of processing parameters.
QStringList additionalExpressionContextVariables() const
Returns a list of additional expression context variables which are available for use when evaluating...
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.
void setProject(QgsProject *project)
Sets the project 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 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.