38#include <QStackedWidget>
42#include "moc_qgsprocessingmodelerparameterwidget.cpp"
44using namespace Qt::StringLiterals;
50 , mParameterDefinition( parameter )
53 setFocusPolicy( Qt::StrongFocus );
58 QHBoxLayout *hLayout =
new QHBoxLayout();
61 const QVariantList acceptedSourcesMetadata = mParameterDefinition->metadata().value( u
"model_widget"_s ).toMap().value( u
"accepted_sources"_s ).toList();
62 for (
const QVariant &acceptedSource : acceptedSourcesMetadata )
68 mSourceButton =
new QToolButton();
69 mSourceButton->setFocusPolicy( Qt::StrongFocus );
72 mSourceButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
73 mSourceButton->setIconSize( QSize( iconSize, iconSize ) );
74 mSourceButton->setPopupMode( QToolButton::InstantPopup );
76 mSourceMenu =
new QMenu(
this );
77 connect( mSourceMenu, &QMenu::aboutToShow,
this, &QgsProcessingModelerParameterWidget::sourceMenuAboutToShow );
78 connect( mSourceMenu, &QMenu::triggered,
this, &QgsProcessingModelerParameterWidget::sourceMenuActionTriggered );
79 mSourceButton->setMenu( mSourceMenu );
81 hLayout->addWidget( mSourceButton );
83 mStackedWidget =
new QStackedWidget();
86 if ( mStaticWidgetWrapper )
89 QWidget *widget = mStaticWidgetWrapper->createWrappedWidget( context );
92 mHasStaticWrapper =
true;
93 mStackedWidget->addWidget( widget );
96 mStackedWidget->addWidget(
new QWidget() );
100 mStackedWidget->addWidget(
new QWidget() );
104 mExpressionWidget->registerExpressionContextGenerator(
this );
105 mStackedWidget->addWidget( mExpressionWidget );
108 mModelInputCombo =
new QComboBox();
109 QHBoxLayout *hLayout2 =
new QHBoxLayout();
110 hLayout2->setContentsMargins( 0, 0, 0, 0 );
111 hLayout2->addWidget(
new QLabel( tr(
"Using model input" ) ) );
112 hLayout2->addWidget( mModelInputCombo, 1 );
113 QWidget *hWidget2 =
new QWidget();
114 hWidget2->setLayout( hLayout2 );
115 mStackedWidget->addWidget( hWidget2 );
118 mChildOutputCombo =
new QComboBox();
119 QHBoxLayout *hLayout3 =
new QHBoxLayout();
120 hLayout3->setContentsMargins( 0, 0, 0, 0 );
121 hLayout3->addWidget(
new QLabel( tr(
"Using algorithm output" ) ) );
122 hLayout3->addWidget( mChildOutputCombo, 1 );
123 QWidget *hWidget3 =
new QWidget();
124 hWidget3->setLayout( hLayout3 );
125 mStackedWidget->addWidget( hWidget3 );
128 if ( mParameterDefinition->isDestination() )
131 mModelOutputName->setPlaceholderText( tr(
"[Enter name if this is a final result]" ) );
132 QHBoxLayout *hLayout4 =
new QHBoxLayout();
133 hLayout4->setContentsMargins( 0, 0, 0, 0 );
134 hLayout4->addWidget( mModelOutputName );
135 QWidget *hWidget4 =
new QWidget();
136 hWidget4->setLayout( hLayout4 );
137 mStackedWidget->addWidget( hWidget4 );
141 hLayout->setContentsMargins( 0, 0, 0, 0 );
142 hLayout->addWidget( mStackedWidget, 1 );
144 setLayout( hLayout );
152 if ( mStaticWidgetWrapper )
153 mStaticWidgetWrapper->setWidgetContext( context );
158 if ( mStaticWidgetWrapper )
159 mStaticWidgetWrapper->registerProcessingContextGenerator( generator );
164 return mParameterDefinition;
169 if ( mStaticWidgetWrapper )
170 return mStaticWidgetWrapper->createWrappedLabel();
179 mStaticValue =
value.staticValue();
180 mModelInputParameterName =
value.parameterName();
181 mOutputChildId =
value.outputChildId();
182 mOutputName =
value.outputName();
183 mExpression =
value.expression();
192 if ( values.size() == 1 )
197 for (
const QgsProcessingModelChildParameterSource &v : values )
198 r << QVariant::fromValue( v );
208 if ( mModelOutputName )
209 mModelOutputName->setText(
value );
216 return currentSourceType() == ModelOutput;
221 return mModelOutputName ? mModelOutputName->text().trimmed() : QString();
226 switch ( currentSourceType() )
230 const QVariant v = mStaticWidgetWrapper->parameterValue();
232 if ( v.userType() == QMetaType::Type::QVariantList )
234 const QVariantList vList = v.toList();
235 if ( std::all_of( vList.begin(), vList.end(), [](
const QVariant &val ) {
236 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();
306 QAction *modelOutputAction = mSourceMenu->addAction( tr(
"Model Output" ) );
307 modelOutputAction->setCheckable( currentSource == ModelOutput );
308 modelOutputAction->setChecked( currentSource == ModelOutput );
312 if ( mHasStaticWrapper
315 QAction *fixedValueAction = mSourceMenu->addAction( tr(
"Value" ) );
316 fixedValueAction->setCheckable( currentSource == StaticValue );
317 fixedValueAction->setChecked( currentSource == StaticValue );
323 QAction *calculatedValueAction = mSourceMenu->addAction( tr(
"Pre-calculated Value" ) );
324 calculatedValueAction->setCheckable( currentSource == Expression );
325 calculatedValueAction->setChecked( currentSource == Expression );
331 QAction *inputValueAction = mSourceMenu->addAction( tr(
"Model Input" ) );
332 inputValueAction->setCheckable( currentSource == ModelParameter );
333 inputValueAction->setChecked( currentSource == ModelParameter );
339 QAction *childOutputValueAction = mSourceMenu->addAction( tr(
"Algorithm Output" ) );
340 childOutputValueAction->setCheckable( currentSource == ChildOutput );
341 childOutputValueAction->setChecked( currentSource == ChildOutput );
348void QgsProcessingModelerParameterWidget::sourceMenuActionTriggered( QAction *action )
355QgsProcessingModelerParameterWidget::SourceType QgsProcessingModelerParameterWidget::currentSourceType()
const
357 return static_cast<SourceType
>( mStackedWidget->currentIndex() );
362 if ( !mLimitedSources.empty() && !mLimitedSources.contains( type ) )
366 type = mLimitedSources.at( 0 );
372 mStackedWidget->setCurrentIndex(
static_cast<int>( StaticValue ) );
374 mSourceButton->setToolTip( tr(
"Value" ) );
379 mStackedWidget->setCurrentIndex(
static_cast<int>( Expression ) );
380 mSourceButton->setToolTip( tr(
"Pre-calculated Value" ) );
386 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelParameter ) );
387 mSourceButton->setToolTip( tr(
"Model Input" ) );
394 mStackedWidget->setCurrentIndex(
static_cast<int>( ChildOutput ) );
395 mSourceButton->setToolTip( tr(
"Algorithm Output" ) );
402 mStackedWidget->setCurrentIndex(
static_cast<int>( ModelOutput ) );
403 mSourceButton->setToolTip( tr(
"Model Output" ) );
412void QgsProcessingModelerParameterWidget::updateUi()
414 mStaticWidgetWrapper->setParameterValue( mStaticValue, mContext );
418 int currentIndex = mModelInputCombo->findData( mModelInputParameterName );
419 if ( currentIndex == -1 && mModelInputCombo->count() > 0 )
421 mModelInputCombo->setCurrentIndex( currentIndex );
423 const QStringList parts = QStringList() << mOutputChildId << mOutputName;
424 currentIndex = mChildOutputCombo->findData( parts );
425 if ( currentIndex == -1 && mChildOutputCombo->count() > 0 )
427 mChildOutputCombo->setCurrentIndex( currentIndex );
432 QgsProcessingModelChildParameterSources sources = mModel->availableSourcesForChild( mChildId, compatibleParameterTypes, compatibleOutputTypes, compatibleDataTypes );
434 for (
const QgsProcessingModelChildParameterSource &source : sources )
436 switch ( source.source() )
439 mModelInputCombo->addItem( mModel->parameterDefinition( source.parameterName() )->description(), source.parameterName() );
444 if ( !mModel->childAlgorithms().contains( source.outputChildId() ) )
447 const QgsProcessingModelChildAlgorithm &alg = mModel->childAlgorithm( source.outputChildId() );
448 if ( !alg.algorithm() )
450 const QString outputDescription = alg.algorithm()->outputDefinition( source.outputName() )->description();
451 const QString childDescription = alg.description();
453 mChildOutputCombo->addItem( tr(
"“%1” from algorithm “%2”" ).arg( outputDescription, childDescription ), QStringList() << source.outputChildId() << source.outputName() );
468 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