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