QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsprocessingwidgetwrapperimpl.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingwidgetwrapperimpl.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 
20 #include "processing/models/qgsprocessingmodelalgorithm.h"
21 #include "qgsprocessingoutputs.h"
24 #include "qgsspinbox.h"
25 #include "qgsdoublespinbox.h"
26 #include "qgsprocessingcontext.h"
27 #include "qgsauthconfigselect.h"
28 #include "qgsapplication.h"
29 #include "qgsfilewidget.h"
30 #include "qgssettings.h"
31 #include "qgsexpressionlineedit.h"
35 #include "qgslayoutmanager.h"
36 #include "qgsproject.h"
37 #include "qgslayoutcombobox.h"
38 #include "qgslayoutitemcombobox.h"
39 #include "qgsprintlayout.h"
40 #include "qgsscalewidget.h"
41 #include "qgssnapindicator.h"
42 #include "qgsmapmouseevent.h"
43 #include "qgsfilterlineedit.h"
44 #include "qgsmapcanvas.h"
45 #include "qgsmessagebar.h"
46 #include "qgscolorbutton.h"
49 #include "qgsfieldcombobox.h"
50 #include "qgsmapthemecollection.h"
51 #include "qgsdatetimeedit.h"
55 #include "qgsextentwidget.h"
59 #include "qgsrasterbandcombobox.h"
61 #include "qgscheckablecombobox.h"
62 #include <QToolButton>
63 #include <QLabel>
64 #include <QHBoxLayout>
65 #include <QVBoxLayout>
66 #include <QCheckBox>
67 #include <QComboBox>
68 #include <QLineEdit>
69 #include <QPlainTextEdit>
70 #include <QRadioButton>
71 #include <QButtonGroup>
72 #include <QMenu>
73 #include <QFileDialog>
74 
76 
77 //
78 // QgsProcessingBooleanWidgetWrapper
79 //
80 
81 
82 QgsProcessingBooleanParameterDefinitionWidget::QgsProcessingBooleanParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
83  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
84 {
85  QVBoxLayout *vlayout = new QVBoxLayout();
86  vlayout->setContentsMargins( 0, 0, 0, 0 );
87 
88  mDefaultCheckBox = new QCheckBox( tr( "Checked" ) );
89  if ( const QgsProcessingParameterBoolean *boolParam = dynamic_cast<const QgsProcessingParameterBoolean *>( definition ) )
90  mDefaultCheckBox->setChecked( QgsProcessingParameters::parameterAsBool( boolParam, boolParam->defaultValue(), context ) );
91  else
92  mDefaultCheckBox->setChecked( false );
93  vlayout->addWidget( mDefaultCheckBox );
94  setLayout( vlayout );
95 }
96 
97 QgsProcessingParameterDefinition *QgsProcessingBooleanParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
98 {
99  auto param = qgis::make_unique< QgsProcessingParameterBoolean >( name, description, mDefaultCheckBox->isChecked() );
100  param->setFlags( flags );
101  return param.release();
102 }
103 
104 
105 QgsProcessingBooleanWidgetWrapper::QgsProcessingBooleanWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
106  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
107 {
108 
109 }
110 
111 QWidget *QgsProcessingBooleanWidgetWrapper::createWidget()
112 {
113  switch ( type() )
114  {
116  {
117  QString description = parameterDefinition()->description();
118  if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
119  description = QObject::tr( "%1 [optional]" ).arg( description );
120 
121  mCheckBox = new QCheckBox( description );
122  mCheckBox->setToolTip( parameterDefinition()->toolTip() );
123 
124  connect( mCheckBox, &QCheckBox::toggled, this, [ = ]
125  {
126  emit widgetValueHasChanged( this );
127  } );
128  return mCheckBox;
129  }
130 
133  {
134  mComboBox = new QComboBox();
135  mComboBox->addItem( tr( "Yes" ), true );
136  mComboBox->addItem( tr( "No" ), false );
137  mComboBox->setToolTip( parameterDefinition()->toolTip() );
138 
139  connect( mComboBox, qgis::overload< int>::of( &QComboBox::currentIndexChanged ), this, [ = ]
140  {
141  emit widgetValueHasChanged( this );
142  } );
143 
144  return mComboBox;
145  }
146  }
147  return nullptr;
148 }
149 
150 QLabel *QgsProcessingBooleanWidgetWrapper::createLabel()
151 {
152  // avoid creating labels in standard dialogs
153  if ( type() == QgsProcessingGui::Standard )
154  return nullptr;
155  else
157 }
158 
159 void QgsProcessingBooleanWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
160 {
161  switch ( type() )
162  {
164  {
165  const bool v = QgsProcessingParameters::parameterAsBool( parameterDefinition(), value, context );
166  mCheckBox->setChecked( v );
167  break;
168  }
169 
172  {
173  const bool v = QgsProcessingParameters::parameterAsBool( parameterDefinition(), value, context );
174  mComboBox->setCurrentIndex( mComboBox->findData( v ) );
175  break;
176  }
177  }
178 }
179 
180 QVariant QgsProcessingBooleanWidgetWrapper::widgetValue() const
181 {
182  switch ( type() )
183  {
185  return mCheckBox->isChecked();
186 
189  return mComboBox->currentData();
190  }
191  return QVariant();
192 }
193 
194 QStringList QgsProcessingBooleanWidgetWrapper::compatibleParameterTypes() const
195 {
196  //pretty much everything is compatible here and can be converted to a bool!
197  return QStringList() << QgsProcessingParameterBoolean::typeName()
211 }
212 
213 QStringList QgsProcessingBooleanWidgetWrapper::compatibleOutputTypes() const
214 {
215  return QStringList() << QgsProcessingOutputNumber::typeName()
222 }
223 
224 QString QgsProcessingBooleanWidgetWrapper::parameterType() const
225 {
227 }
228 
229 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBooleanWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
230 {
231  return new QgsProcessingBooleanWidgetWrapper( parameter, type );
232 }
233 
234 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBooleanWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
235 {
236  return new QgsProcessingBooleanParameterDefinitionWidget( context, widgetContext, definition, algorithm );
237 }
238 
239 
240 //
241 // QgsProcessingCrsWidgetWrapper
242 //
243 
244 QgsProcessingCrsParameterDefinitionWidget::QgsProcessingCrsParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
245  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
246 {
247  QVBoxLayout *vlayout = new QVBoxLayout();
248  vlayout->setContentsMargins( 0, 0, 0, 0 );
249 
250  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
251 
252  mCrsSelector = new QgsProjectionSelectionWidget();
253  if ( const QgsProcessingParameterCrs *crsParam = dynamic_cast<const QgsProcessingParameterCrs *>( definition ) )
254  mCrsSelector->setCrs( QgsProcessingParameters::parameterAsCrs( crsParam, crsParam->defaultValue(), context ) );
255  else
256  mCrsSelector->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
257 
258  vlayout->addWidget( mCrsSelector );
259  setLayout( vlayout );
260 }
261 
262 QgsProcessingParameterDefinition *QgsProcessingCrsParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
263 {
264  auto param = qgis::make_unique< QgsProcessingParameterCrs >( name, description, mCrsSelector->crs().authid() );
265  param->setFlags( flags );
266  return param.release();
267 }
268 
269 QgsProcessingCrsWidgetWrapper::QgsProcessingCrsWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
270  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
271 {
272 
273 }
274 
275 QWidget *QgsProcessingCrsWidgetWrapper::createWidget()
276 {
277  Q_ASSERT( mProjectionSelectionWidget == nullptr );
278  mProjectionSelectionWidget = new QgsProjectionSelectionWidget();
279  mProjectionSelectionWidget->setToolTip( parameterDefinition()->toolTip() );
280 
281  if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
282  mProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
283  else
284  mProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, false );
285 
286  connect( mProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, [ = ]
287  {
288  emit widgetValueHasChanged( this );
289  } );
290 
291  switch ( type() )
292  {
295  {
296  return mProjectionSelectionWidget;
297  }
298 
300  {
301  QWidget *w = new QWidget();
302  w->setToolTip( parameterDefinition()->toolTip() );
303 
304  QVBoxLayout *vl = new QVBoxLayout();
305  vl->setContentsMargins( 0, 0, 0, 0 );
306  w->setLayout( vl );
307 
308  mUseProjectCrsCheckBox = new QCheckBox( tr( "Use project CRS" ) );
309  mUseProjectCrsCheckBox->setToolTip( tr( "Always use the current project CRS when running the model" ) );
310  vl->addWidget( mUseProjectCrsCheckBox );
311  connect( mUseProjectCrsCheckBox, &QCheckBox::toggled, mProjectionSelectionWidget, &QgsProjectionSelectionWidget::setDisabled );
312  connect( mUseProjectCrsCheckBox, &QCheckBox::toggled, this, [ = ]
313  {
314  emit widgetValueHasChanged( this );
315  } );
316 
317  vl->addWidget( mProjectionSelectionWidget );
318 
319  return w;
320  }
321  }
322  return nullptr;
323 }
324 
325 void QgsProcessingCrsWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
326 {
327  if ( mUseProjectCrsCheckBox )
328  {
329  if ( value.toString().compare( QLatin1String( "ProjectCrs" ), Qt::CaseInsensitive ) == 0 )
330  {
331  mUseProjectCrsCheckBox->setChecked( true );
332  return;
333  }
334  else
335  {
336  mUseProjectCrsCheckBox->setChecked( false );
337  }
338  }
339 
340  const QgsCoordinateReferenceSystem v = QgsProcessingParameters::parameterAsCrs( parameterDefinition(), value, context );
341  if ( mProjectionSelectionWidget )
342  mProjectionSelectionWidget->setCrs( v );
343 }
344 
345 QVariant QgsProcessingCrsWidgetWrapper::widgetValue() const
346 {
347  if ( mUseProjectCrsCheckBox && mUseProjectCrsCheckBox->isChecked() )
348  return QStringLiteral( "ProjectCrs" );
349  else if ( mProjectionSelectionWidget )
350  return mProjectionSelectionWidget->crs().isValid() ? mProjectionSelectionWidget->crs() : QVariant();
351  else
352  return QVariant();
353 }
354 
355 QStringList QgsProcessingCrsWidgetWrapper::compatibleParameterTypes() const
356 {
357  return QStringList()
365 }
366 
367 QStringList QgsProcessingCrsWidgetWrapper::compatibleOutputTypes() const
368 {
369  return QStringList() << QgsProcessingOutputVectorLayer::typeName()
373 }
374 
375 QString QgsProcessingCrsWidgetWrapper::modelerExpressionFormatString() const
376 {
377  return tr( "string as EPSG code, WKT or PROJ format, or a string identifying a map layer" );
378 }
379 
380 QString QgsProcessingCrsWidgetWrapper::parameterType() const
381 {
383 }
384 
385 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCrsWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
386 {
387  return new QgsProcessingCrsWidgetWrapper( parameter, type );
388 }
389 
390 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCrsWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
391 {
392  return new QgsProcessingCrsParameterDefinitionWidget( context, widgetContext, definition, algorithm );
393 }
394 
395 
396 
397 //
398 // QgsProcessingStringWidgetWrapper
399 //
400 
401 
402 QgsProcessingStringParameterDefinitionWidget::QgsProcessingStringParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
403  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
404 {
405  QVBoxLayout *vlayout = new QVBoxLayout();
406  vlayout->setContentsMargins( 0, 0, 0, 0 );
407 
408  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
409 
410  mDefaultLineEdit = new QLineEdit();
411  if ( const QgsProcessingParameterString *stringParam = dynamic_cast<const QgsProcessingParameterString *>( definition ) )
412  mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( stringParam, stringParam->defaultValue(), context ) );
413  vlayout->addWidget( mDefaultLineEdit );
414 
415  mMultiLineCheckBox = new QCheckBox( tr( "Multiline input" ) );
416  if ( const QgsProcessingParameterString *stringParam = dynamic_cast<const QgsProcessingParameterString *>( definition ) )
417  mMultiLineCheckBox->setChecked( stringParam->multiLine() );
418  vlayout->addWidget( mMultiLineCheckBox );
419 
420  setLayout( vlayout );
421 }
422 
423 QgsProcessingParameterDefinition *QgsProcessingStringParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
424 {
425  auto param = qgis::make_unique< QgsProcessingParameterString >( name, description, mDefaultLineEdit->text(), mMultiLineCheckBox->isChecked() );
426  param->setFlags( flags );
427  return param.release();
428 }
429 
430 
431 
432 QgsProcessingStringWidgetWrapper::QgsProcessingStringWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
433  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
434 {
435 
436 }
437 
438 QWidget *QgsProcessingStringWidgetWrapper::createWidget()
439 {
440  switch ( type() )
441  {
444  {
445  if ( static_cast< const QgsProcessingParameterString * >( parameterDefinition() )->multiLine() )
446  {
447  mPlainTextEdit = new QPlainTextEdit();
448  mPlainTextEdit->setToolTip( parameterDefinition()->toolTip() );
449 
450  connect( mPlainTextEdit, &QPlainTextEdit::textChanged, this, [ = ]
451  {
452  emit widgetValueHasChanged( this );
453  } );
454  return mPlainTextEdit;
455  }
456  else
457  {
458  mLineEdit = new QLineEdit();
459  mLineEdit->setToolTip( parameterDefinition()->toolTip() );
460 
461  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
462  {
463  emit widgetValueHasChanged( this );
464  } );
465  return mLineEdit;
466  }
467  }
468 
470  {
471  mLineEdit = new QLineEdit();
472  mLineEdit->setToolTip( parameterDefinition()->toolTip() );
473 
474  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
475  {
476  emit widgetValueHasChanged( this );
477  } );
478  return mLineEdit;
479  }
480  }
481  return nullptr;
482 }
483 
484 void QgsProcessingStringWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
485 {
486  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
487  if ( mLineEdit )
488  mLineEdit->setText( v );
489  if ( mPlainTextEdit )
490  mPlainTextEdit->setPlainText( v );
491 }
492 
493 QVariant QgsProcessingStringWidgetWrapper::widgetValue() const
494 {
495  if ( mLineEdit )
496  return mLineEdit->text();
497  else if ( mPlainTextEdit )
498  return mPlainTextEdit->toPlainText();
499  else
500  return QVariant();
501 }
502 
503 QStringList QgsProcessingStringWidgetWrapper::compatibleParameterTypes() const
504 {
505  return QStringList()
516 }
517 
518 QStringList QgsProcessingStringWidgetWrapper::compatibleOutputTypes() const
519 {
520  return QStringList() << QgsProcessingOutputNumber::typeName()
524 }
525 
526 QString QgsProcessingStringWidgetWrapper::parameterType() const
527 {
529 }
530 
531 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingStringWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
532 {
533  return new QgsProcessingStringWidgetWrapper( parameter, type );
534 }
535 
536 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingStringWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
537 {
538  return new QgsProcessingStringParameterDefinitionWidget( context, widgetContext, definition, algorithm );
539 }
540 
541 
542 
543 //
544 // QgsProcessingAuthConfigWidgetWrapper
545 //
546 
547 QgsProcessingAuthConfigWidgetWrapper::QgsProcessingAuthConfigWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
548  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
549 {
550 
551 }
552 
553 QWidget *QgsProcessingAuthConfigWidgetWrapper::createWidget()
554 {
555  switch ( type() )
556  {
560  {
561  mAuthConfigSelect = new QgsAuthConfigSelect();
562  mAuthConfigSelect->setToolTip( parameterDefinition()->toolTip() );
563 
564  connect( mAuthConfigSelect, &QgsAuthConfigSelect::selectedConfigIdChanged, this, [ = ]
565  {
566  emit widgetValueHasChanged( this );
567  } );
568  return mAuthConfigSelect;
569  }
570  }
571  return nullptr;
572 }
573 
574 void QgsProcessingAuthConfigWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
575 {
576  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
577  if ( mAuthConfigSelect )
578  mAuthConfigSelect->setConfigId( v );
579 }
580 
581 QVariant QgsProcessingAuthConfigWidgetWrapper::widgetValue() const
582 {
583  if ( mAuthConfigSelect )
584  return mAuthConfigSelect->configId();
585  else
586  return QVariant();
587 }
588 
589 QStringList QgsProcessingAuthConfigWidgetWrapper::compatibleParameterTypes() const
590 {
591  return QStringList()
595 }
596 
597 QStringList QgsProcessingAuthConfigWidgetWrapper::compatibleOutputTypes() const
598 {
599  return QStringList() << QgsProcessingOutputString::typeName();
600 }
601 
602 QString QgsProcessingAuthConfigWidgetWrapper::parameterType() const
603 {
605 }
606 
607 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAuthConfigWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
608 {
609  return new QgsProcessingAuthConfigWidgetWrapper( parameter, type );
610 }
611 
612 //
613 // QgsProcessingNumericWidgetWrapper
614 //
615 
616 QgsProcessingNumberParameterDefinitionWidget::QgsProcessingNumberParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
617  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
618 {
619  QVBoxLayout *vlayout = new QVBoxLayout();
620  vlayout->setContentsMargins( 0, 0, 0, 0 );
621 
622  vlayout->addWidget( new QLabel( tr( "Number type" ) ) );
623 
624  mTypeComboBox = new QComboBox();
625  mTypeComboBox->addItem( tr( "Float" ), QgsProcessingParameterNumber::Double );
626  mTypeComboBox->addItem( tr( "Integer" ), QgsProcessingParameterNumber::Integer );
627  vlayout->addWidget( mTypeComboBox );
628 
629  vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
630  mMinLineEdit = new QLineEdit();
631  vlayout->addWidget( mMinLineEdit );
632 
633  vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
634  mMaxLineEdit = new QLineEdit();
635  vlayout->addWidget( mMaxLineEdit );
636 
637  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
638  mDefaultLineEdit = new QLineEdit();
639  vlayout->addWidget( mDefaultLineEdit );
640 
641  if ( const QgsProcessingParameterNumber *numberParam = dynamic_cast<const QgsProcessingParameterNumber *>( definition ) )
642  {
643  mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( numberParam->dataType() ) );
644  mMinLineEdit->setText( QString::number( numberParam->minimum() ) );
645  mMaxLineEdit->setText( QString::number( numberParam->maximum() ) );
646  mDefaultLineEdit->setText( numberParam->defaultValue().toString() );
647  }
648 
649  setLayout( vlayout );
650 }
651 
652 QgsProcessingParameterDefinition *QgsProcessingNumberParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
653 {
654  bool ok;
655  double val = mDefaultLineEdit->text().toDouble( &ok );
656 
657  QgsProcessingParameterNumber::Type dataType = static_cast< QgsProcessingParameterNumber::Type >( mTypeComboBox->currentData().toInt() );
658  auto param = qgis::make_unique< QgsProcessingParameterNumber >( name, description, dataType, ok ? val : QVariant() );
659 
660  val = mMinLineEdit->text().toDouble( &ok );
661  if ( ok )
662  {
663  param->setMinimum( val );
664  }
665 
666  val = mMaxLineEdit->text().toDouble( &ok );
667  if ( ok )
668  {
669  param->setMaximum( val );
670  }
671 
672  param->setFlags( flags );
673  return param.release();
674 }
675 
676 QgsProcessingNumericWidgetWrapper::QgsProcessingNumericWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
677  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
678 {
679 
680 }
681 
682 QWidget *QgsProcessingNumericWidgetWrapper::createWidget()
683 {
684  const QgsProcessingParameterNumber *numberDef = static_cast< const QgsProcessingParameterNumber * >( parameterDefinition() );
685  const QVariantMap metadata = numberDef->metadata();
686  const int decimals = metadata.value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "decimals" ), 6 ).toInt();
687  switch ( type() )
688  {
692  {
693  // lots of duplicate code here -- but there's no common interface between QSpinBox/QDoubleSpinBox which would allow us to avoid this
694  QAbstractSpinBox *spinBox = nullptr;
695  switch ( numberDef->dataType() )
696  {
698  mDoubleSpinBox = new QgsDoubleSpinBox();
699  mDoubleSpinBox->setExpressionsEnabled( true );
700  mDoubleSpinBox->setDecimals( decimals );
701 
702  // guess reasonable step value for double spin boxes
703  if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) &&
704  !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() + 1 ) )
705  {
706  double singleStep = calculateStep( numberDef->minimum(), numberDef->maximum() );
707  singleStep = std::max( singleStep, std::pow( 10, -decimals ) );
708  mDoubleSpinBox->setSingleStep( singleStep );
709  }
710 
711  spinBox = mDoubleSpinBox;
712  break;
713 
715  mSpinBox = new QgsSpinBox();
716  mSpinBox->setExpressionsEnabled( true );
717  spinBox = mSpinBox;
718  break;
719  }
720  spinBox->setToolTip( parameterDefinition()->toolTip() );
721 
722  double max = 999999999;
723  if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) )
724  {
725  max = numberDef->maximum();
726  }
727  double min = -999999999;
728  if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) )
729  {
730  min = numberDef->minimum();
731  }
732  if ( mDoubleSpinBox )
733  {
734  mDoubleSpinBox->setMinimum( min );
735  mDoubleSpinBox->setMaximum( max );
736  }
737  else
738  {
739  mSpinBox->setMinimum( static_cast< int >( min ) );
740  mSpinBox->setMaximum( static_cast< int >( max ) );
741  }
742 
744  {
745  mAllowingNull = true;
746  if ( mDoubleSpinBox )
747  {
748  mDoubleSpinBox->setShowClearButton( true );
749  const double min = mDoubleSpinBox->minimum() - 1;
750  mDoubleSpinBox->setMinimum( min );
751  mDoubleSpinBox->setValue( min );
752  }
753  else
754  {
755  mSpinBox->setShowClearButton( true );
756  const int min = mSpinBox->minimum() - 1;
757  mSpinBox->setMinimum( min );
758  mSpinBox->setValue( min );
759  }
760  spinBox->setSpecialValueText( tr( "Not set" ) );
761  }
762  else
763  {
764  if ( numberDef->defaultValue().isValid() )
765  {
766  // if default value for parameter, we clear to that
767  bool ok = false;
768  if ( mDoubleSpinBox )
769  {
770  double defaultVal = numberDef->defaultValue().toDouble( &ok );
771  if ( ok )
772  mDoubleSpinBox->setClearValue( defaultVal );
773  }
774  else
775  {
776  int intVal = numberDef->defaultValue().toInt( &ok );
777  if ( ok )
778  mSpinBox->setClearValue( intVal );
779  }
780  }
781  else if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) )
782  {
783  // otherwise we clear to the minimum, if it's set
784  if ( mDoubleSpinBox )
785  mDoubleSpinBox->setClearValue( numberDef->minimum() );
786  else
787  mSpinBox->setClearValue( static_cast< int >( numberDef->minimum() ) );
788  }
789  else
790  {
791  // last resort, we clear to 0
792  if ( mDoubleSpinBox )
793  {
794  mDoubleSpinBox->setValue( 0 );
795  mDoubleSpinBox->setClearValue( 0 );
796  }
797  else
798  {
799  mSpinBox->setValue( 0 );
800  mSpinBox->setClearValue( 0 );
801  }
802  }
803  }
804 
805  if ( mDoubleSpinBox )
806  connect( mDoubleSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );
807  else if ( mSpinBox )
808  connect( mSpinBox, qgis::overload<int>::of( &QgsSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );
809 
810  return spinBox;
811  }
812  }
813  return nullptr;
814 }
815 
816 void QgsProcessingNumericWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
817 {
818  if ( mDoubleSpinBox )
819  {
820  if ( mAllowingNull && !value.isValid() )
821  mDoubleSpinBox->clear();
822  else
823  {
824  const double v = QgsProcessingParameters::parameterAsDouble( parameterDefinition(), value, context );
825  mDoubleSpinBox->setValue( v );
826  }
827  }
828  else if ( mSpinBox )
829  {
830  if ( mAllowingNull && !value.isValid() )
831  mSpinBox->clear();
832  else
833  {
834  const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
835  mSpinBox->setValue( v );
836  }
837  }
838 }
839 
840 QVariant QgsProcessingNumericWidgetWrapper::widgetValue() const
841 {
842  if ( mDoubleSpinBox )
843  {
844  if ( mAllowingNull && qgsDoubleNear( mDoubleSpinBox->value(), mDoubleSpinBox->minimum() ) )
845  return QVariant();
846  else
847  return mDoubleSpinBox->value();
848  }
849  else if ( mSpinBox )
850  {
851  if ( mAllowingNull && mSpinBox->value() == mSpinBox->minimum() )
852  return QVariant();
853  else
854  return mSpinBox->value();
855  }
856  else
857  return QVariant();
858 }
859 
860 QStringList QgsProcessingNumericWidgetWrapper::compatibleParameterTypes() const
861 {
862  return QStringList()
867 }
868 
869 QStringList QgsProcessingNumericWidgetWrapper::compatibleOutputTypes() const
870 {
871  return QStringList() << QgsProcessingOutputNumber::typeName()
873 }
874 
875 double QgsProcessingNumericWidgetWrapper::calculateStep( const double minimum, const double maximum )
876 {
877  const double valueRange = maximum - minimum;
878  if ( valueRange <= 1.0 )
879  {
880  const double step = valueRange / 10.0;
881  // round to 1 significant figure
882  return qgsRound( step, -std::floor( std::log( step ) ) );
883  }
884  else
885  {
886  return 1.0;
887  }
888 }
889 
890 QString QgsProcessingNumericWidgetWrapper::parameterType() const
891 {
893 }
894 
895 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingNumericWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
896 {
897  return new QgsProcessingNumericWidgetWrapper( parameter, type );
898 }
899 
900 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingNumericWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
901 {
902  return new QgsProcessingNumberParameterDefinitionWidget( context, widgetContext, definition, algorithm );
903 }
904 
905 //
906 // QgsProcessingDistanceWidgetWrapper
907 //
908 
909 QgsProcessingDistanceParameterDefinitionWidget::QgsProcessingDistanceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
910  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
911 {
912  QVBoxLayout *vlayout = new QVBoxLayout();
913  vlayout->setContentsMargins( 0, 0, 0, 0 );
914 
915  vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
916 
917  mParentLayerComboBox = new QComboBox();
918 
919  QString initialParent;
920  if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
921  initialParent = distParam->parentParameterName();
922 
923  if ( auto *lModel = widgetContext.model() )
924  {
925  // populate combo box with other model input choices
926  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
927  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
928  {
929  if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
930  {
931  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
932  if ( !initialParent.isEmpty() && initialParent == definition->name() )
933  {
934  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
935  }
936  }
937  else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
938  {
939  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
940  if ( !initialParent.isEmpty() && initialParent == definition->name() )
941  {
942  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
943  }
944  }
945  else if ( const QgsProcessingParameterMapLayer *definition = dynamic_cast< const QgsProcessingParameterMapLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
946  {
947  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
948  if ( !initialParent.isEmpty() && initialParent == definition->name() )
949  {
950  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
951  }
952  }
953  else if ( const QgsProcessingParameterCrs *definition = dynamic_cast< const QgsProcessingParameterCrs * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
954  {
955  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
956  if ( !initialParent.isEmpty() && initialParent == definition->name() )
957  {
958  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
959  }
960  }
961  }
962  }
963 
964  if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
965  {
966  // if no parent candidates found, we just add the existing one as a placeholder
967  mParentLayerComboBox->addItem( initialParent, initialParent );
968  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
969  }
970 
971  vlayout->addWidget( mParentLayerComboBox );
972 
973  vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
974  mMinLineEdit = new QLineEdit();
975  vlayout->addWidget( mMinLineEdit );
976 
977  vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
978  mMaxLineEdit = new QLineEdit();
979  vlayout->addWidget( mMaxLineEdit );
980 
981  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
982  mDefaultLineEdit = new QLineEdit();
983  vlayout->addWidget( mDefaultLineEdit );
984 
985  if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
986  {
987  mMinLineEdit->setText( QString::number( distParam->minimum() ) );
988  mMaxLineEdit->setText( QString::number( distParam->maximum() ) );
989  mDefaultLineEdit->setText( distParam->defaultValue().toString() );
990  }
991 
992  setLayout( vlayout );
993 }
994 
995 QgsProcessingParameterDefinition *QgsProcessingDistanceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
996 {
997  bool ok;
998  double val = mDefaultLineEdit->text().toDouble( &ok );
999 
1000  auto param = qgis::make_unique< QgsProcessingParameterDistance >( name, description, ok ? val : QVariant(), mParentLayerComboBox->currentData().toString() );
1001 
1002  val = mMinLineEdit->text().toDouble( &ok );
1003  if ( ok )
1004  {
1005  param->setMinimum( val );
1006  }
1007 
1008  val = mMaxLineEdit->text().toFloat( &ok );
1009  if ( ok )
1010  {
1011  param->setMaximum( val );
1012  }
1013 
1014  param->setFlags( flags );
1015  return param.release();
1016 }
1017 
1018 QgsProcessingDistanceWidgetWrapper::QgsProcessingDistanceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1019  : QgsProcessingNumericWidgetWrapper( parameter, type, parent )
1020 {
1021 
1022 }
1023 
1024 QString QgsProcessingDistanceWidgetWrapper::parameterType() const
1025 {
1027 }
1028 
1029 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDistanceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1030 {
1031  return new QgsProcessingDistanceWidgetWrapper( parameter, type );
1032 }
1033 
1034 QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
1035 {
1036  const QgsProcessingParameterDistance *distanceDef = static_cast< const QgsProcessingParameterDistance * >( parameterDefinition() );
1037 
1038  QWidget *spin = QgsProcessingNumericWidgetWrapper::createWidget();
1039  switch ( type() )
1040  {
1042  {
1043  mLabel = new QLabel();
1044  mUnitsCombo = new QComboBox();
1045 
1051 
1052 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
1053  const int labelMargin = static_cast< int >( std::round( mUnitsCombo->fontMetrics().width( 'X' ) ) );
1054 #else
1055  const int labelMargin = static_cast< int >( std::round( mUnitsCombo->fontMetrics().horizontalAdvance( 'X' ) ) );
1056 #endif
1057  QHBoxLayout *layout = new QHBoxLayout();
1058  layout->addWidget( spin, 1 );
1059  layout->insertSpacing( 1, labelMargin / 2 );
1060  layout->insertWidget( 2, mLabel );
1061  layout->insertWidget( 3, mUnitsCombo );
1062 
1063  // bit of fiddlyness here -- we want the initial spacing to only be visible
1064  // when the warning label is shown, so it's embedded inside mWarningLabel
1065  // instead of outside it
1066  mWarningLabel = new QWidget();
1067  QHBoxLayout *warningLayout = new QHBoxLayout();
1068  warningLayout->setContentsMargins( 0, 0, 0, 0 );
1069  QLabel *warning = new QLabel();
1070  QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
1071  const int size = static_cast< int >( std::max( 24.0, spin->minimumSize().height() * 0.5 ) );
1072  warning->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
1073  warning->setToolTip( tr( "Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results." ) );
1074  warningLayout->insertSpacing( 0, labelMargin / 2 );
1075  warningLayout->insertWidget( 1, warning );
1076  mWarningLabel->setLayout( warningLayout );
1077  layout->insertWidget( 4, mWarningLabel );
1078 
1079  QWidget *w = new QWidget();
1080  layout->setContentsMargins( 0, 0, 0, 0 );
1081  w->setLayout( layout );
1082 
1083  setUnits( distanceDef->defaultUnit() );
1084 
1085  return w;
1086  }
1087 
1090  return spin;
1091 
1092  }
1093  return nullptr;
1094 }
1095 
1096 void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
1097 {
1098  QgsProcessingNumericWidgetWrapper::postInitialize( wrappers );
1099  switch ( type() )
1100  {
1102  {
1103  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
1104  {
1105  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDistance * >( parameterDefinition() )->parentParameterName() )
1106  {
1107  setUnitParameterValue( wrapper->parameterValue() );
1109  {
1110  setUnitParameterValue( wrapper->parameterValue() );
1111  } );
1112  break;
1113  }
1114  }
1115  break;
1116  }
1117 
1120  break;
1121  }
1122 }
1123 
1124 void QgsProcessingDistanceWidgetWrapper::setUnitParameterValue( const QVariant &value )
1125 {
1127 
1128  // evaluate value to layer
1129  QgsProcessingContext *context = nullptr;
1130  std::unique_ptr< QgsProcessingContext > tmpContext;
1131  if ( mProcessingContextGenerator )
1132  context = mProcessingContextGenerator->processingContext();
1133 
1134  if ( !context )
1135  {
1136  tmpContext = qgis::make_unique< QgsProcessingContext >();
1137  context = tmpContext.get();
1138  }
1139 
1140  QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsCrs( parameterDefinition(), value, *context );
1141  if ( crs.isValid() )
1142  {
1143  units = crs.mapUnits();
1144  }
1145 
1146  setUnits( units );
1147 }
1148 
1149 void QgsProcessingDistanceWidgetWrapper::setUnits( const QgsUnitTypes::DistanceUnit units )
1150 {
1151  mLabel->setText( QgsUnitTypes::toString( units ) );
1153  {
1154  mUnitsCombo->hide();
1155  mLabel->show();
1156  }
1157  else
1158  {
1159  mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( units ) );
1160  mUnitsCombo->show();
1161  mLabel->hide();
1162  }
1163  mWarningLabel->setVisible( units == QgsUnitTypes::DistanceDegrees );
1164  mBaseUnit = units;
1165 }
1166 
1167 QVariant QgsProcessingDistanceWidgetWrapper::widgetValue() const
1168 {
1169  const QVariant val = QgsProcessingNumericWidgetWrapper::widgetValue();
1170  if ( val.type() == QVariant::Double && mUnitsCombo && mUnitsCombo->isVisible() )
1171  {
1172  QgsUnitTypes::DistanceUnit displayUnit = static_cast<QgsUnitTypes::DistanceUnit >( mUnitsCombo->currentData().toInt() );
1173  return val.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( displayUnit, mBaseUnit );
1174  }
1175  else
1176  {
1177  return val;
1178  }
1179 }
1180 
1181 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDistanceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1182 {
1183  return new QgsProcessingDistanceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1184 }
1185 
1186 //
1187 // QgsProcessingScaleWidgetWrapper
1188 //
1189 
1190 QgsProcessingScaleParameterDefinitionWidget::QgsProcessingScaleParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1191  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1192 {
1193  QVBoxLayout *vlayout = new QVBoxLayout();
1194  vlayout->setContentsMargins( 0, 0, 0, 0 );
1195 
1196  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1197 
1198  mDefaultLineEdit = new QLineEdit();
1199 
1200  if ( const QgsProcessingParameterScale *scaleParam = dynamic_cast<const QgsProcessingParameterScale *>( definition ) )
1201  {
1202  mDefaultLineEdit->setText( scaleParam->defaultValue().toString() );
1203  }
1204 
1205  vlayout->addWidget( mDefaultLineEdit );
1206 
1207  setLayout( vlayout );
1208 }
1209 
1210 QgsProcessingParameterDefinition *QgsProcessingScaleParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1211 {
1212  bool ok;
1213  double val = mDefaultLineEdit->text().toDouble( &ok );
1214  auto param = qgis::make_unique< QgsProcessingParameterScale >( name, description, ok ? val : QVariant() );
1215  param->setFlags( flags );
1216  return param.release();
1217 }
1218 
1219 QgsProcessingScaleWidgetWrapper::QgsProcessingScaleWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1220  : QgsProcessingNumericWidgetWrapper( parameter, type, parent )
1221 {
1222 
1223 }
1224 
1225 QString QgsProcessingScaleWidgetWrapper::parameterType() const
1226 {
1228 }
1229 
1230 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingScaleWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1231 {
1232  return new QgsProcessingScaleWidgetWrapper( parameter, type );
1233 }
1234 
1235 QWidget *QgsProcessingScaleWidgetWrapper::createWidget()
1236 {
1237  const QgsProcessingParameterScale *scaleDef = static_cast< const QgsProcessingParameterScale * >( parameterDefinition() );
1238 
1239  switch ( type() )
1240  {
1244  {
1245  mScaleWidget = new QgsScaleWidget( nullptr );
1247  mScaleWidget->setAllowNull( true );
1248 
1249  mScaleWidget->setMapCanvas( widgetContext().mapCanvas() );
1250  mScaleWidget->setShowCurrentScaleButton( true );
1251 
1252  mScaleWidget->setToolTip( parameterDefinition()->toolTip() );
1253  connect( mScaleWidget, &QgsScaleWidget::scaleChanged, this, [ = ]( double )
1254  {
1255  emit widgetValueHasChanged( this );
1256  } );
1257  return mScaleWidget;
1258  }
1259  }
1260  return nullptr;
1261 }
1262 
1263 void QgsProcessingScaleWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
1264 {
1265  if ( mScaleWidget )
1266  mScaleWidget->setMapCanvas( context.mapCanvas() );
1268 }
1269 
1270 
1271 QVariant QgsProcessingScaleWidgetWrapper::widgetValue() const
1272 {
1273  return mScaleWidget && !mScaleWidget->isNull() ? QVariant( mScaleWidget->scale() ) : QVariant();
1274 }
1275 
1276 void QgsProcessingScaleWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1277 {
1278  if ( mScaleWidget )
1279  {
1280  if ( mScaleWidget->allowNull() && !value.isValid() )
1281  mScaleWidget->setNull();
1282  else
1283  {
1284  const double v = QgsProcessingParameters::parameterAsDouble( parameterDefinition(), value, context );
1285  mScaleWidget->setScale( v );
1286  }
1287  }
1288 }
1289 
1290 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingScaleWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1291 {
1292  return new QgsProcessingScaleParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1293 }
1294 
1295 
1296 //
1297 // QgsProcessingRangeWidgetWrapper
1298 //
1299 
1300 QgsProcessingRangeParameterDefinitionWidget::QgsProcessingRangeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1301  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1302 {
1303  QVBoxLayout *vlayout = new QVBoxLayout();
1304  vlayout->setContentsMargins( 0, 0, 0, 0 );
1305 
1306  vlayout->addWidget( new QLabel( tr( "Number type" ) ) );
1307 
1308  mTypeComboBox = new QComboBox();
1309  mTypeComboBox->addItem( tr( "Float" ), QgsProcessingParameterNumber::Double );
1310  mTypeComboBox->addItem( tr( "Integer" ), QgsProcessingParameterNumber::Integer );
1311  vlayout->addWidget( mTypeComboBox );
1312 
1313  vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
1314  mMinLineEdit = new QLineEdit();
1315  vlayout->addWidget( mMinLineEdit );
1316 
1317  vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
1318  mMaxLineEdit = new QLineEdit();
1319  vlayout->addWidget( mMaxLineEdit );
1320 
1321  if ( const QgsProcessingParameterRange *rangeParam = dynamic_cast<const QgsProcessingParameterRange *>( definition ) )
1322  {
1323  mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( rangeParam->dataType() ) );
1324  const QList< double > range = QgsProcessingParameters::parameterAsRange( rangeParam, rangeParam->defaultValue(), context );
1325  mMinLineEdit->setText( QString::number( range.at( 0 ) ) );
1326  mMaxLineEdit->setText( QString::number( range.at( 1 ) ) );
1327  }
1328 
1329  setLayout( vlayout );
1330 }
1331 
1332 QgsProcessingParameterDefinition *QgsProcessingRangeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1333 {
1334  QString defaultValue;
1335  if ( mMinLineEdit->text().isEmpty() )
1336  {
1337  defaultValue = QStringLiteral( "None" );
1338  }
1339  else
1340  {
1341  defaultValue = mMinLineEdit->text();
1342  }
1343 
1344  if ( mMaxLineEdit->text().isEmpty() )
1345  {
1346  defaultValue += QLatin1String( ",None" );
1347  }
1348  else
1349  {
1350  defaultValue += QStringLiteral( "," ) + mMaxLineEdit->text();
1351  }
1352 
1353  QgsProcessingParameterNumber::Type dataType = static_cast< QgsProcessingParameterNumber::Type >( mTypeComboBox->currentData().toInt() );
1354  auto param = qgis::make_unique< QgsProcessingParameterRange >( name, description, dataType, defaultValue );
1355  param->setFlags( flags );
1356  return param.release();
1357 }
1358 
1359 
1360 QgsProcessingRangeWidgetWrapper::QgsProcessingRangeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1361  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1362 {
1363 
1364 }
1365 
1366 QWidget *QgsProcessingRangeWidgetWrapper::createWidget()
1367 {
1368  const QgsProcessingParameterRange *rangeDef = static_cast< const QgsProcessingParameterRange * >( parameterDefinition() );
1369  switch ( type() )
1370  {
1374  {
1375  QHBoxLayout *layout = new QHBoxLayout();
1376 
1377  mMinSpinBox = new QgsDoubleSpinBox();
1378  mMaxSpinBox = new QgsDoubleSpinBox();
1379 
1380  mMinSpinBox->setExpressionsEnabled( true );
1381  mMinSpinBox->setShowClearButton( false );
1382  mMaxSpinBox->setExpressionsEnabled( true );
1383  mMaxSpinBox->setShowClearButton( false );
1384 
1385  QLabel *minLabel = new QLabel( tr( "Min" ) );
1386  layout->addWidget( minLabel );
1387  layout->addWidget( mMinSpinBox, 1 );
1388 
1389  QLabel *maxLabel = new QLabel( tr( "Max" ) );
1390  layout->addWidget( maxLabel );
1391  layout->addWidget( mMaxSpinBox, 1 );
1392 
1393  QWidget *w = new QWidget();
1394  layout->setContentsMargins( 0, 0, 0, 0 );
1395  w->setLayout( layout );
1396 
1397  if ( rangeDef->dataType() == QgsProcessingParameterNumber::Double )
1398  {
1399  mMinSpinBox->setDecimals( 6 );
1400  mMaxSpinBox->setDecimals( 6 );
1401  }
1402  else
1403  {
1404  mMinSpinBox->setDecimals( 0 );
1405  mMaxSpinBox->setDecimals( 0 );
1406  }
1407 
1408  mMinSpinBox->setMinimum( -99999999.999999 );
1409  mMaxSpinBox->setMinimum( -99999999.999999 );
1410  mMinSpinBox->setMaximum( 99999999.999999 );
1411  mMaxSpinBox->setMaximum( 99999999.999999 );
1412 
1414  {
1415  mAllowingNull = true;
1416 
1417  const double min = mMinSpinBox->minimum() - 1;
1418  mMinSpinBox->setMinimum( min );
1419  mMaxSpinBox->setMinimum( min );
1420  mMinSpinBox->setValue( min );
1421  mMaxSpinBox->setValue( min );
1422 
1423  mMinSpinBox->setShowClearButton( true );
1424  mMaxSpinBox->setShowClearButton( true );
1425  mMinSpinBox->setSpecialValueText( tr( "Not set" ) );
1426  mMaxSpinBox->setSpecialValueText( tr( "Not set" ) );
1427  }
1428 
1429  w->setToolTip( parameterDefinition()->toolTip() );
1430 
1431  connect( mMinSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( const double v )
1432  {
1433  mBlockChangedSignal++;
1434  if ( !mAllowingNull && v > mMaxSpinBox->value() )
1435  mMaxSpinBox->setValue( v );
1436  mBlockChangedSignal--;
1437 
1438  if ( !mBlockChangedSignal )
1439  emit widgetValueHasChanged( this );
1440  } );
1441  connect( mMaxSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( const double v )
1442  {
1443  mBlockChangedSignal++;
1444  if ( !mAllowingNull && v < mMinSpinBox->value() )
1445  mMinSpinBox->setValue( v );
1446  mBlockChangedSignal--;
1447 
1448  if ( !mBlockChangedSignal )
1449  emit widgetValueHasChanged( this );
1450  } );
1451 
1452  return w;
1453  }
1454  }
1455  return nullptr;
1456 }
1457 
1458 void QgsProcessingRangeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1459 {
1460  const QList< double > v = QgsProcessingParameters::parameterAsRange( parameterDefinition(), value, context );
1461  if ( mAllowingNull && v.empty() )
1462  {
1463  mMinSpinBox->clear();
1464  mMaxSpinBox->clear();
1465  }
1466  else
1467  {
1468  if ( v.empty() )
1469  return;
1470 
1471  if ( mAllowingNull )
1472  {
1473  mBlockChangedSignal++;
1474  if ( std::isnan( v.at( 0 ) ) )
1475  mMinSpinBox->clear();
1476  else
1477  mMinSpinBox->setValue( v.at( 0 ) );
1478 
1479  if ( v.count() >= 2 )
1480  {
1481  if ( std::isnan( v.at( 1 ) ) )
1482  mMaxSpinBox->clear();
1483  else
1484  mMaxSpinBox->setValue( v.at( 1 ) );
1485  }
1486  mBlockChangedSignal--;
1487  }
1488  else
1489  {
1490  mBlockChangedSignal++;
1491  mMinSpinBox->setValue( v.at( 0 ) );
1492  if ( v.count() >= 2 )
1493  mMaxSpinBox->setValue( v.at( 1 ) );
1494  mBlockChangedSignal--;
1495  }
1496  }
1497 
1498  if ( !mBlockChangedSignal )
1499  emit widgetValueHasChanged( this );
1500 }
1501 
1502 QVariant QgsProcessingRangeWidgetWrapper::widgetValue() const
1503 {
1504  if ( mAllowingNull )
1505  {
1506  QString value;
1507  if ( qgsDoubleNear( mMinSpinBox->value(), mMinSpinBox->minimum() ) )
1508  value = QStringLiteral( "None" );
1509  else
1510  value = QString::number( mMinSpinBox->value() );
1511 
1512  if ( qgsDoubleNear( mMaxSpinBox->value(), mMaxSpinBox->minimum() ) )
1513  value += QLatin1String( ",None" );
1514  else
1515  value += QStringLiteral( ",%1" ).arg( mMaxSpinBox->value() );
1516 
1517  return value;
1518  }
1519  else
1520  return QStringLiteral( "%1,%2" ).arg( mMinSpinBox->value() ).arg( mMaxSpinBox->value() );
1521 }
1522 
1523 QStringList QgsProcessingRangeWidgetWrapper::compatibleParameterTypes() const
1524 {
1525  return QStringList()
1528 }
1529 
1530 QStringList QgsProcessingRangeWidgetWrapper::compatibleOutputTypes() const
1531 {
1532  return QStringList() << QgsProcessingOutputString::typeName();
1533 }
1534 
1535 QString QgsProcessingRangeWidgetWrapper::modelerExpressionFormatString() const
1536 {
1537  return tr( "string as two comma delimited floats, e.g. '1,10'" );
1538 }
1539 
1540 QString QgsProcessingRangeWidgetWrapper::parameterType() const
1541 {
1543 }
1544 
1545 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRangeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1546 {
1547  return new QgsProcessingRangeWidgetWrapper( parameter, type );
1548 }
1549 
1550 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRangeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1551 {
1552  return new QgsProcessingRangeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1553 }
1554 
1555 
1556 //
1557 // QgsProcessingMatrixWidgetWrapper
1558 //
1559 
1560 QgsProcessingMatrixParameterDefinitionWidget::QgsProcessingMatrixParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1561  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1562 {
1563  QVBoxLayout *vlayout = new QVBoxLayout();
1564  vlayout->setContentsMargins( 0, 0, 0, 0 );
1565 
1566  mMatrixWidget = new QgsProcessingMatrixModelerWidget();
1567  if ( const QgsProcessingParameterMatrix *matrixParam = dynamic_cast<const QgsProcessingParameterMatrix *>( definition ) )
1568  {
1569  mMatrixWidget->setValue( matrixParam->headers(), matrixParam->defaultValue() );
1570  mMatrixWidget->setFixedRows( matrixParam->hasFixedNumberRows() );
1571  }
1572  vlayout->addWidget( mMatrixWidget );
1573  setLayout( vlayout );
1574 }
1575 
1576 QgsProcessingParameterDefinition *QgsProcessingMatrixParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1577 {
1578  auto param = qgis::make_unique< QgsProcessingParameterMatrix >( name, description, 1, mMatrixWidget->fixedRows(), mMatrixWidget->headers(), mMatrixWidget->value() );
1579  param->setFlags( flags );
1580  return param.release();
1581 }
1582 
1583 
1584 QgsProcessingMatrixWidgetWrapper::QgsProcessingMatrixWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1585  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1586 {
1587 
1588 }
1589 
1590 QWidget *QgsProcessingMatrixWidgetWrapper::createWidget()
1591 {
1592  mMatrixWidget = new QgsProcessingMatrixParameterPanel( nullptr, dynamic_cast< const QgsProcessingParameterMatrix *>( parameterDefinition() ) );
1593  mMatrixWidget->setToolTip( parameterDefinition()->toolTip() );
1594 
1595  connect( mMatrixWidget, &QgsProcessingMatrixParameterPanel::changed, this, [ = ]
1596  {
1597  emit widgetValueHasChanged( this );
1598  } );
1599 
1600  switch ( type() )
1601  {
1605  {
1606  return mMatrixWidget;
1607  }
1608  }
1609  return nullptr;
1610 }
1611 
1612 void QgsProcessingMatrixWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1613 {
1614  const QVariantList v = QgsProcessingParameters::parameterAsMatrix( parameterDefinition(), value, context );
1615  if ( mMatrixWidget )
1616  mMatrixWidget->setValue( v );
1617 }
1618 
1619 QVariant QgsProcessingMatrixWidgetWrapper::widgetValue() const
1620 {
1621  if ( mMatrixWidget )
1622  return mMatrixWidget->value().isEmpty() ? QVariant() : mMatrixWidget->value();
1623  else
1624  return QVariant();
1625 }
1626 
1627 QStringList QgsProcessingMatrixWidgetWrapper::compatibleParameterTypes() const
1628 {
1629  return QStringList()
1631 }
1632 
1633 QStringList QgsProcessingMatrixWidgetWrapper::compatibleOutputTypes() const
1634 {
1635  return QStringList();
1636 }
1637 
1638 QString QgsProcessingMatrixWidgetWrapper::modelerExpressionFormatString() const
1639 {
1640  return tr( "comma delimited string of values, or an array of values" );
1641 }
1642 
1643 QString QgsProcessingMatrixWidgetWrapper::parameterType() const
1644 {
1646 }
1647 
1648 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMatrixWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1649 {
1650  return new QgsProcessingMatrixWidgetWrapper( parameter, type );
1651 }
1652 
1653 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMatrixWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1654 {
1655  return new QgsProcessingMatrixParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1656 }
1657 
1658 
1659 //
1660 // QgsProcessingFileWidgetWrapper
1661 //
1662 
1663 
1664 QgsProcessingFileParameterDefinitionWidget::QgsProcessingFileParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1665  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1666 {
1667  QVBoxLayout *vlayout = new QVBoxLayout();
1668  vlayout->setContentsMargins( 0, 0, 0, 0 );
1669 
1670  vlayout->addWidget( new QLabel( tr( "Type" ) ) );
1671 
1672  mTypeComboBox = new QComboBox();
1673  mTypeComboBox->addItem( tr( "File" ), QgsProcessingParameterFile::File );
1674  mTypeComboBox->addItem( tr( "Folder" ), QgsProcessingParameterFile::Folder );
1675  if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1676  mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( fileParam->behavior() ) );
1677  else
1678  mTypeComboBox->setCurrentIndex( 0 );
1679  vlayout->addWidget( mTypeComboBox );
1680 
1681  vlayout->addWidget( new QLabel( tr( "File filter" ) ) );
1682 
1683  mFilterComboBox = new QComboBox();
1684  mFilterComboBox->setEditable( true );
1685  // add some standard ones -- these also act as a demonstration of the required format
1686  mFilterComboBox->addItem( tr( "All Files (*.*)" ) );
1687  mFilterComboBox->addItem( tr( "CSV Files (*.csv)" ) );
1688  mFilterComboBox->addItem( tr( "HTML Files (*.html *.htm)" ) );
1689  mFilterComboBox->addItem( tr( "Text Files (*.txt)" ) );
1690  if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1691  mFilterComboBox->setCurrentText( fileParam->fileFilter() );
1692  else
1693  mFilterComboBox->setCurrentIndex( 0 );
1694  vlayout->addWidget( mFilterComboBox );
1695 
1696  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1697 
1698  mDefaultFileWidget = new QgsFileWidget();
1699  mDefaultFileWidget->lineEdit()->setShowClearButton( true );
1700  if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1701  {
1702  mDefaultFileWidget->setStorageMode( fileParam->behavior() == QgsProcessingParameterFile::File ? QgsFileWidget::GetFile : QgsFileWidget::GetDirectory );
1703  mDefaultFileWidget->setFilePath( fileParam->defaultValue().toString() );
1704  }
1705  else
1706  mDefaultFileWidget->setStorageMode( QgsFileWidget::GetFile );
1707  vlayout->addWidget( mDefaultFileWidget );
1708 
1709  connect( mTypeComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, [ = ]
1710  {
1711  QgsProcessingParameterFile::Behavior behavior = static_cast< QgsProcessingParameterFile::Behavior >( mTypeComboBox->currentData().toInt() );
1712  mFilterComboBox->setEnabled( behavior == QgsProcessingParameterFile::File );
1713  mDefaultFileWidget->setStorageMode( behavior == QgsProcessingParameterFile::File ? QgsFileWidget::GetFile : QgsFileWidget::GetDirectory );
1714  } );
1715  mFilterComboBox->setEnabled( static_cast< QgsProcessingParameterFile::Behavior >( mTypeComboBox->currentData().toInt() ) == QgsProcessingParameterFile::File );
1716 
1717 
1718  setLayout( vlayout );
1719 }
1720 
1721 QgsProcessingParameterDefinition *QgsProcessingFileParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1722 {
1723  auto param = qgis::make_unique< QgsProcessingParameterFile >( name, description );
1724  param->setBehavior( static_cast< QgsProcessingParameterFile::Behavior>( mTypeComboBox->currentData().toInt() ) );
1725  if ( param->behavior() == QgsProcessingParameterFile::File )
1726  param->setFileFilter( mFilterComboBox->currentText() );
1727  if ( !mDefaultFileWidget->filePath().isEmpty() )
1728  param->setDefaultValue( mDefaultFileWidget->filePath() );
1729  param->setFlags( flags );
1730  return param.release();
1731 }
1732 
1733 
1734 QgsProcessingFileWidgetWrapper::QgsProcessingFileWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1735  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1736 {
1737 
1738 }
1739 
1740 QWidget *QgsProcessingFileWidgetWrapper::createWidget()
1741 {
1742  const QgsProcessingParameterFile *fileParam = dynamic_cast< const QgsProcessingParameterFile *>( parameterDefinition() );
1743  switch ( type() )
1744  {
1748  {
1749  mFileWidget = new QgsFileWidget();
1750  mFileWidget->setToolTip( parameterDefinition()->toolTip() );
1751  mFileWidget->setDialogTitle( parameterDefinition()->description() );
1752 
1753  mFileWidget->setDefaultRoot( QgsSettings().value( QStringLiteral( "/Processing/LastInputPath" ), QDir::homePath() ).toString() );
1754 
1755  switch ( fileParam->behavior() )
1756  {
1758  mFileWidget->setStorageMode( QgsFileWidget::GetFile );
1759  if ( !fileParam->fileFilter().isEmpty() )
1760  mFileWidget->setFilter( fileParam->fileFilter() );
1761  else if ( !fileParam->extension().isEmpty() )
1762  mFileWidget->setFilter( tr( "%1 files" ).arg( fileParam->extension().toUpper() ) + QStringLiteral( " (*." ) + fileParam->extension().toLower() + ')' );
1763  break;
1764 
1766  mFileWidget->setStorageMode( QgsFileWidget::GetDirectory );
1767  break;
1768  }
1769 
1770  connect( mFileWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & path )
1771  {
1772  QgsSettings().setValue( QStringLiteral( "/Processing/LastInputPath" ), QFileInfo( path ).canonicalPath() );
1773  emit widgetValueHasChanged( this );
1774  } );
1775  return mFileWidget;
1776  }
1777  }
1778  return nullptr;
1779 }
1780 
1781 void QgsProcessingFileWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1782 {
1783  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
1784  if ( mFileWidget )
1785  mFileWidget->setFilePath( v );
1786 }
1787 
1788 QVariant QgsProcessingFileWidgetWrapper::widgetValue() const
1789 {
1790  if ( mFileWidget )
1791  return mFileWidget->filePath();
1792  else
1793  return QVariant();
1794 }
1795 
1796 QStringList QgsProcessingFileWidgetWrapper::compatibleParameterTypes() const
1797 {
1798  return QStringList()
1801 }
1802 
1803 QStringList QgsProcessingFileWidgetWrapper::compatibleOutputTypes() const
1804 {
1805  return QStringList() << QgsProcessingOutputFile::typeName()
1811 }
1812 
1813 QString QgsProcessingFileWidgetWrapper::modelerExpressionFormatString() const
1814 {
1815  return tr( "string representing a path to a file or folder" );
1816 }
1817 
1818 QString QgsProcessingFileWidgetWrapper::parameterType() const
1819 {
1821 }
1822 
1823 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1824 {
1825  return new QgsProcessingFileWidgetWrapper( parameter, type );
1826 }
1827 
1828 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFileWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1829 {
1830  return new QgsProcessingFileParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1831 }
1832 
1833 
1834 
1835 //
1836 // QgsProcessingExpressionWidgetWrapper
1837 //
1838 
1839 QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1840  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1841 {
1842  QVBoxLayout *vlayout = new QVBoxLayout();
1843  vlayout->setContentsMargins( 0, 0, 0, 0 );
1844 
1845  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1846 
1847  mDefaultLineEdit = new QgsExpressionLineEdit();
1848  if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
1849  mDefaultLineEdit->setExpression( QgsProcessingParameters::parameterAsExpression( expParam, expParam->defaultValue(), context ) );
1850  vlayout->addWidget( mDefaultLineEdit );
1851 
1852  vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
1853 
1854  mParentLayerComboBox = new QComboBox();
1855  mParentLayerComboBox->addItem( tr( "None" ), QVariant() );
1856 
1857  QString initialParent;
1858  if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
1859  initialParent = expParam->parentLayerParameterName();
1860 
1861  if ( auto *lModel = widgetContext.model() )
1862  {
1863  // populate combo box with other model input choices
1864  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
1865  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
1866  {
1867  if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
1868  {
1869  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
1870  if ( !initialParent.isEmpty() && initialParent == definition->name() )
1871  {
1872  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1873  }
1874  }
1875  else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
1876  {
1877  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
1878  if ( !initialParent.isEmpty() && initialParent == definition->name() )
1879  {
1880  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1881  }
1882  }
1883  }
1884  }
1885 
1886  if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
1887  {
1888  // if no parent candidates found, we just add the existing one as a placeholder
1889  mParentLayerComboBox->addItem( initialParent, initialParent );
1890  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1891  }
1892 
1893  vlayout->addWidget( mParentLayerComboBox );
1894  setLayout( vlayout );
1895 }
1896 
1897 QgsProcessingParameterDefinition *QgsProcessingExpressionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1898 {
1899  auto param = qgis::make_unique< QgsProcessingParameterExpression >( name, description, mDefaultLineEdit->expression(), mParentLayerComboBox->currentData().toString() );
1900  param->setFlags( flags );
1901  return param.release();
1902 }
1903 
1904 QgsProcessingExpressionWidgetWrapper::QgsProcessingExpressionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1905  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1906 {
1907 
1908 }
1909 
1910 QWidget *QgsProcessingExpressionWidgetWrapper::createWidget()
1911 {
1912  const QgsProcessingParameterExpression *expParam = dynamic_cast< const QgsProcessingParameterExpression *>( parameterDefinition() );
1913  switch ( type() )
1914  {
1918  {
1919  if ( expParam->parentLayerParameterName().isEmpty() )
1920  {
1921  mExpLineEdit = new QgsExpressionLineEdit();
1922  mExpLineEdit->setToolTip( parameterDefinition()->toolTip() );
1923  mExpLineEdit->setExpressionDialogTitle( parameterDefinition()->description() );
1924  mExpLineEdit->registerExpressionContextGenerator( this );
1925  connect( mExpLineEdit, &QgsExpressionLineEdit::expressionChanged, this, [ = ]( const QString & )
1926  {
1927  emit widgetValueHasChanged( this );
1928  } );
1929  return mExpLineEdit;
1930  }
1931  else
1932  {
1933  if ( expParam->metadata().value( QStringLiteral( "inlineEditor" ) ).toBool() )
1934  {
1935  mExpBuilderWidget = new QgsExpressionBuilderWidget();
1936  mExpBuilderWidget->setToolTip( parameterDefinition()->toolTip() );
1937  mExpBuilderWidget->init( createExpressionContext() );
1938  connect( mExpBuilderWidget, &QgsExpressionBuilderWidget::expressionParsed, this, [ = ]( bool changed )
1939  {
1940  Q_UNUSED( changed );
1941  emit widgetValueHasChanged( this );
1942  } );
1943  return mExpBuilderWidget;
1944  }
1945  else
1946  {
1947  mFieldExpWidget = new QgsFieldExpressionWidget();
1948  mFieldExpWidget->setToolTip( parameterDefinition()->toolTip() );
1949  mFieldExpWidget->setExpressionDialogTitle( parameterDefinition()->description() );
1950  mFieldExpWidget->registerExpressionContextGenerator( this );
1951  connect( mFieldExpWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ]( const QString & )
1952  {
1953  emit widgetValueHasChanged( this );
1954  } );
1955  return mFieldExpWidget;
1956  }
1957  }
1958  }
1959  }
1960  return nullptr;
1961 }
1962 
1963 void QgsProcessingExpressionWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
1964 {
1966  switch ( type() )
1967  {
1970  {
1971  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
1972  {
1973  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterExpression * >( parameterDefinition() )->parentLayerParameterName() )
1974  {
1975  setParentLayerWrapperValue( wrapper );
1977  {
1978  setParentLayerWrapperValue( wrapper );
1979  } );
1980  break;
1981  }
1982  }
1983  break;
1984  }
1985 
1987  break;
1988  }
1989 }
1990 
1991 void QgsProcessingExpressionWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
1992 {
1993  // evaluate value to layer
1994  QgsProcessingContext *context = nullptr;
1995  std::unique_ptr< QgsProcessingContext > tmpContext;
1996  if ( mProcessingContextGenerator )
1997  context = mProcessingContextGenerator->processingContext();
1998 
1999  if ( !context )
2000  {
2001  tmpContext = qgis::make_unique< QgsProcessingContext >();
2002  context = tmpContext.get();
2003  }
2004 
2005  QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), parentWrapper->parameterValue(), *context );
2006  if ( !layer )
2007  {
2008  if ( mFieldExpWidget )
2009  mFieldExpWidget->setLayer( nullptr );
2010  else if ( mExpBuilderWidget )
2011  mExpBuilderWidget->setLayer( nullptr );
2012  else if ( mExpLineEdit )
2013  mExpLineEdit->setLayer( nullptr );
2014  return;
2015  }
2016 
2017  // need to grab ownership of layer if required - otherwise layer may be deleted when context
2018  // goes out of scope
2019  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
2020  if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
2021  {
2022  mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
2023  layer = mParentLayer.get();
2024  }
2025  else
2026  {
2027  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
2028  }
2029 
2030  if ( mFieldExpWidget )
2031  mFieldExpWidget->setLayer( layer );
2032  if ( mExpBuilderWidget )
2033  mExpBuilderWidget->setLayer( layer );
2034  else if ( mExpLineEdit )
2035  mExpLineEdit->setLayer( layer );
2036 }
2037 
2038 void QgsProcessingExpressionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2039 {
2040  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2041  if ( mFieldExpWidget )
2042  mFieldExpWidget->setExpression( v );
2043  else if ( mExpBuilderWidget )
2044  mExpBuilderWidget->setExpressionText( v );
2045  else if ( mExpLineEdit )
2046  mExpLineEdit->setExpression( v );
2047 }
2048 
2049 QVariant QgsProcessingExpressionWidgetWrapper::widgetValue() const
2050 {
2051  if ( mFieldExpWidget )
2052  return mFieldExpWidget->expression();
2053  if ( mExpBuilderWidget )
2054  return mExpBuilderWidget->expressionText();
2055  else if ( mExpLineEdit )
2056  return mExpLineEdit->expression();
2057  else
2058  return QVariant();
2059 }
2060 
2061 QStringList QgsProcessingExpressionWidgetWrapper::compatibleParameterTypes() const
2062 {
2063  return QStringList()
2070 }
2071 
2072 QStringList QgsProcessingExpressionWidgetWrapper::compatibleOutputTypes() const
2073 {
2074  return QStringList()
2077 }
2078 
2079 QString QgsProcessingExpressionWidgetWrapper::modelerExpressionFormatString() const
2080 {
2081  return tr( "string representation of an expression" );
2082 }
2083 
2084 const QgsVectorLayer *QgsProcessingExpressionWidgetWrapper::linkedVectorLayer() const
2085 {
2086  if ( mFieldExpWidget && mFieldExpWidget->layer() )
2087  return mFieldExpWidget->layer();
2088 
2089  if ( mExpBuilderWidget && mExpBuilderWidget->layer() )
2090  return mExpBuilderWidget->layer();
2091 
2093 }
2094 
2095 QString QgsProcessingExpressionWidgetWrapper::parameterType() const
2096 {
2098 }
2099 
2100 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExpressionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2101 {
2102  return new QgsProcessingExpressionWidgetWrapper( parameter, type );
2103 }
2104 
2105 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExpressionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2106 {
2107  return new QgsProcessingExpressionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2108 }
2109 
2110 
2111 
2112 //
2113 // QgsProcessingEnumPanelWidget
2114 //
2115 
2116 QgsProcessingEnumPanelWidget::QgsProcessingEnumPanelWidget( QWidget *parent, const QgsProcessingParameterEnum *param )
2117  : QWidget( parent )
2118  , mParam( param )
2119 {
2120  QHBoxLayout *hl = new QHBoxLayout();
2121  hl->setContentsMargins( 0, 0, 0, 0 );
2122 
2123  mLineEdit = new QLineEdit();
2124  mLineEdit->setEnabled( false );
2125  hl->addWidget( mLineEdit, 1 );
2126 
2127  mToolButton = new QToolButton();
2128  mToolButton->setText( QString( QChar( 0x2026 ) ) );
2129  hl->addWidget( mToolButton );
2130 
2131  setLayout( hl );
2132 
2133  if ( mParam )
2134  {
2135  mLineEdit->setText( tr( "%1 options selected" ).arg( 0 ) );
2136  }
2137 
2138  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingEnumPanelWidget::showDialog );
2139 }
2140 
2141 void QgsProcessingEnumPanelWidget::setValue( const QVariant &value )
2142 {
2143  if ( value.isValid() )
2144  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
2145  else
2146  mValue.clear();
2147 
2148  updateSummaryText();
2149  emit changed();
2150 }
2151 
2152 void QgsProcessingEnumPanelWidget::showDialog()
2153 {
2154  QVariantList availableOptions;
2155  if ( mParam )
2156  {
2157  availableOptions.reserve( mParam->options().size() );
2158  for ( int i = 0; i < mParam->options().count(); ++i )
2159  availableOptions << i;
2160  }
2161 
2162  const QStringList options = mParam ? mParam->options() : QStringList();
2164  if ( panel && panel->dockMode() )
2165  {
2166  QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
2167  widget->setPanelTitle( mParam->description() );
2168 
2169  widget->setValueFormatter( [options]( const QVariant & v ) -> QString
2170  {
2171  const int i = v.toInt();
2172  return options.size() > i ? options.at( i ) : QString();
2173  } );
2174 
2175  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
2176  {
2177  setValue( widget->selectedOptions() );
2178  } );
2179  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
2180  panel->openPanel( widget );
2181  }
2182  else
2183  {
2184  QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
2185 
2186  dlg.setValueFormatter( [options]( const QVariant & v ) -> QString
2187  {
2188  const int i = v.toInt();
2189  return options.size() > i ? options.at( i ) : QString();
2190  } );
2191  if ( dlg.exec() )
2192  {
2193  setValue( dlg.selectedOptions() );
2194  }
2195  }
2196 }
2197 
2198 void QgsProcessingEnumPanelWidget::updateSummaryText()
2199 {
2200  if ( mParam )
2201  mLineEdit->setText( tr( "%1 options selected" ).arg( mValue.count() ) );
2202 }
2203 
2204 
2205 //
2206 // QgsProcessingEnumCheckboxPanelWidget
2207 //
2208 QgsProcessingEnumCheckboxPanelWidget::QgsProcessingEnumCheckboxPanelWidget( QWidget *parent, const QgsProcessingParameterEnum *param, int columns )
2209  : QWidget( parent )
2210  , mParam( param )
2211  , mButtonGroup( new QButtonGroup( this ) )
2212  , mColumns( columns )
2213 {
2214  mButtonGroup->setExclusive( !mParam->allowMultiple() );
2215 
2216  QGridLayout *l = new QGridLayout();
2217  l->setContentsMargins( 0, 0, 0, 0 );
2218 
2219  int rows = static_cast< int >( std::ceil( mParam->options().count() / static_cast< double >( mColumns ) ) );
2220  for ( int i = 0; i < mParam->options().count(); ++i )
2221  {
2222  QAbstractButton *button = nullptr;
2223  if ( mParam->allowMultiple() )
2224  button = new QCheckBox( mParam->options().at( i ) );
2225  else
2226  button = new QRadioButton( mParam->options().at( i ) );
2227 
2228  connect( button, &QAbstractButton::toggled, this, [ = ]
2229  {
2230  if ( !mBlockChangedSignal )
2231  emit changed();
2232  } );
2233 
2234  mButtons.insert( i, button );
2235  mButtonGroup->addButton( button, i );
2236  l->addWidget( button, i % rows, i / rows );
2237  }
2238  l->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, mColumns );
2239  setLayout( l );
2240 
2241  if ( mParam->allowMultiple() )
2242  {
2243  setContextMenuPolicy( Qt::CustomContextMenu );
2244  connect( this, &QWidget::customContextMenuRequested, this, &QgsProcessingEnumCheckboxPanelWidget::showPopupMenu );
2245  }
2246 }
2247 
2248 QVariant QgsProcessingEnumCheckboxPanelWidget::value() const
2249 {
2250  if ( mParam->allowMultiple() )
2251  {
2252  QVariantList value;
2253  for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2254  {
2255  if ( it.value()->isChecked() )
2256  value.append( it.key() );
2257  }
2258  return value;
2259  }
2260  else
2261  {
2262  return mButtonGroup->checkedId() >= 0 ? mButtonGroup->checkedId() : QVariant();
2263  }
2264 }
2265 
2266 void QgsProcessingEnumCheckboxPanelWidget::setValue( const QVariant &value )
2267 {
2268  mBlockChangedSignal = true;
2269  if ( mParam->allowMultiple() )
2270  {
2271  QVariantList selected;
2272  if ( value.isValid() )
2273  selected = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
2274  for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2275  {
2276  it.value()->setChecked( selected.contains( it.key() ) );
2277  }
2278  }
2279  else
2280  {
2281  QVariant v = value;
2282  if ( v.type() == QVariant::List )
2283  v = v.toList().value( 0 );
2284  if ( mButtons.contains( v ) )
2285  mButtons.value( v )->setChecked( true );
2286  }
2287  mBlockChangedSignal = false;
2288  emit changed();
2289 }
2290 
2291 void QgsProcessingEnumCheckboxPanelWidget::showPopupMenu()
2292 {
2293  QMenu popupMenu;
2294  QAction *selectAllAction = new QAction( tr( "Select All" ), &popupMenu );
2295  connect( selectAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::selectAll );
2296  QAction *clearAllAction = new QAction( tr( "Clear Selection" ), &popupMenu );
2297  connect( clearAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::deselectAll );
2298  popupMenu.addAction( selectAllAction );
2299  popupMenu.addAction( clearAllAction );
2300  popupMenu.exec( QCursor::pos() );
2301 }
2302 
2303 void QgsProcessingEnumCheckboxPanelWidget::selectAll()
2304 {
2305  mBlockChangedSignal = true;
2306  for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2307  it.value()->setChecked( true );
2308  mBlockChangedSignal = false;
2309  emit changed();
2310 }
2311 
2312 void QgsProcessingEnumCheckboxPanelWidget::deselectAll()
2313 {
2314  mBlockChangedSignal = true;
2315  for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2316  it.value()->setChecked( false );
2317  mBlockChangedSignal = false;
2318  emit changed();
2319 }
2320 
2321 
2322 //
2323 // QgsProcessingEnumWidgetWrapper
2324 //
2325 
2326 QgsProcessingEnumParameterDefinitionWidget::QgsProcessingEnumParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2327  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2328 {
2329  QVBoxLayout *vlayout = new QVBoxLayout();
2330  vlayout->setContentsMargins( 0, 0, 0, 0 );
2331 
2332  mEnumWidget = new QgsProcessingEnumModelerWidget();
2333  if ( const QgsProcessingParameterEnum *enumParam = dynamic_cast<const QgsProcessingParameterEnum *>( definition ) )
2334  {
2335  mEnumWidget->setAllowMultiple( enumParam->allowMultiple() );
2336  mEnumWidget->setOptions( enumParam->options() );
2337  mEnumWidget->setDefaultOptions( enumParam->defaultValue() );
2338  }
2339  vlayout->addWidget( mEnumWidget );
2340  setLayout( vlayout );
2341 }
2342 
2343 QgsProcessingParameterDefinition *QgsProcessingEnumParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2344 {
2345  auto param = qgis::make_unique< QgsProcessingParameterEnum >( name, description, mEnumWidget->options(), mEnumWidget->allowMultiple(), mEnumWidget->defaultOptions() );
2346  param->setFlags( flags );
2347  return param.release();
2348 }
2349 
2350 
2351 QgsProcessingEnumWidgetWrapper::QgsProcessingEnumWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2352  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2353 {
2354 
2355 }
2356 
2357 QWidget *QgsProcessingEnumWidgetWrapper::createWidget()
2358 {
2359  const QgsProcessingParameterEnum *expParam = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2360  switch ( type() )
2361  {
2363  {
2364  // checkbox panel only for use outside in standard gui!
2365  if ( expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "useCheckBoxes" ), false ).toBool() )
2366  {
2367  const int columns = expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "columns" ), 2 ).toInt();
2368  mCheckboxPanel = new QgsProcessingEnumCheckboxPanelWidget( nullptr, expParam, columns );
2369  mCheckboxPanel->setToolTip( parameterDefinition()->toolTip() );
2370  connect( mCheckboxPanel, &QgsProcessingEnumCheckboxPanelWidget::changed, this, [ = ]
2371  {
2372  emit widgetValueHasChanged( this );
2373  } );
2374  return mCheckboxPanel;
2375  }
2376  }
2377  FALLTHROUGH
2380  {
2381  if ( expParam->allowMultiple() )
2382  {
2383  mPanel = new QgsProcessingEnumPanelWidget( nullptr, expParam );
2384  mPanel->setToolTip( parameterDefinition()->toolTip() );
2385  connect( mPanel, &QgsProcessingEnumPanelWidget::changed, this, [ = ]
2386  {
2387  emit widgetValueHasChanged( this );
2388  } );
2389  return mPanel;
2390  }
2391  else
2392  {
2393  mComboBox = new QComboBox();
2394 
2396  mComboBox->addItem( tr( "[Not selected]" ), QVariant() );
2397  const QStringList options = expParam->options();
2398  for ( int i = 0; i < options.count(); ++i )
2399  mComboBox->addItem( options.at( i ), i );
2400 
2401  mComboBox->setToolTip( parameterDefinition()->toolTip() );
2402  connect( mComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, [ = ]( int )
2403  {
2404  emit widgetValueHasChanged( this );
2405  } );
2406  return mComboBox;
2407  }
2408  }
2409  }
2410  return nullptr;
2411 }
2412 
2413 void QgsProcessingEnumWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2414 {
2415  if ( mComboBox )
2416  {
2417  if ( !value.isValid() )
2418  mComboBox->setCurrentIndex( mComboBox->findData( QVariant() ) );
2419  else
2420  {
2421  const int v = QgsProcessingParameters::parameterAsEnum( parameterDefinition(), value, context );
2422  mComboBox->setCurrentIndex( mComboBox->findData( v ) );
2423  }
2424  }
2425  else if ( mPanel || mCheckboxPanel )
2426  {
2427  QVariantList opts;
2428  if ( value.isValid() )
2429  {
2430  const QList< int > v = QgsProcessingParameters::parameterAsEnums( parameterDefinition(), value, context );
2431  opts.reserve( v.size() );
2432  for ( int i : v )
2433  opts << i;
2434  }
2435  if ( mPanel )
2436  mPanel->setValue( opts );
2437  else if ( mCheckboxPanel )
2438  mCheckboxPanel->setValue( opts );
2439  }
2440 }
2441 
2442 QVariant QgsProcessingEnumWidgetWrapper::widgetValue() const
2443 {
2444  if ( mComboBox )
2445  return mComboBox->currentData();
2446  else if ( mPanel )
2447  return mPanel->value();
2448  else if ( mCheckboxPanel )
2449  return mCheckboxPanel->value();
2450  else
2451  return QVariant();
2452 }
2453 
2454 QStringList QgsProcessingEnumWidgetWrapper::compatibleParameterTypes() const
2455 {
2456  return QStringList()
2460 }
2461 
2462 QStringList QgsProcessingEnumWidgetWrapper::compatibleOutputTypes() const
2463 {
2464  return QStringList()
2467 }
2468 
2469 QString QgsProcessingEnumWidgetWrapper::modelerExpressionFormatString() const
2470 {
2471  return tr( "selected option index (starting from 0), array of indices, or comma separated string of options (e.g. '1,3')" );
2472 }
2473 
2474 QString QgsProcessingEnumWidgetWrapper::parameterType() const
2475 {
2477 }
2478 
2479 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingEnumWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2480 {
2481  return new QgsProcessingEnumWidgetWrapper( parameter, type );
2482 }
2483 
2484 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingEnumWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2485 {
2486  return new QgsProcessingEnumParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2487 }
2488 
2489 //
2490 // QgsProcessingLayoutWidgetWrapper
2491 //
2492 
2493 QgsProcessingLayoutWidgetWrapper::QgsProcessingLayoutWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2494  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2495 {
2496 
2497 }
2498 
2499 QWidget *QgsProcessingLayoutWidgetWrapper::createWidget()
2500 {
2501  const QgsProcessingParameterLayout *layoutParam = dynamic_cast< const QgsProcessingParameterLayout *>( parameterDefinition() );
2502  switch ( type() )
2503  {
2506  {
2507  // combobox only for use outside modeler!
2508  mComboBox = new QgsLayoutComboBox( nullptr, widgetContext().project() ? widgetContext().project()->layoutManager() : nullptr );
2510  mComboBox->setAllowEmptyLayout( true );
2511  mComboBox->setFilters( QgsLayoutManagerProxyModel::FilterPrintLayouts );
2512 
2513  mComboBox->setToolTip( parameterDefinition()->toolTip() );
2514  connect( mComboBox, &QgsLayoutComboBox::layoutChanged, this, [ = ]( QgsMasterLayoutInterface * )
2515  {
2516  emit widgetValueHasChanged( this );
2517  } );
2518  return mComboBox;
2519  }
2520 
2522  {
2523  mPlainComboBox = new QComboBox();
2524  mPlainComboBox->setEditable( true );
2525  mPlainComboBox->setToolTip( tr( "Name of an existing print layout" ) );
2526  if ( widgetContext().project() )
2527  {
2528  const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2529  for ( const QgsPrintLayout *layout : layouts )
2530  mPlainComboBox->addItem( layout->name() );
2531  }
2532 
2533  connect( mPlainComboBox, &QComboBox::currentTextChanged, this, [ = ]( const QString & )
2534  {
2535  emit widgetValueHasChanged( this );
2536  } );
2537  return mPlainComboBox;
2538  }
2539  }
2540  return nullptr;
2541 }
2542 
2543 void QgsProcessingLayoutWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2544 {
2545  if ( mComboBox )
2546  {
2547  if ( !value.isValid() )
2548  mComboBox->setCurrentLayout( nullptr );
2549  else
2550  {
2551  if ( QgsPrintLayout *l = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, context ) )
2552  mComboBox->setCurrentLayout( l );
2553  else
2554  mComboBox->setCurrentLayout( nullptr );
2555  }
2556  }
2557  else if ( mPlainComboBox )
2558  {
2559  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2560  mPlainComboBox->setCurrentText( v );
2561  }
2562 }
2563 
2564 QVariant QgsProcessingLayoutWidgetWrapper::widgetValue() const
2565 {
2566  if ( mComboBox )
2567  {
2568  const QgsMasterLayoutInterface *l = mComboBox->currentLayout();
2569  return l ? l->name() : QVariant();
2570  }
2571  else if ( mPlainComboBox )
2572  return mPlainComboBox->currentText().isEmpty() ? QVariant() : mPlainComboBox->currentText();
2573  else
2574  return QVariant();
2575 }
2576 
2577 void QgsProcessingLayoutWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
2578 {
2580  if ( mPlainComboBox && context.project() )
2581  {
2582  const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2583  for ( const QgsPrintLayout *layout : layouts )
2584  mPlainComboBox->addItem( layout->name() );
2585  }
2586 }
2587 
2588 QStringList QgsProcessingLayoutWidgetWrapper::compatibleParameterTypes() const
2589 {
2590  return QStringList()
2593 }
2594 
2595 QStringList QgsProcessingLayoutWidgetWrapper::compatibleOutputTypes() const
2596 {
2597  return QStringList()
2599 }
2600 
2601 QString QgsProcessingLayoutWidgetWrapper::modelerExpressionFormatString() const
2602 {
2603  return tr( "string representing the name of an existing print layout" );
2604 }
2605 
2606 QString QgsProcessingLayoutWidgetWrapper::parameterType() const
2607 {
2609 }
2610 
2611 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2612 {
2613  return new QgsProcessingLayoutWidgetWrapper( parameter, type );
2614 }
2615 
2616 
2617 
2618 
2619 //
2620 // QgsProcessingLayoutItemWidgetWrapper
2621 //
2622 
2623 
2624 QgsProcessingLayoutItemParameterDefinitionWidget::QgsProcessingLayoutItemParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2625  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2626 {
2627  QVBoxLayout *vlayout = new QVBoxLayout();
2628  vlayout->setContentsMargins( 0, 0, 0, 0 );
2629 
2630  vlayout->addWidget( new QLabel( tr( "Parent layout" ) ) );
2631 
2632  mParentLayoutComboBox = new QComboBox();
2633  QString initialParent;
2634  if ( const QgsProcessingParameterLayoutItem *itemParam = dynamic_cast<const QgsProcessingParameterLayoutItem *>( definition ) )
2635  initialParent = itemParam->parentLayoutParameterName();
2636 
2637  if ( auto *lModel = widgetContext.model() )
2638  {
2639  // populate combo box with other model input choices
2640  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
2641  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
2642  {
2643  if ( const QgsProcessingParameterLayout *definition = dynamic_cast< const QgsProcessingParameterLayout * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
2644  {
2645  mParentLayoutComboBox-> addItem( definition->description(), definition->name() );
2646  if ( !initialParent.isEmpty() && initialParent == definition->name() )
2647  {
2648  mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
2649  }
2650  }
2651  }
2652  }
2653 
2654  if ( mParentLayoutComboBox->count() == 0 && !initialParent.isEmpty() )
2655  {
2656  // if no parent candidates found, we just add the existing one as a placeholder
2657  mParentLayoutComboBox->addItem( initialParent, initialParent );
2658  mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
2659  }
2660 
2661  vlayout->addWidget( mParentLayoutComboBox );
2662  setLayout( vlayout );
2663 }
2664 QgsProcessingParameterDefinition *QgsProcessingLayoutItemParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2665 {
2666  auto param = qgis::make_unique< QgsProcessingParameterLayoutItem >( name, description, QVariant(), mParentLayoutComboBox->currentData().toString() );
2667  param->setFlags( flags );
2668  return param.release();
2669 }
2670 
2671 
2672 QgsProcessingLayoutItemWidgetWrapper::QgsProcessingLayoutItemWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2673  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2674 {
2675 
2676 }
2677 
2678 QWidget *QgsProcessingLayoutItemWidgetWrapper::createWidget()
2679 {
2680  const QgsProcessingParameterLayoutItem *layoutParam = dynamic_cast< const QgsProcessingParameterLayoutItem *>( parameterDefinition() );
2681  switch ( type() )
2682  {
2685  {
2686  // combobox only for use outside modeler!
2687  mComboBox = new QgsLayoutItemComboBox( nullptr, nullptr );
2689  mComboBox->setAllowEmptyItem( true );
2690  if ( layoutParam->itemType() >= 0 )
2691  mComboBox->setItemType( static_cast< QgsLayoutItemRegistry::ItemType >( layoutParam->itemType() ) );
2692 
2693  mComboBox->setToolTip( parameterDefinition()->toolTip() );
2694  connect( mComboBox, &QgsLayoutItemComboBox::itemChanged, this, [ = ]( QgsLayoutItem * )
2695  {
2696  emit widgetValueHasChanged( this );
2697  } );
2698  return mComboBox;
2699  }
2700 
2702  {
2703  mLineEdit = new QLineEdit();
2704  mLineEdit->setToolTip( tr( "UUID or ID of an existing print layout item" ) );
2705  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
2706  {
2707  emit widgetValueHasChanged( this );
2708  } );
2709  return mLineEdit;
2710  }
2711  }
2712  return nullptr;
2713 }
2714 
2715 void QgsProcessingLayoutItemWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
2716 {
2718  switch ( type() )
2719  {
2722  {
2723  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
2724  {
2725  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterLayoutItem * >( parameterDefinition() )->parentLayoutParameterName() )
2726  {
2727  setLayoutParameterValue( wrapper->parameterValue() );
2729  {
2730  setLayoutParameterValue( wrapper->parameterValue() );
2731  } );
2732  break;
2733  }
2734  }
2735  break;
2736  }
2737 
2739  break;
2740  }
2741 }
2742 
2743 void QgsProcessingLayoutItemWidgetWrapper::setLayoutParameterValue( const QVariant &value )
2744 {
2745  QgsPrintLayout *layout = nullptr;
2746 
2747  // evaluate value to layout
2748  QgsProcessingContext *context = nullptr;
2749  std::unique_ptr< QgsProcessingContext > tmpContext;
2750  if ( mProcessingContextGenerator )
2751  context = mProcessingContextGenerator->processingContext();
2752 
2753  if ( !context )
2754  {
2755  tmpContext = qgis::make_unique< QgsProcessingContext >();
2756  context = tmpContext.get();
2757  }
2758 
2759  layout = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, *context );
2760  setLayout( layout );
2761 }
2762 
2763 void QgsProcessingLayoutItemWidgetWrapper::setLayout( QgsPrintLayout *layout )
2764 {
2765  if ( mComboBox )
2766  mComboBox->setCurrentLayout( layout );
2767 }
2768 
2769 void QgsProcessingLayoutItemWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2770 {
2771  if ( mComboBox )
2772  {
2773  if ( !value.isValid() )
2774  mComboBox->setItem( nullptr );
2775  else
2776  {
2777  QgsLayoutItem *item = QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition(), value, context, qobject_cast< QgsPrintLayout * >( mComboBox->currentLayout() ) );
2778  mComboBox->setItem( item );
2779  }
2780  }
2781  else if ( mLineEdit )
2782  {
2783  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2784  mLineEdit->setText( v );
2785  }
2786 }
2787 
2788 QVariant QgsProcessingLayoutItemWidgetWrapper::widgetValue() const
2789 {
2790  if ( mComboBox )
2791  {
2792  const QgsLayoutItem *i = mComboBox->currentItem();
2793  return i ? i->uuid() : QVariant();
2794  }
2795  else if ( mLineEdit )
2796  return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
2797  else
2798  return QVariant();
2799 }
2800 
2801 QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleParameterTypes() const
2802 {
2803  return QStringList()
2806 }
2807 
2808 QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleOutputTypes() const
2809 {
2810  return QStringList()
2812 }
2813 
2814 QString QgsProcessingLayoutItemWidgetWrapper::modelerExpressionFormatString() const
2815 {
2816  return tr( "string representing the UUID or ID of an existing print layout item" );
2817 }
2818 
2819 QString QgsProcessingLayoutItemWidgetWrapper::parameterType() const
2820 {
2822 }
2823 
2824 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutItemWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2825 {
2826  return new QgsProcessingLayoutItemWidgetWrapper( parameter, type );
2827 }
2828 
2829 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingLayoutItemWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2830 {
2831  return new QgsProcessingLayoutItemParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2832 }
2833 
2834 //
2835 // QgsProcessingPointMapTool
2836 //
2837 
2838 QgsProcessingPointMapTool::QgsProcessingPointMapTool( QgsMapCanvas *canvas )
2839  : QgsMapTool( canvas )
2840 {
2841  setCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::CapturePoint ) );
2842  mSnapIndicator.reset( new QgsSnapIndicator( canvas ) );
2843 }
2844 
2845 QgsProcessingPointMapTool::~QgsProcessingPointMapTool() = default;
2846 
2847 void QgsProcessingPointMapTool::deactivate()
2848 {
2849  mSnapIndicator->setMatch( QgsPointLocator::Match() );
2851 }
2852 
2853 void QgsProcessingPointMapTool::canvasMoveEvent( QgsMapMouseEvent *e )
2854 {
2855  e->snapPoint();
2856  mSnapIndicator->setMatch( e->mapPointMatch() );
2857 }
2858 
2859 void QgsProcessingPointMapTool::canvasPressEvent( QgsMapMouseEvent *e )
2860 {
2861  if ( e->button() == Qt::LeftButton )
2862  {
2863  QgsPointXY point = e->snapPoint();
2864  emit clicked( point );
2865  emit complete();
2866  }
2867 }
2868 
2869 void QgsProcessingPointMapTool::keyPressEvent( QKeyEvent *e )
2870 {
2871  if ( e->key() == Qt::Key_Escape )
2872  {
2873 
2874  // Override default shortcut management in MapCanvas
2875  e->ignore();
2876  emit complete();
2877  }
2878 }
2879 
2880 
2881 
2882 //
2883 // QgsProcessingPointPanel
2884 //
2885 
2886 QgsProcessingPointPanel::QgsProcessingPointPanel( QWidget *parent )
2887  : QWidget( parent )
2888 {
2889  QHBoxLayout *l = new QHBoxLayout();
2890  l->setContentsMargins( 0, 0, 0, 0 );
2891  mLineEdit = new QgsFilterLineEdit( );
2892  mLineEdit->setShowClearButton( false );
2893  l->addWidget( mLineEdit, 1 );
2894  mButton = new QToolButton();
2895  mButton->setText( QString( QChar( 0x2026 ) ) );
2896  l->addWidget( mButton );
2897  setLayout( l );
2898 
2899  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsProcessingPointPanel::changed );
2900  connect( mButton, &QToolButton::clicked, this, &QgsProcessingPointPanel::selectOnCanvas );
2901  mButton->setVisible( false );
2902 }
2903 
2904 void QgsProcessingPointPanel::setMapCanvas( QgsMapCanvas *canvas )
2905 {
2906  mCanvas = canvas;
2907  mButton->setVisible( true );
2908 
2909  mCrs = canvas->mapSettings().destinationCrs();
2910  mTool = qgis::make_unique< QgsProcessingPointMapTool >( mCanvas );
2911  connect( mTool.get(), &QgsProcessingPointMapTool::clicked, this, &QgsProcessingPointPanel::updatePoint );
2912  connect( mTool.get(), &QgsProcessingPointMapTool::complete, this, &QgsProcessingPointPanel::pointPicked );
2913 }
2914 
2915 void QgsProcessingPointPanel::setAllowNull( bool allowNull )
2916 {
2917  mLineEdit->setShowClearButton( allowNull );
2918 }
2919 
2920 QVariant QgsProcessingPointPanel::value() const
2921 {
2922  return mLineEdit->showClearButton() && mLineEdit->text().trimmed().isEmpty() ? QVariant() : QVariant( mLineEdit->text() );
2923 }
2924 
2925 void QgsProcessingPointPanel::clear()
2926 {
2927  mLineEdit->clear();
2928 }
2929 
2930 void QgsProcessingPointPanel::setValue( const QgsPointXY &point, const QgsCoordinateReferenceSystem &crs )
2931 {
2932  QString newText = QStringLiteral( "%1,%2" )
2933  .arg( QString::number( point.x(), 'f' ),
2934  QString::number( point.y(), 'f' ) );
2935 
2936  mCrs = crs;
2937  if ( mCrs.isValid() )
2938  {
2939  newText += QStringLiteral( " [%1]" ).arg( mCrs.authid() );
2940  }
2941  mLineEdit->setText( newText );
2942 }
2943 
2944 void QgsProcessingPointPanel::selectOnCanvas()
2945 {
2946  if ( !mCanvas )
2947  return;
2948 
2949  mPrevTool = mCanvas->mapTool();
2950  mCanvas->setMapTool( mTool.get() );
2951 
2952  emit toggleDialogVisibility( false );
2953 }
2954 
2955 void QgsProcessingPointPanel::updatePoint( const QgsPointXY &point )
2956 {
2957  setValue( point, mCanvas->mapSettings().destinationCrs() );
2958 }
2959 
2960 void QgsProcessingPointPanel::pointPicked()
2961 {
2962  if ( !mCanvas )
2963  return;
2964 
2965  mCanvas->setMapTool( mPrevTool );
2966 
2967  emit toggleDialogVisibility( true );
2968 }
2969 
2970 
2971 
2972 //
2973 // QgsProcessingPointWidgetWrapper
2974 //
2975 
2976 QgsProcessingPointParameterDefinitionWidget::QgsProcessingPointParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2977  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2978 {
2979  QVBoxLayout *vlayout = new QVBoxLayout();
2980  vlayout->setContentsMargins( 0, 0, 0, 0 );
2981 
2982  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
2983 
2984  mDefaultLineEdit = new QLineEdit();
2985  mDefaultLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
2986  mDefaultLineEdit->setPlaceholderText( tr( "Point as 'x,y'" ) );
2987  if ( const QgsProcessingParameterPoint *pointParam = dynamic_cast<const QgsProcessingParameterPoint *>( definition ) )
2988  {
2989  QgsPointXY point = QgsProcessingParameters::parameterAsPoint( pointParam, pointParam->defaultValue(), context );
2990  mDefaultLineEdit->setText( QStringLiteral( "%1,%2" ).arg( QString::number( point.x(), 'f' ), QString::number( point.y(), 'f' ) ) );
2991  }
2992 
2993  vlayout->addWidget( mDefaultLineEdit );
2994  setLayout( vlayout );
2995 }
2996 
2997 QgsProcessingParameterDefinition *QgsProcessingPointParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2998 {
2999  auto param = qgis::make_unique< QgsProcessingParameterPoint >( name, description, mDefaultLineEdit->text() );
3000  param->setFlags( flags );
3001  return param.release();
3002 }
3003 
3004 QgsProcessingPointWidgetWrapper::QgsProcessingPointWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3005  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3006 {
3007 
3008 }
3009 
3010 QWidget *QgsProcessingPointWidgetWrapper::createWidget()
3011 {
3012  const QgsProcessingParameterPoint *pointParam = dynamic_cast< const QgsProcessingParameterPoint *>( parameterDefinition() );
3013  switch ( type() )
3014  {
3017  {
3018  mPanel = new QgsProcessingPointPanel( nullptr );
3019  if ( widgetContext().mapCanvas() )
3020  mPanel->setMapCanvas( widgetContext().mapCanvas() );
3021 
3023  mPanel->setAllowNull( true );
3024 
3025  mPanel->setToolTip( parameterDefinition()->toolTip() );
3026 
3027  connect( mPanel, &QgsProcessingPointPanel::changed, this, [ = ]
3028  {
3029  emit widgetValueHasChanged( this );
3030  } );
3031 
3032  if ( mDialog )
3033  setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
3034  return mPanel;
3035  }
3036 
3038  {
3039  mLineEdit = new QLineEdit();
3040  mLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3041  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3042  {
3043  emit widgetValueHasChanged( this );
3044  } );
3045  return mLineEdit;
3046  }
3047  }
3048  return nullptr;
3049 }
3050 
3051 void QgsProcessingPointWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3052 {
3054  if ( mPanel && context.mapCanvas() )
3055  mPanel->setMapCanvas( context.mapCanvas() );
3056 }
3057 
3058 void QgsProcessingPointWidgetWrapper::setDialog( QDialog *dialog )
3059 {
3060  mDialog = dialog;
3061  if ( mPanel )
3062  {
3063  connect( mPanel, &QgsProcessingPointPanel::toggleDialogVisibility, mDialog, [ = ]( bool visible )
3064  {
3065  if ( !visible )
3066  mDialog->showMinimized();
3067  else
3068  {
3069  mDialog->showNormal();
3070  mDialog->raise();
3071  mDialog->activateWindow();
3072  }
3073  } );
3074  }
3076 }
3077 
3078 void QgsProcessingPointWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3079 {
3080  if ( mPanel )
3081  {
3082  if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
3083  mPanel->clear();
3084  else
3085  {
3086  QgsPointXY p = QgsProcessingParameters::parameterAsPoint( parameterDefinition(), value, context );
3087  QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
3088  mPanel->setValue( p, crs );
3089  }
3090  }
3091  else if ( mLineEdit )
3092  {
3093  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3094  mLineEdit->setText( v );
3095  }
3096 }
3097 
3098 QVariant QgsProcessingPointWidgetWrapper::widgetValue() const
3099 {
3100  if ( mPanel )
3101  {
3102  return mPanel->value();
3103  }
3104  else if ( mLineEdit )
3105  return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3106  else
3107  return QVariant();
3108 }
3109 
3110 QStringList QgsProcessingPointWidgetWrapper::compatibleParameterTypes() const
3111 {
3112  return QStringList()
3115 }
3116 
3117 QStringList QgsProcessingPointWidgetWrapper::compatibleOutputTypes() const
3118 {
3119  return QStringList()
3121 }
3122 
3123 QString QgsProcessingPointWidgetWrapper::modelerExpressionFormatString() const
3124 {
3125  return tr( "string of the format 'x,y' or a geometry value (centroid is used)" );
3126 }
3127 
3128 QString QgsProcessingPointWidgetWrapper::parameterType() const
3129 {
3131 }
3132 
3133 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3134 {
3135  return new QgsProcessingPointWidgetWrapper( parameter, type );
3136 }
3137 
3138 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3139 {
3140  return new QgsProcessingPointParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3141 }
3142 
3143 
3144 //
3145 // QgsProcessingGeometryWidgetWrapper
3146 //
3147 
3148 
3149 QgsProcessingGeometryParameterDefinitionWidget::QgsProcessingGeometryParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3150  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3151 {
3152  QVBoxLayout *vlayout = new QVBoxLayout();
3153  vlayout->setContentsMargins( 0, 0, 0, 0 );
3154 
3155  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3156 
3157  mDefaultLineEdit = new QLineEdit();
3158  mDefaultLineEdit->setToolTip( tr( "Geometry as WKT" ) );
3159  mDefaultLineEdit->setPlaceholderText( tr( "Geometry as WKT" ) );
3160  if ( const QgsProcessingParameterGeometry *geometryParam = dynamic_cast<const QgsProcessingParameterGeometry *>( definition ) )
3161  {
3162  QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( geometryParam, geometryParam->defaultValue(), context );
3163  if ( !g.isNull() )
3164  mDefaultLineEdit->setText( g.asWkt() );
3165  }
3166 
3167  vlayout->addWidget( mDefaultLineEdit );
3168  setLayout( vlayout );
3169 }
3170 
3171 QgsProcessingParameterDefinition *QgsProcessingGeometryParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3172 {
3173  auto param = qgis::make_unique< QgsProcessingParameterGeometry >( name, description, mDefaultLineEdit->text() );
3174  param->setFlags( flags );
3175  return param.release();
3176 }
3177 
3178 QgsProcessingGeometryWidgetWrapper::QgsProcessingGeometryWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3179  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3180 {
3181 
3182 }
3183 
3184 QWidget *QgsProcessingGeometryWidgetWrapper::createWidget()
3185 {
3186  switch ( type() )
3187  {
3191  {
3192  mLineEdit = new QLineEdit();
3193  mLineEdit->setToolTip( parameterDefinition()->toolTip() );
3194  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3195  {
3196  emit widgetValueHasChanged( this );
3197  } );
3198  return mLineEdit;
3199  }
3200  }
3201  return nullptr;
3202 }
3203 
3204 void QgsProcessingGeometryWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3205 {
3206  if ( mLineEdit )
3207  {
3208  QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( parameterDefinition(), value, context );
3209  if ( !g.isNull() )
3210  mLineEdit->setText( g.asWkt() );
3211  else
3212  mLineEdit->clear();
3213  }
3214 }
3215 
3216 QVariant QgsProcessingGeometryWidgetWrapper::widgetValue() const
3217 {
3218  if ( mLineEdit )
3219  return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3220  else
3221  return QVariant();
3222 }
3223 
3224 QStringList QgsProcessingGeometryWidgetWrapper::compatibleParameterTypes() const
3225 {
3226  return QStringList()
3231 }
3232 
3233 QStringList QgsProcessingGeometryWidgetWrapper::compatibleOutputTypes() const
3234 {
3235  return QStringList()
3237 }
3238 
3239 QString QgsProcessingGeometryWidgetWrapper::modelerExpressionFormatString() const
3240 {
3241  return tr( "string in the Well-Known-Text format or a geometry value" );
3242 }
3243 
3244 QString QgsProcessingGeometryWidgetWrapper::parameterType() const
3245 {
3247 }
3248 
3249 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingGeometryWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3250 {
3251  return new QgsProcessingGeometryWidgetWrapper( parameter, type );
3252 }
3253 
3254 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingGeometryWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3255 {
3256  return new QgsProcessingGeometryParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3257 }
3258 
3259 
3260 //
3261 // QgsProcessingColorWidgetWrapper
3262 //
3263 
3264 
3265 QgsProcessingColorParameterDefinitionWidget::QgsProcessingColorParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3266  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3267 {
3268  QVBoxLayout *vlayout = new QVBoxLayout();
3269  vlayout->setContentsMargins( 0, 0, 0, 0 );
3270 
3271  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3272 
3273  mDefaultColorButton = new QgsColorButton();
3274  mDefaultColorButton->setShowNull( true );
3275  mAllowOpacity = new QCheckBox( tr( "Allow opacity control" ) );
3276 
3277  if ( const QgsProcessingParameterColor *colorParam = dynamic_cast<const QgsProcessingParameterColor *>( definition ) )
3278  {
3279  const QColor c = QgsProcessingParameters::parameterAsColor( colorParam, colorParam->defaultValue(), context );
3280  if ( !c.isValid() )
3281  mDefaultColorButton->setToNull();
3282  else
3283  mDefaultColorButton->setColor( c );
3284  mAllowOpacity->setChecked( colorParam->opacityEnabled() );
3285  }
3286  else
3287  {
3288  mDefaultColorButton->setToNull();
3289  mAllowOpacity->setChecked( true );
3290  }
3291 
3292  vlayout->addWidget( mDefaultColorButton );
3293  vlayout->addWidget( mAllowOpacity );
3294  setLayout( vlayout );
3295 }
3296 
3297 QgsProcessingParameterDefinition *QgsProcessingColorParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3298 {
3299  auto param = qgis::make_unique< QgsProcessingParameterColor >( name, description, mDefaultColorButton->color(), mAllowOpacity->isChecked() );
3300  param->setFlags( flags );
3301  return param.release();
3302 }
3303 
3304 QgsProcessingColorWidgetWrapper::QgsProcessingColorWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3305  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3306 {
3307 
3308 }
3309 
3310 QWidget *QgsProcessingColorWidgetWrapper::createWidget()
3311 {
3312  const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor *>( parameterDefinition() );
3313  switch ( type() )
3314  {
3318  {
3319  mColorButton = new QgsColorButton( nullptr );
3320  mColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
3321 
3323  mColorButton->setShowNull( true );
3324 
3325  mColorButton->setAllowOpacity( colorParam->opacityEnabled() );
3326  mColorButton->setToolTip( parameterDefinition()->toolTip() );
3327  mColorButton->setColorDialogTitle( parameterDefinition()->description() );
3328  if ( colorParam->defaultValue().value< QColor >().isValid() )
3329  {
3330  mColorButton->setDefaultColor( colorParam->defaultValue().value< QColor >() );
3331  }
3332 
3333  connect( mColorButton, &QgsColorButton::colorChanged, this, [ = ]
3334  {
3335  emit widgetValueHasChanged( this );
3336  } );
3337 
3338  return mColorButton;
3339  }
3340  }
3341  return nullptr;
3342 }
3343 
3344 void QgsProcessingColorWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3345 {
3346  if ( mColorButton )
3347  {
3348  if ( !value.isValid() ||
3349  ( value.type() == QVariant::String && value.toString().isEmpty() )
3350  || ( value.type() == QVariant::Color && !value.value< QColor >().isValid() ) )
3351  mColorButton->setToNull();
3352  else
3353  {
3354  const QColor c = QgsProcessingParameters::parameterAsColor( parameterDefinition(), value, context );
3355  if ( !c.isValid() && mColorButton->showNull() )
3356  mColorButton->setToNull();
3357  else
3358  mColorButton->setColor( c );
3359  }
3360  }
3361 }
3362 
3363 QVariant QgsProcessingColorWidgetWrapper::widgetValue() const
3364 {
3365  if ( mColorButton )
3366  return mColorButton->isNull() ? QVariant() : mColorButton->color();
3367  else
3368  return QVariant();
3369 }
3370 
3371 QStringList QgsProcessingColorWidgetWrapper::compatibleParameterTypes() const
3372 {
3373  return QStringList()
3376 }
3377 
3378 QStringList QgsProcessingColorWidgetWrapper::compatibleOutputTypes() const
3379 {
3380  return QStringList()
3382 }
3383 
3384 QString QgsProcessingColorWidgetWrapper::modelerExpressionFormatString() const
3385 {
3386  return tr( "color style string, e.g. #ff0000 or 255,0,0" );
3387 }
3388 
3389 QString QgsProcessingColorWidgetWrapper::parameterType() const
3390 {
3392 }
3393 
3394 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingColorWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3395 {
3396  return new QgsProcessingColorWidgetWrapper( parameter, type );
3397 }
3398 
3399 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingColorWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3400 {
3401  return new QgsProcessingColorParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3402 }
3403 
3404 
3405 //
3406 // QgsProcessingCoordinateOperationWidgetWrapper
3407 //
3408 
3409 QgsProcessingCoordinateOperationParameterDefinitionWidget::QgsProcessingCoordinateOperationParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3410  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3411 {
3412  QVBoxLayout *vlayout = new QVBoxLayout();
3413  vlayout->setContentsMargins( 0, 0, 0, 0 );
3414 
3415  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3416 
3417  mDefaultLineEdit = new QLineEdit();
3418  if ( const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3419  mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( coordParam, coordParam->defaultValue(), context ) );
3420  vlayout->addWidget( mDefaultLineEdit );
3421 
3422  mSourceParamComboBox = new QComboBox();
3423  mDestParamComboBox = new QComboBox();
3424  QString initialSource;
3425  QString initialDest;
3426  QgsCoordinateReferenceSystem sourceCrs;
3428  if ( const QgsProcessingParameterCoordinateOperation *itemParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3429  {
3430  initialSource = itemParam->sourceCrsParameterName();
3431  initialDest = itemParam->destinationCrsParameterName();
3432  sourceCrs = QgsProcessingUtils::variantToCrs( itemParam->sourceCrs(), context );
3433  destCrs = QgsProcessingUtils::variantToCrs( itemParam->destinationCrs(), context );
3434  }
3435 
3436  mSourceParamComboBox->addItem( QString(), QString() );
3437  mDestParamComboBox->addItem( QString(), QString() );
3438  if ( auto *lModel = widgetContext.model() )
3439  {
3440  // populate combo box with other model input choices
3441  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
3442  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
3443  {
3444  if ( definition && it->parameterName() == definition->name() )
3445  continue;
3446 
3447  // TODO - we should probably filter this list?
3448  mSourceParamComboBox->addItem( it->parameterName(), it->parameterName() );
3449  mDestParamComboBox->addItem( it->parameterName(), it->parameterName() );
3450  if ( !initialSource.isEmpty() && initialSource == it->parameterName() )
3451  {
3452  mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3453  }
3454  if ( !initialDest.isEmpty() && initialDest == it->parameterName() )
3455  {
3456  mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3457  }
3458  }
3459  }
3460 
3461  if ( mSourceParamComboBox->count() == 1 && !initialSource.isEmpty() )
3462  {
3463  // if no source candidates found, we just add the existing one as a placeholder
3464  mSourceParamComboBox->addItem( initialSource, initialSource );
3465  mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3466  }
3467  if ( mDestParamComboBox->count() == 1 && !initialDest.isEmpty() )
3468  {
3469  // if no dest candidates found, we just add the existing one as a placeholder
3470  mDestParamComboBox->addItem( initialDest, initialDest );
3471  mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3472  }
3473 
3474  vlayout->addWidget( new QLabel( tr( "Source CRS parameter" ) ) );
3475  vlayout->addWidget( mSourceParamComboBox );
3476  vlayout->addWidget( new QLabel( tr( "Destination CRS parameter" ) ) );
3477  vlayout->addWidget( mDestParamComboBox );
3478 
3479  mStaticSourceWidget = new QgsProjectionSelectionWidget();
3480  mStaticSourceWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3481  mStaticSourceWidget->setCrs( sourceCrs );
3482  mStaticDestWidget = new QgsProjectionSelectionWidget();
3483  mStaticDestWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3484  mStaticDestWidget->setCrs( destCrs );
3485 
3486  vlayout->addWidget( new QLabel( tr( "Static source CRS" ) ) );
3487  vlayout->addWidget( mStaticSourceWidget );
3488  vlayout->addWidget( new QLabel( tr( "Static destination CRS" ) ) );
3489  vlayout->addWidget( mStaticDestWidget );
3490 
3491  setLayout( vlayout );
3492 }
3493 
3494 QgsProcessingParameterDefinition *QgsProcessingCoordinateOperationParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3495 {
3496  auto param = qgis::make_unique< QgsProcessingParameterCoordinateOperation >( name, description, mDefaultLineEdit->text(),
3497  mSourceParamComboBox->currentText(),
3498  mDestParamComboBox->currentText(),
3499  mStaticSourceWidget->crs().isValid() ? QVariant::fromValue( mStaticSourceWidget->crs() ) : QVariant(),
3500  mStaticDestWidget->crs().isValid() ? QVariant::fromValue( mStaticDestWidget->crs() ) : QVariant() );
3501  param->setFlags( flags );
3502  return param.release();
3503 }
3504 
3505 QgsProcessingCoordinateOperationWidgetWrapper::QgsProcessingCoordinateOperationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3506  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3507 {
3508 
3509 }
3510 
3511 QWidget *QgsProcessingCoordinateOperationWidgetWrapper::createWidget()
3512 {
3513  const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast< const QgsProcessingParameterCoordinateOperation *>( parameterDefinition() );
3515  mSourceCrs = QgsProcessingUtils::variantToCrs( coordParam->sourceCrs(), c );
3516  mDestCrs = QgsProcessingUtils::variantToCrs( coordParam->destinationCrs(), c );
3517  switch ( type() )
3518  {
3520  {
3521  mOperationWidget = new QgsCoordinateOperationWidget( nullptr );
3522  mOperationWidget->setShowMakeDefault( false );
3523  mOperationWidget->setShowFallbackOption( false );
3524  mOperationWidget->setToolTip( parameterDefinition()->toolTip() );
3525  mOperationWidget->setSourceCrs( mSourceCrs );
3526  mOperationWidget->setDestinationCrs( mDestCrs );
3527  mOperationWidget->setMapCanvas( mCanvas );
3528  if ( !coordParam->defaultValue().toString().isEmpty() )
3529  {
3531  deets.proj = coordParam->defaultValue().toString();
3532  mOperationWidget->setSelectedOperation( deets );
3533  }
3534 
3535  connect( mOperationWidget, &QgsCoordinateOperationWidget::operationChanged, this, [ = ]
3536  {
3537  emit widgetValueHasChanged( this );
3538  } );
3539 
3540  return mOperationWidget;
3541  }
3542 
3545  {
3546  mLineEdit = new QLineEdit();
3547  QHBoxLayout *layout = new QHBoxLayout();
3548  layout->addWidget( mLineEdit, 1 );
3549  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3550  {
3551  emit widgetValueHasChanged( this );
3552  } );
3553 
3554  QToolButton *button = new QToolButton();
3555  button->setText( QString( QChar( 0x2026 ) ) );
3556  connect( button, &QToolButton::clicked, this, [ = ]
3557  {
3558  QgsDatumTransformDialog dlg( mSourceCrs, mDestCrs, false, false, false, qMakePair( -1, -1 ), button, Qt::WindowFlags(), mLineEdit->text(), mCanvas );
3559  if ( dlg.exec() )
3560  {
3561  mLineEdit->setText( dlg.selectedDatumTransform().proj );
3562  emit widgetValueHasChanged( this );
3563  }
3564  } );
3565  layout->addWidget( button );
3566 
3567  QWidget *w = new QWidget();
3568  layout->setContentsMargins( 0, 0, 0, 0 );
3569  w->setLayout( layout );
3570  return w;
3571  }
3572 
3573  }
3574  return nullptr;
3575 }
3576 
3577 void QgsProcessingCoordinateOperationWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3578 {
3580  switch ( type() )
3581  {
3584  {
3585  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3586  {
3587  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->sourceCrsParameterName() )
3588  {
3589  setSourceCrsParameterValue( wrapper->parameterValue() );
3591  {
3592  setSourceCrsParameterValue( wrapper->parameterValue() );
3593  } );
3594  }
3595  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->destinationCrsParameterName() )
3596  {
3597  setDestinationCrsParameterValue( wrapper->parameterValue() );
3599  {
3600  setDestinationCrsParameterValue( wrapper->parameterValue() );
3601  } );
3602  }
3603  }
3604  break;
3605  }
3606 
3608  break;
3609  }
3610 }
3611 
3612 void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3613 {
3614  mCanvas = context.mapCanvas();
3615  if ( mOperationWidget )
3616  mOperationWidget->setMapCanvas( context.mapCanvas() );
3617 }
3618 
3619 void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
3620 {
3621  if ( mOperationWidget )
3622  {
3623  if ( !value.isValid() ||
3624  ( value.type() == QVariant::String ) )
3625  {
3627  deets.proj = value.toString();
3628  mOperationWidget->setSelectedOperation( deets );
3629  }
3630  }
3631  if ( mLineEdit )
3632  {
3633  if ( !value.isValid() ||
3634  ( value.type() == QVariant::String ) )
3635  {
3636  mLineEdit->setText( value.toString() );
3637  }
3638  }
3639 }
3640 
3641 QVariant QgsProcessingCoordinateOperationWidgetWrapper::widgetValue() const
3642 {
3643  if ( mOperationWidget )
3644  return mOperationWidget->selectedOperation().proj;
3645  else if ( mLineEdit )
3646  return mLineEdit->text();
3647  else
3648  return QVariant();
3649 }
3650 
3651 QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleParameterTypes() const
3652 {
3653  return QStringList()
3656 }
3657 
3658 QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleOutputTypes() const
3659 {
3660  return QStringList()
3662 }
3663 
3664 QString QgsProcessingCoordinateOperationWidgetWrapper::modelerExpressionFormatString() const
3665 {
3666  return tr( "Proj coordinate operation string, e.g. '+proj=pipeline +step +inv...'" );
3667 }
3668 
3669 void QgsProcessingCoordinateOperationWidgetWrapper::setSourceCrsParameterValue( const QVariant &value )
3670 {
3671  QgsProcessingContext *context = nullptr;
3672  std::unique_ptr< QgsProcessingContext > tmpContext;
3673  if ( mProcessingContextGenerator )
3674  context = mProcessingContextGenerator->processingContext();
3675 
3676  if ( !context )
3677  {
3678  tmpContext = qgis::make_unique< QgsProcessingContext >();
3679  context = tmpContext.get();
3680  }
3681 
3682  mSourceCrs = QgsProcessingUtils::variantToCrs( value, *context );
3683  if ( mOperationWidget )
3684  {
3685  mOperationWidget->setSourceCrs( mSourceCrs );
3686  mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
3687  }
3688 }
3689 
3690 void QgsProcessingCoordinateOperationWidgetWrapper::setDestinationCrsParameterValue( const QVariant &value )
3691 {
3692  QgsProcessingContext *context = nullptr;
3693  std::unique_ptr< QgsProcessingContext > tmpContext;
3694  if ( mProcessingContextGenerator )
3695  context = mProcessingContextGenerator->processingContext();
3696 
3697  if ( !context )
3698  {
3699  tmpContext = qgis::make_unique< QgsProcessingContext >();
3700  context = tmpContext.get();
3701  }
3702 
3703  mDestCrs = QgsProcessingUtils::variantToCrs( value, *context );
3704  if ( mOperationWidget )
3705  {
3706  mOperationWidget->setDestinationCrs( mDestCrs );
3707  mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
3708  }
3709 }
3710 
3711 QString QgsProcessingCoordinateOperationWidgetWrapper::parameterType() const
3712 {
3714 }
3715 
3716 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCoordinateOperationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3717 {
3718  return new QgsProcessingCoordinateOperationWidgetWrapper( parameter, type );
3719 }
3720 
3721 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCoordinateOperationWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3722 {
3723  return new QgsProcessingCoordinateOperationParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3724 }
3725 
3726 
3727 
3728 //
3729 // QgsProcessingFieldPanelWidget
3730 //
3731 
3732 QgsProcessingFieldPanelWidget::QgsProcessingFieldPanelWidget( QWidget *parent, const QgsProcessingParameterField *param )
3733  : QWidget( parent )
3734  , mParam( param )
3735 {
3736  QHBoxLayout *hl = new QHBoxLayout();
3737  hl->setContentsMargins( 0, 0, 0, 0 );
3738 
3739  mLineEdit = new QLineEdit();
3740  mLineEdit->setEnabled( false );
3741  hl->addWidget( mLineEdit, 1 );
3742 
3743  mToolButton = new QToolButton();
3744  mToolButton->setText( QString( QChar( 0x2026 ) ) );
3745  hl->addWidget( mToolButton );
3746 
3747  setLayout( hl );
3748 
3749  if ( mParam )
3750  {
3751  mLineEdit->setText( tr( "%1 options selected" ).arg( 0 ) );
3752  }
3753 
3754  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingFieldPanelWidget::showDialog );
3755 }
3756 
3757 void QgsProcessingFieldPanelWidget::setFields( const QgsFields &fields )
3758 {
3759  mFields = fields;
3760 }
3761 
3762 void QgsProcessingFieldPanelWidget::setValue( const QVariant &value )
3763 {
3764  if ( value.isValid() )
3765  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
3766  else
3767  mValue.clear();
3768 
3769  updateSummaryText();
3770  emit changed();
3771 }
3772 
3773 void QgsProcessingFieldPanelWidget::showDialog()
3774 {
3775  QVariantList availableOptions;
3776  QStringList fieldNames;
3777  availableOptions.reserve( mFields.size() );
3778  for ( const QgsField &field : qgis::as_const( mFields ) )
3779  {
3780  availableOptions << field.name();
3781  }
3782 
3784  if ( panel && panel->dockMode() )
3785  {
3786  QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
3787  widget->setPanelTitle( mParam->description() );
3788 
3789  widget->setValueFormatter( []( const QVariant & v ) -> QString
3790  {
3791  return v.toString();
3792  } );
3793 
3794  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
3795  {
3796  setValue( widget->selectedOptions() );
3797  } );
3798  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
3799  panel->openPanel( widget );
3800  }
3801  else
3802  {
3803  QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
3804 
3805  dlg.setValueFormatter( []( const QVariant & v ) -> QString
3806  {
3807  return v.toString();
3808  } );
3809  if ( dlg.exec() )
3810  {
3811  setValue( dlg.selectedOptions() );
3812  }
3813  }
3814 }
3815 
3816 void QgsProcessingFieldPanelWidget::updateSummaryText()
3817 {
3818  if ( mParam )
3819  mLineEdit->setText( tr( "%1 options selected" ).arg( mValue.count() ) );
3820 }
3821 
3822 
3823 //
3824 // QgsProcessingFieldWidgetWrapper
3825 //
3826 
3827 QgsProcessingFieldParameterDefinitionWidget::QgsProcessingFieldParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3828  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3829 {
3830  QVBoxLayout *vlayout = new QVBoxLayout();
3831  vlayout->setContentsMargins( 0, 0, 0, 0 );
3832 
3833  vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
3834  mParentLayerComboBox = new QComboBox();
3835 
3836  QString initialParent;
3837  if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
3838  initialParent = fieldParam->parentLayerParameterName();
3839 
3840  if ( auto *lModel = widgetContext.model() )
3841  {
3842  // populate combo box with other model input choices
3843  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
3844  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
3845  {
3846  if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
3847  {
3848  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
3849  if ( !initialParent.isEmpty() && initialParent == definition->name() )
3850  {
3851  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
3852  }
3853  }
3854  else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
3855  {
3856  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
3857  if ( !initialParent.isEmpty() && initialParent == definition->name() )
3858  {
3859  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
3860  }
3861  }
3862  }
3863  }
3864 
3865  if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
3866  {
3867  // if no parent candidates found, we just add the existing one as a placeholder
3868  mParentLayerComboBox->addItem( initialParent, initialParent );
3869  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
3870  }
3871 
3872  vlayout->addWidget( mParentLayerComboBox );
3873 
3874  vlayout->addWidget( new QLabel( tr( "Allowed data type" ) ) );
3875  mDataTypeComboBox = new QComboBox();
3876  mDataTypeComboBox->addItem( tr( "Any" ), QgsProcessingParameterField::Any );
3877  mDataTypeComboBox->addItem( tr( "Number" ), QgsProcessingParameterField::Numeric );
3878  mDataTypeComboBox->addItem( tr( "String" ), QgsProcessingParameterField::String );
3879  mDataTypeComboBox->addItem( tr( "Date/time" ), QgsProcessingParameterField::DateTime );
3880  if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
3881  mDataTypeComboBox->setCurrentIndex( mDataTypeComboBox->findData( fieldParam->dataType() ) );
3882 
3883  vlayout->addWidget( mDataTypeComboBox );
3884 
3885  mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple fields" ) );
3886  if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
3887  mAllowMultipleCheckBox->setChecked( fieldParam->allowMultiple() );
3888 
3889  vlayout->addWidget( mAllowMultipleCheckBox );
3890 
3891  mDefaultToAllCheckBox = new QCheckBox( tr( "Select all fields by default" ) );
3892  mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
3893  if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
3894  mDefaultToAllCheckBox->setChecked( fieldParam->defaultToAllFields() );
3895 
3896  vlayout->addWidget( mDefaultToAllCheckBox );
3897 
3898  connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
3899  {
3900  mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
3901  } );
3902 
3903  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3904 
3905  mDefaultLineEdit = new QLineEdit();
3906  mDefaultLineEdit->setToolTip( tr( "Default field name, or ; separated list of field names for multiple field parameters" ) );
3907  if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
3908  {
3909  const QStringList fields = QgsProcessingParameters::parameterAsFields( fieldParam, fieldParam->defaultValue(), context );
3910  mDefaultLineEdit->setText( fields.join( ';' ) );
3911  }
3912  vlayout->addWidget( mDefaultLineEdit );
3913 
3914  setLayout( vlayout );
3915 }
3916 
3917 QgsProcessingParameterDefinition *QgsProcessingFieldParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3918 {
3919  QgsProcessingParameterField::DataType dataType = static_cast< QgsProcessingParameterField::DataType >( mDataTypeComboBox->currentData().toInt() );
3920  auto param = qgis::make_unique< QgsProcessingParameterField >( name, description, mDefaultLineEdit->text(), mParentLayerComboBox->currentData().toString(), dataType, mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
3921  param->setFlags( flags );
3922  return param.release();
3923 }
3924 
3925 QgsProcessingFieldWidgetWrapper::QgsProcessingFieldWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3926  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3927 {
3928 
3929 }
3930 
3931 QWidget *QgsProcessingFieldWidgetWrapper::createWidget()
3932 {
3933  const QgsProcessingParameterField *fieldParam = dynamic_cast< const QgsProcessingParameterField *>( parameterDefinition() );
3934  switch ( type() )
3935  {
3938  {
3939  if ( fieldParam->allowMultiple() )
3940  {
3941  mPanel = new QgsProcessingFieldPanelWidget( nullptr, fieldParam );
3942  mPanel->setToolTip( parameterDefinition()->toolTip() );
3943  connect( mPanel, &QgsProcessingFieldPanelWidget::changed, this, [ = ]
3944  {
3945  emit widgetValueHasChanged( this );
3946  } );
3947  return mPanel;
3948  }
3949  else
3950  {
3951  mComboBox = new QgsFieldComboBox();
3952  mComboBox->setAllowEmptyFieldName( fieldParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
3953 
3954  if ( fieldParam->dataType() == QgsProcessingParameterField::Numeric )
3955  mComboBox->setFilters( QgsFieldProxyModel::Numeric );
3956  else if ( fieldParam->dataType() == QgsProcessingParameterField::String )
3957  mComboBox->setFilters( QgsFieldProxyModel::String );
3958  else if ( fieldParam->dataType() == QgsProcessingParameterField::DateTime )
3960 
3961  mComboBox->setToolTip( parameterDefinition()->toolTip() );
3962  connect( mComboBox, &QgsFieldComboBox::fieldChanged, this, [ = ]( const QString & )
3963  {
3964  emit widgetValueHasChanged( this );
3965  } );
3966  return mComboBox;
3967  }
3968  }
3969 
3971  {
3972  mLineEdit = new QLineEdit();
3973  mLineEdit->setToolTip( QObject::tr( "Name of field (separate field names with ; for multiple field parameters)" ) );
3974  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3975  {
3976  emit widgetValueHasChanged( this );
3977  } );
3978  return mLineEdit;
3979  }
3980 
3981  }
3982  return nullptr;
3983 }
3984 
3985 void QgsProcessingFieldWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3986 {
3988  switch ( type() )
3989  {
3992  {
3993  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3994  {
3995  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterField * >( parameterDefinition() )->parentLayerParameterName() )
3996  {
3997  setParentLayerWrapperValue( wrapper );
3999  {
4000  setParentLayerWrapperValue( wrapper );
4001  } );
4002  break;
4003  }
4004  }
4005  break;
4006  }
4007 
4009  break;
4010  }
4011 }
4012 
4013 void QgsProcessingFieldWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
4014 {
4015  // evaluate value to layer
4016  QgsProcessingContext *context = nullptr;
4017  std::unique_ptr< QgsProcessingContext > tmpContext;
4018  if ( mProcessingContextGenerator )
4019  context = mProcessingContextGenerator->processingContext();
4020 
4021  if ( !context )
4022  {
4023  tmpContext = qgis::make_unique< QgsProcessingContext >();
4024  context = tmpContext.get();
4025  }
4026 
4027  QVariant value = parentWrapper->parameterValue();
4028 
4029  if ( value.canConvert<QgsProcessingFeatureSourceDefinition>() )
4030  {
4031  // input is a QgsProcessingFeatureSourceDefinition - source from it.
4032  // this is normally discouraged, and algorithms should NEVER do this -- but in this case we can make
4033  // certain assumptions due to the fact that we're calling this outside of algorithm/model execution and all sources
4034  // should be real map layers at this stage
4035  QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
4036  value = fromVar.source;
4037  }
4038  QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), value, *context );
4039  if ( layer && layer->isValid() )
4040  {
4041  // need to grab ownership of layer if required - otherwise layer may be deleted when context
4042  // goes out of scope
4043  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
4044  if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
4045  {
4046  mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
4047  layer = mParentLayer.get();
4048  }
4049  else
4050  {
4051  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
4052  }
4053 
4054  if ( mComboBox )
4055  mComboBox->setLayer( layer );
4056  else if ( mPanel )
4057  mPanel->setFields( filterFields( layer->fields() ) );
4058  }
4059  else
4060  {
4061  std::unique_ptr< QgsProcessingFeatureSource > source( QgsProcessingParameters::parameterAsSource( parentWrapper->parameterDefinition(), value, *context ) );
4062  if ( source )
4063  {
4064  const QgsFields fields = source->fields();
4065  if ( mComboBox )
4066  mComboBox->setFields( fields );
4067  else if ( mPanel )
4068  mPanel->setFields( filterFields( fields ) );
4069  }
4070  else
4071  {
4072  if ( mComboBox )
4073  mComboBox->setLayer( nullptr );
4074  else if ( mPanel )
4075  mPanel->setFields( QgsFields() );
4076 
4077  if ( value.isValid() && widgetContext().messageBar() )
4078  {
4079  widgetContext().messageBar()->clearWidgets();
4080  widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent field could not be populated" ),
4081  Qgis::Warning, 5 );
4082  }
4083  }
4084  return;
4085  }
4086 
4087  const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4088  if ( mPanel && fieldParam->defaultToAllFields() )
4089  {
4090  QVariantList val;
4091  val.reserve( mPanel->fields().size() );
4092  for ( const QgsField &field : mPanel->fields() )
4093  val << field.name();
4094  setWidgetValue( val, *context );
4095  }
4096  else if ( fieldParam->defaultValue().isValid() )
4097  setWidgetValue( parameterDefinition()->defaultValue(), *context );
4098 }
4099 
4100 void QgsProcessingFieldWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4101 {
4102  if ( mComboBox )
4103  {
4104  if ( !value.isValid() )
4105  mComboBox->setField( QString() );
4106  else
4107  {
4108  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4109  mComboBox->setField( v );
4110  }
4111  }
4112  else if ( mPanel )
4113  {
4114  QVariantList opts;
4115  if ( value.isValid() )
4116  {
4117  const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4118  opts.reserve( v.size() );
4119  for ( const QString &i : v )
4120  opts << i;
4121  }
4122  if ( mPanel )
4123  mPanel->setValue( opts );
4124  }
4125  else if ( mLineEdit )
4126  {
4127  const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4128  if ( fieldParam->allowMultiple() )
4129  {
4130  const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4131  mLineEdit->setText( v.join( ';' ) );
4132  }
4133  else
4134  {
4135  mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
4136  }
4137  }
4138 }
4139 
4140 QVariant QgsProcessingFieldWidgetWrapper::widgetValue() const
4141 {
4142  if ( mComboBox )
4143  return mComboBox->currentField();
4144  else if ( mPanel )
4145  return mPanel->value();
4146  else if ( mLineEdit )
4147  {
4148  const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4149  if ( fieldParam->allowMultiple() )
4150  {
4151  return mLineEdit->text().split( ';' );
4152  }
4153  else
4154  return mLineEdit->text();
4155  }
4156  else
4157  return QVariant();
4158 }
4159 
4160 QStringList QgsProcessingFieldWidgetWrapper::compatibleParameterTypes() const
4161 {
4162  return QStringList()
4165 }
4166 
4167 QStringList QgsProcessingFieldWidgetWrapper::compatibleOutputTypes() const
4168 {
4169  return QStringList()
4171 }
4172 
4173 QString QgsProcessingFieldWidgetWrapper::modelerExpressionFormatString() const
4174 {
4175  return tr( "selected field names as an array of names, or semicolon separated string of options (e.g. 'fid;place_name')" );
4176 }
4177 
4178 const QgsVectorLayer *QgsProcessingFieldWidgetWrapper::linkedVectorLayer() const
4179 {
4180  if ( mComboBox && mComboBox->layer() )
4181  return mComboBox->layer();
4182 
4184 }
4185 
4186 QgsFields QgsProcessingFieldWidgetWrapper::filterFields( const QgsFields &fields ) const
4187 {
4188  const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4189  QgsFields res;
4190  for ( const QgsField &f : fields )
4191  {
4192  switch ( fieldParam->dataType() )
4193  {
4195  res.append( f );
4196  break;
4197 
4199  if ( f.isNumeric() )
4200  res.append( f );
4201  break;
4202 
4204  if ( f.type() == QVariant::String )
4205  res.append( f );
4206  break;
4207 
4209  if ( f.type() == QVariant::Date || f.type() == QVariant::Time || f.type() == QVariant::DateTime )
4210  res.append( f );
4211  break;
4212  }
4213  }
4214 
4215  return res;
4216 }
4217 
4218 QString QgsProcessingFieldWidgetWrapper::parameterType() const
4219 {
4221 }
4222 
4223 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFieldWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4224 {
4225  return new QgsProcessingFieldWidgetWrapper( parameter, type );
4226 }
4227 
4228 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFieldWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4229 {
4230  return new QgsProcessingFieldParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4231 }
4232 
4233 //
4234 // QgsProcessingMapThemeWidgetWrapper
4235 //
4236 
4237 
4238 QgsProcessingMapThemeParameterDefinitionWidget::QgsProcessingMapThemeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4239  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4240 {
4241  QVBoxLayout *vlayout = new QVBoxLayout();
4242  vlayout->setContentsMargins( 0, 0, 0, 0 );
4243 
4244  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4245 
4246  mDefaultComboBox = new QComboBox();
4247  mDefaultComboBox->addItem( QString(), QVariant( -1 ) );
4248 
4250  for ( const QString &theme : mapThemes )
4251  {
4252  mDefaultComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4253  }
4254  mDefaultComboBox->setEditable( true );
4255 
4256  if ( const QgsProcessingParameterMapTheme *themeParam = dynamic_cast<const QgsProcessingParameterMapTheme *>( definition ) )
4257  {
4258  if ( themeParam->defaultValue().isValid() )
4259  mDefaultComboBox->setCurrentText( QgsProcessingParameters::parameterAsString( themeParam, themeParam->defaultValue(), context ) );
4260  else
4261  mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4262  }
4263  else
4264  mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4265 
4266  vlayout->addWidget( mDefaultComboBox );
4267 
4268  setLayout( vlayout );
4269 }
4270 
4271 QgsProcessingParameterDefinition *QgsProcessingMapThemeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4272 {
4273  QVariant defaultVal;
4274  if ( mDefaultComboBox->currentText().isEmpty() )
4275  defaultVal = QVariant();
4276  else
4277  defaultVal = mDefaultComboBox->currentText();
4278  auto param = qgis::make_unique< QgsProcessingParameterMapTheme>( name, description, defaultVal );
4279  param->setFlags( flags );
4280  return param.release();
4281 }
4282 
4283 
4284 QgsProcessingMapThemeWidgetWrapper::QgsProcessingMapThemeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4285  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4286 {
4287 
4288 }
4289 
4290 QWidget *QgsProcessingMapThemeWidgetWrapper::createWidget()
4291 {
4292  const QgsProcessingParameterMapTheme *themeParam = dynamic_cast< const QgsProcessingParameterMapTheme *>( parameterDefinition() );
4293 
4294  mComboBox = new QComboBox();
4295 
4297  mComboBox->addItem( tr( "[Not selected]" ), QVariant( -1 ) );
4298 
4299  const QStringList mapThemes = widgetContext().project() ? widgetContext().project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
4300  for ( const QString &theme : mapThemes )
4301  {
4302  mComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4303  }
4304 
4305  switch ( type() )
4306  {
4309  break;
4310 
4312  mComboBox->setEditable( true );
4313  break;
4314  }
4315 
4316  mComboBox->setToolTip( parameterDefinition()->toolTip() );
4317  connect( mComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, [ = ]( int )
4318  {
4319  emit widgetValueHasChanged( this );
4320  } );
4321 
4322  return mComboBox;
4323 }
4324 
4325 void QgsProcessingMapThemeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4326 {
4327  const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4328 
4329  if ( !value.isValid() )
4330  mComboBox->setCurrentIndex( mComboBox->findData( QVariant( -1 ) ) );
4331  else
4332  {
4333  if ( mComboBox->isEditable() && mComboBox->findData( v ) == -1 )
4334  {
4335  const QString prev = mComboBox->currentText();
4336  mComboBox->setCurrentText( v );
4337  if ( prev != v )
4338  emit widgetValueHasChanged( this );
4339  }
4340  else
4341  mComboBox->setCurrentIndex( mComboBox->findData( v ) );
4342  }
4343 }
4344 
4345 QVariant QgsProcessingMapThemeWidgetWrapper::widgetValue() const
4346 {
4347  if ( mComboBox )
4348  return mComboBox->currentData().toInt() == -1 ? QVariant() :
4349  !mComboBox->currentData().isValid() && mComboBox->isEditable() ? mComboBox->currentText().isEmpty() ? QVariant() : QVariant( mComboBox->currentText() )
4350  : mComboBox->currentData();
4351  else
4352  return QVariant();
4353 }
4354 
4355 QStringList QgsProcessingMapThemeWidgetWrapper::compatibleParameterTypes() const
4356 {
4357  return QStringList()
4360 }
4361 
4362 QStringList QgsProcessingMapThemeWidgetWrapper::compatibleOutputTypes() const
4363 {
4364  return QStringList()
4366 }
4367 
4368 QString QgsProcessingMapThemeWidgetWrapper::modelerExpressionFormatString() const
4369 {
4370  return tr( "map theme as a string value (e.g. 'base maps')" );
4371 }
4372 
4373 QString QgsProcessingMapThemeWidgetWrapper::parameterType() const
4374 {
4376 }
4377 
4378 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapThemeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4379 {
4380  return new QgsProcessingMapThemeWidgetWrapper( parameter, type );
4381 }
4382 
4383 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapThemeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4384 {
4385  return new QgsProcessingMapThemeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4386 }
4387 
4388 
4389 
4390 //
4391 // QgsProcessingDateTimeWidgetWrapper
4392 //
4393 
4394 
4395 QgsProcessingDateTimeParameterDefinitionWidget::QgsProcessingDateTimeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4396  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4397 {
4398  QVBoxLayout *vlayout = new QVBoxLayout();
4399  vlayout->setContentsMargins( 0, 0, 0, 0 );
4400 
4401  vlayout->addWidget( new QLabel( tr( "Type" ) ) );
4402 
4403  mTypeComboBox = new QComboBox();
4404  mTypeComboBox->addItem( tr( "Date and Time" ), QgsProcessingParameterDateTime::DateTime );
4405  mTypeComboBox->addItem( tr( "Date" ), QgsProcessingParameterDateTime::Date );
4406  mTypeComboBox->addItem( tr( "Time" ), QgsProcessingParameterDateTime::Time );
4407  if ( const QgsProcessingParameterDateTime *datetimeParam = dynamic_cast<const QgsProcessingParameterDateTime *>( definition ) )
4408  mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( datetimeParam->dataType() ) );
4409  else
4410  mTypeComboBox->setCurrentIndex( 0 );
4411  vlayout->addWidget( mTypeComboBox );
4412 
4413  setLayout( vlayout );
4414 }
4415 
4416 QgsProcessingParameterDefinition *QgsProcessingDateTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4417 {
4418  auto param = qgis::make_unique< QgsProcessingParameterDateTime >( name, description );
4419  param->setDataType( static_cast< QgsProcessingParameterDateTime::Type >( mTypeComboBox->currentData().toInt() ) );
4420  param->setFlags( flags );
4421  return param.release();
4422 }
4423 
4424 
4425 QgsProcessingDateTimeWidgetWrapper::QgsProcessingDateTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4426  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4427 {
4428 
4429 }
4430 
4431 QWidget *QgsProcessingDateTimeWidgetWrapper::createWidget()
4432 {
4433  const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
4434 
4435  QgsDateTimeEdit *widget = nullptr;
4436  switch ( dateTimeParam->dataType() )
4437  {
4439  mDateTimeEdit = new QgsDateTimeEdit();
4440  widget = mDateTimeEdit;
4441  break;
4442 
4444  mDateEdit = new QgsDateEdit();
4445  widget = mDateEdit;
4446  break;
4447 
4449  mTimeEdit = new QgsTimeEdit();
4450  widget = mTimeEdit;
4451  break;
4452  }
4453 
4454  if ( dateTimeParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
4455  {
4456  widget->setNullRepresentation( tr( "[Not selected]" ) );
4457  widget->setAllowNull( true );
4458  }
4459  else
4460  {
4461  widget->setAllowNull( false );
4462  }
4463  widget->setToolTip( parameterDefinition()->toolTip() );
4464 
4465  if ( mDateTimeEdit )
4466  {
4467  connect( mDateTimeEdit, &QgsDateTimeEdit::valueChanged, this, [ = ]( const QDateTime & )
4468  {
4469  emit widgetValueHasChanged( this );
4470  } );
4471  }
4472  else if ( mDateEdit )
4473  {
4474  connect( mDateEdit, &QgsDateEdit::dateValueChanged, this, [ = ]( const QDate & )
4475  {
4476  emit widgetValueHasChanged( this );
4477  } );
4478  }
4479  else if ( mTimeEdit )
4480  {
4481  connect( mTimeEdit, &QgsTimeEdit::timeValueChanged, this, [ = ]( const QTime & )
4482  {
4483  emit widgetValueHasChanged( this );
4484  } );
4485  }
4486 
4487  return widget;
4488 }
4489 
4490 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDateTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4491 {
4492  return new QgsProcessingDateTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4493 }
4494 
4495 void QgsProcessingDateTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4496 {
4497  if ( mDateTimeEdit )
4498  {
4499  mDateTimeEdit->setDateTime( QgsProcessingParameters::parameterAsDateTime( parameterDefinition(), value, context ) );
4500  }
4501  else if ( mDateEdit )
4502  {
4503  mDateEdit->setDate( QgsProcessingParameters::parameterAsDate( parameterDefinition(), value, context ) );
4504  }
4505  else if ( mTimeEdit )
4506  {
4507  mTimeEdit->setTime( QgsProcessingParameters::parameterAsTime( parameterDefinition(), value, context ) );
4508  }
4509 }
4510 
4511 QVariant QgsProcessingDateTimeWidgetWrapper::widgetValue() const
4512 {
4513  if ( mDateTimeEdit )
4514  return !mDateTimeEdit->dateTime().isNull() && mDateTimeEdit->dateTime().isValid() ? QVariant( mDateTimeEdit->dateTime() ) : QVariant();
4515  else if ( mDateEdit )
4516  return !mDateEdit->date().isNull() && mDateEdit->date().isValid() ? QVariant( mDateEdit->date() ) : QVariant();
4517  else if ( mTimeEdit )
4518  return !mTimeEdit->time().isNull() && mTimeEdit->time().isValid() ? QVariant( mTimeEdit->time() ) : QVariant();
4519  else
4520  return QVariant();
4521 }
4522 
4523 QStringList QgsProcessingDateTimeWidgetWrapper::compatibleParameterTypes() const
4524 {
4525  return QStringList()
4528 }
4529 
4530 QStringList QgsProcessingDateTimeWidgetWrapper::compatibleOutputTypes() const
4531 {
4532  return QStringList()
4534 }
4535 
4536 QString QgsProcessingDateTimeWidgetWrapper::modelerExpressionFormatString() const
4537 {
4538  const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
4539  if ( dateTimeParam )
4540  {
4541  switch ( dateTimeParam->dataType() )
4542  {
4544  return tr( "datetime value, or a ISO string representation of a datetime" );
4545 
4547  return tr( "date value, or a ISO string representation of a date" );
4548 
4550  return tr( "time value, or a ISO string representation of a time" );
4551  }
4552  }
4553  return QString();
4554 }
4555 
4556 QString QgsProcessingDateTimeWidgetWrapper::parameterType() const
4557 {
4559 }
4560 
4561 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDateTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4562 {
4563  return new QgsProcessingDateTimeWidgetWrapper( parameter, type );
4564 }
4565 
4566 
4567 
4568 //
4569 // QgsProcessingProviderConnectionWidgetWrapper
4570 //
4571 
4572 QgsProcessingProviderConnectionParameterDefinitionWidget::QgsProcessingProviderConnectionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4573  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4574 {
4575  const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( definition );
4576 
4577  QVBoxLayout *vlayout = new QVBoxLayout();
4578  vlayout->setContentsMargins( 0, 0, 0, 0 );
4579 
4580  vlayout->addWidget( new QLabel( tr( "Provider" ) ) );
4581  mProviderComboBox = new QComboBox();
4582  mProviderComboBox->addItem( QObject::tr( "Postgres" ), QStringLiteral( "postgres" ) );
4583  mProviderComboBox->addItem( QObject::tr( "GeoPackage" ), QStringLiteral( "ogr" ) );
4584  mProviderComboBox->addItem( QObject::tr( "Spatialite" ), QStringLiteral( "spatialite" ) );
4585 
4586  vlayout->addWidget( mProviderComboBox );
4587 
4588  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4589 
4590  mDefaultEdit = new QLineEdit();
4591  vlayout->addWidget( mDefaultEdit );
4592  setLayout( vlayout );
4593 
4594  if ( connectionParam )
4595  {
4596  mProviderComboBox->setCurrentIndex( mProviderComboBox->findData( connectionParam->providerId() ) );
4597  mDefaultEdit->setText( connectionParam->defaultValue().toString() );
4598  }
4599 }
4600 
4601 QgsProcessingParameterDefinition *QgsProcessingProviderConnectionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4602 {
4603  QVariant defaultVal;
4604  if ( mDefaultEdit->text().isEmpty() )
4605  defaultVal = QVariant();
4606  else
4607  defaultVal = mDefaultEdit->text();
4608  auto param = qgis::make_unique< QgsProcessingParameterProviderConnection>( name, description, mProviderComboBox->currentData().toString(), defaultVal );
4609  param->setFlags( flags );
4610  return param.release();
4611 }
4612 
4613 
4614 QgsProcessingProviderConnectionWidgetWrapper::QgsProcessingProviderConnectionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4615  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4616 {
4617 
4618 }
4619 
4620 QWidget *QgsProcessingProviderConnectionWidgetWrapper::createWidget()
4621 {
4622  const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( parameterDefinition() );
4623 
4624  mProviderComboBox = new QgsProviderConnectionComboBox( connectionParam->providerId() );
4625  if ( connectionParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
4626  mProviderComboBox->setAllowEmptyConnection( true );
4627 
4628  switch ( type() )
4629  {
4632  break;
4634  mProviderComboBox->setEditable( true );
4635  break;
4636  }
4637 
4638  mProviderComboBox->setToolTip( parameterDefinition()->toolTip() );
4639  connect( mProviderComboBox, &QgsProviderConnectionComboBox::currentTextChanged, this, [ = ]( const QString & )
4640  {
4641  if ( mBlockSignals )
4642  return;
4643 
4644  emit widgetValueHasChanged( this );
4645  } );
4646 
4647  return mProviderComboBox;
4648 }
4649 
4650 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingProviderConnectionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4651 {
4652  return new QgsProcessingProviderConnectionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4653 }
4654 
4655 void QgsProcessingProviderConnectionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4656 {
4657  const QString v = QgsProcessingParameters::parameterAsConnectionName( parameterDefinition(), value, context );
4658 
4659  if ( !value.isValid() )
4660  mProviderComboBox->setCurrentIndex( -1 );
4661  else
4662  {
4663  if ( mProviderComboBox->isEditable() )
4664  {
4665  const QString prev = mProviderComboBox->currentText();
4666  mBlockSignals++;
4667  mProviderComboBox->setConnection( v );
4668  mProviderComboBox->setCurrentText( v );
4669 
4670  mBlockSignals--;
4671  if ( prev != v )
4672  emit widgetValueHasChanged( this );
4673  }
4674  else
4675  mProviderComboBox->setConnection( v );
4676  }
4677 }
4678 
4679 QVariant QgsProcessingProviderConnectionWidgetWrapper::widgetValue() const
4680 {
4681  if ( mProviderComboBox )
4682  if ( mProviderComboBox->isEditable() )
4683  return mProviderComboBox->currentText().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentText() );
4684  else
4685  return mProviderComboBox->currentConnection().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentConnection() );
4686  else
4687  return QVariant();
4688 }
4689 
4690 QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleParameterTypes() const
4691 {
4692  return QStringList()
4696 }
4697 
4698 QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleOutputTypes() const
4699 {
4700  return QStringList()
4702 }
4703 
4704 QString QgsProcessingProviderConnectionWidgetWrapper::modelerExpressionFormatString() const
4705 {
4706  return tr( "connection name as a string value" );
4707 }
4708 
4709 QString QgsProcessingProviderConnectionWidgetWrapper::parameterType() const
4710 {
4712 }
4713 
4714 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingProviderConnectionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4715 {
4716  return new QgsProcessingProviderConnectionWidgetWrapper( parameter, type );
4717 }
4718 
4719 
4720 
4721 
4722 //
4723 // QgsProcessingDatabaseSchemaWidgetWrapper
4724 //
4725 
4726 QgsProcessingDatabaseSchemaParameterDefinitionWidget::QgsProcessingDatabaseSchemaParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4727  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4728 {
4729  const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( definition );
4730 
4731  QVBoxLayout *vlayout = new QVBoxLayout();
4732  vlayout->setContentsMargins( 0, 0, 0, 0 );
4733 
4734  mConnectionParamComboBox = new QComboBox();
4735  QString initialConnection;
4736  if ( schemaParam )
4737  {
4738  initialConnection = schemaParam->parentConnectionParameterName();
4739  }
4740 
4741  if ( auto *lModel = widgetContext.model() )
4742  {
4743  // populate combo box with other model input choices
4744  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4745  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4746  {
4747  if ( definition && it->parameterName() == definition->name() )
4748  continue;
4749 
4750  if ( !dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
4751  continue;
4752 
4753  mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
4754  if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
4755  {
4756  mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
4757  }
4758  }
4759  }
4760 
4761  if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
4762  {
4763  // if no candidates found, we just add the existing one as a placeholder
4764  mConnectionParamComboBox->addItem( initialConnection, initialConnection );
4765  mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
4766  }
4767 
4768  vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
4769  vlayout->addWidget( mConnectionParamComboBox );
4770 
4771  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4772 
4773  mDefaultEdit = new QLineEdit();
4774  vlayout->addWidget( mDefaultEdit );
4775  setLayout( vlayout );
4776 
4777  if ( schemaParam )
4778  {
4779  mDefaultEdit->setText( schemaParam->defaultValue().toString() );
4780  }
4781 }
4782 
4783 QgsProcessingParameterDefinition *QgsProcessingDatabaseSchemaParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4784 {
4785  QVariant defaultVal;
4786  if ( mDefaultEdit->text().isEmpty() )
4787  defaultVal = QVariant();
4788  else
4789  defaultVal = mDefaultEdit->text();
4790  auto param = qgis::make_unique< QgsProcessingParameterDatabaseSchema>( name, description, mConnectionParamComboBox->currentData().toString(), defaultVal );
4791  param->setFlags( flags );
4792  return param.release();
4793 }
4794 
4795 
4796 QgsProcessingDatabaseSchemaWidgetWrapper::QgsProcessingDatabaseSchemaWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4797  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4798 {
4799 
4800 }
4801 
4802 QWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createWidget()
4803 {
4804  const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( parameterDefinition() );
4805 
4806  mSchemaComboBox = new QgsDatabaseSchemaComboBox( QString(), QString() );
4808  mSchemaComboBox->setAllowEmptySchema( true );
4809 
4810  switch ( type() )
4811  {
4814  break;
4816  mSchemaComboBox->comboBox()->setEditable( true );
4817  break;
4818  }
4819 
4820  mSchemaComboBox->setToolTip( parameterDefinition()->toolTip() );
4821  connect( mSchemaComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
4822  {
4823  if ( mBlockSignals )
4824  return;
4825 
4826  emit widgetValueHasChanged( this );
4827  } );
4828 
4829  return mSchemaComboBox;
4830 }
4831 
4832 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4833 {
4834  return new QgsProcessingDatabaseSchemaParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4835 }
4836 
4837 void QgsProcessingDatabaseSchemaWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
4838 {
4839  // evaluate value to connection
4840  QgsProcessingContext *context = nullptr;
4841  std::unique_ptr< QgsProcessingContext > tmpContext;
4842  if ( mProcessingContextGenerator )
4843  context = mProcessingContextGenerator->processingContext();
4844 
4845  if ( !context )
4846  {
4847  tmpContext = qgis::make_unique< QgsProcessingContext >();
4848  context = tmpContext.get();
4849  }
4850 
4851  const QVariant value = parentWrapper->parameterValue();
4852  const QString connection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
4853 
4854  if ( mSchemaComboBox )
4855  mSchemaComboBox->setConnectionName( connection, dynamic_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId() );
4856 
4857  const QgsProcessingParameterDatabaseSchema *schemaParam = static_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() );
4858  if ( schemaParam->defaultValue().isValid() )
4859  setWidgetValue( parameterDefinition()->defaultValue(), *context );
4860 }
4861 
4862 void QgsProcessingDatabaseSchemaWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4863 {
4864  const QString v = QgsProcessingParameters::parameterAsSchema( parameterDefinition(), value, context );
4865 
4866  if ( !value.isValid() )
4867  mSchemaComboBox->comboBox()->setCurrentIndex( -1 );
4868  else
4869  {
4870  if ( mSchemaComboBox->comboBox()->isEditable() )
4871  {
4872  const QString prev = mSchemaComboBox->comboBox()->currentText();
4873  mBlockSignals++;
4874  mSchemaComboBox->setSchema( v );
4875  mSchemaComboBox->comboBox()->setCurrentText( v );
4876 
4877  mBlockSignals--;
4878  if ( prev != v )
4879  emit widgetValueHasChanged( this );
4880  }
4881  else
4882  mSchemaComboBox->setSchema( v );
4883  }
4884 }
4885 
4886 QVariant QgsProcessingDatabaseSchemaWidgetWrapper::widgetValue() const
4887 {
4888  if ( mSchemaComboBox )
4889  if ( mSchemaComboBox->comboBox()->isEditable() )
4890  return mSchemaComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->comboBox()->currentText() );
4891  else
4892  return mSchemaComboBox->currentSchema().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->currentSchema() );
4893  else
4894  return QVariant();
4895 }
4896 
4897 QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleParameterTypes() const
4898 {
4899  return QStringList()
4903 }
4904 
4905 QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleOutputTypes() const
4906 {
4907  return QStringList()
4909 }
4910 
4911 QString QgsProcessingDatabaseSchemaWidgetWrapper::modelerExpressionFormatString() const
4912 {
4913  return tr( "database schema name as a string value" );
4914 }
4915 
4916 QString QgsProcessingDatabaseSchemaWidgetWrapper::parameterType() const
4917 {
4919 }
4920 
4921 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseSchemaWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4922 {
4923  return new QgsProcessingDatabaseSchemaWidgetWrapper( parameter, type );
4924 }
4925 
4926 void QgsProcessingDatabaseSchemaWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
4927 {
4929  switch ( type() )
4930  {
4933  {
4934  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
4935  {
4936  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() )->parentConnectionParameterName() )
4937  {
4938  setParentConnectionWrapperValue( wrapper );
4940  {
4941  setParentConnectionWrapperValue( wrapper );
4942  } );
4943  break;
4944  }
4945  }
4946  break;
4947  }
4948 
4950  break;
4951  }
4952 }
4953 
4954 
4955 
4956 //
4957 // QgsProcessingDatabaseTableWidgetWrapper
4958 //
4959 
4960 QgsProcessingDatabaseTableParameterDefinitionWidget::QgsProcessingDatabaseTableParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4961  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4962 {
4963  const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( definition );
4964 
4965  QVBoxLayout *vlayout = new QVBoxLayout();
4966  vlayout->setContentsMargins( 0, 0, 0, 0 );
4967 
4968  mConnectionParamComboBox = new QComboBox();
4969  mSchemaParamComboBox = new QComboBox();
4970  QString initialConnection;
4971  QString initialSchema;
4972  if ( tableParam )
4973  {
4974  initialConnection = tableParam->parentConnectionParameterName();
4975  initialSchema = tableParam->parentSchemaParameterName();
4976  }
4977 
4978  if ( auto *lModel = widgetContext.model() )
4979  {
4980  // populate combo box with other model input choices
4981  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4982  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4983  {
4984  if ( definition && it->parameterName() == definition->name() )
4985  continue;
4986 
4987  if ( dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
4988  {
4989  mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
4990  if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
4991  {
4992  mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
4993  }
4994  }
4995  else if ( dynamic_cast< const QgsProcessingParameterDatabaseSchema * >( lModel->parameterDefinition( it->parameterName() ) ) )
4996  {
4997  mSchemaParamComboBox->addItem( it->parameterName(), it->parameterName() );
4998  if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
4999  {
5000  mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5001  }
5002  }
5003  }
5004  }
5005 
5006  if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5007  {
5008  // if no candidates found, we just add the existing one as a placeholder
5009  mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5010  mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5011  }
5012 
5013  if ( mSchemaParamComboBox->count() == 0 && !initialSchema.isEmpty() )
5014  {
5015  // if no candidates found, we just add the existing one as a placeholder
5016  mSchemaParamComboBox->addItem( initialSchema, initialSchema );
5017  mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5018  }
5019 
5020  vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5021  vlayout->addWidget( mConnectionParamComboBox );
5022 
5023  vlayout->addWidget( new QLabel( tr( "Database schema parameter" ) ) );
5024  vlayout->addWidget( mSchemaParamComboBox );
5025 
5026  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5027 
5028  mDefaultEdit = new QLineEdit();
5029  vlayout->addWidget( mDefaultEdit );
5030  setLayout( vlayout );
5031 
5032  if ( tableParam )
5033  {
5034  mDefaultEdit->setText( tableParam->defaultValue().toString() );
5035  }
5036 }
5037 
5038 QgsProcessingParameterDefinition *QgsProcessingDatabaseTableParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5039 {
5040  QVariant defaultVal;
5041  if ( mDefaultEdit->text().isEmpty() )
5042  defaultVal = QVariant();
5043  else
5044  defaultVal = mDefaultEdit->text();
5045  auto param = qgis::make_unique< QgsProcessingParameterDatabaseTable>( name, description,
5046  mConnectionParamComboBox->currentData().toString(),
5047  mSchemaParamComboBox->currentData().toString(),
5048  defaultVal );
5049  param->setFlags( flags );
5050  return param.release();
5051 }
5052 
5053 
5054 QgsProcessingDatabaseTableWidgetWrapper::QgsProcessingDatabaseTableWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5055  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5056 {
5057 
5058 }
5059 
5060 QWidget *QgsProcessingDatabaseTableWidgetWrapper::createWidget()
5061 {
5062  const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( parameterDefinition() );
5063 
5064  mTableComboBox = new QgsDatabaseTableComboBox( QString(), QString() );
5066  mTableComboBox->setAllowEmptyTable( true );
5067 
5068  if ( type() == QgsProcessingGui::Modeler || tableParam->allowNewTableNames() )
5069  mTableComboBox->comboBox()->setEditable( true );
5070 
5071  mTableComboBox->setToolTip( parameterDefinition()->toolTip() );
5072  connect( mTableComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5073  {
5074  if ( mBlockSignals )
5075  return;
5076 
5077  emit widgetValueHasChanged( this );
5078  } );
5079 
5080  return mTableComboBox;
5081 }
5082 
5083 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseTableWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5084 {
5085  return new QgsProcessingDatabaseTableParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5086 }
5087 
5088 void QgsProcessingDatabaseTableWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5089 {
5090  // evaluate value to connection
5091  QgsProcessingContext *context = nullptr;
5092  std::unique_ptr< QgsProcessingContext > tmpContext;
5093  if ( mProcessingContextGenerator )
5094  context = mProcessingContextGenerator->processingContext();
5095 
5096  if ( !context )
5097  {
5098  tmpContext = qgis::make_unique< QgsProcessingContext >();
5099  context = tmpContext.get();
5100  }
5101 
5102  QVariant value = parentWrapper->parameterValue();
5103  mConnection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5104  mProvider = dynamic_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId();
5105  if ( mTableComboBox && !mSchema.isEmpty() )
5106  {
5107  mTableComboBox->setSchema( mSchema );
5108  mTableComboBox->setConnectionName( mConnection, mProvider );
5109 
5110  const QgsProcessingParameterDatabaseTable *tableParam = static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5111  if ( tableParam->defaultValue().isValid() )
5112  setWidgetValue( parameterDefinition()->defaultValue(), *context );
5113  }
5114 }
5115 
5116 void QgsProcessingDatabaseTableWidgetWrapper::setParentSchemaWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5117 {
5118  // evaluate value to schema
5119  QgsProcessingContext *context = nullptr;
5120  std::unique_ptr< QgsProcessingContext > tmpContext;
5121  if ( mProcessingContextGenerator )
5122  context = mProcessingContextGenerator->processingContext();
5123 
5124  if ( !context )
5125  {
5126  tmpContext = qgis::make_unique< QgsProcessingContext >();
5127  context = tmpContext.get();
5128  }
5129 
5130  QVariant value = parentWrapper->parameterValue();
5131  mSchema = value.isValid() ? QgsProcessingParameters::parameterAsSchema( parentWrapper->parameterDefinition(), value, *context ) : QString();
5132 
5133  if ( mTableComboBox && !mSchema.isEmpty() && !mConnection.isEmpty() )
5134  {
5135  mTableComboBox->setSchema( mSchema );
5136  mTableComboBox->setConnectionName( mConnection, mProvider );
5137 
5138  const QgsProcessingParameterDatabaseTable *tableParam = static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5139  if ( tableParam->defaultValue().isValid() )
5140  setWidgetValue( parameterDefinition()->defaultValue(), *context );
5141  }
5142 
5143 }
5144 
5145 void QgsProcessingDatabaseTableWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5146 {
5147  const QString v = QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition(), value, context );
5148 
5149  if ( !value.isValid() )
5150  mTableComboBox->comboBox()->setCurrentIndex( -1 );
5151  else
5152  {
5153  if ( mTableComboBox->comboBox()->isEditable() )
5154  {
5155  const QString prev = mTableComboBox->comboBox()->currentText();
5156  mBlockSignals++;
5157  mTableComboBox->setTable( v );
5158  mTableComboBox->comboBox()->setCurrentText( v );
5159 
5160  mBlockSignals--;
5161  if ( prev != v )
5162  emit widgetValueHasChanged( this );
5163  }
5164  else
5165  mTableComboBox->setTable( v );
5166  }
5167 }
5168 
5169 QVariant QgsProcessingDatabaseTableWidgetWrapper::widgetValue() const
5170 {
5171  if ( mTableComboBox )
5172  if ( mTableComboBox->comboBox()->isEditable() )
5173  return mTableComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mTableComboBox->comboBox()->currentText() );
5174  else
5175  return mTableComboBox->currentTable().isEmpty() ? QVariant() : QVariant( mTableComboBox->currentTable() );
5176  else
5177  return QVariant();
5178 }
5179 
5180 QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleParameterTypes() const
5181 {
5182  return QStringList()
5186 }
5187 
5188 QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleOutputTypes() const
5189 {
5190  return QStringList()
5192 }
5193 
5194 QString QgsProcessingDatabaseTableWidgetWrapper::modelerExpressionFormatString() const
5195 {
5196  return tr( "database table name as a string value" );
5197 }
5198 
5199 QString QgsProcessingDatabaseTableWidgetWrapper::parameterType() const
5200 {
5202 }
5203 
5204 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseTableWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5205 {
5206  return new QgsProcessingDatabaseTableWidgetWrapper( parameter, type );
5207 }
5208 
5209 void QgsProcessingDatabaseTableWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5210 {
5212  switch ( type() )
5213  {
5216  {
5217  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5218  {
5219  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentConnectionParameterName() )
5220  {
5221  setParentConnectionWrapperValue( wrapper );
5223  {
5224  setParentConnectionWrapperValue( wrapper );
5225  } );
5226  }
5227  else if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentSchemaParameterName() )
5228  {
5229  setParentSchemaWrapperValue( wrapper );
5231  {
5232  setParentSchemaWrapperValue( wrapper );
5233  } );
5234  }
5235  }
5236  break;
5237  }
5238 
5240  break;
5241  }
5242 }
5243 
5244 
5245 //
5246 // QgsProcessingExtentWidgetWrapper
5247 //
5248 
5249 QgsProcessingExtentParameterDefinitionWidget::QgsProcessingExtentParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5250  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5251 {
5252  QVBoxLayout *vlayout = new QVBoxLayout();
5253  vlayout->setContentsMargins( 0, 0, 0, 0 );
5254 
5255  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5256 
5257  mDefaultWidget = new QgsExtentWidget();
5258  mDefaultWidget->setNullValueAllowed( true, tr( "Not set" ) );
5259  if ( const QgsProcessingParameterExtent *extentParam = dynamic_cast<const QgsProcessingParameterExtent *>( definition ) )
5260  {
5261  if ( extentParam->defaultValue().isValid() )
5262  {
5263  QgsRectangle rect = QgsProcessingParameters::parameterAsExtent( extentParam, extentParam->defaultValue(), context );
5264  QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsExtentCrs( extentParam, extentParam->defaultValue(), context );
5265  mDefaultWidget->setCurrentExtent( rect, crs );
5266  mDefaultWidget->setOutputExtentFromCurrent();
5267  }
5268  else
5269  {
5270  mDefaultWidget->clear();
5271  }
5272  }
5273 
5274  vlayout->addWidget( mDefaultWidget );
5275  setLayout( vlayout );
5276 }
5277 
5278 QgsProcessingParameterDefinition *QgsProcessingExtentParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5279 {
5280  const QString defaultVal = mDefaultWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5281  QString::number( mDefaultWidget->outputExtent().xMinimum(), 'f', 9 ),
5282  QString::number( mDefaultWidget->outputExtent().xMaximum(), 'f', 9 ),
5283  QString::number( mDefaultWidget->outputExtent().yMinimum(), 'f', 9 ),
5284  QString::number( mDefaultWidget->outputExtent().yMaximum(), 'f', 9 ),
5285  mDefaultWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mDefaultWidget->outputCrs().authid() ) : QString()
5286  ) : QString();
5287  auto param = qgis::make_unique< QgsProcessingParameterExtent >( name, description, !defaultVal.isEmpty() ? QVariant( defaultVal ) : QVariant() );
5288  param->setFlags( flags );
5289  return param.release();
5290 }
5291 
5292 
5293 
5294 QgsProcessingExtentWidgetWrapper::QgsProcessingExtentWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5295  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5296 {
5297 
5298 }
5299 
5300 QWidget *QgsProcessingExtentWidgetWrapper::createWidget()
5301 {
5302  const QgsProcessingParameterExtent *extentParam = dynamic_cast< const QgsProcessingParameterExtent *>( parameterDefinition() );
5303  switch ( type() )
5304  {
5308  {
5309  mExtentWidget = new QgsExtentWidget( nullptr );
5310  if ( widgetContext().mapCanvas() )
5311  mExtentWidget->setMapCanvas( widgetContext().mapCanvas() );
5312 
5314  mExtentWidget->setNullValueAllowed( true, tr( "Not set" ) );
5315 
5316  mExtentWidget->setToolTip( parameterDefinition()->toolTip() );
5317 
5318  connect( mExtentWidget, &QgsExtentWidget::extentChanged, this, [ = ]
5319  {
5320  emit widgetValueHasChanged( this );
5321  } );
5322 
5323  if ( mDialog && type() != QgsProcessingGui::Modeler )
5324  setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
5325 
5326  return mExtentWidget;
5327  }
5328  }
5329  return nullptr;
5330 }
5331 
5332 void QgsProcessingExtentWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5333 {
5335  if ( mExtentWidget && context.mapCanvas() && type() != QgsProcessingGui::Modeler )
5336  mExtentWidget->setMapCanvas( context.mapCanvas() );
5337 }
5338 
5339 void QgsProcessingExtentWidgetWrapper::setDialog( QDialog *dialog )
5340 {
5341  mDialog = dialog;
5342  if ( mExtentWidget && mDialog && type() != QgsProcessingGui::Modeler )
5343  {
5344  connect( mExtentWidget, &QgsExtentWidget::toggleDialogVisibility, mDialog, [ = ]( bool visible )
5345  {
5346  if ( !visible )
5347  mDialog->showMinimized();
5348  else
5349  {
5350  mDialog->showNormal();
5351  mDialog->raise();
5352  mDialog->activateWindow();
5353  }
5354  } );
5355  }
5357 }
5358 
5359 void QgsProcessingExtentWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5360 {
5361  if ( mExtentWidget )
5362  {
5363  if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
5364  mExtentWidget->clear();
5365  else
5366  {
5367  QgsRectangle r = QgsProcessingParameters::parameterAsExtent( parameterDefinition(), value, context );
5368  QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
5369  mExtentWidget->setCurrentExtent( r, crs );
5370  mExtentWidget->setOutputExtentFromUser( r, crs );
5371  }
5372  }
5373 }
5374 
5375 QVariant QgsProcessingExtentWidgetWrapper::widgetValue() const
5376 {
5377  if ( mExtentWidget )
5378  {
5379  const QString val = mExtentWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5380  QString::number( mExtentWidget->outputExtent().xMinimum(), 'f', 9 ),
5381  QString::number( mExtentWidget->outputExtent().xMaximum(), 'f', 9 ),
5382  QString::number( mExtentWidget->outputExtent().yMinimum(), 'f', 9 ),
5383  QString::number( mExtentWidget->outputExtent().yMaximum(), 'f', 9 ),
5384  mExtentWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mExtentWidget->outputCrs().authid() ) : QString()
5385  ) : QString();
5386 
5387  return val.isEmpty() ? QVariant() : QVariant( val );
5388  }
5389  else
5390  return QVariant();
5391 }
5392 
5393 QStringList QgsProcessingExtentWidgetWrapper::compatibleParameterTypes() const
5394 {
5395  return QStringList()
5403 
5404 }
5405 
5406 QStringList QgsProcessingExtentWidgetWrapper::compatibleOutputTypes() const
5407 {
5408  return QStringList()
5413 }
5414 
5415 QString QgsProcessingExtentWidgetWrapper::modelerExpressionFormatString() const
5416 {
5417  return tr( "string of the format 'x min,x max,y min,y max' or a geometry value (bounding box is used)" );
5418 }
5419 
5420 QString QgsProcessingExtentWidgetWrapper::parameterType() const
5421 {
5423 }
5424 
5425 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExtentWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5426 {
5427  return new QgsProcessingExtentWidgetWrapper( parameter, type );
5428 }
5429 
5430 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExtentWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5431 {
5432  return new QgsProcessingExtentParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5433 }
5434 
5435 
5436 
5437 //
5438 // QgsProcessingMapLayerWidgetWrapper
5439 //
5440 
5441 QgsProcessingMapLayerParameterDefinitionWidget::QgsProcessingMapLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5442  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5443 {
5444  QVBoxLayout *vlayout = new QVBoxLayout();
5445  vlayout->setContentsMargins( 0, 0, 0, 0 );
5446 
5447  vlayout->addWidget( new QLabel( tr( "Layer type" ) ) );
5448  mLayerTypeComboBox = new QgsCheckableComboBox();
5449  mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
5450  mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
5451  mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
5452  mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
5453  mLayerTypeComboBox->addItem( tr( "Vector (Any Geometry Type)" ), QgsProcessing::TypeVectorAnyGeometry );
5454  mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
5455  mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
5456 
5457  if ( const QgsProcessingParameterMapLayer *layerParam = dynamic_cast<const QgsProcessingParameterMapLayer *>( definition ) )
5458  {
5459  for ( int i : layerParam->dataTypes() )
5460  {
5461  mLayerTypeComboBox->setItemCheckState( mLayerTypeComboBox->findData( i ), Qt::Checked );
5462  }
5463  }
5464 
5465  vlayout->addWidget( mLayerTypeComboBox );
5466 
5467  setLayout( vlayout );
5468 }
5469 
5470 QgsProcessingParameterDefinition *QgsProcessingMapLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5471 {
5472  QList< int > dataTypes;
5473  for ( const QVariant &v : mLayerTypeComboBox->checkedItemsData() )
5474  dataTypes << v.toInt();
5475 
5476  auto param = qgis::make_unique< QgsProcessingParameterMapLayer >( name, description );
5477  param->setDataTypes( dataTypes );
5478  param->setFlags( flags );
5479  return param.release();
5480 }
5481 
5482 QgsProcessingMapLayerWidgetWrapper::QgsProcessingMapLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5483  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5484 {
5485 
5486 }
5487 
5488 QWidget *QgsProcessingMapLayerWidgetWrapper::createWidget()
5489 {
5490  mComboBox = new QgsProcessingMapLayerComboBox( parameterDefinition(), type() );
5491 
5492  switch ( type() )
5493  {
5496  break;
5498  mComboBox->setEditable( true );
5499  break;
5500  }
5501 
5502  mComboBox->setToolTip( parameterDefinition()->toolTip() );
5503 
5504  connect( mComboBox, &QgsProcessingMapLayerComboBox::valueChanged, this, [ = ]()
5505  {
5506  if ( mBlockSignals )
5507  return;
5508 
5509  emit widgetValueHasChanged( this );
5510  } );
5511 
5512  setWidgetContext( widgetContext() );
5513  return mComboBox;
5514 }
5515 
5516 void QgsProcessingMapLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5517 {
5519  if ( mComboBox )
5520  {
5521  mComboBox->setWidgetContext( context );
5522 
5523  if ( !( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional ) )
5524  {
5525  // non optional parameter -- if no default value set, default to active layer
5526  if ( !parameterDefinition()->defaultValue().isValid() )
5527  mComboBox->setLayer( context.activeLayer() );
5528  }
5529  }
5530 }
5531 
5532 void QgsProcessingMapLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5533 {
5534  if ( mComboBox )
5535  mComboBox->setValue( value, context );
5536 }
5537 
5538 QVariant QgsProcessingMapLayerWidgetWrapper::widgetValue() const
5539 {
5540  return mComboBox ? mComboBox->value() : QVariant();
5541 }
5542 
5543 QStringList QgsProcessingMapLayerWidgetWrapper::compatibleParameterTypes() const
5544 {
5545  return QStringList()
5552 }
5553 
5554 QStringList QgsProcessingMapLayerWidgetWrapper::compatibleOutputTypes() const
5555 {
5556  return QStringList()
5562 }
5563 
5564 QString QgsProcessingMapLayerWidgetWrapper::modelerExpressionFormatString() const
5565 {
5566  return tr( "path to a map layer" );
5567 }
5568 
5569 QString QgsProcessingMapLayerWidgetWrapper::parameterType() const
5570 {
5572 }
5573 
5574 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5575 {
5576  return new QgsProcessingMapLayerWidgetWrapper( parameter, type );
5577 }
5578 
5579 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5580 {
5581  return new QgsProcessingMapLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5582 }
5583 
5584 
5585 //
5586 // QgsProcessingRasterLayerWidgetWrapper
5587 //
5588 
5589 QgsProcessingRasterLayerWidgetWrapper::QgsProcessingRasterLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5590  : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
5591 {
5592 
5593 }
5594 
5595 QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleParameterTypes() const
5596 {
5597  return QStringList()
5602 }
5603 
5604 QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleOutputTypes() const
5605 {
5606  return QStringList()
5612 }
5613 
5614 QString QgsProcessingRasterLayerWidgetWrapper::modelerExpressionFormatString() const
5615 {
5616  return tr( "path to a raster layer" );
5617 }
5618 
5619 QString QgsProcessingRasterLayerWidgetWrapper::parameterType() const
5620 {
5622 }
5623 
5624 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5625 {
5626  return new QgsProcessingRasterLayerWidgetWrapper( parameter, type );
5627 }
5628 
5629 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRasterLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5630 {
5631  Q_UNUSED( context );
5632  Q_UNUSED( widgetContext );
5633  Q_UNUSED( definition );
5634  Q_UNUSED( algorithm );
5635 
5636  return nullptr;
5637 }
5638 
5639 
5640 //
5641 // QgsProcessingVectorLayerWidgetWrapper
5642 //
5643 
5644 QgsProcessingVectorLayerParameterDefinitionWidget::QgsProcessingVectorLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5645  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5646 {
5647  QVBoxLayout *vlayout = new QVBoxLayout();
5648  vlayout->setContentsMargins( 0, 0, 0, 0 );
5649 
5650  vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
5651  mGeometryTypeComboBox = new QgsCheckableComboBox();
5652  mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
5653  mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
5654  mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
5655  mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
5656  mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
5657 
5658  if ( const QgsProcessingParameterVectorLayer *vectorParam = dynamic_cast<const QgsProcessingParameterVectorLayer *>( definition ) )
5659  {
5660  for ( int i : vectorParam->dataTypes() )
5661  {
5662  mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
5663  }
5664  }
5665 
5666  vlayout->addWidget( mGeometryTypeComboBox );
5667 
5668  setLayout( vlayout );
5669 }
5670 
5671 QgsProcessingParameterDefinition *QgsProcessingVectorLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5672 {
5673  QList< int > dataTypes;
5674  for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
5675  dataTypes << v.toInt();
5676 
5677  auto param = qgis::make_unique< QgsProcessingParameterVectorLayer >( name, description, dataTypes );
5678  param->setFlags( flags );
5679  return param.release();
5680 }
5681 
5682 
5683 QgsProcessingVectorLayerWidgetWrapper::QgsProcessingVectorLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5684  : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
5685 {
5686 
5687 }
5688 
5689 QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleParameterTypes() const
5690 {
5691  return QStringList()
5696 }
5697 
5698 QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleOutputTypes() const
5699 {
5700  return QStringList()
5706 }
5707 
5708 QString QgsProcessingVectorLayerWidgetWrapper::modelerExpressionFormatString() const
5709 {
5710  return tr( "path to a vector layer" );
5711 }
5712 
5713 QList<int> QgsProcessingVectorLayerWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
5714 {
5715  if ( const QgsProcessingParameterVectorLayer *param = dynamic_cast< const QgsProcessingParameterVectorLayer *>( parameter ) )
5716  return param->dataTypes();
5717  else
5718  return QList< int >();
5719 }
5720 
5721 QString QgsProcessingVectorLayerWidgetWrapper::parameterType() const
5722 {
5724 }
5725 
5726 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5727 {
5728  return new QgsProcessingVectorLayerWidgetWrapper( parameter, type );
5729 }
5730 
5731 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingVectorLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5732 {
5733  return new QgsProcessingVectorLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5734 }
5735 
5736 
5737 
5738 //
5739 // QgsProcessingFeatureSourceLayerWidgetWrapper
5740 //
5741 
5742 QgsProcessingFeatureSourceParameterDefinitionWidget::QgsProcessingFeatureSourceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5743  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5744 {
5745  QVBoxLayout *vlayout = new QVBoxLayout();
5746  vlayout->setContentsMargins( 0, 0, 0, 0 );
5747 
5748  vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
5749  mGeometryTypeComboBox = new QgsCheckableComboBox();
5750  mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
5751  mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
5752  mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
5753  mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
5754  mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
5755 
5756  if ( const QgsProcessingParameterFeatureSource *sourceParam = dynamic_cast<const QgsProcessingParameterFeatureSource *>( definition ) )
5757  {
5758  for ( int i : sourceParam->dataTypes() )
5759  {
5760  mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
5761  }
5762  }
5763  else
5764  {
5765  mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( QgsProcessing::TypeVectorAnyGeometry ), Qt::Checked );
5766  }
5767 
5768  vlayout->addWidget( mGeometryTypeComboBox );
5769 
5770  setLayout( vlayout );
5771 }
5772 
5773 QgsProcessingParameterDefinition *QgsProcessingFeatureSourceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5774 {
5775  QList< int > dataTypes;
5776  for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
5777  dataTypes << v.toInt();
5778 
5779  auto param = qgis::make_unique< QgsProcessingParameterFeatureSource >( name, description, dataTypes );
5780  param->setFlags( flags );
5781  return param.release();
5782 }
5783 
5784 QgsProcessingFeatureSourceWidgetWrapper::QgsProcessingFeatureSourceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5785  : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
5786 {
5787 
5788 }
5789 
5790 QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleParameterTypes() const
5791 {
5792  return QStringList()
5798 }
5799 
5800 QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleOutputTypes() const
5801 {
5802  return QStringList()
5808 }
5809 
5810 QString QgsProcessingFeatureSourceWidgetWrapper::modelerExpressionFormatString() const
5811 {
5812  return tr( "path to a vector layer" );
5813 }
5814 
5815 QList<int> QgsProcessingFeatureSourceWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
5816 {
5817  if ( const QgsProcessingParameterFeatureSource *param = dynamic_cast< const QgsProcessingParameterFeatureSource *>( parameter ) )
5818  return param->dataTypes();
5819  else
5820  return QList< int >();
5821 }
5822 
5823 QString QgsProcessingFeatureSourceWidgetWrapper::parameterType() const
5824 {
5826 }
5827 
5828 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSourceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5829 {
5830  return new QgsProcessingFeatureSourceWidgetWrapper( parameter, type );
5831 }
5832 
5833 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFeatureSourceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5834 {
5835  return new QgsProcessingFeatureSourceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5836 }
5837 
5838 //
5839 // QgsProcessingMeshLayerWidgetWrapper
5840 //
5841 
5842 QgsProcessingMeshLayerWidgetWrapper::QgsProcessingMeshLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5843  : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
5844 {
5845 
5846 }
5847 
5848 QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleParameterTypes() const
5849 {
5850  return QStringList()
5855 }
5856 
5857 QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleOutputTypes() const
5858 {
5859  return QStringList()
5861  // TODO << QgsProcessingOutputMeshLayer::typeName()
5865 }
5866 
5867 QString QgsProcessingMeshLayerWidgetWrapper::modelerExpressionFormatString() const
5868 {
5869  return tr( "path to a mesh layer" );
5870 }
5871 
5872 QString QgsProcessingMeshLayerWidgetWrapper::parameterType() const
5873 {
5875 }
5876 
5877 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5878 {
5879  return new QgsProcessingMeshLayerWidgetWrapper( parameter, type );
5880 }
5881 
5882 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5883 {
5884  Q_UNUSED( context );
5885  Q_UNUSED( widgetContext );
5886  Q_UNUSED( definition );
5887  Q_UNUSED( algorithm );
5888 
5889  return nullptr;
5890 }
5891 
5892 
5893 
5894 //
5895 // QgsProcessingRasterBandPanelWidget
5896 //
5897 
5898 QgsProcessingRasterBandPanelWidget::QgsProcessingRasterBandPanelWidget( QWidget *parent, const QgsProcessingParameterBand *param )
5899  : QWidget( parent )
5900  , mParam( param )
5901 {
5902  QHBoxLayout *hl = new QHBoxLayout();
5903  hl->setContentsMargins( 0, 0, 0, 0 );
5904 
5905  mLineEdit = new QLineEdit();
5906  mLineEdit->setEnabled( false );
5907  hl->addWidget( mLineEdit, 1 );
5908 
5909  mToolButton = new QToolButton();
5910  mToolButton->setText( QString( QChar( 0x2026 ) ) );
5911  hl->addWidget( mToolButton );
5912 
5913  setLayout( hl );
5914 
5915  if ( mParam )
5916  {
5917  mLineEdit->setText( tr( "%1 bands selected" ).arg( 0 ) );
5918  }
5919 
5920  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingRasterBandPanelWidget::showDialog );
5921 }
5922 
5923 void QgsProcessingRasterBandPanelWidget::setBands( const QList< int > &bands )
5924 {
5925  mBands = bands;
5926 }
5927 
5928 void QgsProcessingRasterBandPanelWidget::setBandNames( const QHash<int, QString> &names )
5929 {
5930  mBandNames = names;
5931 }
5932 
5933 void QgsProcessingRasterBandPanelWidget::setValue( const QVariant &value )
5934 {
5935  if ( value.isValid() )
5936  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
5937  else
5938  mValue.clear();
5939 
5940  updateSummaryText();
5941  emit changed();
5942 }
5943 
5944 void QgsProcessingRasterBandPanelWidget::showDialog()
5945 {
5946  QVariantList availableOptions;
5947  QStringList fieldNames;
5948  availableOptions.reserve( mBands.size() );
5949  for ( int band : qgis::as_const( mBands ) )
5950  {
5951  availableOptions << band;
5952  }
5953 
5955  if ( panel && panel->dockMode() )
5956  {
5957  QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
5958  widget->setPanelTitle( mParam->description() );
5959 
5960  widget->setValueFormatter( [this]( const QVariant & v ) -> QString
5961  {
5962  int band = v.toInt();
5963  return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
5964  } );
5965 
5966  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
5967  {
5968  setValue( widget->selectedOptions() );
5969  } );
5970  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
5971  panel->openPanel( widget );
5972  }
5973  else
5974  {
5975  QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
5976 
5977  dlg.setValueFormatter( [this]( const QVariant & v ) -> QString
5978  {
5979  int band = v.toInt();
5980  return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
5981  } );
5982  if ( dlg.exec() )
5983  {
5984  setValue( dlg.selectedOptions() );
5985  }
5986  }
5987 }
5988 
5989 void QgsProcessingRasterBandPanelWidget::updateSummaryText()
5990 {
5991  if ( mParam )
5992  mLineEdit->setText( tr( "%1 bands selected" ).arg( mValue.count() ) );
5993 }
5994 
5995 
5996 
5997 //
5998 // QgsProcessingBandWidgetWrapper
5999 //
6000 
6001 QgsProcessingBandParameterDefinitionWidget::QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6002  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6003 {
6004  QVBoxLayout *vlayout = new QVBoxLayout();
6005  vlayout->setContentsMargins( 0, 0, 0, 0 );
6006 
6007  vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
6008 
6009  mDefaultLineEdit = new QLineEdit();
6010  mDefaultLineEdit->setToolTip( tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6011  if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6012  {
6013  const QList< int > bands = QgsProcessingParameters::parameterAsInts( bandParam, bandParam->defaultValue(), context );
6014  QStringList defVal;
6015  for ( int b : bands )
6016  {
6017  defVal << QString::number( b );
6018  }
6019 
6020  mDefaultLineEdit->setText( defVal.join( ';' ) );
6021  }
6022  vlayout->addWidget( mDefaultLineEdit );
6023 
6024  vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
6025  mParentLayerComboBox = new QComboBox();
6026 
6027  QString initialParent;
6028  if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6029  initialParent = bandParam->parentLayerParameterName();
6030 
6031  if ( auto *lModel = widgetContext.model() )
6032  {
6033  // populate combo box with other model input choices
6034  const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
6035  for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
6036  {
6037  if ( const QgsProcessingParameterRasterLayer *definition = dynamic_cast< const QgsProcessingParameterRasterLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
6038  {
6039  mParentLayerComboBox-> addItem( definition->description(), definition->name() );
6040  if ( !initialParent.isEmpty() && initialParent == definition->name() )
6041  {
6042  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6043  }
6044  }
6045  }
6046  }
6047 
6048  if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
6049  {
6050  // if no parent candidates found, we just add the existing one as a placeholder
6051  mParentLayerComboBox->addItem( initialParent, initialParent );
6052  mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6053  }
6054 
6055  vlayout->addWidget( mParentLayerComboBox );
6056 
6057  mAllowMultipleCheckBox = new QCheckBox( tr( "Allow multiple" ) );
6058  if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6059  mAllowMultipleCheckBox->setChecked( bandParam->allowMultiple() );
6060 
6061  vlayout->addWidget( mAllowMultipleCheckBox );
6062  setLayout( vlayout );
6063 }
6064 
6065 QgsProcessingParameterDefinition *QgsProcessingBandParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6066 {
6067  auto param = qgis::make_unique< QgsProcessingParameterBand >( name, description, mDefaultLineEdit->text().split( ';' ), mParentLayerComboBox->currentData().toString(), false, mAllowMultipleCheckBox->isChecked() );
6068  param->setFlags( flags );
6069  return param.release();
6070 }
6071 
6072 QgsProcessingBandWidgetWrapper::QgsProcessingBandWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6073  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6074 {
6075 
6076 }
6077 
6078 QWidget *QgsProcessingBandWidgetWrapper::createWidget()
6079 {
6080  const QgsProcessingParameterBand *bandParam = dynamic_cast< const QgsProcessingParameterBand *>( parameterDefinition() );
6081  switch ( type() )
6082  {
6085  {
6086  if ( bandParam->allowMultiple() )
6087  {
6088  mPanel = new QgsProcessingRasterBandPanelWidget( nullptr, bandParam );
6089  mPanel->setToolTip( parameterDefinition()->toolTip() );
6090  connect( mPanel, &QgsProcessingRasterBandPanelWidget::changed, this, [ = ]
6091  {
6092  emit widgetValueHasChanged( this );
6093  } );
6094  return mPanel;
6095  }
6096  else
6097  {
6098  mComboBox = new QgsRasterBandComboBox();
6099  mComboBox->setShowNotSetOption( bandParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
6100 
6101  mComboBox->setToolTip( parameterDefinition()->toolTip() );
6102  connect( mComboBox, &QgsRasterBandComboBox::bandChanged, this, [ = ]( int )
6103  {
6104  emit widgetValueHasChanged( this );
6105  } );
6106  return mComboBox;
6107  }
6108  }
6109 
6111  {
6112  mLineEdit = new QLineEdit();
6113  mLineEdit->setToolTip( QObject::tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6114  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
6115  {
6116  emit widgetValueHasChanged( this );
6117  } );
6118  return mLineEdit;
6119  }
6120 
6121  }
6122  return nullptr;
6123 }
6124 
6125 void QgsProcessingBandWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
6126 {
6128  switch ( type() )
6129  {
6132  {
6133  for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
6134  {
6135  if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterBand * >( parameterDefinition() )->parentLayerParameterName() )
6136  {
6137  setParentLayerWrapperValue( wrapper );
6139  {
6140  setParentLayerWrapperValue( wrapper );
6141  } );
6142  break;
6143  }
6144  }
6145  break;
6146  }
6147 
6149  break;
6150  }
6151 }
6152 
6153 void QgsProcessingBandWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
6154 {
6155  // evaluate value to layer
6156  QgsProcessingContext *context = nullptr;
6157  std::unique_ptr< QgsProcessingContext > tmpContext;
6158  if ( mProcessingContextGenerator )
6159  context = mProcessingContextGenerator->processingContext();
6160 
6161  if ( !context )
6162  {
6163  tmpContext = qgis::make_unique< QgsProcessingContext >();
6164  context = tmpContext.get();
6165  }
6166 
6167  QVariant value = parentWrapper->parameterValue();
6168 
6169  QgsRasterLayer *layer = QgsProcessingParameters::parameterAsRasterLayer( parentWrapper->parameterDefinition(), value, *context );
6170  if ( layer && layer->isValid() )
6171  {
6172  // need to grab ownership of layer if required - otherwise layer may be deleted when context
6173  // goes out of scope
6174  std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
6175  if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::RasterLayer )
6176  {
6177  mParentLayer.reset( qobject_cast< QgsRasterLayer * >( ownedLayer.release() ) );
6178  layer = mParentLayer.get();
6179  }
6180  else
6181  {
6182  // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
6183  }
6184 
6185  if ( mComboBox )
6186  mComboBox->setLayer( layer );
6187  else if ( mPanel )
6188  {
6189  QgsRasterDataProvider *provider = layer->dataProvider();
6190  if ( provider && layer->isValid() )
6191  {
6192  //fill available bands
6193  int nBands = provider->bandCount();
6194  QList< int > bands;
6195  QHash< int, QString > bandNames;
6196  for ( int i = 1; i <= nBands; ++i )
6197  {
6198  bandNames.insert( i, QgsRasterBandComboBox::displayBandName( provider, i ) );
6199  bands << i;
6200  }
6201  mPanel->setBands( bands );
6202  mPanel->setBandNames( bandNames );
6203  }
6204  }
6205  }
6206  else
6207  {
6208  if ( mComboBox )
6209  mComboBox->setLayer( nullptr );
6210  else if ( mPanel )
6211  mPanel->setBands( QList< int >() );
6212 
6213  if ( value.isValid() && widgetContext().messageBar() )
6214  {
6215  widgetContext().messageBar()->clearWidgets();
6216  widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent bands could not be populated" ),
6217  Qgis::Warning, 5 );
6218  }
6219  }
6220 
6221  if ( parameterDefinition()->defaultValue().isValid() )
6222  setWidgetValue( parameterDefinition()->defaultValue(), *context );
6223 }
6224 
6225 void QgsProcessingBandWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6226 {
6227  if ( mComboBox )
6228  {
6229  if ( !value.isValid() )
6230  mComboBox->setBand( -1 );
6231  else
6232  {
6233  const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
6234  mComboBox->setBand( v );
6235  }
6236  }
6237  else if ( mPanel )
6238  {
6239  QVariantList opts;
6240  if ( value.isValid() )
6241  {
6242  const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6243  opts.reserve( v.size() );
6244  for ( int i : v )
6245  opts << i;
6246  }
6247  if ( mPanel )
6248  mPanel->setValue( value.isValid() ? opts : QVariant() );
6249  }
6250  else if ( mLineEdit )
6251  {
6252  const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6253  if ( bandParam->allowMultiple() )
6254  {
6255  const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6256  QStringList opts;
6257  opts.reserve( v.size() );
6258  for ( int i : v )
6259  opts << QString::number( i );
6260  mLineEdit->setText( value.isValid() && !opts.empty() ? opts.join( ';' ) : QString() );
6261  }
6262  else
6263  {
6264  if ( value.isValid() )
6265  mLineEdit->setText( QString::number( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) ) );
6266  else
6267  mLineEdit->clear();
6268  }
6269  }
6270 }
6271 
6272 QVariant QgsProcessingBandWidgetWrapper::widgetValue() const
6273 {
6274  if ( mComboBox )
6275  return mComboBox->currentBand() == -1 ? QVariant() : mComboBox->currentBand();
6276  else if ( mPanel )
6277  return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
6278  else if ( mLineEdit )
6279  {
6280  const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6281  if ( bandParam->allowMultiple() )
6282  {
6283  const QStringList parts = mLineEdit->text().split( ';', QString::SkipEmptyParts );
6284  QVariantList res;
6285  res.reserve( parts.count() );
6286  for ( const QString &s : parts )
6287  {
6288  bool ok = false;
6289  int band = s.toInt( &ok );
6290  if ( ok )
6291  res << band;
6292  }
6293  return res.isEmpty() ? QVariant() : res;
6294  }
6295  else
6296  {
6297  return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
6298  }
6299  }
6300  else
6301  return QVariant();
6302 }
6303 
6304 QStringList QgsProcessingBandWidgetWrapper::compatibleParameterTypes() const
6305 {
6306  return QStringList()
6309 }
6310 
6311 QStringList QgsProcessingBandWidgetWrapper::compatibleOutputTypes() const
6312 {
6313  return QStringList()
6315 }
6316 
6317 QString QgsProcessingBandWidgetWrapper::modelerExpressionFormatString() const
6318 {
6319  return tr( "selected band numbers as an array of numbers, or semicolon separated string of options (e.g. '1;3')" );
6320 }
6321 
6322 QString QgsProcessingBandWidgetWrapper::parameterType() const
6323 {
6325 }
6326 
6327 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBandWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6328 {
6329  return new QgsProcessingBandWidgetWrapper( parameter, type );
6330 }
6331 
6332 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBandWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6333 {
6334  return new QgsProcessingBandParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6335 }
6336 
6337 
6338 
6339 //
6340 // QgsProcessingMultipleLayerPanelWidget
6341 //
6342 
6343 QgsProcessingMultipleLayerPanelWidget::QgsProcessingMultipleLayerPanelWidget( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
6344  : QWidget( parent )
6345  , mParam( param )
6346 {
6347  QHBoxLayout *hl = new QHBoxLayout();
6348  hl->setContentsMargins( 0, 0, 0, 0 );
6349 
6350  mLineEdit = new QLineEdit();
6351  mLineEdit->setEnabled( false );
6352  hl->addWidget( mLineEdit, 1 );
6353 
6354  mToolButton = new QToolButton();
6355  mToolButton->setText( QString( QChar( 0x2026 ) ) );
6356  hl->addWidget( mToolButton );
6357 
6358  setLayout( hl );
6359 
6360  if ( mParam )
6361  {
6362  mLineEdit->setText( tr( "%1 inputs selected" ).arg( 0 ) );
6363  }
6364 
6365  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMultipleLayerPanelWidget::showDialog );
6366 }
6367 
6368 void QgsProcessingMultipleLayerPanelWidget::setValue( const QVariant &value )
6369 {
6370  if ( value.isValid() )
6371  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
6372  else
6373  mValue.clear();
6374 
6375  updateSummaryText();
6376  emit changed();
6377 }
6378 
6379 void QgsProcessingMultipleLayerPanelWidget::setProject( QgsProject *project )
6380 {
6381  mProject = project;
6382 }
6383 
6384 void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorithm *model, const QString &modelChildAlgorithmID )
6385 {
6386  mModel = model;
6387  if ( !model )
6388  return;
6389 
6390  switch ( mParam->layerType() )
6391  {
6393  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFile::typeName(),
6394  QStringList() << QgsProcessingOutputFile::typeName() );
6395  break;
6396 
6398  {
6399  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterRasterLayer::typeName()
6402  QStringList() << QgsProcessingOutputFile::typeName()
6406  break;
6407  }
6408 
6410  {
6411  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMeshLayer::typeName()
6414  QStringList() << QgsProcessingOutputFile::typeName()
6417  break;
6418  }
6419 
6421  {
6422  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6426  QStringList() << QgsProcessingOutputFile::typeName()
6430  QList< int >() << QgsProcessing::TypeVector );
6431  break;
6432  }
6433 
6435  {
6436  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6440  QStringList() << QgsProcessingOutputFile::typeName()
6444  break;
6445  }
6446 
6448  {
6449  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6453  QStringList() << QgsProcessingOutputFile::typeName()
6458  break;
6459  }
6460 
6462  {
6463  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6467  QStringList() << QgsProcessingOutputFile::typeName()
6472  break;
6473  }
6474 
6476  {
6477  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6481  QStringList() << QgsProcessingOutputFile::typeName()
6486  break;
6487  }
6488 
6490  {
6491  mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6497  QStringList() << QgsProcessingOutputFile::typeName()
6501  // << QgsProcessingOutputMeshLayer::typeName()
6503  break;
6504  }
6505  }
6506 }
6507 
6508 void QgsProcessingMultipleLayerPanelWidget::showDialog()
6509 {
6511  if ( panel && panel->dockMode() )
6512  {
6513  QgsProcessingMultipleInputPanelWidget *widget = new QgsProcessingMultipleInputPanelWidget( mParam, mValue, mModelSources, mModel );
6514  widget->setPanelTitle( mParam->description() );
6515  widget->setProject( mProject );
6516  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
6517  {
6518  setValue( widget->selectedOptions() );
6519  } );
6520  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
6521  panel->openPanel( widget );
6522  }
6523  else
6524  {
6525  QgsProcessingMultipleInputDialog dlg( mParam, mValue, mModelSources, mModel, this, Qt::WindowFlags() );
6526  dlg.setProject( mProject );
6527  if ( dlg.exec() )
6528  {
6529  setValue( dlg.selectedOptions() );
6530  }
6531  }
6532 }
6533 
6534 void QgsProcessingMultipleLayerPanelWidget::updateSummaryText()
6535 {
6536  if ( mParam )
6537  mLineEdit->setText( tr( "%1 inputs selected" ).arg( mValue.count() ) );
6538 }
6539 
6540 //
6541 // QgsProcessingMultipleLayerWidgetWrapper
6542 //
6543 
6544 QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6545  : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6546 {
6547  QVBoxLayout *vlayout = new QVBoxLayout();
6548  vlayout->setContentsMargins( 0, 0, 0, 0 );
6549 
6550  vlayout->addWidget( new QLabel( tr( "Allowed layer type" ) ) );
6551  mLayerTypeComboBox = new QComboBox();
6552  mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
6553  mLayerTypeComboBox->addItem( tr( "Vector (No Geometry Required)" ), QgsProcessing::TypeVector );
6554  mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
6555  mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
6556  mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
6557  mLayerTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6558  mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
6559  mLayerTypeComboBox->addItem( tr( "File" ), QgsProcessing::TypeFile );
6560  mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
6561  if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
6562  mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( layersParam->layerType() ) );
6563 
6564  vlayout->addWidget( mLayerTypeComboBox );
6565  setLayout( vlayout );
6566 }
6567 
6568 QgsProcessingParameterDefinition *QgsProcessingMultipleLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6569 {
6570  auto param = qgis::make_unique< QgsProcessingParameterMultipleLayers >( name, description, static_cast< QgsProcessing::SourceType >( mLayerTypeComboBox->currentData().toInt() ) );
6571  param->setFlags( flags );
6572  return param.release();
6573 }
6574 
6575 QgsProcessingMultipleLayerWidgetWrapper::QgsProcessingMultipleLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6576  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6577 {
6578 
6579 }
6580 
6581 QWidget *QgsProcessingMultipleLayerWidgetWrapper::createWidget()
6582 {
6583  const QgsProcessingParameterMultipleLayers *layerParam = dynamic_cast< const QgsProcessingParameterMultipleLayers *>( parameterDefinition() );
6584 
6585  mPanel = new QgsProcessingMultipleLayerPanelWidget( nullptr, layerParam );
6586  mPanel->setToolTip( parameterDefinition()->toolTip() );
6587  mPanel->setProject( widgetContext().project() );
6588  mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
6589  connect( mPanel, &QgsProcessingMultipleLayerPanelWidget::changed, this, [ = ]
6590  {
6591  emit widgetValueHasChanged( this );
6592  } );
6593  return mPanel;
6594 }
6595 
6596 void QgsProcessingMultipleLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
6597 {
6599  if ( mPanel )
6600  {
6601  mPanel->setProject( context.project() );
6602  mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
6603  }
6604 }
6605 
6606 void QgsProcessingMultipleLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6607 {
6608  if ( mPanel )
6609  {
6610  QVariantList opts;
6611  if ( value.isValid() )
6612  {
6613  const QList< QgsMapLayer * > v = QgsProcessingParameters::parameterAsLayerList( parameterDefinition(), value, context );
6614  opts.reserve( v.size() );
6615  for ( const QgsMapLayer *l : v )
6616  opts << l->source();
6617  }
6618 
6619  for ( const QVariant &v : value.toList() )
6620  {
6621  if ( v.canConvert< QgsProcessingModelChildParameterSource >() )
6622  {
6623  const QgsProcessingModelChildParameterSource source = v.value< QgsProcessingModelChildParameterSource >();
6624  opts << QVariant::fromValue( source );
6625  }
6626  }
6627 
6628  if ( mPanel )
6629  mPanel->setValue( value.isValid() ? opts : QVariant() );
6630  }
6631 }
6632 
6633 QVariant QgsProcessingMultipleLayerWidgetWrapper::widgetValue() const
6634 {
6635  if ( mPanel )
6636  return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
6637  else
6638  return QVariant();
6639 }
6640 
6641 QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleParameterTypes() const
6642 {
6643  return QStringList()
6652 }
6653 
6654 QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleOutputTypes() const
6655 {
6656  return QStringList()
6663 }
6664 
6665 QString QgsProcessingMultipleLayerWidgetWrapper::modelerExpressionFormatString() const
6666 {
6667  return tr( "an array of layer paths, or semicolon separated string of layer paths" );
6668 }
6669 
6670 QString QgsProcessingMultipleLayerWidgetWrapper::parameterType() const
6671 {
6673 }
6674 
6675 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMultipleLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6676 {
6677  return new QgsProcessingMultipleLayerWidgetWrapper( parameter, type );
6678 }
6679 
6680 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMultipleLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6681 {
6682  return new QgsProcessingMultipleLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6683 }
6684 
6685 
6686 //
6687 // QgsProcessingOutputWidgetWrapper
6688 //
6689 
6690 QgsProcessingOutputWidgetWrapper::QgsProcessingOutputWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6691  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6692 {
6693 
6694 }
6695 
6696 QWidget *QgsProcessingOutputWidgetWrapper::createWidget()
6697 {
6698  const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( parameterDefinition() );
6699  switch ( type() )
6700  {
6703  {
6704  mOutputWidget = new QgsProcessingLayerOutputDestinationWidget( destParam, false );
6705  if ( mProcessingContextGenerator )
6706  mOutputWidget->setContext( mProcessingContextGenerator->processingContext() );
6707  if ( mParametersGenerator )
6708  mOutputWidget->registerProcessingParametersGenerator( mParametersGenerator );
6709  mOutputWidget->setToolTip( parameterDefinition()->toolTip() );
6710 
6711  connect( mOutputWidget, &QgsProcessingLayerOutputDestinationWidget::destinationChanged, this, [ = ]()
6712  {
6713  if ( mBlockSignals )
6714  return;
6715 
6716  emit widgetValueHasChanged( this );
6717  } );
6718 
6719  if ( type() == QgsProcessingGui::Standard
6723  mOutputWidget->addOpenAfterRunningOption();
6724 
6725  return mOutputWidget;
6726  }
6728  break;
6729  }
6730 
6731  return nullptr;
6732 }
6733 
6734 
6735 void QgsProcessingOutputWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
6736 {
6737  if ( mOutputWidget )
6738  mOutputWidget->setValue( value );
6739 }
6740 
6741 QVariant QgsProcessingOutputWidgetWrapper::widgetValue() const
6742 {
6743  if ( mOutputWidget )
6744  return mOutputWidget->value();
6745 
6746  return QVariant();
6747 }
6748 
6749 QVariantMap QgsProcessingOutputWidgetWrapper::customProperties() const
6750 {
6751  QVariantMap res;
6752  if ( mOutputWidget )
6753  res.insert( QStringLiteral( "OPEN_AFTER_RUNNING" ), mOutputWidget->openAfterRunning() );
6754  return res;
6755 }
6756 
6757 QStringList QgsProcessingOutputWidgetWrapper::compatibleParameterTypes() const
6758 {
6759  return QStringList()
6766 }
6767 
6768 QStringList QgsProcessingOutputWidgetWrapper::compatibleOutputTypes() const
6769 {
6770  return QStringList()
6774 }
6775 
6776 //
6777 // QgsProcessingFeatureSinkWidgetWrapper
6778 //
6779 
6780 QgsProcessingFeatureSinkWidgetWrapper::QgsProcessingFeatureSinkWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6781  : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
6782 {
6783 
6784 }
6785 
6786 QString QgsProcessingFeatureSinkWidgetWrapper::parameterType() const
6787 {
6789 }
6790 
6791 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSinkWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6792 {
6793  return new QgsProcessingFeatureSinkWidgetWrapper( parameter, type );
6794 }
6795 
6796 QString QgsProcessingFeatureSinkWidgetWrapper::modelerExpressionFormatString() const
6797 {
6798  return tr( "path to layer destination" );
6799 }
6800 
6801 //
6802 // QgsProcessingFeatureSinkWidgetWrapper
6803 //
6804 
6805 QgsProcessingVectorDestinationWidgetWrapper::QgsProcessingVectorDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6806  : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
6807 {
6808 
6809 }
6810 
6811 QString QgsProcessingVectorDestinationWidgetWrapper::parameterType() const
6812 {
6814 }
6815 
6816 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6817 {
6818  return new QgsProcessingVectorDestinationWidgetWrapper( parameter, type );
6819 }
6820 
6821 QString QgsProcessingVectorDestinationWidgetWrapper::modelerExpressionFormatString() const
6822 {
6823  return tr( "path to layer destination" );
6824 }
6825 
6826 //
6827 // QgsProcessingFeatureSinkWidgetWrapper
6828 //
6829 
6830 QgsProcessingRasterDestinationWidgetWrapper::QgsProcessingRasterDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6831  : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
6832 {
6833 
6834 }
6835 
6836 QString QgsProcessingRasterDestinationWidgetWrapper::parameterType() const
6837 {
6839 }
6840 
6841 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6842 {
6843  return new QgsProcessingRasterDestinationWidgetWrapper( parameter, type );
6844 }
6845 
6846 QString QgsProcessingRasterDestinationWidgetWrapper::modelerExpressionFormatString() const
6847 {
6848  return tr( "path to layer destination" );
6849 }
6850 
6851 //
6852 // QgsProcessingFileDestinationWidgetWrapper
6853 //
6854 
6855 QgsProcessingFileDestinationWidgetWrapper::QgsProcessingFileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6856  : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
6857 {
6858 
6859 }
6860 
6861 QString QgsProcessingFileDestinationWidgetWrapper::parameterType() const
6862 {
6864 }
6865 
6866 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6867 {
6868  return new QgsProcessingFileDestinationWidgetWrapper( parameter, type );
6869 }
6870 
6871 QString QgsProcessingFileDestinationWidgetWrapper::modelerExpressionFormatString() const
6872 {
6873  return tr( "path to file destination" );
6874 }
6875 
6876 //
6877 // QgsProcessingFolderDestinationWidgetWrapper
6878 //
6879 
6880 QgsProcessingFolderDestinationWidgetWrapper::QgsProcessingFolderDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6881  : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
6882 {
6883 
6884 }
6885 
6886 QString QgsProcessingFolderDestinationWidgetWrapper::parameterType() const
6887 {
6889 }
6890 
6891 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFolderDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6892 {
6893  return new QgsProcessingFolderDestinationWidgetWrapper( parameter, type );
6894 }
6895 
6896 QString QgsProcessingFolderDestinationWidgetWrapper::modelerExpressionFormatString() const
6897 {
6898  return tr( "path to folder destination" );
6899 }
6900 
QgsFieldProxyModel::Numeric
@ Numeric
All numeric fields.
Definition: qgsfieldproxymodel.h:45
QgsProcessingParameterMatrix
A table (matrix) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1792
qgscolorbutton.h
QgsDateTimeEdit
The QgsDateTimeEdit class is a QDateTimeEdit with the capability of setting/reading null date/times.
Definition: qgsdatetimeedit.h:37
QgsProcessingParameterWidgetContext::activeLayer
QgsMapLayer * activeLayer() const
Returns the current active layer.
Definition: qgsprocessingwidgetwrapper.cpp:84
QgsProcessingParameterWidgetContext
Contains settings which reflect the context in which a Processing parameter widget is shown,...
Definition: qgsprocessingwidgetwrapper.h:100
QgsFieldProxyModel::Time
@ Time
Time fields.
Definition: qgsfieldproxymodel.h:47
QgsRasterBandComboBox::bandChanged
void bandChanged(int band)
Emitted when the currently selected band changes.
QgsFileWidget::fileChanged
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
QgsProcessingParameterDatabaseSchema::parentConnectionParameterName
QString parentConnectionParameterName() const
Returns the name of the parent connection parameter, or an empty string if this is not set.
Definition: qgsprocessingparameters.cpp:7596
QgsProcessingParameters::parameterAsMatrix
static QVariantList parameterAsMatrix(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a matrix/table of values.
Definition: qgsprocessingparameters.cpp:1619
QgsLayoutItemComboBox
The QgsLayoutItemComboBox class is a combo box which displays items of a matching type from a layout.
Definition: qgslayoutitemcombobox.h:35
QgsCoordinateOperationWidget
A widget for selecting the coordinate operation to use when transforming between a source and destina...
Definition: qgscoordinateoperationwidget.h:34
QgsProcessingParameterDistance::defaultUnit
QgsUnitTypes::DistanceUnit defaultUnit() const
Returns the default distance unit for the parameter.
Definition: qgsprocessingparameters.h:2105
QgsProcessingParameterNumber::Double
@ Double
Double/float values.
Definition: qgsprocessingparameters.h:1967
QgsProcessingParameterField::String
@ String
Accepts string fields.
Definition: qgsprocessingparameters.h:2625
QgsProcessingParameterField::DataType
DataType
Field data types.
Definition: qgsprocessingparameters.h:2622
QgsProcessingParameterProviderConnection::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3756
QgsPointXY::y
double y
Definition: qgspointxy.h:48
qgsprocessingmatrixmodelerwidget.h
QgsMapThemeCollection::mapThemes
QStringList mapThemes
Definition: qgsmapthemecollection.h:48
qgsprojectionselectionwidget.h
QgsProcessingParameters::parameterAsCrs
static QgsCoordinateReferenceSystem parameterAsCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a coordinate reference system.
Definition: qgsprocessingparameters.cpp:956
QgsLayoutComboBox
The QgsLayoutComboBox class is a combo box which displays available layouts from a QgsLayoutManager.
Definition: qgslayoutcombobox.h:31
QgsProcessingParameters::parameterAsConnectionName
static QString parameterAsConnectionName(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a connection name string.
Definition: qgsprocessingparameters.cpp:2028
QgsProcessingParameterRasterDestination::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3083
QgsProcessingParameterEnum::allowMultiple
bool allowMultiple() const
Returns true if the parameter allows multiple selected values.
Definition: qgsprocessingparameters.cpp:4285
QgsCoordinateReferenceSystem::mapUnits
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Definition: qgscoordinatereferencesystem.h:209
qgsdoublespinbox.h
QgsProcessingParameterField::Numeric
@ Numeric
Accepts numeric fields.
Definition: qgsprocessingparameters.h:2624
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsProcessingParameterDatabaseTable::parentConnectionParameterName
QString parentConnectionParameterName() const
Returns the name of the parent connection parameter, or an empty string if this is not set.
Definition: qgsprocessingparameters.cpp:7736
QgsFieldProxyModel::DateTime
@ DateTime
Datetime fieldss.
Definition: qgsfieldproxymodel.h:49
QgsLayoutItemRegistry::ItemType
ItemType
Item types.
Definition: qgslayoutitemregistry.h:307
QgsProcessingParameters::parameterAsEnums
static QList< int > parameterAsEnums(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to list of enum values.
Definition: qgsprocessingparameters.cpp:445
qgsrasterbandcombobox.h
qgscoordinateoperationwidget.h
qgsmapcanvas.h
QgsProcessingParameters::parameterAsGeometry
static QgsGeometry parameterAsGeometry(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a geometry.
Definition: qgsprocessingparameters.cpp:1420
QgsProcessingParameterNumber
A numeric parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1960
QgsMapLayerType::VectorLayer
@ VectorLayer
qgsprocessingmaplayercombobox.h
qgsmapthemecollection.h
QgsFieldProxyModel::Date
@ Date
Date or datetime fields.
Definition: qgsfieldproxymodel.h:46
QgsFields::isEmpty
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
QgsUnitTypes::DistanceUnknownUnit
@ DistanceUnknownUnit
Unknown distance unit.
Definition: qgsunittypes.h:78
QgsExpressionBuilderWidget
A reusable widget that can be used to build a expression string.
Definition: qgsexpressionbuilderwidget.h:43
QgsProcessingParameterDefinition::description
QString description() const
Returns the description for the parameter.
Definition: qgsprocessingparameters.h:474
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:49
QgsProcessingParameterWidgetContext::mapCanvas
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Definition: qgsprocessingwidgetwrapper.cpp:39
algorithm
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
QgsProcessingParameters::parameterAsDatabaseTableName
static QString parameterAsDatabaseTableName(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a database table name.
Definition: qgsprocessingparameters.cpp:2058
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:391
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
QgsProcessingParameterDatabaseTable::parentSchemaParameterName
QString parentSchemaParameterName() const
Returns the name of the parent schema parameter, or an empty string if this is not set.
Definition: qgsprocessingparameters.cpp:7746
QgsProcessingContext::takeResultLayer
QgsMapLayer * takeResultLayer(const QString &id)
Takes the result map layer with matching id from the context and transfers ownership of it back to th...
Definition: qgsprocessingcontext.cpp:126
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
QgsMapMouseEvent::snapPoint
QgsPointXY snapPoint()
snapPoint will snap the points using the map canvas snapping utils configuration
Definition: qgsmapmouseevent.cpp:43
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsProcessingParameters::parameterAsFields
static QStringList parameterAsFields(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of fields.
Definition: qgsprocessingparameters.cpp:1873
QgsApplication::getThemeCursor
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
Definition: qgsapplication.cpp:656
QgsProcessingParameterDefinition::flags
Flags flags() const
Returns any flags associated with the parameter.
Definition: qgsprocessingparameters.h:522
QgsProcessingParameterDefinition::metadata
QVariantMap metadata() const
Returns the parameter's freeform metadata.
Definition: qgsprocessingparameters.h:582
QgsUnitTypes::unitType
static Q_INVOKABLE QgsUnitTypes::DistanceUnitType unitType(QgsUnitTypes::DistanceUnit unit)
Returns the type for a distance unit.
Definition: qgsunittypes.cpp:73
QgsProcessingParameterFile::Folder
@ Folder
Parameter is a folder.
Definition: qgsprocessingparameters.h:1696
QgsProcessingParameterMapTheme
A map theme parameter for processing algorithms, allowing users to select an existing map theme from ...
Definition: qgsprocessingparameters.h:3582
Qgis::Warning
@ Warning
Definition: qgis.h:91
QgsCoordinateOperationWidget::OperationDetails
Coordinate operation details.
Definition: qgscoordinateoperationwidget.h:40
QgsProcessingParameterFile::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1712
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:50
QgsProjectionSelectionWidget::crsChanged
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext
virtual void setWidgetContext(const QgsProcessingParameterWidgetContext &context)
Sets the context in which the Processing parameter widget is shown, e.g., the parent model algorithm,...
Definition: qgsprocessingwidgetwrapper.cpp:121
QgsDateEdit::dateValueChanged
void dateValueChanged(const QDate &date)
Signal emitted whenever the date changes.
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:79
QgsMapTool::deactivate
virtual void deactivate()
called when map tool is being deactivated
Definition: qgsmaptool.cpp:96
QgsProcessingParameters::parameterAsExtentCrs
static QgsCoordinateReferenceSystem parameterAsExtentCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Returns the coordinate reference system associated with an extent parameter value.
Definition: qgsprocessingparameters.cpp:1220
qgslayoutmanager.h
QgsProcessingParameterLayoutItem::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3352
qgsfilterlineedit.h
QgsFileWidget::GetFile
@ GetFile
Select a single file.
Definition: qgsfilewidget.h:66
QgsDatumTransformDialog
Definition: qgsdatumtransformdialog.h:35
QgsProcessingParameters::parameterAsDate
static QDate parameterAsDate(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static date value.
Definition: qgsprocessingparameters.cpp:343
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:40
QgsProcessingParameterGeometry::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1649
QgsProviderConnectionComboBox
The QgsProviderConnectionComboBox class is a combo box which displays the list of connections registe...
Definition: qgsproviderconnectioncombobox.h:50
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsProcessingParameterVectorDestination::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3008
QgsProjectionSelectionWidget
A widget for selecting a projection.
Definition: qgsprojectionselectionwidget.h:39
QgsProcessingParameterMultipleLayers::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1891
QgsProcessingParameterFile::fileFilter
QString fileFilter() const
Returns the file filter string for file destinations compatible with this parameter.
Definition: qgsprocessingparameters.cpp:3306
QgsProcessingParameterDefinition
Base class for the definition of processing parameters.
Definition: qgsprocessingparameters.h:331
QgsProcessing::TypeVectorLine
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:49
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsProcessingParameterFeatureSource
An input feature source (such as vector layers) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2734
QgsProcessingParameterMapLayer
A map layer parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2578
QgsMapLayer::isValid
bool isValid
Definition: qgsmaplayer.h:91
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:828
QgsDatabaseSchemaComboBox
The QgsDatabaseSchemaComboBox class is a combo box which displays the list of schemas for a specific ...
Definition: qgsdatabaseschemacombobox.h:51
field
const QgsField & field
Definition: qgsfield.h:456
QgsFields::append
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
QgsProcessingOutputBoolean::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:351
QgsProcessingOutputMultipleLayers::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:260
QgsUnitTypes::DistanceUnit
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:68
QgsProcessingParameterLayout::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3312
QgsProcessing::TypeVectorPoint
@ TypeVectorPoint
Vector point layers.
Definition: qgsprocessing.h:48
QgsAbstractProcessingParameterWidgetWrapper
A widget wrapper for Processing parameter value widgets.
Definition: qgsprocessingwidgetwrapper.h:267
QgsProcessingParameterField::defaultToAllFields
bool defaultToAllFields() const
Returns whether a parameter which allows multiple selections (see allowMultiple()) should automatical...
Definition: qgsprocessingparameters.cpp:4993
QgsProcessingParameterMultipleLayers
A parameter for processing algorithms which accepts multiple map layers.
Definition: qgsprocessingparameters.h:1878
QgsProcessingParameters::parameterAsSchema
static QString parameterAsSchema(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a database schema name.
Definition: qgsprocessingparameters.cpp:2043
QgsProcessingParameters::parameterAsRasterLayer
static QgsRasterLayer * parameterAsRasterLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a raster layer.
Definition: qgsprocessingparameters.cpp:816
QgsProcessingFeatureSourceDefinition::source
QgsProperty source
Source definition.
Definition: qgsprocessingparameters.h:117
QgsField::name
QString name
Definition: qgsfield.h:59
QgsUnitTypes::DistanceKilometers
@ DistanceKilometers
Kilometers.
Definition: qgsunittypes.h:70
qgsextentwidget.h
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:83
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsProcessingParameterField::allowMultiple
bool allowMultiple() const
Returns whether multiple field selections are permitted.
Definition: qgsprocessingparameters.cpp:4983
qgsprocessingenummodelerwidget.h
QgsProcessingOutputFolder::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:374
QgsProcessingParameterMeshLayer::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2558
qgssnapindicator.h
QgsProcessingParameterCoordinateOperation::destinationCrs
QVariant destinationCrs() const
Returns the static destination CRS, or an invalid value if this is not set.
Definition: qgsprocessingparameters.h:3553
QgsProcessingParameterDatabaseTable::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3884
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:95
QgsSnapIndicator
Class that shows snapping marker on map canvas for the current snapping match.
Definition: qgssnapindicator.h:33
QgsProcessingGui::Standard
@ Standard
Standard algorithm dialog.
Definition: qgsprocessinggui.h:40
QgsProcessingParameterRange::dataType
QgsProcessingParameterNumber::Type dataType() const
Returns the acceptable data type for the range.
Definition: qgsprocessingparameters.cpp:4028
QgsProcessingParameterNumber::dataType
Type dataType() const
Returns the acceptable data type for the parameter.
Definition: qgsprocessingparameters.cpp:3901
QgsProcessingParameterBand::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3239
QgsProcessingOutputRasterLayer::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:229
QgsFields::toList
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfields.cpp:212
QgsColorButton::colorChanged
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
QgsProcessingParameterColor
A color parameter for processing algorithms.
Definition: qgsprocessingparameters.h:3412
QgsProcessingParameterFeatureSink::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2910
QgsLayoutManagerProxyModel::FilterPrintLayouts
@ FilterPrintLayouts
Includes print layouts.
Definition: qgslayoutmanager.h:247
qgsdatabasetablecombobox.h
QgsProcessingParameterDatabaseTable
A database table name parameter for processing algorithms, allowing users to select from existing dat...
Definition: qgsprocessingparameters.h:3862
QgsProcessingParameterFile::File
@ File
Parameter is a single file.
Definition: qgsprocessingparameters.h:1695
qgsscalewidget.h
QgsProcessingParameters::parameterAsRange
static QList< double > parameterAsRange(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a range of values.
Definition: qgsprocessingparameters.cpp:1807
QgsProcessingDestinationParameter
Base class for all parameter definitions which represent file or layer destinations,...
Definition: qgsprocessingparameters.h:2774
qgsapplication.h
QgsMapTool
Abstract base class for all map tools.
Definition: qgsmaptool.h:64
QgsAuthConfigSelect::selectedConfigIdChanged
void selectedConfigIdChanged(const QString &authcfg)
Emitted when authentication config is changed or missing.
QgsMessageBar::clearWidgets
bool clearWidgets()
Removes all items from the bar.
Definition: qgsmessagebar.cpp:181
QgsProcessingParameters::parameterAsLayerList
static QList< QgsMapLayer * > parameterAsLayerList(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of map layers.
Definition: qgsprocessingparameters.cpp:1658
QgsProcessingParameterEnum::options
QStringList options() const
Returns the list of acceptable options for the parameter.
Definition: qgsprocessingparameters.cpp:4275
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsProcessingFeatureSourceDefinition
Encapsulates settings relating to a feature source input to a processing algorithm.
Definition: qgsprocessingparameters.h:56
QgsUnitTypes::fromUnitToUnitFactor
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
Definition: qgsunittypes.cpp:352
qgsfieldcombobox.h
QgsProcessingParameterColor::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3427
QgsDateEdit
The QgsDateEdit class is a QDateEdit widget with the capability of setting/reading null dates.
Definition: qgsdatetimeedit.h:273
QgsProcessingParameterScale
A double numeric parameter for map scale values.
Definition: qgsprocessingparameters.h:2136
QgsMapMouseEvent::mapPointMatch
QgsPointLocator::Match mapPointMatch() const
Returns the matching data from the most recently snapped point.
Definition: qgsmapmouseevent.h:97
qgscheckablecombobox.h
QgsProcessingParameterRange
A numeric range parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2170
QgsCoordinateOperationWidget::OperationDetails::proj
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.
Definition: qgscoordinateoperationwidget.h:48
QgsProcessingParameterWidgetContext::project
QgsProject * project() const
Returns the project associated with the widget.
Definition: qgsprocessingwidgetwrapper.cpp:69
QgsFieldProxyModel::String
@ String
String fields.
Definition: qgsfieldproxymodel.h:41
QgsProcessingParameterRange::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2184
QgsPrintLayout
Print layout, a QgsLayout subclass for static or atlas-based layouts.
Definition: qgsprintlayout.h:31
QgsProcessing::TypeMapLayer
@ TypeMapLayer
Any map layer type (raster or vector or mesh)
Definition: qgsprocessing.h:46
QgsExtentWidget::extentChanged
void extentChanged(const QgsRectangle &r)
Emitted when the widget's extent is changed.
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:30
QgsProcessingParameters::parameterAsExtent
static QgsRectangle parameterAsExtent(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a rectangular extent.
Definition: qgsprocessingparameters.cpp:972
QgsRasterBandComboBox
A combobox widget which displays the bands present in a raster layer.
Definition: qgsrasterbandcombobox.h:34
QgsFileWidget::GetDirectory
@ GetDirectory
Select a directory.
Definition: qgsfilewidget.h:67
QgsProcessing::TypeVector
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:53
QgsProcessingParameterAuthConfig::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2396
QgsProcessingOutputMapLayer::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:167
QgsUnitTypes::DistanceDegrees
@ DistanceDegrees
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:75
QgsProcessingParameterBand::allowMultiple
bool allowMultiple() const
Returns whether multiple band selections are permitted.
Definition: qgsprocessingparameters.cpp:6340
QgsProcessingParameterDateTime::DateTime
@ DateTime
Datetime values.
Definition: qgsprocessingparameters.h:3631
QgsProcessingParameterCrs
A coordinate reference system parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1538
QgsProcessingParameterRasterLayer::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2235
QgsProcessingParameterPoint::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1615
QgsExtentWidget::toggleDialogVisibility
void toggleDialogVisibility(bool visible)
Emitted when the parent dialog visibility must be changed (e.g.
QgsProcessingParameterExtent::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1582
QgsProcessingParameters::parameterAsVectorLayer
static QgsVectorLayer * parameterAsVectorLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a vector layer.
Definition: qgsprocessingparameters.cpp:946
QgsProcessingParameters::parameterAsPoint
static QgsPointXY parameterAsPoint(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Evaluates the parameter with matching definition to a point.
Definition: qgsprocessingparameters.cpp:1302
QgsProcessingParameters::parameterAsDateTime
static QDateTime parameterAsDateTime(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static datetime value.
Definition: qgsprocessingparameters.cpp:306
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsProcessingParameterGeometry
A geometry parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1635
QgsProcessing::TypeMesh
@ TypeMesh
Mesh layers.
Definition: qgsprocessing.h:54
qgsspinbox.h
qgsdatetimeedit.h
QgsUnitTypes::toString
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
Definition: qgsunittypes.cpp:199
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsProcessingParameterFile::extension
QString extension() const
Returns any specified file extension for the parameter.
Definition: qgsprocessingparameters.h:1738
QgsProcessing::TypeRaster
@ TypeRaster
Raster layers.
Definition: qgsprocessing.h:51
qgsRound
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:363
QgsProcessingParameterDefinition::name
QString name() const
Returns the name of the parameter.
Definition: qgsprocessingparameters.h:460
QgsProcessingParameterField::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2642
QgsPanelWidget::acceptPanel
void acceptPanel()
Accept the panel.
Definition: qgspanelwidget.cpp:107
QgsFieldExpressionWidget::fieldChanged
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QgsProcessingGui::Batch
@ Batch
Batch processing dialog.
Definition: qgsprocessinggui.h:41
QgsMapLayerType::RasterLayer
@ RasterLayer
QgsProcessingParameterLayoutItem
A print layout item parameter, allowing users to select a particular item from a print layout.
Definition: qgsprocessingparameters.h:3338
QgsProcessingParameterField::setDataType
void setDataType(DataType type)
Sets the acceptable data type for the field.
Definition: qgsprocessingparameters.cpp:4978
QgsProcessing::TypeVectorAnyGeometry
@ TypeVectorAnyGeometry
Any vector layer with geometry.
Definition: qgsprocessing.h:47
QgsProcessingParameterNumber::maximum
double maximum() const
Returns the maximum value acceptable by the parameter.
Definition: qgsprocessingparameters.cpp:3891
QgsProcessingParameters::parameterAsInts
static QList< int > parameterAsInts(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of integer values.
Definition: qgsprocessingparameters.cpp:249
QgsProcessingParameterString
A string parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2324
QgsUnitTypes::Standard
@ Standard
Unit is a standard measurement unit.
Definition: qgsunittypes.h:87
QgsDateTimeEdit::setNullRepresentation
void setNullRepresentation(const QString &null)
Sets the widget's null representation, which defaults to QgsApplication::nullRepresentation().
Definition: qgsdatetimeedit.cpp:235
QgsProcessingParameterField::DateTime
@ DateTime
Accepts datetime fields.
Definition: qgsprocessingparameters.h:2626
QgsProcessingParameterExtent
A rectangular map extent parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1570
QgsProcessingParameterString::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2337
qgsprocessingoutputdestinationwidget.h
QgsProcessingParameterEnum::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2270
QgsUnitTypes::DistanceFeet
@ DistanceFeet
Imperial feet.
Definition: qgsunittypes.h:71
QgsRasterLayer::dataProvider
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Definition: qgsrasterlayer.cpp:234
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:924
QgsProcessingParameterProviderConnection::providerId
QString providerId() const
Returns the ID of the provider associated with the connections.
Definition: qgsprocessingparameters.h:3770
QgsProcessingParameterRasterLayer
A raster layer parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2223
QgsFieldComboBox
The QgsFieldComboBox is a combo box which displays the list of fields of a given layer.
Definition: qgsfieldcombobox.h:39
QgsUnitTypes::DistanceMeters
@ DistanceMeters
Meters.
Definition: qgsunittypes.h:69
QgsProcessingParameters::parameterAsLayout
static QgsPrintLayout * parameterAsLayout(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a print layout.
Definition: qgsprocessingparameters.cpp:1931
QgsProcessingParameters::parameterAsPointCrs
static QgsCoordinateReferenceSystem parameterAsPointCrs(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Returns the coordinate reference system associated with an point parameter value.
Definition: qgsprocessingparameters.cpp:1386
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:148
QgsProcessingParameterProviderConnection
A data provider connection parameter for processing algorithms, allowing users to select from availab...
Definition: qgsprocessingparameters.h:3741
QgsProcessingGui::Modeler
@ Modeler
Modeler dialog.
Definition: qgsprocessinggui.h:42
QgsScaleWidget
A combobox which lets the user select map scale from predefined list and highlights nearest to curren...
Definition: qgsscalewidget.h:35
QgsDateTimeEdit::valueChanged
void valueChanged(const QDateTime &date)
Signal emitted whenever the value changes.
qgsmessagebar.h
QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:149
qgsprocessingwidgetwrapperimpl.h
QgsAbstractProcessingParameterWidgetWrapper::linkedVectorLayer
virtual const QgsVectorLayer * linkedVectorLayer() const
Returns the optional vector layer associated with this widget wrapper, or nullptr if no vector layer ...
Definition: qgsprocessingwidgetwrapper.cpp:245
QgsProcessingOutputVectorLayer::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:191
QgsProcessingParameterFile
An input file or folder parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1689
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
QgsProject::mapThemeCollection
QgsMapThemeCollection * mapThemeCollection
Definition: qgsproject.h:103
QgsProcessingParameterVectorLayer
A vector layer (with or without geometry) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2504
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:113
QgsProcessingParameterFeatureSource::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2747
QgsRasterLayer
Represents a raster layer.
Definition: qgsrasterlayer.h:71
QgsExtentWidget
A widget for configuration of a map extent.
Definition: qgsextentwidget.h:51
qgsexpressionbuilderwidget.h
QgsProcessingParameterDatabaseTable::allowNewTableNames
bool allowNewTableNames() const
Returns true if the parameter allows users to enter names for a new (non-existing) tables.
Definition: qgsprocessingparameters.cpp:7796
QgsMasterLayoutInterface::name
virtual QString name() const =0
Returns the layout's name.
QgsProcessingAbstractParameterDefinitionWidget
Abstract base class for widgets which allow users to specify the properties of a Processing parameter...
Definition: qgsprocessingparameterdefinitionwidget.h:44
QgsProcessingParameterFolderDestination::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3204
QgsProcessingParameterNumber::Integer
@ Integer
Integer values.
Definition: qgsprocessingparameters.h:1966
qgsproviderconnectioncombobox.h
QgsProcessingParameterDateTime::Time
@ Time
Time values.
Definition: qgsprocessingparameters.h:3633
QgsProjectionSelectionWidget::CrsNotSet
@ CrsNotSet
Not set (hidden by default)
Definition: qgsprojectionselectionwidget.h:53
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
QgsProcessingParameterLayout
A print layout parameter, allowing users to select a print layout.
Definition: qgsprocessingparameters.h:3300
QgsTimeEdit::timeValueChanged
void timeValueChanged(const QTime &time)
Signal emitted whenever the time changes.
QgsLayoutManager::printLayouts
QList< QgsPrintLayout * > printLayouts() const
Returns a list of all print layouts contained in the manager.
Definition: qgslayoutmanager.cpp:110
QgsProcessingParameterDatabaseSchema
A database schema parameter for processing algorithms, allowing users to select from existing schemas...
Definition: qgsprocessingparameters.h:3800
QgsProcessingParameterDistance
A double numeric parameter for distance values.
Definition: qgsprocessingparameters.h:2063
QgsDateTimeEdit::setAllowNull
void setAllowNull(bool allowNull)
Determines if the widget allows setting null date/time.
Definition: qgsdatetimeedit.cpp:61
QgsProcessingParameterExpression::parentLayerParameterName
QString parentLayerParameterName() const
Returns the name of the parent layer parameter, or an empty string if this is not set.
Definition: qgsprocessingparameters.cpp:4545
QgsProcessingParameterPoint
A point parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1603
QgsProcessingParameterLayoutItem::itemType
int itemType() const
Returns the acceptable item type, or -1 if any item type is allowed.
Definition: qgsprocessingparameters.cpp:6798
QgsSpinBox
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Definition: qgsspinbox.h:43
QgsPointLocator::Match
Definition: qgspointlocator.h:185
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsTimeEdit
The QgsTimeEdit class is a QTimeEdit widget with the capability of setting/reading null date/times.
Definition: qgsdatetimeedit.h:227
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Definition: qgsmapsettings.cpp:318
QgsDatabaseTableComboBox
The QgsDatabaseTableComboBox class is a combo box which displays the list of tables for a specific da...
Definition: qgsdatabasetablecombobox.h:51
QgsProcessingParameterFileDestination::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3145
qgsprocessingoutputs.h
QgsAbstractProcessingParameterWidgetWrapper::createLabel
virtual QLabel * createLabel()
Creates a new label to accompany widgets created by the wrapper.
Definition: qgsprocessingwidgetwrapper.cpp:224
qgsprocessingparameters.h
qgslayoutitemcombobox.h
QgsProcessingParameterNumber::minimum
double minimum() const
Returns the minimum value acceptable by the parameter.
Definition: qgsprocessingparameters.cpp:3881
QgsMapMouseEvent
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
Definition: qgsmapmouseevent.h:36
QgsProcessingParameterDateTime::dataType
Type dataType() const
Returns the acceptable data type for the parameter.
Definition: qgsprocessingparameters.cpp:7361
QgsLayoutItem::uuid
virtual QString uuid() const
Returns the item identification string.
Definition: qgslayoutitem.h:343
QgsGeometry::asWkt
QString asWkt(int precision=17) const
Exports the geometry to WKT.
Definition: qgsgeometry.cpp:1288
QgsProcessingOutputString::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:328
QgsProcessingParameterBoolean
A boolean parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1507
qgslayoutcombobox.h
QgsProcessingGui::WidgetType
WidgetType
Types of dialogs which Processing widgets can be created for.
Definition: qgsprocessinggui.h:39
QgsProcessingParameterDateTime
A datetime (or pure date or time) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:3625
QgsProcessingAlgorithm
Abstract base class for processing algorithms.
Definition: qgsprocessingalgorithm.h:52
c
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
Definition: porting_processing.dox:1
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
qgsexpressionlineedit.h
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsProcessingParameterExpression
An expression parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2416
QgsProcessingParameterExpression::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2429
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsProcessingParameterMapTheme::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3594
QgsAbstractProcessingParameterWidgetWrapper::setDialog
virtual void setDialog(QDialog *dialog)
Sets the parent dialog in which the wrapper is shown.
Definition: qgsprocessingwidgetwrapper.cpp:305
QgsProcessingParameterDistance::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2079
QgsProcessingUtils::variantToCrs
static QgsCoordinateReferenceSystem variantToCrs(const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue=QVariant())
Converts a variant value to a coordinate reference system.
Definition: qgsprocessingutils.cpp:426
QgsAbstractProcessingParameterWidgetWrapper::parameterValue
QVariant parameterValue() const
Returns the current value of the parameter.
Definition: qgsprocessingwidgetwrapper.cpp:201
qgsprintlayout.h
QgsProcessingParameterMatrix::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1806
qgssettings.h
QgsColorButton
A cross platform button subclass for selecting colors.
Definition: qgscolorbutton.h:36
QgsProcessingParameterDateTime::Type
Type
Datetime data type.
Definition: qgsprocessingparameters.h:3630
QgsProcessingParameterBoolean::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1519
QgsProcessing::TypeFile
@ TypeFile
Files (i.e. non map layer sources, such as text files)
Definition: qgsprocessing.h:52
QgsExpressionLineEdit
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
Definition: qgsexpressionlineedit.h:49
QgsUnitTypes::DistanceYards
@ DistanceYards
Imperial yards.
Definition: qgsunittypes.h:73
QgsProcessingParameters::parameterAsLayoutItem
static QgsLayoutItem * parameterAsLayoutItem(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, QgsPrintLayout *layout)
Evaluates the parameter with matching definition to a print layout item, taken from the specified lay...
Definition: qgsprocessingparameters.cpp:1955
QgsScaleWidget::scaleChanged
void scaleChanged(double scale)
Emitted when user has finished editing/selecting a new scale.
qgsdatumtransformdialog.h
QgsDoubleSpinBox
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Definition: qgsdoublespinbox.h:43
QgsProcessingParameterBand
A raster band parameter for Processing algorithms.
Definition: qgsprocessingparameters.h:3225
qgsprocessingcontext.h
qgsprocessingmatrixparameterdialog.h
QgsUnitTypes::DistanceMiles
@ DistanceMiles
Terrestrial miles.
Definition: qgsunittypes.h:74
QgsCheckableComboBox
QComboBox subclass which allows selecting multiple items.
Definition: qgscheckablecombobox.h:125
QgsLayoutItemComboBox::itemChanged
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
QgsLayoutComboBox::layoutChanged
void layoutChanged(QgsMasterLayoutInterface *layout)
Emitted whenever the currently selected layout changes.
QgsProcessingParameterWidgetContext::model
QgsProcessingModelAlgorithm * model() const
Returns the model which the parameter widget is associated with.
Definition: qgsprocessingwidgetwrapper.cpp:94
qgsfieldexpressionwidget.h
QgsProcessingParameterVectorLayer::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2519
QgsProcessingParameterScale::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2149
qgsfilewidget.h
QgsProcessingParameterCoordinateOperation::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3490
QgsRasterInterface::bandCount
virtual int bandCount() const =0
Gets number of bands.
QgsProcessingParameters::parameterAsExpression
static QString parameterAsExpression(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to an expression.
Definition: qgsprocessingparameters.cpp:152
QgsProcessingOutputNumber::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:306
QgsProcessingParameters::parameterAsColor
static QColor parameterAsColor(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Returns the color associated with an point parameter value, or an invalid color if the parameter was ...
Definition: qgsprocessingparameters.cpp:1981
QgsProcessingParameterDefinition::type
virtual QString type() const =0
Unique parameter type name.
QgsProject::layoutManager
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages print layouts, atlases and reports within the pro...
Definition: qgsproject.cpp:3050
QgsMasterLayoutInterface
Interface for master layout type objects, such as print layouts and reports.
Definition: qgsmasterlayoutinterface.h:43
QgsProcessingParameterEnum
An enum based parameter for processing algorithms, allowing for selection from predefined values.
Definition: qgsprocessingparameters.h:2256
qgsprocessingmultipleselectiondialog.h
QgsAbstractProcessingParameterWidgetWrapper::widgetContext
const QgsProcessingParameterWidgetContext & widgetContext() const
Returns the context in which the Processing parameter widget is shown, e.g., the parent model algorit...
Definition: qgsprocessingwidgetwrapper.cpp:126
QgsProcessingParameterDefinition::FlagOptional
@ FlagOptional
Parameter is optional.
Definition: qgsprocessingparameters.h:425
QgsProcessingParameterCoordinateOperation
A coordinate operation parameter for processing algorithms, for selection between available coordinat...
Definition: qgsprocessingparameters.h:3476
QgsProcessingParameterDefinition::defaultValue
QVariant defaultValue() const
Returns the default value for the parameter.
Definition: qgsprocessingparameters.h:509
qgsauthconfigselect.h
QgsProcessingParameterField::Any
@ Any
Accepts any field.
Definition: qgsprocessingparameters.h:2623
QgsProcessingParameterNumber::Type
Type
Numeric data type.
Definition: qgsprocessingparameters.h:1965
qgsmapmouseevent.h
QgsAbstractProcessingParameterWidgetWrapper::parameterDefinition
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
Definition: qgsprocessingwidgetwrapper.cpp:181
QgsProcessingParameterField::dataType
DataType dataType() const
Returns the acceptable data type for the field.
Definition: qgsprocessingparameters.cpp:4973
QgsProcessingParameters::parameterAsEnum
static int parameterAsEnum(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a enum value.
Definition: qgsprocessingparameters.cpp:423
QgsFieldExpressionWidget
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
Definition: qgsfieldexpressionwidget.h:47
QgsProcessingParameterFile::behavior
Behavior behavior() const
Returns the parameter behavior (e.g.
Definition: qgsprocessingparameters.h:1723
QgsFileWidget
The QgsFileWidget class creates a widget for selecting a file or a folder.
Definition: qgsfilewidget.h:37
QgsProcessingParameterNumber::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1984
QgsProcessing::SourceType
SourceType
Data source types enum.
Definition: qgsprocessing.h:45
QgsProcessingParameterCoordinateOperation::sourceCrs
QVariant sourceCrs() const
Returns the static source CRS, or an invalid value if this is not set.
Definition: qgsprocessingparameters.h:3539
QgsProcessingParameterDateTime::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3650
QgsExpressionLineEdit::expressionChanged
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
QgsProcessingParameterField
A vector layer or feature source field parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2617
QgsRasterDataProvider
Base class for raster data providers.
Definition: qgsrasterdataprovider.h:89
QgsProcessingParameterCrs::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:1550
QgsProcessingParameters::parameterAsTime
static QTime parameterAsTime(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static time value.
Definition: qgsprocessingparameters.cpp:380
qgsproject.h
QgsProcessingParameterDateTime::Date
@ Date
Date values.
Definition: qgsprocessingparameters.h:3632
QgsMessageBar::pushMessage
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::Info, int duration=5)
A convenience method for pushing a message with the specified text to the bar.
Definition: qgsmessagebar.cpp:379
QgsProcessingParameters::parameterAsDouble
static double parameterAsDouble(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static double value.
Definition: qgsprocessingparameters.cpp:180
QgsFieldComboBox::fieldChanged
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QgsProcessingParameters::parameterAsInt
static int parameterAsInt(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static integer value.
Definition: qgsprocessingparameters.cpp:207
QgsProcessingParameters::parameterAsSource
static QgsProcessingFeatureSource * parameterAsSource(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a feature source.
Definition: qgsprocessingparameters.cpp:651
QgsExpressionBuilderWidget::expressionParsed
void expressionParsed(bool isValid)
Emitted when the user changes the expression in the widget.
QgsProcessingParameterMapLayer::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:2591
QgsProcessingParameterFile::Behavior
Behavior
Parameter behavior.
Definition: qgsprocessingparameters.h:1694
QgsProcessingParameterDatabaseSchema::typeName
static QString typeName()
Returns the type name for the parameter class.
Definition: qgsprocessingparameters.h:3817
QgsProcessingParameterColor::opacityEnabled
bool opacityEnabled() const
Returns true if the parameter allows opacity control.
Definition: qgsprocessingparameters.cpp:6920
QgsRasterBandComboBox::displayBandName
static QString displayBandName(QgsRasterDataProvider *provider, int band)
Returns a user-friendly band name for the specified band.
Definition: qgsrasterbandcombobox.cpp:164
QgsProcessingParameterWidgetContext::messageBar
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
Definition: qgsprocessingwidgetwrapper.cpp:49
QgsProcessingParameterDefinition::setFlags
void setFlags(Flags flags)
Sets the flags associated with the parameter.
Definition: qgsprocessingparameters.h:528
QgsProcessingParameters::parameterAsBool
static bool parameterAsBool(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static boolean value.
Definition: qgsprocessingparameters.cpp:514
QgsAbstractProcessingParameterWidgetWrapper::postInitialize
virtual void postInitialize(const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers)
Called after all wrappers have been created within a particular dialog or context,...
Definition: qgsprocessingwidgetwrapper.cpp:252
QgsCoordinateOperationWidget::operationChanged
void operationChanged()
Emitted when the operation selected in the dialog is changed.
QgsProcessingParameters::parameterAsString
static QString parameterAsString(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static string value.
Definition: qgsprocessingparameters.cpp:120
qgsdatabaseschemacombobox.h
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50
QgsProcessingOutputFile::typeName
static QString typeName()
Returns the type name for the output class.
Definition: qgsprocessingoutputs.h:397