38#include <QStackedWidget>
42#include "moc_qgsprocessingmodelerparameterwidget.cpp"
44using namespace Qt::StringLiterals;
52 , mParameterDefinition( parameter )
55 setFocusPolicy( Qt::StrongFocus );
60 QHBoxLayout *hLayout =
new QHBoxLayout();
63 const QVariantList acceptedSourcesMetadata = mParameterDefinition->metadata().value( u
"model_widget"_s ).toMap().value( u
"accepted_sources"_s ).toList();
64 for (
const QVariant &acceptedSource : acceptedSourcesMetadata )
70 mSourceButton =
new QToolButton();
71 mSourceButton->setFocusPolicy( Qt::StrongFocus );
74 mSourceButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
75 mSourceButton->setIconSize( QSize( iconSize, iconSize ) );
76 mSourceButton->setPopupMode( QToolButton::InstantPopup );
78 mSourceMenu =
new QMenu(
this );
79 connect( mSourceMenu, &QMenu::aboutToShow,
this, &QgsProcessingModelerParameterWidget::sourceMenuAboutToShow );
80 connect( mSourceMenu, &QMenu::triggered,
this, &QgsProcessingModelerParameterWidget::sourceMenuActionTriggered );
81 mSourceButton->setMenu( mSourceMenu );
83 hLayout->addWidget( mSourceButton );
85 mStackedWidget =
new QStackedWidget();
88 if ( mStaticWidgetWrapper )
91 QWidget *widget = mStaticWidgetWrapper->createWrappedWidget( context );
94 mHasStaticWrapper =
true;
95 mStackedWidget->addWidget( widget );
98 mStackedWidget->addWidget(
new QWidget() );
102 mStackedWidget->addWidget(
new QWidget() );
106 mExpressionWidget->registerExpressionContextGenerator(
this );
107 mStackedWidget->addWidget( mExpressionWidget );
110 mModelInputCombo =
new QComboBox();
111 mModelInputCombo->setSizeAdjustPolicy( QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon );
112 QHBoxLayout *hLayout2 =
new QHBoxLayout();
113 hLayout2->setContentsMargins( 0, 0, 0, 0 );
114 hLayout2->addWidget(
new QLabel( tr(
"Using model input" ) ) );
115 hLayout2->addWidget( mModelInputCombo, 1 );
116 QWidget *hWidget2 =
new QWidget();
117 hWidget2->setLayout( hLayout2 );
118 mStackedWidget->addWidget( hWidget2 );
119 connect( mModelInputCombo, qOverload< int >( &QComboBox::currentIndexChanged ),
this, &QgsProcessingModelerParameterWidget::emitChangedSignal );
121 mChildOutputCombo =
new QComboBox();
122 mChildOutputCombo->setSizeAdjustPolicy( QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon );
123 QHBoxLayout *hLayout3 =
new QHBoxLayout();
124 hLayout3->setContentsMargins( 0, 0, 0, 0 );
125 hLayout3->addWidget(
new QLabel( tr(
"Using algorithm output" ) ) );
126 hLayout3->addWidget( mChildOutputCombo, 1 );
127 QWidget *hWidget3 =
new QWidget();
128 hWidget3->setLayout( hLayout3 );
129 mStackedWidget->addWidget( hWidget3 );
130 connect( mChildOutputCombo, qOverload< int >( &QComboBox::currentIndexChanged ),
this, &QgsProcessingModelerParameterWidget::emitChangedSignal );
132 if ( mParameterDefinition->isDestination() )
135 mModelOutputName->setPlaceholderText( tr(
"[Enter name if this is a final result]" ) );
136 QHBoxLayout *hLayout4 =
new QHBoxLayout();
137 hLayout4->setContentsMargins( 0, 0, 0, 0 );
138 hLayout4->addWidget( mModelOutputName );
139 QWidget *hWidget4 =
new QWidget();
140 hWidget4->setLayout( hLayout4 );
141 mStackedWidget->addWidget( hWidget4 );
145 hLayout->setContentsMargins( 0, 0, 0, 0 );
146 hLayout->addWidget( mStackedWidget, 1 );
148 setLayout( hLayout );
156 if ( mStaticWidgetWrapper )
157 mStaticWidgetWrapper->setWidgetContext( context );
162 if ( mStaticWidgetWrapper )
163 mStaticWidgetWrapper->registerProcessingContextGenerator( generator );
168 return mParameterDefinition;
173 if ( mStaticWidgetWrapper )
174 return mStaticWidgetWrapper->createWrappedLabel();
183 mStaticValue =
value.staticValue();
184 mModelInputParameterName =
value.parameterName();
185 mOutputChildId =
value.outputChildId();
186 mOutputName =
value.outputName();
187 mExpression =
value.expression();
189 mBlockChangesSignal++;
192 mBlockChangesSignal--;
198 if ( values.size() == 1 )
203 for (
const QgsProcessingModelChildParameterSource &v : values )
204 r << QVariant::fromValue( v );
206 mBlockChangesSignal++;
209 mBlockChangesSignal--;
216 mBlockChangesSignal++;
217 if ( mModelOutputName )
218 mModelOutputName->setText(
value );
220 mBlockChangesSignal--;
226 return currentSourceType() == ModelOutput;
231 return mModelOutputName ? mModelOutputName->text().trimmed() : QString();
236 switch ( currentSourceType() )
240 const QVariant v = mStaticWidgetWrapper->parameterValue();
242 if ( v.userType() == QMetaType::Type::QVariantList )
244 const QVariantList vList = v.toList();
245 if ( std::all_of( vList.begin(), vList.end(), [](
const QVariant &val ) { return val.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>(); } ) )
250 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromStaticValue( v ) );
254 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromExpression( mExpressionWidget->expression() ) );
257 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromModelParameter( mModelInputCombo->currentData().toString() ) );
261 const QStringList parts = mChildOutputCombo->currentData().toStringList();
262 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromChildOutput( parts.value( 0, QString() ), parts.value( 1, QString() ) ) );
266 return mModelOutputName ? ( mModelOutputName->text().trimmed().isEmpty() ? QVariant() : mModelOutputName->text() ) : QVariant();
269 return QVariant::fromValue( QgsProcessingModelChildParameterSource() );
274 if ( mStaticWidgetWrapper )
275 mStaticWidgetWrapper->setDialog( dialog );
284 if ( mModel->childAlgorithms().contains( mChildId ) )
285 alg = mModel->childAlgorithm( mChildId ).algorithm();
290 QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
293 QStringList highlightedVariables = childScope->
variableNames();
294 QStringList highlightedFunctions = childScope->
functionNames();
296 highlightedVariables += mModel->variables().keys();
298 c.setHighlightedVariables( highlightedVariables );
299 c.setHighlightedFunctions( highlightedFunctions );
305void QgsProcessingModelerParameterWidget::sourceMenuAboutToShow()
307 mSourceMenu->clear();
309 const SourceType currentSource = currentSourceType();
313 QAction *modelOutputAction = mSourceMenu->addAction( tr(
"Model Output" ) );
314 modelOutputAction->setCheckable( currentSource == ModelOutput );
315 modelOutputAction->setChecked( currentSource == ModelOutput );
321 QAction *fixedValueAction = mSourceMenu->addAction( tr(
"Value" ) );
322 fixedValueAction->setCheckable( currentSource == StaticValue );
323 fixedValueAction->setChecked( currentSource == StaticValue );
329 QAction *calculatedValueAction = mSourceMenu->addAction( tr(
"Pre-calculated Value" ) );
330 calculatedValueAction->setCheckable( currentSource == Expression );
331 calculatedValueAction->setChecked( currentSource == Expression );
337 QAction *inputValueAction = mSourceMenu->addAction( tr(
"Model Input" ) );
338 inputValueAction->setCheckable( currentSource == ModelParameter );
339 inputValueAction->setChecked( currentSource == ModelParameter );
345 QAction *childOutputValueAction = mSourceMenu->addAction( tr(
"Algorithm Output" ) );
346 childOutputValueAction->setCheckable( currentSource == ChildOutput );
347 childOutputValueAction->setChecked( currentSource == ChildOutput );
354void QgsProcessingModelerParameterWidget::sourceMenuActionTriggered( QAction *action )
357 mBlockChangesSignal++;
359 mBlockChangesSignal--;
363void QgsProcessingModelerParameterWidget::emitChangedSignal()
365 if ( mBlockChangesSignal )
371QgsProcessingModelerParameterWidget::SourceType QgsProcessingModelerParameterWidget::currentSourceType()
const
373 return static_cast<SourceType
>( mStackedWidget->currentIndex() );
378 if ( !mLimitedSources.empty() && !mLimitedSources.contains( type ) )
382 type = mLimitedSources.at( 0 );
388 mStackedWidget->setCurrentIndex(
static_cast<int>( StaticValue ) );
390 mSourceButton->setToolTip( tr(
"Value" ) );
395 mStackedWidget->setCurrentIndex(
static_cast<int>( Expression ) );
396 mSourceButton->setToolTip( tr(
"Pre-calculated Value" ) );
402 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelParameter ) );
403 mSourceButton->setToolTip( tr(
"Model Input" ) );
410 mStackedWidget->setCurrentIndex(
static_cast<int>( ChildOutput ) );
411 mSourceButton->setToolTip( tr(
"Algorithm Output" ) );
418 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelOutput ) );
419 mSourceButton->setToolTip( tr(
"Model Output" ) );
428void QgsProcessingModelerParameterWidget::updateUi()
430 mStaticWidgetWrapper->setParameterValue( mStaticValue, mContext );
434 int currentIndex = mModelInputCombo->findData( mModelInputParameterName );
435 if ( currentIndex == -1 && mModelInputCombo->count() > 0 )
437 mModelInputCombo->setCurrentIndex( currentIndex );
439 const QStringList parts = QStringList() << mOutputChildId << mOutputName;
440 currentIndex = mChildOutputCombo->findData( parts );
441 if ( currentIndex == -1 && mChildOutputCombo->count() > 0 )
443 mChildOutputCombo->setCurrentIndex( currentIndex );
448 QgsProcessingModelChildParameterSources sources = mModel->availableSourcesForChild( mChildId, compatibleParameterTypes, compatibleOutputTypes, compatibleDataTypes );
450 for (
const QgsProcessingModelChildParameterSource &source : sources )
452 switch ( source.source() )
455 mModelInputCombo->addItem( mModel->parameterDefinition( source.parameterName() )->description(), source.parameterName() );
460 if ( !mModel->childAlgorithms().contains( source.outputChildId() ) )
463 const QgsProcessingModelChildAlgorithm &alg = mModel->childAlgorithm( source.outputChildId() );
464 if ( !alg.algorithm() )
466 const QString outputDescription = alg.algorithm()->outputDefinition( source.outputName() )->description();
467 const QString childDescription = alg.description();
469 mChildOutputCombo->addItem( tr(
"“%1” from algorithm “%2”" ).arg( outputDescription, childDescription ), QStringList() << source.outputChildId() << source.outputName() );
484 mExpressionWidget->setExpectedOutputFormat( text );
ProcessingModelChildParameterSource
Processing model child parameter sources.
@ ExpressionText
Parameter value is taken from a text with expressions, evaluated just before the algorithm runs.
@ ModelOutput
Parameter value is linked to an output parameter for the model.
@ ChildOutput
Parameter value is taken from an output generated by a child algorithm.
@ ModelParameter
Parameter value is taken from a parent model parameter.
@ StaticValue
Parameter value is a static value.
@ Expression
Parameter value is taken from an expression, evaluated just before the algorithm runs.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Single scope for storing variables and functions for use within a QgsExpressionContext.
QStringList functionNames() const
Retrieves a list of names of functions contained in the scope.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
static QgsExpressionContextScope * processingModelAlgorithmScope(const QgsProcessingModelAlgorithm *model, const QVariantMap ¶meters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing model algorithm,...
static QgsExpressionContextScope * processingAlgorithmScope(const QgsProcessingAlgorithm *algorithm, const QVariantMap ¶meters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing algorithm,...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A widget which includes a line edit for entering expressions together with a button to open the expre...
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
void valueChanged(const QString &value)
Same as textChanged() but with support for null values.
static QgsProcessingGuiRegistry * processingGuiRegistry()
Returns the global processing gui registry, used for registering the GUI behavior of processing algor...
Abstract base class for processing algorithms.
An interface for objects which can create Processing contexts.
Contains information about the context in which a processing algorithm is executed.
Base class for the definition of processing parameters.
virtual bool isDestination() const
Returns true if this parameter represents a file or layer destination, e.g.
Contains settings which reflect the context in which a Processing parameter widget is shown.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
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