QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
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
2449 if ( mParam->usesStaticStrings() )
2450 {
2451 for ( QString o : mParam->options() )
2452 {
2453 availableOptions << o;
2454 }
2455 }
2456 else
2457 {
2458 for ( int i = 0; i < mParam->options().count(); ++i )
2459 availableOptions << i;
2460 }
2461 }
2462
2463 const QStringList options = mParam ? mParam->options() : QStringList();
2465 if ( panel && panel->dockMode() )
2466 {
2467 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
2468 widget->setPanelTitle( mParam->description() );
2469
2470 if ( mParam->usesStaticStrings() )
2471 {
2472 widget->setValueFormatter( [options]( const QVariant & v ) -> QString
2473 {
2474 const QString i = v.toString();
2475 return options.contains( i ) ? i : QString();
2476 } );
2477 }
2478 else
2479 {
2480 widget->setValueFormatter( [options]( const QVariant & v ) -> QString
2481 {
2482 const int i = v.toInt();
2483 return options.size() > i ? options.at( i ) : QString();
2484 } );
2485 }
2486
2487 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
2488 {
2489 setValue( widget->selectedOptions() );
2490 } );
2491 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
2492 panel->openPanel( widget );
2493 }
2494 else
2495 {
2496 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
2497
2498 dlg.setValueFormatter( [options]( const QVariant & v ) -> QString
2499 {
2500 const int i = v.toInt();
2501 return options.size() > i ? options.at( i ) : QString();
2502 } );
2503 if ( dlg.exec() )
2504 {
2505 setValue( dlg.selectedOptions() );
2506 }
2507 }
2508}
2509
2510void QgsProcessingEnumPanelWidget::updateSummaryText()
2511{
2512 if ( !mParam )
2513 return;
2514
2515 if ( mValue.empty() )
2516 {
2517 mLineEdit->setText( tr( "%1 options selected" ).arg( 0 ) );
2518 }
2519 else
2520 {
2521 QStringList values;
2522 values.reserve( mValue.size() );
2523 if ( mParam->usesStaticStrings() )
2524 {
2525 for ( const QVariant &val : std::as_const( mValue ) )
2526 {
2527 values << val.toString();
2528 }
2529 }
2530 else
2531 {
2532 const QStringList options = mParam->options();
2533 for ( const QVariant &val : std::as_const( mValue ) )
2534 {
2535 const int i = val.toInt();
2536 values << ( options.size() > i ? options.at( i ) : QString() );
2537 }
2538 }
2539
2540 const QString concatenated = values.join( tr( "," ) );
2541 if ( concatenated.length() < 100 )
2542 mLineEdit->setText( concatenated );
2543 else
2544 mLineEdit->setText( tr( "%n option(s) selected", nullptr, mValue.count() ) );
2545 }
2546}
2547
2548
2549//
2550// QgsProcessingEnumCheckboxPanelWidget
2551//
2552QgsProcessingEnumCheckboxPanelWidget::QgsProcessingEnumCheckboxPanelWidget( QWidget *parent, const QgsProcessingParameterEnum *param, int columns )
2553 : QWidget( parent )
2554 , mParam( param )
2555 , mButtonGroup( new QButtonGroup( this ) )
2556 , mColumns( columns )
2557{
2558 mButtonGroup->setExclusive( !mParam->allowMultiple() );
2559
2560 QGridLayout *l = new QGridLayout();
2561 l->setContentsMargins( 0, 0, 0, 0 );
2562
2563 int rows = static_cast< int >( std::ceil( mParam->options().count() / static_cast< double >( mColumns ) ) );
2564 for ( int i = 0; i < mParam->options().count(); ++i )
2565 {
2566 QAbstractButton *button = nullptr;
2567 if ( mParam->allowMultiple() )
2568 button = new QCheckBox( mParam->options().at( i ) );
2569 else
2570 button = new QRadioButton( mParam->options().at( i ) );
2571
2572 connect( button, &QAbstractButton::toggled, this, [ = ]
2573 {
2574 if ( !mBlockChangedSignal )
2575 emit changed();
2576 } );
2577
2578 mButtons.insert( i, button );
2579
2580 mButtonGroup->addButton( button, i );
2581 l->addWidget( button, i % rows, i / rows );
2582 }
2583 l->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, mColumns );
2584 setLayout( l );
2585
2586 if ( mParam->allowMultiple() )
2587 {
2588 setContextMenuPolicy( Qt::CustomContextMenu );
2589 connect( this, &QWidget::customContextMenuRequested, this, &QgsProcessingEnumCheckboxPanelWidget::showPopupMenu );
2590 }
2591}
2592
2593QVariant QgsProcessingEnumCheckboxPanelWidget::value() const
2594{
2595 if ( mParam->allowMultiple() )
2596 {
2597 QVariantList value;
2598 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2599 {
2600 if ( it.value()->isChecked() )
2601 value.append( mParam->usesStaticStrings() ? mParam->options().at( it.key().toInt() ) : it.key() );
2602 }
2603 return value;
2604 }
2605 else
2606 {
2607 if ( mParam->usesStaticStrings() )
2608 return mButtonGroup->checkedId() >= 0 ? mParam->options().at( mButtonGroup->checkedId() ) : QVariant();
2609 else
2610 return mButtonGroup->checkedId() >= 0 ? mButtonGroup->checkedId() : QVariant();
2611 }
2612}
2613
2614void QgsProcessingEnumCheckboxPanelWidget::setValue( const QVariant &value )
2615{
2616 mBlockChangedSignal = true;
2617 if ( mParam->allowMultiple() )
2618 {
2619 QVariantList selected;
2620 if ( value.isValid() )
2621 selected = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
2622 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2623 {
2624 QVariant v = mParam->usesStaticStrings() ? mParam->options().at( it.key().toInt() ) : it.key();
2625 it.value()->setChecked( selected.contains( v ) );
2626 }
2627 }
2628 else
2629 {
2630 QVariant v = value;
2631 if ( v.type() == QVariant::List )
2632 v = v.toList().value( 0 );
2633
2634 v = mParam->usesStaticStrings() ? mParam->options().indexOf( v.toString() ) : v;
2635 if ( mButtons.contains( v ) )
2636 mButtons.value( v )->setChecked( true );
2637 }
2638 mBlockChangedSignal = false;
2639 emit changed();
2640}
2641
2642void QgsProcessingEnumCheckboxPanelWidget::showPopupMenu()
2643{
2644 QMenu popupMenu;
2645 QAction *selectAllAction = new QAction( tr( "Select All" ), &popupMenu );
2646 connect( selectAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::selectAll );
2647 QAction *clearAllAction = new QAction( tr( "Clear Selection" ), &popupMenu );
2648 connect( clearAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::deselectAll );
2649 popupMenu.addAction( selectAllAction );
2650 popupMenu.addAction( clearAllAction );
2651 popupMenu.exec( QCursor::pos() );
2652}
2653
2654void QgsProcessingEnumCheckboxPanelWidget::selectAll()
2655{
2656 mBlockChangedSignal = true;
2657 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2658 it.value()->setChecked( true );
2659 mBlockChangedSignal = false;
2660 emit changed();
2661}
2662
2663void QgsProcessingEnumCheckboxPanelWidget::deselectAll()
2664{
2665 mBlockChangedSignal = true;
2666 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2667 it.value()->setChecked( false );
2668 mBlockChangedSignal = false;
2669 emit changed();
2670}
2671
2672
2673//
2674// QgsProcessingEnumWidgetWrapper
2675//
2676
2677QgsProcessingEnumParameterDefinitionWidget::QgsProcessingEnumParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2678 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2679{
2680 QVBoxLayout *vlayout = new QVBoxLayout();
2681 vlayout->setContentsMargins( 0, 0, 0, 0 );
2682
2683 mEnumWidget = new QgsProcessingEnumModelerWidget();
2684 if ( const QgsProcessingParameterEnum *enumParam = dynamic_cast<const QgsProcessingParameterEnum *>( definition ) )
2685 {
2686 mEnumWidget->setAllowMultiple( enumParam->allowMultiple() );
2687 mEnumWidget->setOptions( enumParam->options() );
2688 mEnumWidget->setDefaultOptions( enumParam->defaultValueForGui() );
2689 }
2690 vlayout->addWidget( mEnumWidget );
2691 setLayout( vlayout );
2692}
2693
2694QgsProcessingParameterDefinition *QgsProcessingEnumParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2695{
2696 auto param = std::make_unique< QgsProcessingParameterEnum >( name, description, mEnumWidget->options(), mEnumWidget->allowMultiple(), mEnumWidget->defaultOptions() );
2697 param->setFlags( flags );
2698 return param.release();
2699}
2700
2701
2702QgsProcessingEnumWidgetWrapper::QgsProcessingEnumWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2703 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2704{
2705
2706}
2707
2708QWidget *QgsProcessingEnumWidgetWrapper::createWidget()
2709{
2710 const QgsProcessingParameterEnum *expParam = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2711 switch ( type() )
2712 {
2714 {
2715 // checkbox panel only for use outside in standard gui!
2716 if ( expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "useCheckBoxes" ), false ).toBool() )
2717 {
2718 const int columns = expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "columns" ), 2 ).toInt();
2719 mCheckboxPanel = new QgsProcessingEnumCheckboxPanelWidget( nullptr, expParam, columns );
2720 mCheckboxPanel->setToolTip( parameterDefinition()->toolTip() );
2721 connect( mCheckboxPanel, &QgsProcessingEnumCheckboxPanelWidget::changed, this, [ = ]
2722 {
2723 emit widgetValueHasChanged( this );
2724 } );
2725 return mCheckboxPanel;
2726 }
2727 }
2731 {
2732 if ( expParam->allowMultiple() )
2733 {
2734 mPanel = new QgsProcessingEnumPanelWidget( nullptr, expParam );
2735 mPanel->setToolTip( parameterDefinition()->toolTip() );
2736 connect( mPanel, &QgsProcessingEnumPanelWidget::changed, this, [ = ]
2737 {
2738 emit widgetValueHasChanged( this );
2739 } );
2740 return mPanel;
2741 }
2742 else
2743 {
2744 mComboBox = new QComboBox();
2745
2747 mComboBox->addItem( tr( "[Not selected]" ), QVariant() );
2748 const QStringList options = expParam->options();
2749 const QVariantList iconList = expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "icons" ) ).toList();
2750 for ( int i = 0; i < options.count(); ++i )
2751 {
2752 const QIcon icon = iconList.value( i ).value< QIcon >();
2753
2754 if ( expParam->usesStaticStrings() )
2755 mComboBox->addItem( icon, options.at( i ), options.at( i ) );
2756 else
2757 mComboBox->addItem( icon, options.at( i ), i );
2758 }
2759
2760 mComboBox->setToolTip( parameterDefinition()->toolTip() );
2761 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
2762 {
2763 emit widgetValueHasChanged( this );
2764 } );
2765 return mComboBox;
2766 }
2767 }
2768 }
2769 return nullptr;
2770}
2771
2772void QgsProcessingEnumWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2773{
2774 if ( mComboBox )
2775 {
2776 if ( !value.isValid() )
2777 mComboBox->setCurrentIndex( mComboBox->findData( QVariant() ) );
2778 else
2779 {
2780 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2781 if ( enumDef->usesStaticStrings() )
2782 {
2783 const QString v = QgsProcessingParameters::parameterAsEnumString( parameterDefinition(), value, context );
2784 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
2785 }
2786 else
2787 {
2788 const int v = QgsProcessingParameters::parameterAsEnum( parameterDefinition(), value, context );
2789 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
2790 }
2791 }
2792 }
2793 else if ( mPanel || mCheckboxPanel )
2794 {
2795 QVariantList opts;
2796 if ( value.isValid() )
2797 {
2798 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2799 if ( enumDef->usesStaticStrings() )
2800 {
2801 const QStringList v = QgsProcessingParameters::parameterAsEnumStrings( parameterDefinition(), value, context );
2802 opts.reserve( v.size() );
2803 for ( QString i : v )
2804 opts << i;
2805 }
2806 else
2807 {
2808 const QList< int > v = QgsProcessingParameters::parameterAsEnums( parameterDefinition(), value, context );
2809 opts.reserve( v.size() );
2810 for ( int i : v )
2811 opts << i;
2812 }
2813 }
2814 if ( mPanel )
2815 mPanel->setValue( opts );
2816 else if ( mCheckboxPanel )
2817 mCheckboxPanel->setValue( opts );
2818 }
2819}
2820
2821QVariant QgsProcessingEnumWidgetWrapper::widgetValue() const
2822{
2823 if ( mComboBox )
2824 return mComboBox->currentData();
2825 else if ( mPanel )
2826 return mPanel->value();
2827 else if ( mCheckboxPanel )
2828 return mCheckboxPanel->value();
2829 else
2830 return QVariant();
2831}
2832
2833QStringList QgsProcessingEnumWidgetWrapper::compatibleParameterTypes() const
2834{
2835 return QStringList()
2839}
2840
2841QStringList QgsProcessingEnumWidgetWrapper::compatibleOutputTypes() const
2842{
2843 return QStringList()
2846}
2847
2848QString QgsProcessingEnumWidgetWrapper::modelerExpressionFormatString() const
2849{
2850 return tr( "selected option index (starting from 0), array of indices, or comma separated string of options (e.g. '1,3')" );
2851}
2852
2853QString QgsProcessingEnumWidgetWrapper::parameterType() const
2854{
2856}
2857
2858QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingEnumWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2859{
2860 return new QgsProcessingEnumWidgetWrapper( parameter, type );
2861}
2862
2863QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingEnumWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2864{
2865 return new QgsProcessingEnumParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2866}
2867
2868//
2869// QgsProcessingLayoutWidgetWrapper
2870//
2871
2872QgsProcessingLayoutWidgetWrapper::QgsProcessingLayoutWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2873 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2874{
2875
2876}
2877
2878QWidget *QgsProcessingLayoutWidgetWrapper::createWidget()
2879{
2880 const QgsProcessingParameterLayout *layoutParam = dynamic_cast< const QgsProcessingParameterLayout *>( parameterDefinition() );
2881 switch ( type() )
2882 {
2885 {
2886 // combobox only for use outside modeler!
2887 mComboBox = new QgsLayoutComboBox( nullptr, widgetContext().project() ? widgetContext().project()->layoutManager() : nullptr );
2889 mComboBox->setAllowEmptyLayout( true );
2890 mComboBox->setFilters( QgsLayoutManagerProxyModel::FilterPrintLayouts );
2891
2892 mComboBox->setToolTip( parameterDefinition()->toolTip() );
2893 connect( mComboBox, &QgsLayoutComboBox::layoutChanged, this, [ = ]( QgsMasterLayoutInterface * )
2894 {
2895 emit widgetValueHasChanged( this );
2896 } );
2897 return mComboBox;
2898 }
2899
2901 {
2902 mPlainComboBox = new QComboBox();
2903 mPlainComboBox->setEditable( true );
2904 mPlainComboBox->setToolTip( tr( "Name of an existing print layout" ) );
2905 if ( widgetContext().project() )
2906 {
2907 const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2908 for ( const QgsPrintLayout *layout : layouts )
2909 mPlainComboBox->addItem( layout->name() );
2910 }
2911
2912 connect( mPlainComboBox, &QComboBox::currentTextChanged, this, [ = ]( const QString & )
2913 {
2914 emit widgetValueHasChanged( this );
2915 } );
2916 return mPlainComboBox;
2917 }
2918 }
2919 return nullptr;
2920}
2921
2922void QgsProcessingLayoutWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2923{
2924 if ( mComboBox )
2925 {
2926 if ( !value.isValid() )
2927 mComboBox->setCurrentLayout( nullptr );
2928 else
2929 {
2930 if ( QgsPrintLayout *l = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, context ) )
2931 mComboBox->setCurrentLayout( l );
2932 else
2933 mComboBox->setCurrentLayout( nullptr );
2934 }
2935 }
2936 else if ( mPlainComboBox )
2937 {
2938 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2939 mPlainComboBox->setCurrentText( v );
2940 }
2941}
2942
2943QVariant QgsProcessingLayoutWidgetWrapper::widgetValue() const
2944{
2945 if ( mComboBox )
2946 {
2947 const QgsMasterLayoutInterface *l = mComboBox->currentLayout();
2948 return l ? l->name() : QVariant();
2949 }
2950 else if ( mPlainComboBox )
2951 return mPlainComboBox->currentText().isEmpty() ? QVariant() : mPlainComboBox->currentText();
2952 else
2953 return QVariant();
2954}
2955
2956void QgsProcessingLayoutWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
2957{
2959 if ( mPlainComboBox && context.project() )
2960 {
2961 const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2962 for ( const QgsPrintLayout *layout : layouts )
2963 mPlainComboBox->addItem( layout->name() );
2964 }
2965}
2966
2967QStringList QgsProcessingLayoutWidgetWrapper::compatibleParameterTypes() const
2968{
2969 return QStringList()
2972}
2973
2974QStringList QgsProcessingLayoutWidgetWrapper::compatibleOutputTypes() const
2975{
2976 return QStringList()
2978}
2979
2980QString QgsProcessingLayoutWidgetWrapper::modelerExpressionFormatString() const
2981{
2982 return tr( "string representing the name of an existing print layout" );
2983}
2984
2985QString QgsProcessingLayoutWidgetWrapper::parameterType() const
2986{
2988}
2989
2990QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2991{
2992 return new QgsProcessingLayoutWidgetWrapper( parameter, type );
2993}
2994
2995
2996
2997
2998//
2999// QgsProcessingLayoutItemWidgetWrapper
3000//
3001
3002
3003QgsProcessingLayoutItemParameterDefinitionWidget::QgsProcessingLayoutItemParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3004 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3005{
3006 QVBoxLayout *vlayout = new QVBoxLayout();
3007 vlayout->setContentsMargins( 0, 0, 0, 0 );
3008
3009 vlayout->addWidget( new QLabel( tr( "Parent layout" ) ) );
3010
3011 mParentLayoutComboBox = new QComboBox();
3012 QString initialParent;
3013 if ( const QgsProcessingParameterLayoutItem *itemParam = dynamic_cast<const QgsProcessingParameterLayoutItem *>( definition ) )
3014 initialParent = itemParam->parentLayoutParameterName();
3015
3016 if ( auto *lModel = widgetContext.model() )
3017 {
3018 // populate combo box with other model input choices
3019 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
3020 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
3021 {
3022 if ( const QgsProcessingParameterLayout *definition = dynamic_cast< const QgsProcessingParameterLayout * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
3023 {
3024 mParentLayoutComboBox-> addItem( definition->description(), definition->name() );
3025 if ( !initialParent.isEmpty() && initialParent == definition->name() )
3026 {
3027 mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
3028 }
3029 }
3030 }
3031 }
3032
3033 if ( mParentLayoutComboBox->count() == 0 && !initialParent.isEmpty() )
3034 {
3035 // if no parent candidates found, we just add the existing one as a placeholder
3036 mParentLayoutComboBox->addItem( initialParent, initialParent );
3037 mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
3038 }
3039
3040 vlayout->addWidget( mParentLayoutComboBox );
3041 setLayout( vlayout );
3042}
3043QgsProcessingParameterDefinition *QgsProcessingLayoutItemParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3044{
3045 auto param = std::make_unique< QgsProcessingParameterLayoutItem >( name, description, QVariant(), mParentLayoutComboBox->currentData().toString() );
3046 param->setFlags( flags );
3047 return param.release();
3048}
3049
3050
3051QgsProcessingLayoutItemWidgetWrapper::QgsProcessingLayoutItemWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3052 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3053{
3054
3055}
3056
3057QWidget *QgsProcessingLayoutItemWidgetWrapper::createWidget()
3058{
3059 const QgsProcessingParameterLayoutItem *layoutParam = dynamic_cast< const QgsProcessingParameterLayoutItem *>( parameterDefinition() );
3060 switch ( type() )
3061 {
3064 {
3065 // combobox only for use outside modeler!
3066 mComboBox = new QgsLayoutItemComboBox( nullptr, nullptr );
3068 mComboBox->setAllowEmptyItem( true );
3069 if ( layoutParam->itemType() >= 0 )
3070 mComboBox->setItemType( static_cast< QgsLayoutItemRegistry::ItemType >( layoutParam->itemType() ) );
3071
3072 mComboBox->setToolTip( parameterDefinition()->toolTip() );
3073 connect( mComboBox, &QgsLayoutItemComboBox::itemChanged, this, [ = ]( QgsLayoutItem * )
3074 {
3075 emit widgetValueHasChanged( this );
3076 } );
3077 return mComboBox;
3078 }
3079
3081 {
3082 mLineEdit = new QLineEdit();
3083 mLineEdit->setToolTip( tr( "UUID or ID of an existing print layout item" ) );
3084 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3085 {
3086 emit widgetValueHasChanged( this );
3087 } );
3088 return mLineEdit;
3089 }
3090 }
3091 return nullptr;
3092}
3093
3094void QgsProcessingLayoutItemWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3095{
3097 switch ( type() )
3098 {
3101 {
3102 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3103 {
3104 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterLayoutItem * >( parameterDefinition() )->parentLayoutParameterName() )
3105 {
3106 setLayoutParameterValue( wrapper->parameterValue() );
3108 {
3109 setLayoutParameterValue( wrapper->parameterValue() );
3110 } );
3111 break;
3112 }
3113 }
3114 break;
3115 }
3116
3118 break;
3119 }
3120}
3121
3122void QgsProcessingLayoutItemWidgetWrapper::setLayoutParameterValue( const QVariant &value )
3123{
3124 QgsPrintLayout *layout = nullptr;
3125
3126 // evaluate value to layout
3127 QgsProcessingContext *context = nullptr;
3128 std::unique_ptr< QgsProcessingContext > tmpContext;
3129 if ( mProcessingContextGenerator )
3130 context = mProcessingContextGenerator->processingContext();
3131
3132 if ( !context )
3133 {
3134 tmpContext = std::make_unique< QgsProcessingContext >();
3135 context = tmpContext.get();
3136 }
3137
3138 layout = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, *context );
3139 setLayout( layout );
3140}
3141
3142void QgsProcessingLayoutItemWidgetWrapper::setLayout( QgsPrintLayout *layout )
3143{
3144 if ( mComboBox )
3145 mComboBox->setCurrentLayout( layout );
3146}
3147
3148void QgsProcessingLayoutItemWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3149{
3150 if ( mComboBox )
3151 {
3152 if ( !value.isValid() )
3153 mComboBox->setItem( nullptr );
3154 else
3155 {
3156 QgsLayoutItem *item = QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition(), value, context, qobject_cast< QgsPrintLayout * >( mComboBox->currentLayout() ) );
3157 mComboBox->setItem( item );
3158 }
3159 }
3160 else if ( mLineEdit )
3161 {
3162 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3163 mLineEdit->setText( v );
3164 }
3165}
3166
3167QVariant QgsProcessingLayoutItemWidgetWrapper::widgetValue() const
3168{
3169 if ( mComboBox )
3170 {
3171 const QgsLayoutItem *i = mComboBox->currentItem();
3172 return i ? i->uuid() : QVariant();
3173 }
3174 else if ( mLineEdit )
3175 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3176 else
3177 return QVariant();
3178}
3179
3180QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleParameterTypes() const
3181{
3182 return QStringList()
3185}
3186
3187QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleOutputTypes() const
3188{
3189 return QStringList()
3191}
3192
3193QString QgsProcessingLayoutItemWidgetWrapper::modelerExpressionFormatString() const
3194{
3195 return tr( "string representing the UUID or ID of an existing print layout item" );
3196}
3197
3198QString QgsProcessingLayoutItemWidgetWrapper::parameterType() const
3199{
3201}
3202
3203QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutItemWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3204{
3205 return new QgsProcessingLayoutItemWidgetWrapper( parameter, type );
3206}
3207
3208QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingLayoutItemWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3209{
3210 return new QgsProcessingLayoutItemParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3211}
3212
3213//
3214// QgsProcessingPointMapTool
3215//
3216
3217QgsProcessingPointMapTool::QgsProcessingPointMapTool( QgsMapCanvas *canvas )
3218 : QgsMapTool( canvas )
3219{
3221 mSnapIndicator.reset( new QgsSnapIndicator( canvas ) );
3222}
3223
3224QgsProcessingPointMapTool::~QgsProcessingPointMapTool() = default;
3225
3226void QgsProcessingPointMapTool::deactivate()
3227{
3228 mSnapIndicator->setMatch( QgsPointLocator::Match() );
3230}
3231
3232void QgsProcessingPointMapTool::canvasMoveEvent( QgsMapMouseEvent *e )
3233{
3234 e->snapPoint();
3235 mSnapIndicator->setMatch( e->mapPointMatch() );
3236}
3237
3238void QgsProcessingPointMapTool::canvasPressEvent( QgsMapMouseEvent *e )
3239{
3240 if ( e->button() == Qt::LeftButton )
3241 {
3242 QgsPointXY point = e->snapPoint();
3243 emit clicked( point );
3244 emit complete();
3245 }
3246}
3247
3248void QgsProcessingPointMapTool::keyPressEvent( QKeyEvent *e )
3249{
3250 if ( e->key() == Qt::Key_Escape )
3251 {
3252
3253 // Override default shortcut management in MapCanvas
3254 e->ignore();
3255 emit complete();
3256 }
3257}
3258
3259
3260
3261//
3262// QgsProcessingPointPanel
3263//
3264
3265QgsProcessingPointPanel::QgsProcessingPointPanel( QWidget *parent )
3266 : QWidget( parent )
3267{
3268 QHBoxLayout *l = new QHBoxLayout();
3269 l->setContentsMargins( 0, 0, 0, 0 );
3270 mLineEdit = new QgsFilterLineEdit( );
3271 mLineEdit->setShowClearButton( false );
3272 l->addWidget( mLineEdit, 1 );
3273 mButton = new QToolButton();
3274 mButton->setText( QString( QChar( 0x2026 ) ) );
3275 l->addWidget( mButton );
3276 setLayout( l );
3277
3278 connect( mLineEdit, &QLineEdit::textChanged, this, &QgsProcessingPointPanel::changed );
3279 connect( mButton, &QToolButton::clicked, this, &QgsProcessingPointPanel::selectOnCanvas );
3280 mButton->setVisible( false );
3281}
3282
3283void QgsProcessingPointPanel::setMapCanvas( QgsMapCanvas *canvas )
3284{
3285 mCanvas = canvas;
3286 mButton->setVisible( true );
3287
3288 mCrs = canvas->mapSettings().destinationCrs();
3289 mTool = std::make_unique< QgsProcessingPointMapTool >( mCanvas );
3290 connect( mTool.get(), &QgsProcessingPointMapTool::clicked, this, &QgsProcessingPointPanel::updatePoint );
3291 connect( mTool.get(), &QgsProcessingPointMapTool::complete, this, &QgsProcessingPointPanel::pointPicked );
3292}
3293
3294void QgsProcessingPointPanel::setAllowNull( bool allowNull )
3295{
3296 mLineEdit->setShowClearButton( allowNull );
3297}
3298
3299QVariant QgsProcessingPointPanel::value() const
3300{
3301 return mLineEdit->showClearButton() && mLineEdit->text().trimmed().isEmpty() ? QVariant() : QVariant( mLineEdit->text() );
3302}
3303
3304void QgsProcessingPointPanel::clear()
3305{
3306 mLineEdit->clear();
3307}
3308
3309void QgsProcessingPointPanel::setValue( const QgsPointXY &point, const QgsCoordinateReferenceSystem &crs )
3310{
3311 QString newText = QStringLiteral( "%1,%2" )
3312 .arg( QString::number( point.x(), 'f' ),
3313 QString::number( point.y(), 'f' ) );
3314
3315 mCrs = crs;
3316 if ( mCrs.isValid() )
3317 {
3318 newText += QStringLiteral( " [%1]" ).arg( mCrs.authid() );
3319 }
3320 mLineEdit->setText( newText );
3321}
3322
3323void QgsProcessingPointPanel::selectOnCanvas()
3324{
3325 if ( !mCanvas )
3326 return;
3327
3328 mPrevTool = mCanvas->mapTool();
3329 mCanvas->setMapTool( mTool.get() );
3330
3331 emit toggleDialogVisibility( false );
3332}
3333
3334void QgsProcessingPointPanel::updatePoint( const QgsPointXY &point )
3335{
3336 setValue( point, mCanvas->mapSettings().destinationCrs() );
3337}
3338
3339void QgsProcessingPointPanel::pointPicked()
3340{
3341 if ( !mCanvas )
3342 return;
3343
3344 mCanvas->setMapTool( mPrevTool );
3345
3346 emit toggleDialogVisibility( true );
3347}
3348
3349
3350
3351//
3352// QgsProcessingPointWidgetWrapper
3353//
3354
3355QgsProcessingPointParameterDefinitionWidget::QgsProcessingPointParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3356 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3357{
3358 QVBoxLayout *vlayout = new QVBoxLayout();
3359 vlayout->setContentsMargins( 0, 0, 0, 0 );
3360
3361 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3362
3363 mDefaultLineEdit = new QLineEdit();
3364 mDefaultLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3365 mDefaultLineEdit->setPlaceholderText( tr( "Point as 'x,y'" ) );
3366 if ( const QgsProcessingParameterPoint *pointParam = dynamic_cast<const QgsProcessingParameterPoint *>( definition ) )
3367 {
3368 QgsPointXY point = QgsProcessingParameters::parameterAsPoint( pointParam, pointParam->defaultValueForGui(), context );
3369 mDefaultLineEdit->setText( QStringLiteral( "%1,%2" ).arg( QString::number( point.x(), 'f' ), QString::number( point.y(), 'f' ) ) );
3370 }
3371
3372 vlayout->addWidget( mDefaultLineEdit );
3373 setLayout( vlayout );
3374}
3375
3376QgsProcessingParameterDefinition *QgsProcessingPointParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3377{
3378 auto param = std::make_unique< QgsProcessingParameterPoint >( name, description, mDefaultLineEdit->text() );
3379 param->setFlags( flags );
3380 return param.release();
3381}
3382
3383QgsProcessingPointWidgetWrapper::QgsProcessingPointWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3384 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3385{
3386
3387}
3388
3389QWidget *QgsProcessingPointWidgetWrapper::createWidget()
3390{
3391 const QgsProcessingParameterPoint *pointParam = dynamic_cast< const QgsProcessingParameterPoint *>( parameterDefinition() );
3392 switch ( type() )
3393 {
3396 {
3397 mPanel = new QgsProcessingPointPanel( nullptr );
3398 if ( widgetContext().mapCanvas() )
3399 mPanel->setMapCanvas( widgetContext().mapCanvas() );
3400
3402 mPanel->setAllowNull( true );
3403
3404 mPanel->setToolTip( parameterDefinition()->toolTip() );
3405
3406 connect( mPanel, &QgsProcessingPointPanel::changed, this, [ = ]
3407 {
3408 emit widgetValueHasChanged( this );
3409 } );
3410
3411 if ( mDialog )
3412 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
3413 return mPanel;
3414 }
3415
3417 {
3418 mLineEdit = new QLineEdit();
3419 mLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3420 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3421 {
3422 emit widgetValueHasChanged( this );
3423 } );
3424 return mLineEdit;
3425 }
3426 }
3427 return nullptr;
3428}
3429
3430void QgsProcessingPointWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3431{
3433 if ( mPanel && context.mapCanvas() )
3434 mPanel->setMapCanvas( context.mapCanvas() );
3435}
3436
3437void QgsProcessingPointWidgetWrapper::setDialog( QDialog *dialog )
3438{
3439 mDialog = dialog;
3440 if ( mPanel )
3441 {
3442 connect( mPanel, &QgsProcessingPointPanel::toggleDialogVisibility, mDialog, [ = ]( bool visible )
3443 {
3444 if ( !visible )
3445 mDialog->showMinimized();
3446 else
3447 {
3448 mDialog->showNormal();
3449 mDialog->raise();
3450 mDialog->activateWindow();
3451 }
3452 } );
3453 }
3455}
3456
3457void QgsProcessingPointWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3458{
3459 if ( mPanel )
3460 {
3461 if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
3462 mPanel->clear();
3463 else
3464 {
3465 QgsPointXY p = QgsProcessingParameters::parameterAsPoint( parameterDefinition(), value, context );
3466 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
3467 mPanel->setValue( p, crs );
3468 }
3469 }
3470 else if ( mLineEdit )
3471 {
3472 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3473 mLineEdit->setText( v );
3474 }
3475}
3476
3477QVariant QgsProcessingPointWidgetWrapper::widgetValue() const
3478{
3479 if ( mPanel )
3480 {
3481 return mPanel->value();
3482 }
3483 else if ( mLineEdit )
3484 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3485 else
3486 return QVariant();
3487}
3488
3489QStringList QgsProcessingPointWidgetWrapper::compatibleParameterTypes() const
3490{
3491 return QStringList()
3494}
3495
3496QStringList QgsProcessingPointWidgetWrapper::compatibleOutputTypes() const
3497{
3498 return QStringList()
3500}
3501
3502QString QgsProcessingPointWidgetWrapper::modelerExpressionFormatString() const
3503{
3504 return tr( "string of the format 'x,y' or a geometry value (centroid is used)" );
3505}
3506
3507QString QgsProcessingPointWidgetWrapper::parameterType() const
3508{
3510}
3511
3512QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3513{
3514 return new QgsProcessingPointWidgetWrapper( parameter, type );
3515}
3516
3517QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3518{
3519 return new QgsProcessingPointParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3520}
3521
3522
3523//
3524// QgsProcessingGeometryWidgetWrapper
3525//
3526
3527
3528QgsProcessingGeometryParameterDefinitionWidget::QgsProcessingGeometryParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3529 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3530{
3531 QVBoxLayout *vlayout = new QVBoxLayout();
3532 vlayout->setContentsMargins( 0, 0, 0, 0 );
3533
3534 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3535
3536 mDefaultLineEdit = new QLineEdit();
3537 mDefaultLineEdit->setToolTip( tr( "Geometry as WKT" ) );
3538 mDefaultLineEdit->setPlaceholderText( tr( "Geometry as WKT" ) );
3539 if ( const QgsProcessingParameterGeometry *geometryParam = dynamic_cast<const QgsProcessingParameterGeometry *>( definition ) )
3540 {
3541 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( geometryParam, geometryParam->defaultValueForGui(), context );
3542 if ( !g.isNull() )
3543 mDefaultLineEdit->setText( g.asWkt() );
3544 }
3545
3546 vlayout->addWidget( mDefaultLineEdit );
3547 setLayout( vlayout );
3548}
3549
3550QgsProcessingParameterDefinition *QgsProcessingGeometryParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3551{
3552 auto param = std::make_unique< QgsProcessingParameterGeometry >( name, description, mDefaultLineEdit->text() );
3553 param->setFlags( flags );
3554 return param.release();
3555}
3556
3557QgsProcessingGeometryWidgetWrapper::QgsProcessingGeometryWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3558 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3559{
3560
3561}
3562
3563QWidget *QgsProcessingGeometryWidgetWrapper::createWidget()
3564{
3565 switch ( type() )
3566 {
3570 {
3571 mLineEdit = new QLineEdit();
3572 mLineEdit->setToolTip( parameterDefinition()->toolTip() );
3573 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3574 {
3575 emit widgetValueHasChanged( this );
3576 } );
3577 return mLineEdit;
3578 }
3579 }
3580 return nullptr;
3581}
3582
3583void QgsProcessingGeometryWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3584{
3585 if ( mLineEdit )
3586 {
3587 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( parameterDefinition(), value, context );
3588 if ( !g.isNull() )
3589 mLineEdit->setText( g.asWkt() );
3590 else
3591 mLineEdit->clear();
3592 }
3593}
3594
3595QVariant QgsProcessingGeometryWidgetWrapper::widgetValue() const
3596{
3597 if ( mLineEdit )
3598 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3599 else
3600 return QVariant();
3601}
3602
3603QStringList QgsProcessingGeometryWidgetWrapper::compatibleParameterTypes() const
3604{
3605 return QStringList()
3610}
3611
3612QStringList QgsProcessingGeometryWidgetWrapper::compatibleOutputTypes() const
3613{
3614 return QStringList()
3616}
3617
3618QString QgsProcessingGeometryWidgetWrapper::modelerExpressionFormatString() const
3619{
3620 return tr( "string in the Well-Known-Text format or a geometry value" );
3621}
3622
3623QString QgsProcessingGeometryWidgetWrapper::parameterType() const
3624{
3626}
3627
3628QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingGeometryWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3629{
3630 return new QgsProcessingGeometryWidgetWrapper( parameter, type );
3631}
3632
3633QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingGeometryWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3634{
3635 return new QgsProcessingGeometryParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3636}
3637
3638
3639//
3640// QgsProcessingColorWidgetWrapper
3641//
3642
3643
3644QgsProcessingColorParameterDefinitionWidget::QgsProcessingColorParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3645 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3646{
3647 QVBoxLayout *vlayout = new QVBoxLayout();
3648 vlayout->setContentsMargins( 0, 0, 0, 0 );
3649
3650 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3651
3652 mDefaultColorButton = new QgsColorButton();
3653 mDefaultColorButton->setShowNull( true );
3654 mAllowOpacity = new QCheckBox( tr( "Allow opacity control" ) );
3655
3656 if ( const QgsProcessingParameterColor *colorParam = dynamic_cast<const QgsProcessingParameterColor *>( definition ) )
3657 {
3658 const QColor c = QgsProcessingParameters::parameterAsColor( colorParam, colorParam->defaultValueForGui(), context );
3659 if ( !c.isValid() )
3660 mDefaultColorButton->setToNull();
3661 else
3662 mDefaultColorButton->setColor( c );
3663 mAllowOpacity->setChecked( colorParam->opacityEnabled() );
3664 }
3665 else
3666 {
3667 mDefaultColorButton->setToNull();
3668 mAllowOpacity->setChecked( true );
3669 }
3670
3671 vlayout->addWidget( mDefaultColorButton );
3672 vlayout->addWidget( mAllowOpacity );
3673 setLayout( vlayout );
3674}
3675
3676QgsProcessingParameterDefinition *QgsProcessingColorParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3677{
3678 auto param = std::make_unique< QgsProcessingParameterColor >( name, description, mDefaultColorButton->color(), mAllowOpacity->isChecked() );
3679 param->setFlags( flags );
3680 return param.release();
3681}
3682
3683QgsProcessingColorWidgetWrapper::QgsProcessingColorWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3684 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3685{
3686
3687}
3688
3689QWidget *QgsProcessingColorWidgetWrapper::createWidget()
3690{
3691 const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor *>( parameterDefinition() );
3692 switch ( type() )
3693 {
3697 {
3698 mColorButton = new QgsColorButton( nullptr );
3699 mColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
3700
3702 mColorButton->setShowNull( true );
3703
3704 mColorButton->setAllowOpacity( colorParam->opacityEnabled() );
3705 mColorButton->setToolTip( parameterDefinition()->toolTip() );
3706 mColorButton->setColorDialogTitle( parameterDefinition()->description() );
3707 if ( colorParam->defaultValueForGui().value< QColor >().isValid() )
3708 {
3709 mColorButton->setDefaultColor( colorParam->defaultValueForGui().value< QColor >() );
3710 }
3711
3712 connect( mColorButton, &QgsColorButton::colorChanged, this, [ = ]
3713 {
3714 emit widgetValueHasChanged( this );
3715 } );
3716
3717 return mColorButton;
3718 }
3719 }
3720 return nullptr;
3721}
3722
3723void QgsProcessingColorWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3724{
3725 if ( mColorButton )
3726 {
3727 if ( !value.isValid() ||
3728 ( value.type() == QVariant::String && value.toString().isEmpty() )
3729 || ( value.type() == QVariant::Color && !value.value< QColor >().isValid() ) )
3730 mColorButton->setToNull();
3731 else
3732 {
3733 const QColor c = QgsProcessingParameters::parameterAsColor( parameterDefinition(), value, context );
3734 if ( !c.isValid() && mColorButton->showNull() )
3735 mColorButton->setToNull();
3736 else
3737 mColorButton->setColor( c );
3738 }
3739 }
3740}
3741
3742QVariant QgsProcessingColorWidgetWrapper::widgetValue() const
3743{
3744 if ( mColorButton )
3745 return mColorButton->isNull() ? QVariant() : mColorButton->color();
3746 else
3747 return QVariant();
3748}
3749
3750QStringList QgsProcessingColorWidgetWrapper::compatibleParameterTypes() const
3751{
3752 return QStringList()
3755}
3756
3757QStringList QgsProcessingColorWidgetWrapper::compatibleOutputTypes() const
3758{
3759 return QStringList()
3761}
3762
3763QString QgsProcessingColorWidgetWrapper::modelerExpressionFormatString() const
3764{
3765 return tr( "color style string, e.g. #ff0000 or 255,0,0" );
3766}
3767
3768QString QgsProcessingColorWidgetWrapper::parameterType() const
3769{
3771}
3772
3773QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingColorWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3774{
3775 return new QgsProcessingColorWidgetWrapper( parameter, type );
3776}
3777
3778QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingColorWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3779{
3780 return new QgsProcessingColorParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3781}
3782
3783
3784//
3785// QgsProcessingCoordinateOperationWidgetWrapper
3786//
3787
3788QgsProcessingCoordinateOperationParameterDefinitionWidget::QgsProcessingCoordinateOperationParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3789 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3790{
3791 QVBoxLayout *vlayout = new QVBoxLayout();
3792 vlayout->setContentsMargins( 0, 0, 0, 0 );
3793
3794 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3795
3796 mDefaultLineEdit = new QLineEdit();
3797 if ( const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3798 mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( coordParam, coordParam->defaultValueForGui(), context ) );
3799 vlayout->addWidget( mDefaultLineEdit );
3800
3801 mSourceParamComboBox = new QComboBox();
3802 mDestParamComboBox = new QComboBox();
3803 QString initialSource;
3804 QString initialDest;
3807 if ( const QgsProcessingParameterCoordinateOperation *itemParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3808 {
3809 initialSource = itemParam->sourceCrsParameterName();
3810 initialDest = itemParam->destinationCrsParameterName();
3811 sourceCrs = QgsProcessingUtils::variantToCrs( itemParam->sourceCrs(), context );
3812 destCrs = QgsProcessingUtils::variantToCrs( itemParam->destinationCrs(), context );
3813 }
3814
3815 mSourceParamComboBox->addItem( QString(), QString() );
3816 mDestParamComboBox->addItem( QString(), QString() );
3817 if ( auto *lModel = widgetContext.model() )
3818 {
3819 // populate combo box with other model input choices
3820 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
3821 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
3822 {
3823 if ( definition && it->parameterName() == definition->name() )
3824 continue;
3825
3826 // TODO - we should probably filter this list?
3827 mSourceParamComboBox->addItem( it->parameterName(), it->parameterName() );
3828 mDestParamComboBox->addItem( it->parameterName(), it->parameterName() );
3829 if ( !initialSource.isEmpty() && initialSource == it->parameterName() )
3830 {
3831 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3832 }
3833 if ( !initialDest.isEmpty() && initialDest == it->parameterName() )
3834 {
3835 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3836 }
3837 }
3838 }
3839
3840 if ( mSourceParamComboBox->count() == 1 && !initialSource.isEmpty() )
3841 {
3842 // if no source candidates found, we just add the existing one as a placeholder
3843 mSourceParamComboBox->addItem( initialSource, initialSource );
3844 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3845 }
3846 if ( mDestParamComboBox->count() == 1 && !initialDest.isEmpty() )
3847 {
3848 // if no dest candidates found, we just add the existing one as a placeholder
3849 mDestParamComboBox->addItem( initialDest, initialDest );
3850 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3851 }
3852
3853 vlayout->addWidget( new QLabel( tr( "Source CRS parameter" ) ) );
3854 vlayout->addWidget( mSourceParamComboBox );
3855 vlayout->addWidget( new QLabel( tr( "Destination CRS parameter" ) ) );
3856 vlayout->addWidget( mDestParamComboBox );
3857
3858 mStaticSourceWidget = new QgsProjectionSelectionWidget();
3859 mStaticSourceWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3860 mStaticSourceWidget->setCrs( sourceCrs );
3861 mStaticDestWidget = new QgsProjectionSelectionWidget();
3862 mStaticDestWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3863 mStaticDestWidget->setCrs( destCrs );
3864
3865 vlayout->addWidget( new QLabel( tr( "Static source CRS" ) ) );
3866 vlayout->addWidget( mStaticSourceWidget );
3867 vlayout->addWidget( new QLabel( tr( "Static destination CRS" ) ) );
3868 vlayout->addWidget( mStaticDestWidget );
3869
3870 setLayout( vlayout );
3871}
3872
3873QgsProcessingParameterDefinition *QgsProcessingCoordinateOperationParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3874{
3875 auto param = std::make_unique< QgsProcessingParameterCoordinateOperation >( name, description, mDefaultLineEdit->text(),
3876 mSourceParamComboBox->currentText(),
3877 mDestParamComboBox->currentText(),
3878 mStaticSourceWidget->crs().isValid() ? QVariant::fromValue( mStaticSourceWidget->crs() ) : QVariant(),
3879 mStaticDestWidget->crs().isValid() ? QVariant::fromValue( mStaticDestWidget->crs() ) : QVariant() );
3880 param->setFlags( flags );
3881 return param.release();
3882}
3883
3884QgsProcessingCoordinateOperationWidgetWrapper::QgsProcessingCoordinateOperationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3885 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3886{
3887
3888}
3889
3890QWidget *QgsProcessingCoordinateOperationWidgetWrapper::createWidget()
3891{
3892 const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast< const QgsProcessingParameterCoordinateOperation *>( parameterDefinition() );
3894 mSourceCrs = QgsProcessingUtils::variantToCrs( coordParam->sourceCrs(), c );
3895 mDestCrs = QgsProcessingUtils::variantToCrs( coordParam->destinationCrs(), c );
3896 switch ( type() )
3897 {
3899 {
3900 mOperationWidget = new QgsCoordinateOperationWidget( nullptr );
3901 mOperationWidget->setShowMakeDefault( false );
3902 mOperationWidget->setShowFallbackOption( false );
3903 mOperationWidget->setToolTip( parameterDefinition()->toolTip() );
3904 mOperationWidget->setSourceCrs( mSourceCrs );
3905 mOperationWidget->setDestinationCrs( mDestCrs );
3906 mOperationWidget->setMapCanvas( mCanvas );
3907 if ( !coordParam->defaultValueForGui().toString().isEmpty() )
3908 {
3910 deets.proj = coordParam->defaultValueForGui().toString();
3911 mOperationWidget->setSelectedOperation( deets );
3912 }
3913
3914 connect( mOperationWidget, &QgsCoordinateOperationWidget::operationChanged, this, [ = ]
3915 {
3916 emit widgetValueHasChanged( this );
3917 } );
3918
3919 return mOperationWidget;
3920 }
3921
3924 {
3925 mLineEdit = new QLineEdit();
3926 QHBoxLayout *layout = new QHBoxLayout();
3927 layout->addWidget( mLineEdit, 1 );
3928 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3929 {
3930 emit widgetValueHasChanged( this );
3931 } );
3932
3933 QToolButton *button = new QToolButton();
3934 button->setText( QString( QChar( 0x2026 ) ) );
3935 connect( button, &QToolButton::clicked, this, [ = ]
3936 {
3937 QgsDatumTransformDialog dlg( mSourceCrs, mDestCrs, false, false, false, qMakePair( -1, -1 ), button, Qt::WindowFlags(), mLineEdit->text(), mCanvas );
3938 if ( dlg.exec() )
3939 {
3940 mLineEdit->setText( dlg.selectedDatumTransform().proj );
3941 emit widgetValueHasChanged( this );
3942 }
3943 } );
3944 layout->addWidget( button );
3945
3946 QWidget *w = new QWidget();
3947 layout->setContentsMargins( 0, 0, 0, 0 );
3948 w->setLayout( layout );
3949 return w;
3950 }
3951
3952 }
3953 return nullptr;
3954}
3955
3956void QgsProcessingCoordinateOperationWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3957{
3959 switch ( type() )
3960 {
3963 {
3964 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3965 {
3966 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->sourceCrsParameterName() )
3967 {
3968 setSourceCrsParameterValue( wrapper->parameterValue() );
3970 {
3971 setSourceCrsParameterValue( wrapper->parameterValue() );
3972 } );
3973 }
3974 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->destinationCrsParameterName() )
3975 {
3976 setDestinationCrsParameterValue( wrapper->parameterValue() );
3978 {
3979 setDestinationCrsParameterValue( wrapper->parameterValue() );
3980 } );
3981 }
3982 }
3983 break;
3984 }
3985
3987 break;
3988 }
3989}
3990
3991void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3992{
3993 mCanvas = context.mapCanvas();
3994 if ( mOperationWidget )
3995 mOperationWidget->setMapCanvas( context.mapCanvas() );
3996}
3997
3998void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
3999{
4000 if ( mOperationWidget )
4001 {
4002 if ( !value.isValid() ||
4003 ( value.type() == QVariant::String ) )
4004 {
4006 deets.proj = value.toString();
4007 mOperationWidget->setSelectedOperation( deets );
4008 }
4009 }
4010 if ( mLineEdit )
4011 {
4012 if ( !value.isValid() ||
4013 ( value.type() == QVariant::String ) )
4014 {
4015 mLineEdit->setText( value.toString() );
4016 }
4017 }
4018}
4019
4020QVariant QgsProcessingCoordinateOperationWidgetWrapper::widgetValue() const
4021{
4022 if ( mOperationWidget )
4023 return mOperationWidget->selectedOperation().proj;
4024 else if ( mLineEdit )
4025 return mLineEdit->text();
4026 else
4027 return QVariant();
4028}
4029
4030QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleParameterTypes() const
4031{
4032 return QStringList()
4035}
4036
4037QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleOutputTypes() const
4038{
4039 return QStringList()
4041}
4042
4043QString QgsProcessingCoordinateOperationWidgetWrapper::modelerExpressionFormatString() const
4044{
4045 return tr( "Proj coordinate operation string, e.g. '+proj=pipeline +step +inv...'" );
4046}
4047
4048void QgsProcessingCoordinateOperationWidgetWrapper::setSourceCrsParameterValue( const QVariant &value )
4049{
4050 QgsProcessingContext *context = nullptr;
4051 std::unique_ptr< QgsProcessingContext > tmpContext;
4052 if ( mProcessingContextGenerator )
4053 context = mProcessingContextGenerator->processingContext();
4054
4055 if ( !context )
4056 {
4057 tmpContext = std::make_unique< QgsProcessingContext >();
4058 context = tmpContext.get();
4059 }
4060
4061 mSourceCrs = QgsProcessingUtils::variantToCrs( value, *context );
4062 if ( mOperationWidget )
4063 {
4064 mOperationWidget->setSourceCrs( mSourceCrs );
4065 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
4066 }
4067}
4068
4069void QgsProcessingCoordinateOperationWidgetWrapper::setDestinationCrsParameterValue( const QVariant &value )
4070{
4071 QgsProcessingContext *context = nullptr;
4072 std::unique_ptr< QgsProcessingContext > tmpContext;
4073 if ( mProcessingContextGenerator )
4074 context = mProcessingContextGenerator->processingContext();
4075
4076 if ( !context )
4077 {
4078 tmpContext = std::make_unique< QgsProcessingContext >();
4079 context = tmpContext.get();
4080 }
4081
4082 mDestCrs = QgsProcessingUtils::variantToCrs( value, *context );
4083 if ( mOperationWidget )
4084 {
4085 mOperationWidget->setDestinationCrs( mDestCrs );
4086 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
4087 }
4088}
4089
4090QString QgsProcessingCoordinateOperationWidgetWrapper::parameterType() const
4091{
4093}
4094
4095QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCoordinateOperationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4096{
4097 return new QgsProcessingCoordinateOperationWidgetWrapper( parameter, type );
4098}
4099
4100QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCoordinateOperationWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4101{
4102 return new QgsProcessingCoordinateOperationParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4103}
4104
4105
4106
4107//
4108// QgsProcessingFieldPanelWidget
4109//
4110
4111QgsProcessingFieldPanelWidget::QgsProcessingFieldPanelWidget( QWidget *parent, const QgsProcessingParameterField *param )
4112 : QWidget( parent )
4113 , mParam( param )
4114{
4115 QHBoxLayout *hl = new QHBoxLayout();
4116 hl->setContentsMargins( 0, 0, 0, 0 );
4117
4118 mLineEdit = new QLineEdit();
4119 mLineEdit->setEnabled( false );
4120 hl->addWidget( mLineEdit, 1 );
4121
4122 mToolButton = new QToolButton();
4123 mToolButton->setText( QString( QChar( 0x2026 ) ) );
4124 hl->addWidget( mToolButton );
4125
4126 setLayout( hl );
4127
4128 if ( mParam )
4129 {
4130 mLineEdit->setText( tr( "%n field(s) selected", nullptr, 0 ) );
4131 }
4132
4133 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingFieldPanelWidget::showDialog );
4134}
4135
4136void QgsProcessingFieldPanelWidget::setFields( const QgsFields &fields )
4137{
4138 mFields = fields;
4139}
4140
4141void QgsProcessingFieldPanelWidget::setValue( const QVariant &value )
4142{
4143 if ( value.isValid() )
4144 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
4145 else
4146 mValue.clear();
4147
4148 updateSummaryText();
4149 emit changed();
4150}
4151
4152void QgsProcessingFieldPanelWidget::showDialog()
4153{
4154 QVariantList availableOptions;
4155 QStringList fieldNames;
4156 availableOptions.reserve( mFields.size() );
4157 for ( const QgsField &field : std::as_const( mFields ) )
4158 {
4159 availableOptions << field.name();
4160 }
4161
4163 if ( panel && panel->dockMode() )
4164 {
4165 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
4166 widget->setPanelTitle( mParam->description() );
4167
4168 widget->setValueFormatter( []( const QVariant & v ) -> QString
4169 {
4170 return v.toString();
4171 } );
4172
4173 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
4174 {
4175 setValue( widget->selectedOptions() );
4176 } );
4177 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
4178 panel->openPanel( widget );
4179 }
4180 else
4181 {
4182 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
4183
4184 dlg.setValueFormatter( []( const QVariant & v ) -> QString
4185 {
4186 return v.toString();
4187 } );
4188 if ( dlg.exec() )
4189 {
4190 setValue( dlg.selectedOptions() );
4191 }
4192 }
4193}
4194
4195void QgsProcessingFieldPanelWidget::updateSummaryText()
4196{
4197 if ( !mParam )
4198 return;
4199
4200 if ( mValue.empty() )
4201 {
4202 mLineEdit->setText( tr( "%n field(s) selected", nullptr, 0 ) );
4203 }
4204 else
4205 {
4206 QStringList values;
4207 values.reserve( mValue.size() );
4208 for ( const QVariant &val : std::as_const( mValue ) )
4209 {
4210 values << val.toString();
4211 }
4212
4213 const QString concatenated = values.join( tr( "," ) );
4214 if ( concatenated.length() < 100 )
4215 mLineEdit->setText( concatenated );
4216 else
4217 mLineEdit->setText( tr( "%n field(s) selected", nullptr, mValue.count() ) );
4218 }
4219}
4220
4221
4222//
4223// QgsProcessingFieldWidgetWrapper
4224//
4225
4226QgsProcessingFieldParameterDefinitionWidget::QgsProcessingFieldParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4227 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4228{
4229 QVBoxLayout *vlayout = new QVBoxLayout();
4230 vlayout->setContentsMargins( 0, 0, 0, 0 );
4231
4232 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
4233 mParentLayerComboBox = new QComboBox();
4234
4235 QString initialParent;
4236 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4237 initialParent = fieldParam->parentLayerParameterName();
4238
4239 if ( auto *lModel = widgetContext.model() )
4240 {
4241 // populate combo box with other model input choices
4242 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4243 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4244 {
4245 if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4246 {
4247 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4248 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4249 {
4250 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4251 }
4252 }
4253 else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4254 {
4255 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4256 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4257 {
4258 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4259 }
4260 }
4261 else if ( const QgsProcessingParameterMultipleLayers *definition = dynamic_cast< const QgsProcessingParameterMultipleLayers * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4262 {
4263 if ( definition->layerType() == QgsProcessing::TypeVector )
4264 {
4265 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4266 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4267 {
4268 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4269 }
4270 }
4271 }
4272 }
4273 }
4274
4275 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
4276 {
4277 // if no parent candidates found, we just add the existing one as a placeholder
4278 mParentLayerComboBox->addItem( initialParent, initialParent );
4279 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4280 }
4281
4282 vlayout->addWidget( mParentLayerComboBox );
4283
4284 vlayout->addWidget( new QLabel( tr( "Allowed data type" ) ) );
4285 mDataTypeComboBox = new QComboBox();
4286 mDataTypeComboBox->addItem( tr( "Any" ), QgsProcessingParameterField::Any );
4287 mDataTypeComboBox->addItem( tr( "Number" ), QgsProcessingParameterField::Numeric );
4288 mDataTypeComboBox->addItem( tr( "String" ), QgsProcessingParameterField::String );
4289 mDataTypeComboBox->addItem( tr( "Date/time" ), QgsProcessingParameterField::DateTime );
4290 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4291 mDataTypeComboBox->setCurrentIndex( mDataTypeComboBox->findData( fieldParam->dataType() ) );
4292
4293 vlayout->addWidget( mDataTypeComboBox );
4294
4295 mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple fields" ) );
4296 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4297 mAllowMultipleCheckBox->setChecked( fieldParam->allowMultiple() );
4298
4299 vlayout->addWidget( mAllowMultipleCheckBox );
4300
4301 mDefaultToAllCheckBox = new QCheckBox( tr( "Select all fields by default" ) );
4302 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4303 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4304 mDefaultToAllCheckBox->setChecked( fieldParam->defaultToAllFields() );
4305
4306 vlayout->addWidget( mDefaultToAllCheckBox );
4307
4308 connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
4309 {
4310 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4311 } );
4312
4313 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4314
4315 mDefaultLineEdit = new QLineEdit();
4316 mDefaultLineEdit->setToolTip( tr( "Default field name, or ; separated list of field names for multiple field parameters" ) );
4317 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4318 {
4319 const QStringList fields = QgsProcessingParameters::parameterAsFields( fieldParam, fieldParam->defaultValueForGui(), context );
4320 mDefaultLineEdit->setText( fields.join( ';' ) );
4321 }
4322 vlayout->addWidget( mDefaultLineEdit );
4323
4324 setLayout( vlayout );
4325}
4326
4327QgsProcessingParameterDefinition *QgsProcessingFieldParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4328{
4329 QgsProcessingParameterField::DataType dataType = static_cast< QgsProcessingParameterField::DataType >( mDataTypeComboBox->currentData().toInt() );
4330
4331 QVariant defaultValue;
4332 if ( !mDefaultLineEdit->text().trimmed().isEmpty() )
4333 {
4334 defaultValue = mDefaultLineEdit->text();
4335 }
4336 auto param = std::make_unique< QgsProcessingParameterField >( name, description, defaultValue, mParentLayerComboBox->currentData().toString(), dataType, mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
4337 param->setFlags( flags );
4338 return param.release();
4339}
4340
4341QgsProcessingFieldWidgetWrapper::QgsProcessingFieldWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4342 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4343{
4344
4345}
4346
4347QWidget *QgsProcessingFieldWidgetWrapper::createWidget()
4348{
4349 const QgsProcessingParameterField *fieldParam = dynamic_cast< const QgsProcessingParameterField *>( parameterDefinition() );
4350 switch ( type() )
4351 {
4354 {
4355 if ( fieldParam->allowMultiple() )
4356 {
4357 mPanel = new QgsProcessingFieldPanelWidget( nullptr, fieldParam );
4358 mPanel->setToolTip( parameterDefinition()->toolTip() );
4359 connect( mPanel, &QgsProcessingFieldPanelWidget::changed, this, [ = ]
4360 {
4361 emit widgetValueHasChanged( this );
4362 } );
4363 return mPanel;
4364 }
4365 else
4366 {
4367 mComboBox = new QgsFieldComboBox();
4368 mComboBox->setAllowEmptyFieldName( fieldParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
4369
4370 if ( fieldParam->dataType() == QgsProcessingParameterField::Numeric )
4371 mComboBox->setFilters( QgsFieldProxyModel::Numeric );
4372 else if ( fieldParam->dataType() == QgsProcessingParameterField::String )
4373 mComboBox->setFilters( QgsFieldProxyModel::String );
4374 else if ( fieldParam->dataType() == QgsProcessingParameterField::DateTime )
4376
4377 mComboBox->setToolTip( parameterDefinition()->toolTip() );
4378 connect( mComboBox, &QgsFieldComboBox::fieldChanged, this, [ = ]( const QString & )
4379 {
4380 emit widgetValueHasChanged( this );
4381 } );
4382 return mComboBox;
4383 }
4384 }
4385
4387 {
4388 mLineEdit = new QLineEdit();
4389 mLineEdit->setToolTip( QObject::tr( "Name of field (separate field names with ; for multiple field parameters)" ) );
4390 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
4391 {
4392 emit widgetValueHasChanged( this );
4393 } );
4394 return mLineEdit;
4395 }
4396
4397 }
4398 return nullptr;
4399}
4400
4401void QgsProcessingFieldWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
4402{
4404 switch ( type() )
4405 {
4408 {
4409 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
4410 {
4411 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterField * >( parameterDefinition() )->parentLayerParameterName() )
4412 {
4413 setParentLayerWrapperValue( wrapper );
4415 {
4416 setParentLayerWrapperValue( wrapper );
4417 } );
4418 break;
4419 }
4420 }
4421 break;
4422 }
4423
4425 break;
4426 }
4427}
4428
4429void QgsProcessingFieldWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
4430{
4431 // evaluate value to layer
4432 QgsProcessingContext *context = nullptr;
4433 std::unique_ptr< QgsProcessingContext > tmpContext;
4434 if ( mProcessingContextGenerator )
4435 context = mProcessingContextGenerator->processingContext();
4436
4437 if ( !context )
4438 {
4439 tmpContext = std::make_unique< QgsProcessingContext >();
4440 context = tmpContext.get();
4441 }
4442
4443 QVariant value = parentWrapper->parameterValue();
4444
4445 if ( value.userType() == QMetaType::type( "QgsProcessingFeatureSourceDefinition" ) )
4446 {
4447 // input is a QgsProcessingFeatureSourceDefinition - source from it.
4448 // this is normally discouraged, and algorithms should NEVER do this -- but in this case we can make
4449 // certain assumptions due to the fact that we're calling this outside of algorithm/model execution and all sources
4450 // should be real map layers at this stage
4451 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
4452 value = fromVar.source;
4453 }
4454
4455 bool valueSet = false;
4456 const QList< QgsMapLayer * > layers = QgsProcessingParameters::parameterAsLayerList( parentWrapper->parameterDefinition(), value, *context );
4457
4458 // several layers, populate with intersection of layers fields
4459 if ( layers.count() > 1 )
4460 {
4461 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4462 QgsFields fields = vlayer && vlayer->isValid() ? vlayer->fields() : QgsFields();
4463 const QList< QgsMapLayer * > remainingLayers = layers.mid( 1 );
4464 for ( QgsMapLayer *layer : remainingLayers )
4465 {
4466 if ( fields.isEmpty() )
4467 break;
4468
4469 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer );
4470 if ( !vlayer || !vlayer->isValid() )
4471 {
4472 fields = QgsFields();
4473 break;
4474 }
4475
4476 for ( int fieldIdx = fields.count() - 1; fieldIdx >= 0; fieldIdx-- )
4477 {
4478 if ( vlayer->fields().lookupField( fields.at( fieldIdx ).name() ) < 0 )
4479 fields.remove( fieldIdx );
4480 }
4481 }
4482
4483 if ( mComboBox )
4484 mComboBox->setFields( fields );
4485 else if ( mPanel )
4486 mPanel->setFields( filterFields( fields ) );
4487
4488 valueSet = true;
4489 }
4490
4491 // only one layer
4492 if ( !valueSet && !layers.isEmpty() && layers.at( 0 )->isValid() )
4493 {
4494 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4495
4496 // need to grab ownership of layer if required - otherwise layer may be deleted when context
4497 // goes out of scope
4498 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
4499 if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
4500 {
4501 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
4502 layer = mParentLayer.get();
4503 }
4504 else
4505 {
4506 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
4507 }
4508
4509 if ( mComboBox )
4510 mComboBox->setLayer( layer );
4511 else if ( mPanel )
4512 mPanel->setFields( filterFields( layer->fields() ) );
4513
4514 valueSet = true;
4515 }
4516
4517 if ( !valueSet )
4518 {
4519 std::unique_ptr< QgsProcessingFeatureSource > source( QgsProcessingParameters::parameterAsSource( parentWrapper->parameterDefinition(), value, *context ) );
4520 if ( source )
4521 {
4522 const QgsFields fields = source->fields();
4523 if ( mComboBox )
4524 mComboBox->setFields( fields );
4525 else if ( mPanel )
4526 mPanel->setFields( filterFields( fields ) );
4527
4528 valueSet = true;
4529 }
4530 }
4531
4532 if ( !valueSet )
4533 {
4534 if ( mComboBox )
4535 mComboBox->setLayer( nullptr );
4536 else if ( mPanel )
4537 mPanel->setFields( QgsFields() );
4538
4539 if ( value.isValid() && widgetContext().messageBar() )
4540 {
4541 widgetContext().messageBar()->clearWidgets();
4542 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent field could not be populated" ),
4544 }
4545 return;
4546 }
4547
4548 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4549 if ( mPanel && fieldParam->defaultToAllFields() )
4550 {
4551 QVariantList val;
4552 val.reserve( mPanel->fields().size() );
4553 for ( const QgsField &field : mPanel->fields() )
4554 val << field.name();
4555 setWidgetValue( val, *context );
4556 }
4557 else if ( fieldParam->defaultValueForGui().isValid() )
4558 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
4559}
4560
4561void QgsProcessingFieldWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4562{
4563 if ( mComboBox )
4564 {
4565 if ( !value.isValid() )
4566 mComboBox->setField( QString() );
4567 else
4568 {
4569 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4570 mComboBox->setField( v );
4571 }
4572 }
4573 else if ( mPanel )
4574 {
4575 QVariantList opts;
4576 if ( value.isValid() )
4577 {
4578 const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4579 opts.reserve( v.size() );
4580 for ( const QString &i : v )
4581 opts << i;
4582 }
4583 if ( mPanel )
4584 mPanel->setValue( opts );
4585 }
4586 else if ( mLineEdit )
4587 {
4588 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4589 if ( fieldParam->allowMultiple() )
4590 {
4591 const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4592 mLineEdit->setText( v.join( ';' ) );
4593 }
4594 else
4595 {
4596 mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
4597 }
4598 }
4599}
4600
4601QVariant QgsProcessingFieldWidgetWrapper::widgetValue() const
4602{
4603 if ( mComboBox )
4604 return mComboBox->currentField();
4605 else if ( mPanel )
4606 return mPanel->value();
4607 else if ( mLineEdit )
4608 {
4609 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4610 if ( fieldParam->allowMultiple() )
4611 {
4612 return mLineEdit->text().split( ';' );
4613 }
4614 else
4615 return mLineEdit->text();
4616 }
4617 else
4618 return QVariant();
4619}
4620
4621QStringList QgsProcessingFieldWidgetWrapper::compatibleParameterTypes() const
4622{
4623 return QStringList()
4626}
4627
4628QStringList QgsProcessingFieldWidgetWrapper::compatibleOutputTypes() const
4629{
4630 return QStringList()
4632}
4633
4634QString QgsProcessingFieldWidgetWrapper::modelerExpressionFormatString() const
4635{
4636 return tr( "selected field names as an array of names, or semicolon separated string of options (e.g. 'fid;place_name')" );
4637}
4638
4639const QgsVectorLayer *QgsProcessingFieldWidgetWrapper::linkedVectorLayer() const
4640{
4641 if ( mComboBox && mComboBox->layer() )
4642 return mComboBox->layer();
4643
4645}
4646
4647QgsFields QgsProcessingFieldWidgetWrapper::filterFields( const QgsFields &fields ) const
4648{
4649 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4650 QgsFields res;
4651 for ( const QgsField &f : fields )
4652 {
4653 switch ( fieldParam->dataType() )
4654 {
4656 res.append( f );
4657 break;
4658
4660 if ( f.isNumeric() )
4661 res.append( f );
4662 break;
4663
4665 if ( f.type() == QVariant::String )
4666 res.append( f );
4667 break;
4668
4670 if ( f.type() == QVariant::Date || f.type() == QVariant::Time || f.type() == QVariant::DateTime )
4671 res.append( f );
4672 break;
4673 }
4674 }
4675
4676 return res;
4677}
4678
4679QString QgsProcessingFieldWidgetWrapper::parameterType() const
4680{
4682}
4683
4684QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFieldWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4685{
4686 return new QgsProcessingFieldWidgetWrapper( parameter, type );
4687}
4688
4689QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFieldWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4690{
4691 return new QgsProcessingFieldParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4692}
4693
4694//
4695// QgsProcessingMapThemeWidgetWrapper
4696//
4697
4698
4699QgsProcessingMapThemeParameterDefinitionWidget::QgsProcessingMapThemeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4700 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4701{
4702 QVBoxLayout *vlayout = new QVBoxLayout();
4703 vlayout->setContentsMargins( 0, 0, 0, 0 );
4704
4705 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4706
4707 mDefaultComboBox = new QComboBox();
4708 mDefaultComboBox->addItem( QString(), QVariant( -1 ) );
4709
4710 const QStringList mapThemes = widgetContext.project() ? widgetContext.project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
4711 for ( const QString &theme : mapThemes )
4712 {
4713 mDefaultComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4714 }
4715 mDefaultComboBox->setEditable( true );
4716
4717 if ( const QgsProcessingParameterMapTheme *themeParam = dynamic_cast<const QgsProcessingParameterMapTheme *>( definition ) )
4718 {
4719 if ( themeParam->defaultValueForGui().isValid() )
4720 mDefaultComboBox->setCurrentText( QgsProcessingParameters::parameterAsString( themeParam, themeParam->defaultValueForGui(), context ) );
4721 else
4722 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4723 }
4724 else
4725 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4726
4727 vlayout->addWidget( mDefaultComboBox );
4728
4729 setLayout( vlayout );
4730}
4731
4732QgsProcessingParameterDefinition *QgsProcessingMapThemeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4733{
4734 QVariant defaultVal;
4735 if ( mDefaultComboBox->currentText().isEmpty() )
4736 defaultVal = QVariant();
4737 else
4738 defaultVal = mDefaultComboBox->currentText();
4739 auto param = std::make_unique< QgsProcessingParameterMapTheme>( name, description, defaultVal );
4740 param->setFlags( flags );
4741 return param.release();
4742}
4743
4744
4745QgsProcessingMapThemeWidgetWrapper::QgsProcessingMapThemeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4746 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4747{
4748
4749}
4750
4751QWidget *QgsProcessingMapThemeWidgetWrapper::createWidget()
4752{
4753 const QgsProcessingParameterMapTheme *themeParam = dynamic_cast< const QgsProcessingParameterMapTheme *>( parameterDefinition() );
4754
4755 mComboBox = new QComboBox();
4756
4758 mComboBox->addItem( tr( "[Not selected]" ), QVariant( -1 ) );
4759
4760 const QStringList mapThemes = widgetContext().project() ? widgetContext().project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
4761 for ( const QString &theme : mapThemes )
4762 {
4763 mComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4764 }
4765
4766 switch ( type() )
4767 {
4770 break;
4771
4773 mComboBox->setEditable( true );
4774 break;
4775 }
4776
4777 mComboBox->setToolTip( parameterDefinition()->toolTip() );
4778 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
4779 {
4780 emit widgetValueHasChanged( this );
4781 } );
4782
4783 return mComboBox;
4784}
4785
4786void QgsProcessingMapThemeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4787{
4788 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4789
4790 if ( !value.isValid() )
4791 mComboBox->setCurrentIndex( mComboBox->findData( QVariant( -1 ) ) );
4792 else
4793 {
4794 if ( mComboBox->isEditable() && mComboBox->findData( v ) == -1 )
4795 {
4796 const QString prev = mComboBox->currentText();
4797 mComboBox->setCurrentText( v );
4798 if ( prev != v )
4799 emit widgetValueHasChanged( this );
4800 }
4801 else
4802 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
4803 }
4804}
4805
4806QVariant QgsProcessingMapThemeWidgetWrapper::widgetValue() const
4807{
4808 if ( mComboBox )
4809 return mComboBox->currentData().toInt() == -1 ? QVariant() :
4810 !mComboBox->currentData().isValid() && mComboBox->isEditable() ? mComboBox->currentText().isEmpty() ? QVariant() : QVariant( mComboBox->currentText() )
4811 : mComboBox->currentData();
4812 else
4813 return QVariant();
4814}
4815
4816QStringList QgsProcessingMapThemeWidgetWrapper::compatibleParameterTypes() const
4817{
4818 return QStringList()
4821}
4822
4823QStringList QgsProcessingMapThemeWidgetWrapper::compatibleOutputTypes() const
4824{
4825 return QStringList()
4827}
4828
4829QString QgsProcessingMapThemeWidgetWrapper::modelerExpressionFormatString() const
4830{
4831 return tr( "map theme as a string value (e.g. 'base maps')" );
4832}
4833
4834QString QgsProcessingMapThemeWidgetWrapper::parameterType() const
4835{
4837}
4838
4839QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapThemeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4840{
4841 return new QgsProcessingMapThemeWidgetWrapper( parameter, type );
4842}
4843
4844QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapThemeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4845{
4846 return new QgsProcessingMapThemeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4847}
4848
4849
4850
4851//
4852// QgsProcessingDateTimeWidgetWrapper
4853//
4854
4855
4856QgsProcessingDateTimeParameterDefinitionWidget::QgsProcessingDateTimeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4857 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4858{
4859 QVBoxLayout *vlayout = new QVBoxLayout();
4860 vlayout->setContentsMargins( 0, 0, 0, 0 );
4861
4862 vlayout->addWidget( new QLabel( tr( "Type" ) ) );
4863
4864 mTypeComboBox = new QComboBox();
4865 mTypeComboBox->addItem( tr( "Date and Time" ), QgsProcessingParameterDateTime::DateTime );
4866 mTypeComboBox->addItem( tr( "Date" ), QgsProcessingParameterDateTime::Date );
4867 mTypeComboBox->addItem( tr( "Time" ), QgsProcessingParameterDateTime::Time );
4868 if ( const QgsProcessingParameterDateTime *datetimeParam = dynamic_cast<const QgsProcessingParameterDateTime *>( definition ) )
4869 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( datetimeParam->dataType() ) );
4870 else
4871 mTypeComboBox->setCurrentIndex( 0 );
4872 vlayout->addWidget( mTypeComboBox );
4873
4874 setLayout( vlayout );
4875}
4876
4877QgsProcessingParameterDefinition *QgsProcessingDateTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4878{
4879 auto param = std::make_unique< QgsProcessingParameterDateTime >( name, description );
4880 param->setDataType( static_cast< QgsProcessingParameterDateTime::Type >( mTypeComboBox->currentData().toInt() ) );
4881 param->setFlags( flags );
4882 return param.release();
4883}
4884
4885
4886QgsProcessingDateTimeWidgetWrapper::QgsProcessingDateTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4887 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4888{
4889
4890}
4891
4892QWidget *QgsProcessingDateTimeWidgetWrapper::createWidget()
4893{
4894 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
4895
4896 QgsDateTimeEdit *widget = nullptr;
4897 switch ( dateTimeParam->dataType() )
4898 {
4900 mDateTimeEdit = new QgsDateTimeEdit();
4901 widget = mDateTimeEdit;
4902 break;
4903
4905 mDateEdit = new QgsDateEdit();
4906 widget = mDateEdit;
4907 break;
4908
4910 mTimeEdit = new QgsTimeEdit();
4911 widget = mTimeEdit;
4912 break;
4913 }
4914
4916 {
4917 widget->setNullRepresentation( tr( "[Not selected]" ) );
4918 widget->setAllowNull( true );
4919 }
4920 else
4921 {
4922 widget->setAllowNull( false );
4923 }
4924 widget->setToolTip( parameterDefinition()->toolTip() );
4925
4926 if ( mDateTimeEdit )
4927 {
4928 connect( mDateTimeEdit, &QgsDateTimeEdit::valueChanged, this, [ = ]( const QDateTime & )
4929 {
4930 emit widgetValueHasChanged( this );
4931 } );
4932 }
4933 else if ( mDateEdit )
4934 {
4935 connect( mDateEdit, &QgsDateEdit::dateValueChanged, this, [ = ]( const QDate & )
4936 {
4937 emit widgetValueHasChanged( this );
4938 } );
4939 }
4940 else if ( mTimeEdit )
4941 {
4942 connect( mTimeEdit, &QgsTimeEdit::timeValueChanged, this, [ = ]( const QTime & )
4943 {
4944 emit widgetValueHasChanged( this );
4945 } );
4946 }
4947
4948 return widget;
4949}
4950
4951QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDateTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4952{
4953 return new QgsProcessingDateTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4954}
4955
4956void QgsProcessingDateTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4957{
4958 if ( mDateTimeEdit )
4959 {
4960 mDateTimeEdit->setDateTime( QgsProcessingParameters::parameterAsDateTime( parameterDefinition(), value, context ) );
4961 }
4962 else if ( mDateEdit )
4963 {
4964 mDateEdit->setDate( QgsProcessingParameters::parameterAsDate( parameterDefinition(), value, context ) );
4965 }
4966 else if ( mTimeEdit )
4967 {
4968 mTimeEdit->setTime( QgsProcessingParameters::parameterAsTime( parameterDefinition(), value, context ) );
4969 }
4970}
4971
4972QVariant QgsProcessingDateTimeWidgetWrapper::widgetValue() const
4973{
4974 if ( mDateTimeEdit )
4975 return !mDateTimeEdit->dateTime().isNull() && mDateTimeEdit->dateTime().isValid() ? QVariant( mDateTimeEdit->dateTime() ) : QVariant();
4976 else if ( mDateEdit )
4977 return !mDateEdit->date().isNull() && mDateEdit->date().isValid() ? QVariant( mDateEdit->date() ) : QVariant();
4978 else if ( mTimeEdit )
4979 return !mTimeEdit->time().isNull() && mTimeEdit->time().isValid() ? QVariant( mTimeEdit->time() ) : QVariant();
4980 else
4981 return QVariant();
4982}
4983
4984QStringList QgsProcessingDateTimeWidgetWrapper::compatibleParameterTypes() const
4985{
4986 return QStringList()
4989}
4990
4991QStringList QgsProcessingDateTimeWidgetWrapper::compatibleOutputTypes() const
4992{
4993 return QStringList()
4995}
4996
4997QString QgsProcessingDateTimeWidgetWrapper::modelerExpressionFormatString() const
4998{
4999 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
5000 if ( dateTimeParam )
5001 {
5002 switch ( dateTimeParam->dataType() )
5003 {
5005 return tr( "datetime value, or a ISO string representation of a datetime" );
5006
5008 return tr( "date value, or a ISO string representation of a date" );
5009
5011 return tr( "time value, or a ISO string representation of a time" );
5012 }
5013 }
5014 return QString();
5015}
5016
5017QString QgsProcessingDateTimeWidgetWrapper::parameterType() const
5018{
5020}
5021
5022QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDateTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5023{
5024 return new QgsProcessingDateTimeWidgetWrapper( parameter, type );
5025}
5026
5027
5028
5029//
5030// QgsProcessingProviderConnectionWidgetWrapper
5031//
5032
5033QgsProcessingProviderConnectionParameterDefinitionWidget::QgsProcessingProviderConnectionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5034 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5035{
5036 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( definition );
5037
5038 QVBoxLayout *vlayout = new QVBoxLayout();
5039 vlayout->setContentsMargins( 0, 0, 0, 0 );
5040
5041 vlayout->addWidget( new QLabel( tr( "Provider" ) ) );
5042 mProviderComboBox = new QComboBox();
5043 mProviderComboBox->addItem( QObject::tr( "Postgres" ), QStringLiteral( "postgres" ) );
5044 mProviderComboBox->addItem( QObject::tr( "GeoPackage" ), QStringLiteral( "ogr" ) );
5045 mProviderComboBox->addItem( QObject::tr( "Spatialite" ), QStringLiteral( "spatialite" ) );
5046
5047 vlayout->addWidget( mProviderComboBox );
5048
5049 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5050
5051 mDefaultEdit = new QLineEdit();
5052 vlayout->addWidget( mDefaultEdit );
5053 setLayout( vlayout );
5054
5055 if ( connectionParam )
5056 {
5057 mProviderComboBox->setCurrentIndex( mProviderComboBox->findData( connectionParam->providerId() ) );
5058 mDefaultEdit->setText( connectionParam->defaultValueForGui().toString() );
5059 }
5060}
5061
5062QgsProcessingParameterDefinition *QgsProcessingProviderConnectionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5063{
5064 QVariant defaultVal;
5065 if ( mDefaultEdit->text().isEmpty() )
5066 defaultVal = QVariant();
5067 else
5068 defaultVal = mDefaultEdit->text();
5069 auto param = std::make_unique< QgsProcessingParameterProviderConnection>( name, description, mProviderComboBox->currentData().toString(), defaultVal );
5070 param->setFlags( flags );
5071 return param.release();
5072}
5073
5074
5075QgsProcessingProviderConnectionWidgetWrapper::QgsProcessingProviderConnectionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5076 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5077{
5078
5079}
5080
5081QWidget *QgsProcessingProviderConnectionWidgetWrapper::createWidget()
5082{
5083 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( parameterDefinition() );
5084
5085 mProviderComboBox = new QgsProviderConnectionComboBox( connectionParam->providerId() );
5086 if ( connectionParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
5087 mProviderComboBox->setAllowEmptyConnection( true );
5088
5089 switch ( type() )
5090 {
5093 break;
5095 mProviderComboBox->setEditable( true );
5096 break;
5097 }
5098
5099 mProviderComboBox->setToolTip( parameterDefinition()->toolTip() );
5100 connect( mProviderComboBox, &QgsProviderConnectionComboBox::currentTextChanged, this, [ = ]( const QString & )
5101 {
5102 if ( mBlockSignals )
5103 return;
5104
5105 emit widgetValueHasChanged( this );
5106 } );
5107
5108 return mProviderComboBox;
5109}
5110
5111QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingProviderConnectionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5112{
5113 return new QgsProcessingProviderConnectionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5114}
5115
5116void QgsProcessingProviderConnectionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5117{
5118 const QString v = QgsProcessingParameters::parameterAsConnectionName( parameterDefinition(), value, context );
5119
5120 if ( !value.isValid() )
5121 mProviderComboBox->setCurrentIndex( -1 );
5122 else
5123 {
5124 if ( mProviderComboBox->isEditable() )
5125 {
5126 const QString prev = mProviderComboBox->currentText();
5127 mBlockSignals++;
5128 mProviderComboBox->setConnection( v );
5129 mProviderComboBox->setCurrentText( v );
5130
5131 mBlockSignals--;
5132 if ( prev != v )
5133 emit widgetValueHasChanged( this );
5134 }
5135 else
5136 mProviderComboBox->setConnection( v );
5137 }
5138}
5139
5140QVariant QgsProcessingProviderConnectionWidgetWrapper::widgetValue() const
5141{
5142 if ( mProviderComboBox )
5143 if ( mProviderComboBox->isEditable() )
5144 return mProviderComboBox->currentText().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentText() );
5145 else
5146 return mProviderComboBox->currentConnection().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentConnection() );
5147 else
5148 return QVariant();
5149}
5150
5151QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleParameterTypes() const
5152{
5153 return QStringList()
5157}
5158
5159QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleOutputTypes() const
5160{
5161 return QStringList()
5163}
5164
5165QString QgsProcessingProviderConnectionWidgetWrapper::modelerExpressionFormatString() const
5166{
5167 return tr( "connection name as a string value" );
5168}
5169
5170QString QgsProcessingProviderConnectionWidgetWrapper::parameterType() const
5171{
5173}
5174
5175QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingProviderConnectionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5176{
5177 return new QgsProcessingProviderConnectionWidgetWrapper( parameter, type );
5178}
5179
5180
5181
5182
5183//
5184// QgsProcessingDatabaseSchemaWidgetWrapper
5185//
5186
5187QgsProcessingDatabaseSchemaParameterDefinitionWidget::QgsProcessingDatabaseSchemaParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5188 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5189{
5190 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( definition );
5191
5192 QVBoxLayout *vlayout = new QVBoxLayout();
5193 vlayout->setContentsMargins( 0, 0, 0, 0 );
5194
5195 mConnectionParamComboBox = new QComboBox();
5196 QString initialConnection;
5197 if ( schemaParam )
5198 {
5199 initialConnection = schemaParam->parentConnectionParameterName();
5200 }
5201
5202 if ( auto *lModel = widgetContext.model() )
5203 {
5204 // populate combo box with other model input choices
5205 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5206 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5207 {
5208 if ( definition && it->parameterName() == definition->name() )
5209 continue;
5210
5211 if ( !dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5212 continue;
5213
5214 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5215 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5216 {
5217 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5218 }
5219 }
5220 }
5221
5222 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5223 {
5224 // if no candidates found, we just add the existing one as a placeholder
5225 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5226 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5227 }
5228
5229 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5230 vlayout->addWidget( mConnectionParamComboBox );
5231
5232 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5233
5234 mDefaultEdit = new QLineEdit();
5235 vlayout->addWidget( mDefaultEdit );
5236 setLayout( vlayout );
5237
5238 if ( schemaParam )
5239 {
5240 mDefaultEdit->setText( schemaParam->defaultValueForGui().toString() );
5241 }
5242}
5243
5244QgsProcessingParameterDefinition *QgsProcessingDatabaseSchemaParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5245{
5246 QVariant defaultVal;
5247 if ( mDefaultEdit->text().isEmpty() )
5248 defaultVal = QVariant();
5249 else
5250 defaultVal = mDefaultEdit->text();
5251 auto param = std::make_unique< QgsProcessingParameterDatabaseSchema>( name, description, mConnectionParamComboBox->currentData().toString(), defaultVal );
5252 param->setFlags( flags );
5253 return param.release();
5254}
5255
5256
5257QgsProcessingDatabaseSchemaWidgetWrapper::QgsProcessingDatabaseSchemaWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5258 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5259{
5260
5261}
5262
5263QWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createWidget()
5264{
5265 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( parameterDefinition() );
5266
5267 mSchemaComboBox = new QgsDatabaseSchemaComboBox( QString(), QString() );
5269 mSchemaComboBox->setAllowEmptySchema( true );
5270
5271 switch ( type() )
5272 {
5275 break;
5277 mSchemaComboBox->comboBox()->setEditable( true );
5278 break;
5279 }
5280
5281 mSchemaComboBox->setToolTip( parameterDefinition()->toolTip() );
5282 connect( mSchemaComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5283 {
5284 if ( mBlockSignals )
5285 return;
5286
5287 emit widgetValueHasChanged( this );
5288 } );
5289
5290 return mSchemaComboBox;
5291}
5292
5293QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5294{
5295 return new QgsProcessingDatabaseSchemaParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5296}
5297
5298void QgsProcessingDatabaseSchemaWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5299{
5300 // evaluate value to connection
5301 QgsProcessingContext *context = nullptr;
5302 std::unique_ptr< QgsProcessingContext > tmpContext;
5303 if ( mProcessingContextGenerator )
5304 context = mProcessingContextGenerator->processingContext();
5305
5306 if ( !context )
5307 {
5308 tmpContext = std::make_unique< QgsProcessingContext >();
5309 context = tmpContext.get();
5310 }
5311
5312 const QVariant value = parentWrapper->parameterValue();
5313 const QString connection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5314
5315 if ( mSchemaComboBox )
5316 mSchemaComboBox->setConnectionName( connection, qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId() );
5317
5318 const QgsProcessingParameterDatabaseSchema *schemaParam = qgis::down_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() );
5319 if ( schemaParam->defaultValueForGui().isValid() )
5320 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5321}
5322
5323void QgsProcessingDatabaseSchemaWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5324{
5325 const QString v = QgsProcessingParameters::parameterAsSchema( parameterDefinition(), value, context );
5326
5327 if ( !value.isValid() )
5328 mSchemaComboBox->comboBox()->setCurrentIndex( -1 );
5329 else
5330 {
5331 if ( mSchemaComboBox->comboBox()->isEditable() )
5332 {
5333 const QString prev = mSchemaComboBox->comboBox()->currentText();
5334 mBlockSignals++;
5335 mSchemaComboBox->setSchema( v );
5336 mSchemaComboBox->comboBox()->setCurrentText( v );
5337
5338 mBlockSignals--;
5339 if ( prev != v )
5340 emit widgetValueHasChanged( this );
5341 }
5342 else
5343 mSchemaComboBox->setSchema( v );
5344 }
5345}
5346
5347QVariant QgsProcessingDatabaseSchemaWidgetWrapper::widgetValue() const
5348{
5349 if ( mSchemaComboBox )
5350 if ( mSchemaComboBox->comboBox()->isEditable() )
5351 return mSchemaComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->comboBox()->currentText() );
5352 else
5353 return mSchemaComboBox->currentSchema().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->currentSchema() );
5354 else
5355 return QVariant();
5356}
5357
5358QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleParameterTypes() const
5359{
5360 return QStringList()
5364}
5365
5366QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleOutputTypes() const
5367{
5368 return QStringList()
5370}
5371
5372QString QgsProcessingDatabaseSchemaWidgetWrapper::modelerExpressionFormatString() const
5373{
5374 return tr( "database schema name as a string value" );
5375}
5376
5377QString QgsProcessingDatabaseSchemaWidgetWrapper::parameterType() const
5378{
5380}
5381
5382QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseSchemaWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5383{
5384 return new QgsProcessingDatabaseSchemaWidgetWrapper( parameter, type );
5385}
5386
5387void QgsProcessingDatabaseSchemaWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5388{
5390 switch ( type() )
5391 {
5394 {
5395 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5396 {
5397 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() )->parentConnectionParameterName() )
5398 {
5399 setParentConnectionWrapperValue( wrapper );
5401 {
5402 setParentConnectionWrapperValue( wrapper );
5403 } );
5404 break;
5405 }
5406 }
5407 break;
5408 }
5409
5411 break;
5412 }
5413}
5414
5415
5416
5417//
5418// QgsProcessingDatabaseTableWidgetWrapper
5419//
5420
5421QgsProcessingDatabaseTableParameterDefinitionWidget::QgsProcessingDatabaseTableParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5422 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5423{
5424 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( definition );
5425
5426 QVBoxLayout *vlayout = new QVBoxLayout();
5427 vlayout->setContentsMargins( 0, 0, 0, 0 );
5428
5429 mConnectionParamComboBox = new QComboBox();
5430 mSchemaParamComboBox = new QComboBox();
5431 QString initialConnection;
5432 QString initialSchema;
5433 if ( tableParam )
5434 {
5435 initialConnection = tableParam->parentConnectionParameterName();
5436 initialSchema = tableParam->parentSchemaParameterName();
5437 }
5438
5439 if ( auto *lModel = widgetContext.model() )
5440 {
5441 // populate combo box with other model input choices
5442 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5443 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5444 {
5445 if ( definition && it->parameterName() == definition->name() )
5446 continue;
5447
5448 if ( dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5449 {
5450 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5451 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5452 {
5453 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5454 }
5455 }
5456 else if ( dynamic_cast< const QgsProcessingParameterDatabaseSchema * >( lModel->parameterDefinition( it->parameterName() ) ) )
5457 {
5458 mSchemaParamComboBox->addItem( it->parameterName(), it->parameterName() );
5459 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5460 {
5461 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5462 }
5463 }
5464 }
5465 }
5466
5467 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5468 {
5469 // if no candidates found, we just add the existing one as a placeholder
5470 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5471 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5472 }
5473
5474 if ( mSchemaParamComboBox->count() == 0 && !initialSchema.isEmpty() )
5475 {
5476 // if no candidates found, we just add the existing one as a placeholder
5477 mSchemaParamComboBox->addItem( initialSchema, initialSchema );
5478 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5479 }
5480
5481 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5482 vlayout->addWidget( mConnectionParamComboBox );
5483
5484 vlayout->addWidget( new QLabel( tr( "Database schema parameter" ) ) );
5485 vlayout->addWidget( mSchemaParamComboBox );
5486
5487 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5488
5489 mDefaultEdit = new QLineEdit();
5490 vlayout->addWidget( mDefaultEdit );
5491 setLayout( vlayout );
5492
5493 if ( tableParam )
5494 {
5495 mDefaultEdit->setText( tableParam->defaultValueForGui().toString() );
5496 }
5497}
5498
5499QgsProcessingParameterDefinition *QgsProcessingDatabaseTableParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5500{
5501 QVariant defaultVal;
5502 if ( mDefaultEdit->text().isEmpty() )
5503 defaultVal = QVariant();
5504 else
5505 defaultVal = mDefaultEdit->text();
5506 auto param = std::make_unique< QgsProcessingParameterDatabaseTable>( name, description,
5507 mConnectionParamComboBox->currentData().toString(),
5508 mSchemaParamComboBox->currentData().toString(),
5509 defaultVal );
5510 param->setFlags( flags );
5511 return param.release();
5512}
5513
5514
5515QgsProcessingDatabaseTableWidgetWrapper::QgsProcessingDatabaseTableWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5516 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5517{
5518
5519}
5520
5521QWidget *QgsProcessingDatabaseTableWidgetWrapper::createWidget()
5522{
5523 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( parameterDefinition() );
5524
5525 mTableComboBox = new QgsDatabaseTableComboBox( QString(), QString() );
5527 mTableComboBox->setAllowEmptyTable( true );
5528
5529 if ( type() == QgsProcessingGui::Modeler || tableParam->allowNewTableNames() )
5530 mTableComboBox->comboBox()->setEditable( true );
5531
5532 mTableComboBox->setToolTip( parameterDefinition()->toolTip() );
5533 connect( mTableComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5534 {
5535 if ( mBlockSignals )
5536 return;
5537
5538 emit widgetValueHasChanged( this );
5539 } );
5540
5541 return mTableComboBox;
5542}
5543
5544QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseTableWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5545{
5546 return new QgsProcessingDatabaseTableParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5547}
5548
5549void QgsProcessingDatabaseTableWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5550{
5551 // evaluate value to connection
5552 QgsProcessingContext *context = nullptr;
5553 std::unique_ptr< QgsProcessingContext > tmpContext;
5554 if ( mProcessingContextGenerator )
5555 context = mProcessingContextGenerator->processingContext();
5556
5557 if ( !context )
5558 {
5559 tmpContext = std::make_unique< QgsProcessingContext >();
5560 context = tmpContext.get();
5561 }
5562
5563 QVariant value = parentWrapper->parameterValue();
5564 mConnection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5565 mProvider = qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId();
5566 if ( mTableComboBox && !mSchema.isEmpty() )
5567 {
5568 mTableComboBox->setSchema( mSchema );
5569 mTableComboBox->setConnectionName( mConnection, mProvider );
5570
5571 const QgsProcessingParameterDatabaseTable *tableParam = qgis::down_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5572 if ( tableParam->defaultValueForGui().isValid() )
5573 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5574 }
5575}
5576
5577void QgsProcessingDatabaseTableWidgetWrapper::setParentSchemaWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5578{
5579 // evaluate value to schema
5580 QgsProcessingContext *context = nullptr;
5581 std::unique_ptr< QgsProcessingContext > tmpContext;
5582 if ( mProcessingContextGenerator )
5583 context = mProcessingContextGenerator->processingContext();
5584
5585 if ( !context )
5586 {
5587 tmpContext = std::make_unique< QgsProcessingContext >();
5588 context = tmpContext.get();
5589 }
5590
5591 QVariant value = parentWrapper->parameterValue();
5592 mSchema = value.isValid() ? QgsProcessingParameters::parameterAsSchema( parentWrapper->parameterDefinition(), value, *context ) : QString();
5593
5594 if ( mTableComboBox && !mSchema.isEmpty() && !mConnection.isEmpty() )
5595 {
5596 mTableComboBox->setSchema( mSchema );
5597 mTableComboBox->setConnectionName( mConnection, mProvider );
5598
5599 const QgsProcessingParameterDatabaseTable *tableParam = static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5600 if ( tableParam->defaultValueForGui().isValid() )
5601 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5602 }
5603
5604}
5605
5606void QgsProcessingDatabaseTableWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5607{
5608 const QString v = QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition(), value, context );
5609
5610 if ( !value.isValid() )
5611 mTableComboBox->comboBox()->setCurrentIndex( -1 );
5612 else
5613 {
5614 if ( mTableComboBox->comboBox()->isEditable() )
5615 {
5616 const QString prev = mTableComboBox->comboBox()->currentText();
5617 mBlockSignals++;
5618 mTableComboBox->setTable( v );
5619 mTableComboBox->comboBox()->setCurrentText( v );
5620
5621 mBlockSignals--;
5622 if ( prev != v )
5623 emit widgetValueHasChanged( this );
5624 }
5625 else
5626 mTableComboBox->setTable( v );
5627 }
5628}
5629
5630QVariant QgsProcessingDatabaseTableWidgetWrapper::widgetValue() const
5631{
5632 if ( mTableComboBox )
5633 if ( mTableComboBox->comboBox()->isEditable() )
5634 return mTableComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mTableComboBox->comboBox()->currentText() );
5635 else
5636 return mTableComboBox->currentTable().isEmpty() ? QVariant() : QVariant( mTableComboBox->currentTable() );
5637 else
5638 return QVariant();
5639}
5640
5641QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleParameterTypes() const
5642{
5643 return QStringList()
5647}
5648
5649QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleOutputTypes() const
5650{
5651 return QStringList()
5653}
5654
5655QString QgsProcessingDatabaseTableWidgetWrapper::modelerExpressionFormatString() const
5656{
5657 return tr( "database table name as a string value" );
5658}
5659
5660QString QgsProcessingDatabaseTableWidgetWrapper::parameterType() const
5661{
5663}
5664
5665QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseTableWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5666{
5667 return new QgsProcessingDatabaseTableWidgetWrapper( parameter, type );
5668}
5669
5670void QgsProcessingDatabaseTableWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5671{
5673 switch ( type() )
5674 {
5677 {
5678 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5679 {
5680 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentConnectionParameterName() )
5681 {
5682 setParentConnectionWrapperValue( wrapper );
5684 {
5685 setParentConnectionWrapperValue( wrapper );
5686 } );
5687 }
5688 else if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentSchemaParameterName() )
5689 {
5690 setParentSchemaWrapperValue( wrapper );
5692 {
5693 setParentSchemaWrapperValue( wrapper );
5694 } );
5695 }
5696 }
5697 break;
5698 }
5699
5701 break;
5702 }
5703}
5704
5705
5706//
5707// QgsProcessingExtentWidgetWrapper
5708//
5709
5710QgsProcessingExtentParameterDefinitionWidget::QgsProcessingExtentParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5711 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5712{
5713 QVBoxLayout *vlayout = new QVBoxLayout();
5714 vlayout->setContentsMargins( 0, 0, 0, 0 );
5715
5716 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5717
5718 mDefaultWidget = new QgsExtentWidget();
5719 mDefaultWidget->setNullValueAllowed( true, tr( "Not set" ) );
5720 if ( const QgsProcessingParameterExtent *extentParam = dynamic_cast<const QgsProcessingParameterExtent *>( definition ) )
5721 {
5722 if ( extentParam->defaultValueForGui().isValid() )
5723 {
5724 QgsRectangle rect = QgsProcessingParameters::parameterAsExtent( extentParam, extentParam->defaultValueForGui(), context );
5725 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsExtentCrs( extentParam, extentParam->defaultValueForGui(), context );
5726 mDefaultWidget->setCurrentExtent( rect, crs );
5727 mDefaultWidget->setOutputExtentFromCurrent();
5728 }
5729 else
5730 {
5731 mDefaultWidget->clear();
5732 }
5733 }
5734
5735 vlayout->addWidget( mDefaultWidget );
5736 setLayout( vlayout );
5737}
5738
5739QgsProcessingParameterDefinition *QgsProcessingExtentParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5740{
5741 const QString defaultVal = mDefaultWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5742 QString::number( mDefaultWidget->outputExtent().xMinimum(), 'f', 9 ),
5743 QString::number( mDefaultWidget->outputExtent().xMaximum(), 'f', 9 ),
5744 QString::number( mDefaultWidget->outputExtent().yMinimum(), 'f', 9 ),
5745 QString::number( mDefaultWidget->outputExtent().yMaximum(), 'f', 9 ),
5746 mDefaultWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mDefaultWidget->outputCrs().authid() ) : QString()
5747 ) : QString();
5748 auto param = std::make_unique< QgsProcessingParameterExtent >( name, description, !defaultVal.isEmpty() ? QVariant( defaultVal ) : QVariant() );
5749 param->setFlags( flags );
5750 return param.release();
5751}
5752
5753
5754
5755QgsProcessingExtentWidgetWrapper::QgsProcessingExtentWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5756 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5757{
5758
5759}
5760
5761QWidget *QgsProcessingExtentWidgetWrapper::createWidget()
5762{
5763 const QgsProcessingParameterExtent *extentParam = dynamic_cast< const QgsProcessingParameterExtent *>( parameterDefinition() );
5764 switch ( type() )
5765 {
5769 {
5770 mExtentWidget = new QgsExtentWidget( nullptr );
5771 if ( widgetContext().mapCanvas() )
5772 mExtentWidget->setMapCanvas( widgetContext().mapCanvas() );
5773
5775 mExtentWidget->setNullValueAllowed( true, tr( "Not set" ) );
5776
5777 mExtentWidget->setToolTip( parameterDefinition()->toolTip() );
5778
5779 connect( mExtentWidget, &QgsExtentWidget::extentChanged, this, [ = ]
5780 {
5781 emit widgetValueHasChanged( this );
5782 } );
5783
5784 if ( mDialog && type() != QgsProcessingGui::Modeler )
5785 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
5786
5787 return mExtentWidget;
5788 }
5789 }
5790 return nullptr;
5791}
5792
5793void QgsProcessingExtentWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5794{
5796 if ( mExtentWidget && context.mapCanvas() && type() != QgsProcessingGui::Modeler )
5797 mExtentWidget->setMapCanvas( context.mapCanvas() );
5798}
5799
5800void QgsProcessingExtentWidgetWrapper::setDialog( QDialog *dialog )
5801{
5802 mDialog = dialog;
5803 if ( mExtentWidget && mDialog && type() != QgsProcessingGui::Modeler )
5804 {
5805 connect( mExtentWidget, &QgsExtentWidget::toggleDialogVisibility, mDialog, [ = ]( bool visible )
5806 {
5807 if ( !visible )
5808 mDialog->showMinimized();
5809 else
5810 {
5811 mDialog->showNormal();
5812 mDialog->raise();
5813 mDialog->activateWindow();
5814 }
5815 } );
5816 }
5818}
5819
5820void QgsProcessingExtentWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5821{
5822 if ( mExtentWidget )
5823 {
5824 if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
5825 mExtentWidget->clear();
5826 else
5827 {
5828 QgsRectangle r = QgsProcessingParameters::parameterAsExtent( parameterDefinition(), value, context );
5829 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
5830 mExtentWidget->setCurrentExtent( r, crs );
5831 mExtentWidget->setOutputExtentFromUser( r, crs );
5832 }
5833 }
5834}
5835
5836QVariant QgsProcessingExtentWidgetWrapper::widgetValue() const
5837{
5838 if ( mExtentWidget )
5839 {
5840 const QString val = mExtentWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5841 QString::number( mExtentWidget->outputExtent().xMinimum(), 'f', 9 ),
5842 QString::number( mExtentWidget->outputExtent().xMaximum(), 'f', 9 ),
5843 QString::number( mExtentWidget->outputExtent().yMinimum(), 'f', 9 ),
5844 QString::number( mExtentWidget->outputExtent().yMaximum(), 'f', 9 ),
5845 mExtentWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mExtentWidget->outputCrs().authid() ) : QString()
5846 ) : QString();
5847
5848 return val.isEmpty() ? QVariant() : QVariant( val );
5849 }
5850 else
5851 return QVariant();
5852}
5853
5854QStringList QgsProcessingExtentWidgetWrapper::compatibleParameterTypes() const
5855{
5856 return QStringList()
5866}
5867
5868QStringList QgsProcessingExtentWidgetWrapper::compatibleOutputTypes() const
5869{
5870 return QStringList()
5875}
5876
5877QString QgsProcessingExtentWidgetWrapper::modelerExpressionFormatString() const
5878{
5879 return tr( "string of the format 'x min,x max,y min,y max' or a geometry value (bounding box is used)" );
5880}
5881
5882QString QgsProcessingExtentWidgetWrapper::parameterType() const
5883{
5885}
5886
5887QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExtentWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5888{
5889 return new QgsProcessingExtentWidgetWrapper( parameter, type );
5890}
5891
5892QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExtentWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5893{
5894 return new QgsProcessingExtentParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5895}
5896
5897
5898
5899//
5900// QgsProcessingMapLayerWidgetWrapper
5901//
5902
5903QgsProcessingMapLayerParameterDefinitionWidget::QgsProcessingMapLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5904 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5905{
5906 QVBoxLayout *vlayout = new QVBoxLayout();
5907 vlayout->setContentsMargins( 0, 0, 0, 0 );
5908
5909 vlayout->addWidget( new QLabel( tr( "Layer type" ) ) );
5910 mLayerTypeComboBox = new QgsCheckableComboBox();
5911 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
5912 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
5913 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
5914 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
5915 mLayerTypeComboBox->addItem( tr( "Vector (Any Geometry Type)" ), QgsProcessing::TypeVectorAnyGeometry );
5916 mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
5917 mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
5918 mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );
5919 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), QgsProcessing::TypePointCloud );
5920 mLayerTypeComboBox->addItem( tr( "Annotation" ), QgsProcessing::TypeAnnotation );
5921
5922 if ( const QgsProcessingParameterMapLayer *layerParam = dynamic_cast<const QgsProcessingParameterMapLayer *>( definition ) )
5923 {
5924 for ( int i : layerParam->dataTypes() )
5925 {
5926 mLayerTypeComboBox->setItemCheckState( mLayerTypeComboBox->findData( i ), Qt::Checked );
5927 }
5928 }
5929
5930 vlayout->addWidget( mLayerTypeComboBox );
5931
5932 setLayout( vlayout );
5933}
5934
5935QgsProcessingParameterDefinition *QgsProcessingMapLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5936{
5937 QList< int > dataTypes;
5938 for ( const QVariant &v : mLayerTypeComboBox->checkedItemsData() )
5939 dataTypes << v.toInt();
5940
5941 auto param = std::make_unique< QgsProcessingParameterMapLayer >( name, description );
5942 param->setDataTypes( dataTypes );
5943 param->setFlags( flags );
5944 return param.release();
5945}
5946
5947QgsProcessingMapLayerWidgetWrapper::QgsProcessingMapLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5948 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5949{
5950
5951}
5952
5953QWidget *QgsProcessingMapLayerWidgetWrapper::createWidget()
5954{
5955 mComboBox = new QgsProcessingMapLayerComboBox( parameterDefinition(), type() );
5956
5957 switch ( type() )
5958 {
5961 break;
5963 mComboBox->setEditable( true );
5964 break;
5965 }
5966
5967 mComboBox->setToolTip( parameterDefinition()->toolTip() );
5968
5969 connect( mComboBox, &QgsProcessingMapLayerComboBox::valueChanged, this, [ = ]()
5970 {
5971 if ( mBlockSignals )
5972 return;
5973
5974 emit widgetValueHasChanged( this );
5975 } );
5976
5977 setWidgetContext( widgetContext() );
5978 return mComboBox;
5979}
5980
5981void QgsProcessingMapLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5982{
5984 if ( mComboBox )
5985 {
5986 mComboBox->setWidgetContext( context );
5987
5988 if ( !( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional ) )
5989 {
5990 // non optional parameter -- if no default value set, default to active layer
5991 if ( !parameterDefinition()->defaultValueForGui().isValid() )
5992 mComboBox->setLayer( context.activeLayer() );
5993 }
5994 }
5995}
5996
5997void QgsProcessingMapLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5998{
5999 if ( mComboBox )
6000 mComboBox->setValue( value, context );
6001}
6002
6003QVariant QgsProcessingMapLayerWidgetWrapper::widgetValue() const
6004{
6005 return mComboBox ? mComboBox->value() : QVariant();
6006}
6007
6008QStringList QgsProcessingMapLayerWidgetWrapper::compatibleParameterTypes() const
6009{
6010 return QStringList()
6019}
6020
6021QStringList QgsProcessingMapLayerWidgetWrapper::compatibleOutputTypes() const
6022{
6023 return QStringList()
6029}
6030
6031QString QgsProcessingMapLayerWidgetWrapper::modelerExpressionFormatString() const
6032{
6033 return tr( "path to a map layer" );
6034}
6035
6036QgsProcessingModelChildParameterSource::Source QgsProcessingMapLayerWidgetWrapper::defaultModelSource( const QgsProcessingParameterDefinition * ) const
6037{
6038 return QgsProcessingModelChildParameterSource::ModelParameter;
6039}
6040
6041QString QgsProcessingMapLayerWidgetWrapper::parameterType() const
6042{
6044}
6045
6046QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6047{
6048 return new QgsProcessingMapLayerWidgetWrapper( parameter, type );
6049}
6050
6051QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6052{
6053 return new QgsProcessingMapLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6054}
6055
6056
6057//
6058// QgsProcessingRasterLayerWidgetWrapper
6059//
6060
6061QgsProcessingRasterLayerWidgetWrapper::QgsProcessingRasterLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6062 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6063{
6064
6065}
6066
6067QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleParameterTypes() const
6068{
6069 return QStringList()
6074}
6075
6076QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleOutputTypes() const
6077{
6078 return QStringList()
6084}
6085
6086QString QgsProcessingRasterLayerWidgetWrapper::modelerExpressionFormatString() const
6087{
6088 return tr( "path to a raster layer" );
6089}
6090
6091QString QgsProcessingRasterLayerWidgetWrapper::parameterType() const
6092{
6094}
6095
6096QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6097{
6098 return new QgsProcessingRasterLayerWidgetWrapper( parameter, type );
6099}
6100
6101QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRasterLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6102{
6103 Q_UNUSED( context );
6104 Q_UNUSED( widgetContext );
6105 Q_UNUSED( definition );
6106 Q_UNUSED( algorithm );
6107
6108 return nullptr;
6109}
6110
6111
6112//
6113// QgsProcessingVectorLayerWidgetWrapper
6114//
6115
6116QgsProcessingVectorLayerParameterDefinitionWidget::QgsProcessingVectorLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6117 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6118{
6119 QVBoxLayout *vlayout = new QVBoxLayout();
6120 vlayout->setContentsMargins( 0, 0, 0, 0 );
6121
6122 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6123 mGeometryTypeComboBox = new QgsCheckableComboBox();
6124 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
6125 mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
6126 mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
6127 mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
6128 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6129
6130 if ( const QgsProcessingParameterVectorLayer *vectorParam = dynamic_cast<const QgsProcessingParameterVectorLayer *>( definition ) )
6131 {
6132 for ( int i : vectorParam->dataTypes() )
6133 {
6134 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6135 }
6136 }
6137
6138 vlayout->addWidget( mGeometryTypeComboBox );
6139
6140 setLayout( vlayout );
6141}
6142
6143QgsProcessingParameterDefinition *QgsProcessingVectorLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6144{
6145 QList< int > dataTypes;
6146 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6147 dataTypes << v.toInt();
6148
6149 auto param = std::make_unique< QgsProcessingParameterVectorLayer >( name, description, dataTypes );
6150 param->setFlags( flags );
6151 return param.release();
6152}
6153
6154
6155QgsProcessingVectorLayerWidgetWrapper::QgsProcessingVectorLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6156 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6157{
6158
6159}
6160
6161QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleParameterTypes() const
6162{
6163 return QStringList()
6168}
6169
6170QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleOutputTypes() const
6171{
6172 return QStringList()
6178}
6179
6180QString QgsProcessingVectorLayerWidgetWrapper::modelerExpressionFormatString() const
6181{
6182 return tr( "path to a vector layer" );
6183}
6184
6185QList<int> QgsProcessingVectorLayerWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6186{
6187 if ( const QgsProcessingParameterVectorLayer *param = dynamic_cast< const QgsProcessingParameterVectorLayer *>( parameter ) )
6188 return param->dataTypes();
6189 else
6190 return QList< int >();
6191}
6192
6193QString QgsProcessingVectorLayerWidgetWrapper::parameterType() const
6194{
6196}
6197
6198QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6199{
6200 return new QgsProcessingVectorLayerWidgetWrapper( parameter, type );
6201}
6202
6203QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingVectorLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6204{
6205 return new QgsProcessingVectorLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6206}
6207
6208
6209
6210//
6211// QgsProcessingFeatureSourceLayerWidgetWrapper
6212//
6213
6214QgsProcessingFeatureSourceParameterDefinitionWidget::QgsProcessingFeatureSourceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6215 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6216{
6217 QVBoxLayout *vlayout = new QVBoxLayout();
6218 vlayout->setContentsMargins( 0, 0, 0, 0 );
6219
6220 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6221 mGeometryTypeComboBox = new QgsCheckableComboBox();
6222 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
6223 mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
6224 mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
6225 mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
6226 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6227
6228 if ( const QgsProcessingParameterFeatureSource *sourceParam = dynamic_cast<const QgsProcessingParameterFeatureSource *>( definition ) )
6229 {
6230 for ( int i : sourceParam->dataTypes() )
6231 {
6232 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6233 }
6234 }
6235 else
6236 {
6237 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( QgsProcessing::TypeVectorAnyGeometry ), Qt::Checked );
6238 }
6239
6240 vlayout->addWidget( mGeometryTypeComboBox );
6241
6242 setLayout( vlayout );
6243}
6244
6245QgsProcessingParameterDefinition *QgsProcessingFeatureSourceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6246{
6247 QList< int > dataTypes;
6248 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6249 dataTypes << v.toInt();
6250
6251 auto param = std::make_unique< QgsProcessingParameterFeatureSource >( name, description, dataTypes );
6252 param->setFlags( flags );
6253 return param.release();
6254}
6255
6256QgsProcessingFeatureSourceWidgetWrapper::QgsProcessingFeatureSourceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6257 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6258{
6259
6260}
6261
6262QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleParameterTypes() const
6263{
6264 return QStringList()
6270}
6271
6272QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleOutputTypes() const
6273{
6274 return QStringList()
6280}
6281
6282QString QgsProcessingFeatureSourceWidgetWrapper::modelerExpressionFormatString() const
6283{
6284 return tr( "path to a vector layer" );
6285}
6286
6287QList<int> QgsProcessingFeatureSourceWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6288{
6289 if ( const QgsProcessingParameterFeatureSource *param = dynamic_cast< const QgsProcessingParameterFeatureSource *>( parameter ) )
6290 return param->dataTypes();
6291 else
6292 return QList< int >();
6293}
6294
6295QString QgsProcessingFeatureSourceWidgetWrapper::parameterType() const
6296{
6298}
6299
6300QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSourceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6301{
6302 return new QgsProcessingFeatureSourceWidgetWrapper( parameter, type );
6303}
6304
6305QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFeatureSourceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6306{
6307 return new QgsProcessingFeatureSourceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6308}
6309
6310//
6311// QgsProcessingMeshLayerWidgetWrapper
6312//
6313
6314QgsProcessingMeshLayerWidgetWrapper::QgsProcessingMeshLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6315 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6316{
6317
6318}
6319
6320QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleParameterTypes() const
6321{
6322 return QStringList()
6327}
6328
6329QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleOutputTypes() const
6330{
6331 return QStringList()
6333 // TODO << QgsProcessingOutputMeshLayer::typeName()
6337}
6338
6339QString QgsProcessingMeshLayerWidgetWrapper::modelerExpressionFormatString() const
6340{
6341 return tr( "path to a mesh layer" );
6342}
6343
6344QString QgsProcessingMeshLayerWidgetWrapper::parameterType() const
6345{
6347}
6348
6349QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6350{
6351 return new QgsProcessingMeshLayerWidgetWrapper( parameter, type );
6352}
6353
6354QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6355{
6356 Q_UNUSED( context );
6357 Q_UNUSED( widgetContext );
6358 Q_UNUSED( definition );
6359 Q_UNUSED( algorithm );
6360
6361 return nullptr;
6362}
6363
6364
6365
6366//
6367// QgsProcessingRasterBandPanelWidget
6368//
6369
6370QgsProcessingRasterBandPanelWidget::QgsProcessingRasterBandPanelWidget( QWidget *parent, const QgsProcessingParameterBand *param )
6371 : QWidget( parent )
6372 , mParam( param )
6373{
6374 QHBoxLayout *hl = new QHBoxLayout();
6375 hl->setContentsMargins( 0, 0, 0, 0 );
6376
6377 mLineEdit = new QLineEdit();
6378 mLineEdit->setEnabled( false );
6379 hl->addWidget( mLineEdit, 1 );
6380
6381 mToolButton = new QToolButton();
6382 mToolButton->setText( QString( QChar( 0x2026 ) ) );
6383 hl->addWidget( mToolButton );
6384
6385 setLayout( hl );
6386
6387 if ( mParam )
6388 {
6389 mLineEdit->setText( tr( "%n band(s) selected", nullptr, 0 ) );
6390 }
6391
6392 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingRasterBandPanelWidget::showDialog );
6393}
6394
6395void QgsProcessingRasterBandPanelWidget::setBands( const QList< int > &bands )
6396{
6397 mBands = bands;
6398}
6399
6400void QgsProcessingRasterBandPanelWidget::setBandNames( const QHash<int, QString> &names )
6401{
6402 mBandNames = names;
6403}
6404
6405void QgsProcessingRasterBandPanelWidget::setValue( const QVariant &value )
6406{
6407 if ( value.isValid() )
6408 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
6409 else
6410 mValue.clear();
6411
6412 updateSummaryText();
6413 emit changed();
6414}
6415
6416void QgsProcessingRasterBandPanelWidget::showDialog()
6417{
6418 QVariantList availableOptions;
6419 QStringList fieldNames;
6420 availableOptions.reserve( mBands.size() );
6421 for ( int band : std::as_const( mBands ) )
6422 {
6423 availableOptions << band;
6424 }
6425
6427 if ( panel && panel->dockMode() )
6428 {
6429 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
6430 widget->setPanelTitle( mParam->description() );
6431
6432 widget->setValueFormatter( [this]( const QVariant & v ) -> QString
6433 {
6434 int band = v.toInt();
6435 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6436 } );
6437
6438 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
6439 {
6440 setValue( widget->selectedOptions() );
6441 } );
6442 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
6443 panel->openPanel( widget );
6444 }
6445 else
6446 {
6447 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
6448
6449 dlg.setValueFormatter( [this]( const QVariant & v ) -> QString
6450 {
6451 int band = v.toInt();
6452 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6453 } );
6454 if ( dlg.exec() )
6455 {
6456 setValue( dlg.selectedOptions() );
6457 }
6458 }
6459}
6460
6461void QgsProcessingRasterBandPanelWidget::updateSummaryText()
6462{
6463 if ( mParam )
6464 mLineEdit->setText( tr( "%n band(s) selected", nullptr, mValue.count() ) );
6465}
6466
6467
6468
6469//
6470// QgsProcessingBandWidgetWrapper
6471//
6472
6473QgsProcessingBandParameterDefinitionWidget::QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6474 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6475{
6476 QVBoxLayout *vlayout = new QVBoxLayout();
6477 vlayout->setContentsMargins( 0, 0, 0, 0 );
6478
6479 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
6480
6481 mDefaultLineEdit = new QLineEdit();
6482 mDefaultLineEdit->setToolTip( tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6483 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6484 {
6485 const QList< int > bands = QgsProcessingParameters::parameterAsInts( bandParam, bandParam->defaultValueForGui(), context );
6486 QStringList defVal;
6487 for ( int b : bands )
6488 {
6489 defVal << QString::number( b );
6490 }
6491
6492 mDefaultLineEdit->setText( defVal.join( ';' ) );
6493 }
6494 vlayout->addWidget( mDefaultLineEdit );
6495
6496 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
6497 mParentLayerComboBox = new QComboBox();
6498
6499 QString initialParent;
6500 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6501 initialParent = bandParam->parentLayerParameterName();
6502
6503 if ( auto *lModel = widgetContext.model() )
6504 {
6505 // populate combo box with other model input choices
6506 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
6507 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
6508 {
6509 if ( const QgsProcessingParameterRasterLayer *definition = dynamic_cast< const QgsProcessingParameterRasterLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
6510 {
6511 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
6512 if ( !initialParent.isEmpty() && initialParent == definition->name() )
6513 {
6514 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6515 }
6516 }
6517 }
6518 }
6519
6520 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
6521 {
6522 // if no parent candidates found, we just add the existing one as a placeholder
6523 mParentLayerComboBox->addItem( initialParent, initialParent );
6524 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6525 }
6526
6527 vlayout->addWidget( mParentLayerComboBox );
6528
6529 mAllowMultipleCheckBox = new QCheckBox( tr( "Allow multiple" ) );
6530 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6531 mAllowMultipleCheckBox->setChecked( bandParam->allowMultiple() );
6532
6533 vlayout->addWidget( mAllowMultipleCheckBox );
6534 setLayout( vlayout );
6535}
6536
6537QgsProcessingParameterDefinition *QgsProcessingBandParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6538{
6539 auto param = std::make_unique< QgsProcessingParameterBand >( name, description, mDefaultLineEdit->text().split( ';' ), mParentLayerComboBox->currentData().toString(), false, mAllowMultipleCheckBox->isChecked() );
6540 param->setFlags( flags );
6541 return param.release();
6542}
6543
6544QgsProcessingBandWidgetWrapper::QgsProcessingBandWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6545 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6546{
6547
6548}
6549
6550QWidget *QgsProcessingBandWidgetWrapper::createWidget()
6551{
6552 const QgsProcessingParameterBand *bandParam = dynamic_cast< const QgsProcessingParameterBand *>( parameterDefinition() );
6553 switch ( type() )
6554 {
6557 {
6558 if ( bandParam->allowMultiple() )
6559 {
6560 mPanel = new QgsProcessingRasterBandPanelWidget( nullptr, bandParam );
6561 mPanel->setToolTip( parameterDefinition()->toolTip() );
6562 connect( mPanel, &QgsProcessingRasterBandPanelWidget::changed, this, [ = ]
6563 {
6564 emit widgetValueHasChanged( this );
6565 } );
6566 return mPanel;
6567 }
6568 else
6569 {
6570 mComboBox = new QgsRasterBandComboBox();
6571 mComboBox->setShowNotSetOption( bandParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
6572
6573 mComboBox->setToolTip( parameterDefinition()->toolTip() );
6574 connect( mComboBox, &QgsRasterBandComboBox::bandChanged, this, [ = ]( int )
6575 {
6576 emit widgetValueHasChanged( this );
6577 } );
6578 return mComboBox;
6579 }
6580 }
6581
6583 {
6584 mLineEdit = new QLineEdit();
6585 mLineEdit->setToolTip( QObject::tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6586 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
6587 {
6588 emit widgetValueHasChanged( this );
6589 } );
6590 return mLineEdit;
6591 }
6592
6593 }
6594 return nullptr;
6595}
6596
6597void QgsProcessingBandWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
6598{
6600 switch ( type() )
6601 {
6604 {
6605 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
6606 {
6607 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterBand * >( parameterDefinition() )->parentLayerParameterName() )
6608 {
6609 setParentLayerWrapperValue( wrapper );
6611 {
6612 setParentLayerWrapperValue( wrapper );
6613 } );
6614 break;
6615 }
6616 }
6617 break;
6618 }
6619
6621 break;
6622 }
6623}
6624
6625void QgsProcessingBandWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
6626{
6627 // evaluate value to layer
6628 QgsProcessingContext *context = nullptr;
6629 std::unique_ptr< QgsProcessingContext > tmpContext;
6630 if ( mProcessingContextGenerator )
6631 context = mProcessingContextGenerator->processingContext();
6632
6633 if ( !context )
6634 {
6635 tmpContext = std::make_unique< QgsProcessingContext >();
6636 context = tmpContext.get();
6637 }
6638
6639 QVariant value = parentWrapper->parameterValue();
6640
6641 QgsRasterLayer *layer = QgsProcessingParameters::parameterAsRasterLayer( parentWrapper->parameterDefinition(), value, *context );
6642 if ( layer && layer->isValid() )
6643 {
6644 // need to grab ownership of layer if required - otherwise layer may be deleted when context
6645 // goes out of scope
6646 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
6647 if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::RasterLayer )
6648 {
6649 mParentLayer.reset( qobject_cast< QgsRasterLayer * >( ownedLayer.release() ) );
6650 layer = mParentLayer.get();
6651 }
6652 else
6653 {
6654 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
6655 }
6656
6657 if ( mComboBox )
6658 mComboBox->setLayer( layer );
6659 else if ( mPanel )
6660 {
6661 QgsRasterDataProvider *provider = layer->dataProvider();
6662 if ( provider && layer->isValid() )
6663 {
6664 //fill available bands
6665 int nBands = provider->bandCount();
6666 QList< int > bands;
6667 QHash< int, QString > bandNames;
6668 for ( int i = 1; i <= nBands; ++i )
6669 {
6670 bandNames.insert( i, QgsRasterBandComboBox::displayBandName( provider, i ) );
6671 bands << i;
6672 }
6673 mPanel->setBands( bands );
6674 mPanel->setBandNames( bandNames );
6675 }
6676 }
6677 }
6678 else
6679 {
6680 if ( mComboBox )
6681 mComboBox->setLayer( nullptr );
6682 else if ( mPanel )
6683 mPanel->setBands( QList< int >() );
6684
6685 if ( value.isValid() && widgetContext().messageBar() )
6686 {
6687 widgetContext().messageBar()->clearWidgets();
6688 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent bands could not be populated" ),
6690 }
6691 }
6692
6693 if ( parameterDefinition()->defaultValueForGui().isValid() )
6694 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
6695}
6696
6697void QgsProcessingBandWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6698{
6699 if ( mComboBox )
6700 {
6701 if ( !value.isValid() )
6702 mComboBox->setBand( -1 );
6703 else
6704 {
6705 const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
6706 mComboBox->setBand( v );
6707 }
6708 }
6709 else if ( mPanel )
6710 {
6711 QVariantList opts;
6712 if ( value.isValid() )
6713 {
6714 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6715 opts.reserve( v.size() );
6716 for ( int i : v )
6717 opts << i;
6718 }
6719 if ( mPanel )
6720 mPanel->setValue( value.isValid() ? opts : QVariant() );
6721 }
6722 else if ( mLineEdit )
6723 {
6724 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6725 if ( bandParam->allowMultiple() )
6726 {
6727 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6728 QStringList opts;
6729 opts.reserve( v.size() );
6730 for ( int i : v )
6731 opts << QString::number( i );
6732 mLineEdit->setText( value.isValid() && !opts.empty() ? opts.join( ';' ) : QString() );
6733 }
6734 else
6735 {
6736 if ( value.isValid() )
6737 mLineEdit->setText( QString::number( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) ) );
6738 else
6739 mLineEdit->clear();
6740 }
6741 }
6742}
6743
6744QVariant QgsProcessingBandWidgetWrapper::widgetValue() const
6745{
6746 if ( mComboBox )
6747 return mComboBox->currentBand() == -1 ? QVariant() : mComboBox->currentBand();
6748 else if ( mPanel )
6749 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
6750 else if ( mLineEdit )
6751 {
6752 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6753 if ( bandParam->allowMultiple() )
6754 {
6755#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
6756 const QStringList parts = mLineEdit->text().split( ';', QString::SkipEmptyParts );
6757#else
6758 const QStringList parts = mLineEdit->text().split( ';', Qt::SkipEmptyParts );
6759#endif
6760 QVariantList res;
6761 res.reserve( parts.count() );
6762 for ( const QString &s : parts )
6763 {
6764 bool ok = false;
6765 int band = s.toInt( &ok );
6766 if ( ok )
6767 res << band;
6768 }
6769 return res.isEmpty() ? QVariant() : res;
6770 }
6771 else
6772 {
6773 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
6774 }
6775 }
6776 else
6777 return QVariant();
6778}
6779
6780QStringList QgsProcessingBandWidgetWrapper::compatibleParameterTypes() const
6781{
6782 return QStringList()
6785}
6786
6787QStringList QgsProcessingBandWidgetWrapper::compatibleOutputTypes() const
6788{
6789 return QStringList()
6791}
6792
6793QString QgsProcessingBandWidgetWrapper::modelerExpressionFormatString() const
6794{
6795 return tr( "selected band numbers as an array of numbers, or semicolon separated string of options (e.g. '1;3')" );
6796}
6797
6798QString QgsProcessingBandWidgetWrapper::parameterType() const
6799{
6801}
6802
6803QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBandWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6804{
6805 return new QgsProcessingBandWidgetWrapper( parameter, type );
6806}
6807
6808QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBandWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6809{
6810 return new QgsProcessingBandParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6811}
6812
6813
6814
6815//
6816// QgsProcessingMultipleLayerPanelWidget
6817//
6818
6819QgsProcessingMultipleLayerPanelWidget::QgsProcessingMultipleLayerPanelWidget( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
6820 : QWidget( parent )
6821 , mParam( param )
6822{
6823 QHBoxLayout *hl = new QHBoxLayout();
6824 hl->setContentsMargins( 0, 0, 0, 0 );
6825
6826 mLineEdit = new QLineEdit();
6827 mLineEdit->setEnabled( false );
6828 hl->addWidget( mLineEdit, 1 );
6829
6830 mToolButton = new QToolButton();
6831 mToolButton->setText( QString( QChar( 0x2026 ) ) );
6832 hl->addWidget( mToolButton );
6833
6834 setLayout( hl );
6835
6836 if ( mParam )
6837 {
6838 mLineEdit->setText( tr( "%n input(s) selected", nullptr, 0 ) );
6839 }
6840
6841 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMultipleLayerPanelWidget::showDialog );
6842}
6843
6844void QgsProcessingMultipleLayerPanelWidget::setValue( const QVariant &value )
6845{
6846 if ( value.isValid() )
6847 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
6848 else
6849 mValue.clear();
6850
6851 updateSummaryText();
6852 emit changed();
6853}
6854
6855void QgsProcessingMultipleLayerPanelWidget::setProject( QgsProject *project )
6856{
6857 mProject = project;
6858 if ( mProject )
6859 {
6860 connect( mProject, &QgsProject::layerRemoved, this, [&]( const QString & layerId )
6861 {
6862 if ( mValue.removeAll( layerId ) )
6863 {
6864 updateSummaryText();
6865 emit changed();
6866 }
6867 } );
6868 }
6869}
6870
6871void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorithm *model, const QString &modelChildAlgorithmID )
6872{
6873 mModel = model;
6874 if ( !model )
6875 return;
6876
6877 switch ( mParam->layerType() )
6878 {
6880 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFile::typeName(),
6881 QStringList() << QgsProcessingOutputFile::typeName() );
6882 break;
6883
6885 {
6886 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterRasterLayer::typeName()
6889 QStringList() << QgsProcessingOutputFile::typeName()
6893 break;
6894 }
6895
6897 {
6898 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMeshLayer::typeName()
6901 QStringList() << QgsProcessingOutputFile::typeName()
6904 break;
6905 }
6906
6908 {
6909 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
6912 QStringList() << QgsProcessingOutputFile::typeName()
6915 break;
6916 }
6917
6919 {
6920 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterPointCloudLayer::typeName()
6923 QStringList() << QgsProcessingOutputFile::typeName()
6926 break;
6927 }
6928
6930 {
6931 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterAnnotationLayer::typeName()
6933 QStringList() << QgsProcessingOutputMapLayer::typeName()
6935 break;
6936 }
6937
6939 {
6940 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6944 QStringList() << QgsProcessingOutputFile::typeName()
6948 QList< int >() << QgsProcessing::TypeVector );
6949 break;
6950 }
6951
6953 {
6954 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6958 QStringList() << QgsProcessingOutputFile::typeName()
6962 break;
6963 }
6964
6966 {
6967 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6971 QStringList() << QgsProcessingOutputFile::typeName()
6976 break;
6977 }
6978
6980 {
6981 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6985 QStringList() << QgsProcessingOutputFile::typeName()
6990 break;
6991 }
6992
6994 {
6995 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6999 QStringList() << QgsProcessingOutputFile::typeName()
7004 break;
7005 }
7006
7008 {
7009 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7015 QStringList() << QgsProcessingOutputFile::typeName()
7019 // << QgsProcessingOutputMeshLayer::typeName()
7021 break;
7022 }
7023 }
7024}
7025
7026void QgsProcessingMultipleLayerPanelWidget::showDialog()
7027{
7029 if ( panel && panel->dockMode() )
7030 {
7031 QgsProcessingMultipleInputPanelWidget *widget = new QgsProcessingMultipleInputPanelWidget( mParam, mValue, mModelSources, mModel );
7032 widget->setPanelTitle( mParam->description() );
7033 widget->setProject( mProject );
7034 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
7035 {
7036 setValue( widget->selectedOptions() );
7037 } );
7038 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
7039 panel->openPanel( widget );
7040 }
7041 else
7042 {
7043 QgsProcessingMultipleInputDialog dlg( mParam, mValue, mModelSources, mModel, this, Qt::WindowFlags() );
7044 dlg.setProject( mProject );
7045 if ( dlg.exec() )
7046 {
7047 setValue( dlg.selectedOptions() );
7048 }
7049 }
7050}
7051
7052void QgsProcessingMultipleLayerPanelWidget::updateSummaryText()
7053{
7054 if ( mParam )
7055 mLineEdit->setText( tr( "%n input(s) selected", nullptr, mValue.count() ) );
7056}
7057
7058//
7059// QgsProcessingMultipleLayerWidgetWrapper
7060//
7061
7062QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
7063 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
7064{
7065 QVBoxLayout *vlayout = new QVBoxLayout();
7066 vlayout->setContentsMargins( 0, 0, 0, 0 );
7067
7068 vlayout->addWidget( new QLabel( tr( "Allowed layer type" ) ) );
7069 mLayerTypeComboBox = new QComboBox();
7070 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
7071 mLayerTypeComboBox->addItem( tr( "Vector (No Geometry Required)" ), QgsProcessing::TypeVector );
7072 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
7073 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
7074 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
7075 mLayerTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
7076 mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
7077 mLayerTypeComboBox->addItem( tr( "File" ), QgsProcessing::TypeFile );
7078 mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
7079 mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );
7080 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), QgsProcessing::TypePointCloud );
7081 mLayerTypeComboBox->addItem( tr( "Annotation" ), QgsProcessing::TypeAnnotation );
7082 if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
7083 mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( layersParam->layerType() ) );
7084
7085 vlayout->addWidget( mLayerTypeComboBox );
7086 setLayout( vlayout );
7087}
7088
7089QgsProcessingParameterDefinition *QgsProcessingMultipleLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
7090{
7091 auto param = std::make_unique< QgsProcessingParameterMultipleLayers >( name, description, static_cast< QgsProcessing::SourceType >( mLayerTypeComboBox->currentData().toInt() ) );
7092 param->setFlags( flags );
7093 return param.release();
7094}
7095
7096QgsProcessingMultipleLayerWidgetWrapper::QgsProcessingMultipleLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7097 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7098{
7099
7100}
7101
7102QWidget *QgsProcessingMultipleLayerWidgetWrapper::createWidget()
7103{
7104 const QgsProcessingParameterMultipleLayers *layerParam = dynamic_cast< const QgsProcessingParameterMultipleLayers *>( parameterDefinition() );
7105
7106 mPanel = new QgsProcessingMultipleLayerPanelWidget( nullptr, layerParam );
7107 mPanel->setToolTip( parameterDefinition()->toolTip() );
7108 mPanel->setProject( widgetContext().project() );
7109 if ( type() == QgsProcessingGui::Modeler )
7110 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7111 connect( mPanel, &QgsProcessingMultipleLayerPanelWidget::changed, this, [ = ]
7112 {
7113 emit widgetValueHasChanged( this );
7114 } );
7115 return mPanel;
7116}
7117
7118void QgsProcessingMultipleLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7119{
7121 if ( mPanel )
7122 {
7123 mPanel->setProject( context.project() );
7124 if ( type() == QgsProcessingGui::Modeler )
7125 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7126 }
7127}
7128
7129void QgsProcessingMultipleLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7130{
7131 if ( mPanel )
7132 {
7133 QVariantList opts;
7134 if ( value.isValid() )
7135 {
7136 const QList< QgsMapLayer * > v = QgsProcessingParameters::parameterAsLayerList( parameterDefinition(), value, context );
7137 opts.reserve( v.size() );
7138 for ( const QgsMapLayer *l : v )
7139 opts << l->source();
7140 }
7141
7142 for ( const QVariant &v : value.toList() )
7143 {
7144 if ( v.userType() == QMetaType::type( "QgsProcessingModelChildParameterSource" ) )
7145 {
7146 const QgsProcessingModelChildParameterSource source = v.value< QgsProcessingModelChildParameterSource >();
7147 opts << QVariant::fromValue( source );
7148 }
7149 }
7150
7151 if ( mPanel )
7152 mPanel->setValue( value.isValid() ? opts : QVariant() );
7153 }
7154}
7155
7156QVariant QgsProcessingMultipleLayerWidgetWrapper::widgetValue() const
7157{
7158 if ( mPanel )
7159 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
7160 else
7161 return QVariant();
7162}
7163
7164QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleParameterTypes() const
7165{
7166 return QStringList()
7175}
7176
7177QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleOutputTypes() const
7178{
7179 return QStringList()
7186}
7187
7188QString QgsProcessingMultipleLayerWidgetWrapper::modelerExpressionFormatString() const
7189{
7190 return tr( "an array of layer paths, or semicolon separated string of layer paths" );
7191}
7192
7193QString QgsProcessingMultipleLayerWidgetWrapper::parameterType() const
7194{
7196}
7197
7198QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMultipleLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7199{
7200 return new QgsProcessingMultipleLayerWidgetWrapper( parameter, type );
7201}
7202
7203QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMultipleLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7204{
7205 return new QgsProcessingMultipleLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
7206}
7207
7208
7209//
7210// QgsProcessingPointCloudLayerWidgetWrapper
7211//
7212
7213QgsProcessingPointCloudLayerWidgetWrapper::QgsProcessingPointCloudLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7214 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
7215{
7216
7217}
7218
7219QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleParameterTypes() const
7220{
7221 return QStringList()
7226}
7227
7228QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleOutputTypes() const
7229{
7230 return QStringList()
7232 // TODO << QgsProcessingOutputPointCloudLayer::typeName()
7236}
7237
7238QString QgsProcessingPointCloudLayerWidgetWrapper::modelerExpressionFormatString() const
7239{
7240 return tr( "path to a point cloud layer" );
7241}
7242
7243QString QgsProcessingPointCloudLayerWidgetWrapper::parameterType() const
7244{
7246}
7247
7248QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7249{
7250 return new QgsProcessingPointCloudLayerWidgetWrapper( parameter, type );
7251}
7252
7253QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7254{
7255 Q_UNUSED( context );
7256 Q_UNUSED( widgetContext );
7257 Q_UNUSED( definition );
7258 Q_UNUSED( algorithm );
7259
7260 return nullptr;
7261}
7262
7263
7264//
7265// QgsProcessingAnnotationLayerWidgetWrapper
7266//
7267
7268QgsProcessingAnnotationLayerWidgetWrapper::QgsProcessingAnnotationLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7269 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7270{
7271
7272}
7273
7274QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleParameterTypes() const
7275{
7276 return QStringList()
7281}
7282
7283QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleOutputTypes() const
7284{
7285 return QStringList()
7288}
7289
7290QString QgsProcessingAnnotationLayerWidgetWrapper::modelerExpressionFormatString() const
7291{
7292 return tr( "name of an annotation layer, or \"main\" for the main annotation layer" );
7293}
7294
7295QString QgsProcessingAnnotationLayerWidgetWrapper::parameterType() const
7296{
7298}
7299
7300QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAnnotationLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7301{
7302 return new QgsProcessingAnnotationLayerWidgetWrapper( parameter, type );
7303}
7304
7305QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingAnnotationLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7306{
7307 Q_UNUSED( context );
7308 Q_UNUSED( widgetContext );
7309 Q_UNUSED( definition );
7310 Q_UNUSED( algorithm );
7311
7312 return nullptr;
7313}
7314
7315void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7316{
7318 if ( mComboBox )
7319 {
7320 if ( mWidgetContext.project() )
7321 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7322 }
7323}
7324
7325QWidget *QgsProcessingAnnotationLayerWidgetWrapper::createWidget()
7326{
7327 mComboBox = new QgsMapLayerComboBox( );
7328 mComboBox->setFilters( QgsMapLayerProxyModel::AnnotationLayer );
7329
7330 switch ( type() )
7331 {
7334 break;
7336 mComboBox->setEditable( true );
7337 break;
7338 }
7339
7340 mComboBox->setToolTip( parameterDefinition()->toolTip() );
7341
7342 if ( mWidgetContext.project() )
7343 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7344
7345 if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
7346 mComboBox->setAllowEmptyLayer( true );
7347
7348 connect( mComboBox, &QgsMapLayerComboBox::layerChanged, this, [ = ]()
7349 {
7350 if ( mBlockSignals )
7351 return;
7352
7353 emit widgetValueHasChanged( this );
7354 } );
7355
7356 setWidgetContext( widgetContext() );
7357 return mComboBox;
7358}
7359
7360void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7361{
7362 if ( mComboBox )
7363 {
7364 if ( !value.isValid() && parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
7365 {
7366 mComboBox->setLayer( nullptr );
7367 return;
7368 }
7369
7370 QVariant val = value;
7371 if ( val.userType() == QMetaType::type( "QgsProperty" ) )
7372 {
7373 if ( val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
7374 {
7375 val = val.value< QgsProperty >().staticValue();
7376 }
7377 else
7378 {
7379 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), parameterDefinition()->defaultValueForGui().toString() );
7380 }
7381 }
7382
7383 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
7384 if ( !layer && val.type() == QVariant::String )
7385 {
7387 }
7388
7389 if ( layer )
7390 {
7391 mComboBox->setLayer( layer );
7392 }
7393 }
7394}
7395
7396QVariant QgsProcessingAnnotationLayerWidgetWrapper::widgetValue() const
7397{
7398 return mComboBox && mComboBox->currentLayer() ?
7399 ( mWidgetContext.project() ? ( mComboBox->currentLayer() == mWidgetContext.project()->mainAnnotationLayer() ? QStringLiteral( "main" ) : mComboBox->currentLayer()->id() ) : mComboBox->currentLayer()->id() )
7400 : QVariant();
7401}
7402
7403
7404
7405//
7406// QgsProcessingOutputWidgetWrapper
7407//
7408
7409QgsProcessingOutputWidgetWrapper::QgsProcessingOutputWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7410 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7411{
7412
7413}
7414
7415QWidget *QgsProcessingOutputWidgetWrapper::createWidget()
7416{
7417 const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( parameterDefinition() );
7418 switch ( type() )
7419 {
7422 {
7423 mOutputWidget = new QgsProcessingLayerOutputDestinationWidget( destParam, false );
7424 if ( mProcessingContextGenerator )
7425 mOutputWidget->setContext( mProcessingContextGenerator->processingContext() );
7426 if ( mParametersGenerator )
7427 mOutputWidget->registerProcessingParametersGenerator( mParametersGenerator );
7428 mOutputWidget->setToolTip( parameterDefinition()->toolTip() );
7429
7430 connect( mOutputWidget, &QgsProcessingLayerOutputDestinationWidget::destinationChanged, this, [ = ]()
7431 {
7432 if ( mBlockSignals )
7433 return;
7434
7435 emit widgetValueHasChanged( this );
7436 } );
7437
7438 if ( type() == QgsProcessingGui::Standard
7443 mOutputWidget->addOpenAfterRunningOption();
7444
7445 return mOutputWidget;
7446 }
7448 break;
7449 }
7450
7451 return nullptr;
7452}
7453
7454
7455void QgsProcessingOutputWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
7456{
7457 if ( mOutputWidget )
7458 mOutputWidget->setValue( value );
7459}
7460
7461QVariant QgsProcessingOutputWidgetWrapper::widgetValue() const
7462{
7463 if ( mOutputWidget )
7464 return mOutputWidget->value();
7465
7466 return QVariant();
7467}
7468
7469QVariantMap QgsProcessingOutputWidgetWrapper::customProperties() const
7470{
7471 QVariantMap res;
7472 if ( mOutputWidget )
7473 res.insert( QStringLiteral( "OPEN_AFTER_RUNNING" ), mOutputWidget->openAfterRunning() );
7474 return res;
7475}
7476
7477QStringList QgsProcessingOutputWidgetWrapper::compatibleParameterTypes() const
7478{
7479 return QStringList()
7486}
7487
7488QStringList QgsProcessingOutputWidgetWrapper::compatibleOutputTypes() const
7489{
7490 return QStringList()
7494}
7495
7496//
7497// QgsProcessingFeatureSinkWidgetWrapper
7498//
7499
7500QgsProcessingFeatureSinkWidgetWrapper::QgsProcessingFeatureSinkWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7501 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7502{
7503
7504}
7505
7506QString QgsProcessingFeatureSinkWidgetWrapper::parameterType() const
7507{
7509}
7510
7511QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSinkWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7512{
7513 return new QgsProcessingFeatureSinkWidgetWrapper( parameter, type );
7514}
7515
7516QString QgsProcessingFeatureSinkWidgetWrapper::modelerExpressionFormatString() const
7517{
7518 return tr( "path to layer destination" );
7519}
7520
7521//
7522// QgsProcessingFeatureSinkWidgetWrapper
7523//
7524
7525QgsProcessingVectorDestinationWidgetWrapper::QgsProcessingVectorDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7526 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7527{
7528
7529}
7530
7531QString QgsProcessingVectorDestinationWidgetWrapper::parameterType() const
7532{
7534}
7535
7536QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7537{
7538 return new QgsProcessingVectorDestinationWidgetWrapper( parameter, type );
7539}
7540
7541QString QgsProcessingVectorDestinationWidgetWrapper::modelerExpressionFormatString() const
7542{
7543 return tr( "path to layer destination" );
7544}
7545
7546//
7547// QgsProcessingRasterDestinationWidgetWrapper
7548//
7549
7550QgsProcessingRasterDestinationWidgetWrapper::QgsProcessingRasterDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7551 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7552{
7553
7554}
7555
7556QString QgsProcessingRasterDestinationWidgetWrapper::parameterType() const
7557{
7559}
7560
7561QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7562{
7563 return new QgsProcessingRasterDestinationWidgetWrapper( parameter, type );
7564}
7565
7566QString QgsProcessingRasterDestinationWidgetWrapper::modelerExpressionFormatString() const
7567{
7568 return tr( "path to layer destination" );
7569}
7570
7571//
7572// QgsProcessingPointCloudDestinationWidgetWrapper
7573//
7574
7575QgsProcessingPointCloudDestinationWidgetWrapper::QgsProcessingPointCloudDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7576 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7577{
7578
7579}
7580
7581QString QgsProcessingPointCloudDestinationWidgetWrapper::parameterType() const
7582{
7584}
7585
7586QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7587{
7588 return new QgsProcessingPointCloudDestinationWidgetWrapper( parameter, type );
7589}
7590
7591QString QgsProcessingPointCloudDestinationWidgetWrapper::modelerExpressionFormatString() const
7592{
7593 return tr( "path to layer destination" );
7594}
7595
7596//
7597// QgsProcessingFileDestinationWidgetWrapper
7598//
7599
7600QgsProcessingFileDestinationWidgetWrapper::QgsProcessingFileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7601 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7602{
7603
7604}
7605
7606QString QgsProcessingFileDestinationWidgetWrapper::parameterType() const
7607{
7609}
7610
7611QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7612{
7613 return new QgsProcessingFileDestinationWidgetWrapper( parameter, type );
7614}
7615
7616QString QgsProcessingFileDestinationWidgetWrapper::modelerExpressionFormatString() const
7617{
7618 return tr( "path to file destination" );
7619}
7620
7621//
7622// QgsProcessingFolderDestinationWidgetWrapper
7623//
7624
7625QgsProcessingFolderDestinationWidgetWrapper::QgsProcessingFolderDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7626 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7627{
7628
7629}
7630
7631QString QgsProcessingFolderDestinationWidgetWrapper::parameterType() const
7632{
7634}
7635
7636QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFolderDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7637{
7638 return new QgsProcessingFolderDestinationWidgetWrapper( parameter, type );
7639}
7640
7641QString QgsProcessingFolderDestinationWidgetWrapper::modelerExpressionFormatString() const
7642{
7643 return tr( "path to folder destination" );
7644}
7645
@ Info
Information message.
Definition qgis.h:116
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.
@ CapturePoint
Select and capture a point or a feature.
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.
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.
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.
int count() const
Returns number of items.
bool isEmpty() const
Checks whether the container is empty.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
The QgsFileWidget class creates a widget for selecting a file or a folder.
@ GetFile
Select a single file.
@ GetDirectory
Select a directory.
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.
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.
void setAllowEmptyLayout(bool allowEmpty)
Sets whether an optional empty layout ("not set") option is present in the combobox.
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.
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.
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
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
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.
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.
@ TypePlugin
Plugin layers.
@ TypeVectorLine
Vector line layers.
@ TypeMapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
@ TypeVectorPolygon
Vector polygon layers.
@ TypeFile
Files (i.e. non map layer sources, such as text files)
@ TypeAnnotation
Annotation layers.
@ TypePointCloud
Point cloud layers.
@ TypeMesh
Mesh layers.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ TypeRaster
Raster layers.
@ TypeVectorPoint
Vector point layers.
@ TypeVectorAnyGeometry
Any vector layer with geometry.
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.
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.
@ StaticProperty
Static property (QgsStaticProperty)
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.
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.
@ DistanceMeters
Meters.
@ DistanceDegrees
Degrees, for planar geographic CRS distance measurements.
@ DistanceKilometers
Kilometers.
@ DistanceMiles
Terrestrial miles.
@ DistanceUnknownUnit
Unknown distance unit.
@ DistanceYards
Imperial yards.
@ DistanceFeet
Imperial feet.
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.
TemporalUnit
Temporal units.
@ TemporalWeeks
Weeks.
@ TemporalMilliseconds
Milliseconds.
@ TemporalDays
Days.
@ TemporalDecades
Decades.
@ TemporalCenturies
Centuries.
@ TemporalSeconds
Seconds.
@ TemporalMinutes
Minutes.
@ TemporalYears
Years.
@ TemporalHours
Hours.
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:476
const QgsCoordinateReferenceSystem & crs
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.