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 QHBoxLayout *hLayout2 =
new QHBoxLayout();
112 hLayout2->setContentsMargins( 0, 0, 0, 0 );
113 hLayout2->addWidget(
new QLabel( tr(
"Using model input" ) ) );
114 hLayout2->addWidget( mModelInputCombo, 1 );
115 QWidget *hWidget2 =
new QWidget();
116 hWidget2->setLayout( hLayout2 );
117 mStackedWidget->addWidget( hWidget2 );
120 mChildOutputCombo =
new QComboBox();
121 QHBoxLayout *hLayout3 =
new QHBoxLayout();
122 hLayout3->setContentsMargins( 0, 0, 0, 0 );
123 hLayout3->addWidget(
new QLabel( tr(
"Using algorithm output" ) ) );
124 hLayout3->addWidget( mChildOutputCombo, 1 );
125 QWidget *hWidget3 =
new QWidget();
126 hWidget3->setLayout( hLayout3 );
127 mStackedWidget->addWidget( hWidget3 );
130 if ( mParameterDefinition->isDestination() )
133 mModelOutputName->setPlaceholderText( tr(
"[Enter name if this is a final result]" ) );
134 QHBoxLayout *hLayout4 =
new QHBoxLayout();
135 hLayout4->setContentsMargins( 0, 0, 0, 0 );
136 hLayout4->addWidget( mModelOutputName );
137 QWidget *hWidget4 =
new QWidget();
138 hWidget4->setLayout( hLayout4 );
139 mStackedWidget->addWidget( hWidget4 );
143 hLayout->setContentsMargins( 0, 0, 0, 0 );
144 hLayout->addWidget( mStackedWidget, 1 );
146 setLayout( hLayout );
154 if ( mStaticWidgetWrapper )
155 mStaticWidgetWrapper->setWidgetContext( context );
160 if ( mStaticWidgetWrapper )
161 mStaticWidgetWrapper->registerProcessingContextGenerator( generator );
166 return mParameterDefinition;
171 if ( mStaticWidgetWrapper )
172 return mStaticWidgetWrapper->createWrappedLabel();
181 mStaticValue =
value.staticValue();
182 mModelInputParameterName =
value.parameterName();
183 mOutputChildId =
value.outputChildId();
184 mOutputName =
value.outputName();
185 mExpression =
value.expression();
194 if ( values.size() == 1 )
199 for (
const QgsProcessingModelChildParameterSource &v : values )
200 r << QVariant::fromValue( v );
210 if ( mModelOutputName )
211 mModelOutputName->setText(
value );
218 return currentSourceType() == ModelOutput;
223 return mModelOutputName ? mModelOutputName->text().trimmed() : QString();
228 switch ( currentSourceType() )
232 const QVariant v = mStaticWidgetWrapper->parameterValue();
234 if ( v.userType() == QMetaType::Type::QVariantList )
236 const QVariantList vList = v.toList();
237 if ( std::all_of( vList.begin(), vList.end(), [](
const QVariant &val ) { return val.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>(); } ) )
242 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromStaticValue( v ) );
246 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromExpression( mExpressionWidget->expression() ) );
249 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromModelParameter( mModelInputCombo->currentData().toString() ) );
253 const QStringList parts = mChildOutputCombo->currentData().toStringList();
254 return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromChildOutput( parts.value( 0, QString() ), parts.value( 1, QString() ) ) );
258 return mModelOutputName ? ( mModelOutputName->text().trimmed().isEmpty() ? QVariant() : mModelOutputName->text() ) : QVariant();
261 return QVariant::fromValue( QgsProcessingModelChildParameterSource() );
266 if ( mStaticWidgetWrapper )
267 mStaticWidgetWrapper->setDialog( dialog );
276 if ( mModel->childAlgorithms().contains( mChildId ) )
277 alg = mModel->childAlgorithm( mChildId ).algorithm();
282 QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
285 QStringList highlightedVariables = childScope->
variableNames();
286 QStringList highlightedFunctions = childScope->
functionNames();
288 highlightedVariables += mModel->variables().keys();
290 c.setHighlightedVariables( highlightedVariables );
291 c.setHighlightedFunctions( highlightedFunctions );
297void QgsProcessingModelerParameterWidget::sourceMenuAboutToShow()
299 mSourceMenu->clear();
301 const SourceType currentSource = currentSourceType();
305 QAction *modelOutputAction = mSourceMenu->addAction( tr(
"Model Output" ) );
306 modelOutputAction->setCheckable( currentSource == ModelOutput );
307 modelOutputAction->setChecked( currentSource == ModelOutput );
313 QAction *fixedValueAction = mSourceMenu->addAction( tr(
"Value" ) );
314 fixedValueAction->setCheckable( currentSource == StaticValue );
315 fixedValueAction->setChecked( currentSource == StaticValue );
321 QAction *calculatedValueAction = mSourceMenu->addAction( tr(
"Pre-calculated Value" ) );
322 calculatedValueAction->setCheckable( currentSource == Expression );
323 calculatedValueAction->setChecked( currentSource == Expression );
329 QAction *inputValueAction = mSourceMenu->addAction( tr(
"Model Input" ) );
330 inputValueAction->setCheckable( currentSource == ModelParameter );
331 inputValueAction->setChecked( currentSource == ModelParameter );
337 QAction *childOutputValueAction = mSourceMenu->addAction( tr(
"Algorithm Output" ) );
338 childOutputValueAction->setCheckable( currentSource == ChildOutput );
339 childOutputValueAction->setChecked( currentSource == ChildOutput );
346void QgsProcessingModelerParameterWidget::sourceMenuActionTriggered( QAction *action )
353QgsProcessingModelerParameterWidget::SourceType QgsProcessingModelerParameterWidget::currentSourceType()
const
355 return static_cast<SourceType
>( mStackedWidget->currentIndex() );
360 if ( !mLimitedSources.empty() && !mLimitedSources.contains( type ) )
364 type = mLimitedSources.at( 0 );
370 mStackedWidget->setCurrentIndex(
static_cast<int>( StaticValue ) );
372 mSourceButton->setToolTip( tr(
"Value" ) );
377 mStackedWidget->setCurrentIndex(
static_cast<int>( Expression ) );
378 mSourceButton->setToolTip( tr(
"Pre-calculated Value" ) );
384 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelParameter ) );
385 mSourceButton->setToolTip( tr(
"Model Input" ) );
392 mStackedWidget->setCurrentIndex(
static_cast<int>( ChildOutput ) );
393 mSourceButton->setToolTip( tr(
"Algorithm Output" ) );
400 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelOutput ) );
401 mSourceButton->setToolTip( tr(
"Model Output" ) );
410void QgsProcessingModelerParameterWidget::updateUi()
412 mStaticWidgetWrapper->setParameterValue( mStaticValue, mContext );
416 int currentIndex = mModelInputCombo->findData( mModelInputParameterName );
417 if ( currentIndex == -1 && mModelInputCombo->count() > 0 )
419 mModelInputCombo->setCurrentIndex( currentIndex );
421 const QStringList parts = QStringList() << mOutputChildId << mOutputName;
422 currentIndex = mChildOutputCombo->findData( parts );
423 if ( currentIndex == -1 && mChildOutputCombo->count() > 0 )
425 mChildOutputCombo->setCurrentIndex( currentIndex );
430 QgsProcessingModelChildParameterSources sources = mModel->availableSourcesForChild( mChildId, compatibleParameterTypes, compatibleOutputTypes, compatibleDataTypes );
432 for (
const QgsProcessingModelChildParameterSource &source : sources )
434 switch ( source.source() )
437 mModelInputCombo->addItem( mModel->parameterDefinition( source.parameterName() )->description(), source.parameterName() );
442 if ( !mModel->childAlgorithms().contains( source.outputChildId() ) )
445 const QgsProcessingModelChildAlgorithm &alg = mModel->childAlgorithm( source.outputChildId() );
446 if ( !alg.algorithm() )
448 const QString outputDescription = alg.algorithm()->outputDefinition( source.outputName() )->description();
449 const QString childDescription = alg.description();
451 mChildOutputCombo->addItem( tr(
"“%1” from algorithm “%2”" ).arg( outputDescription, childDescription ), QStringList() << source.outputChildId() << source.outputName() );
466 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