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