QGIS API Documentation 3.38.0-Grenoble (exported)
Loading...
Searching...
No Matches
qgsprocessingwidgetwrapperimpl.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingwidgetwrapperimpl.cpp
3 ---------------------
4 begin : August 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
24#include "qgsspinbox.h"
25#include "qgsdoublespinbox.h"
27#include "qgsauthconfigselect.h"
28#include "qgsapplication.h"
29#include "qgsfilewidget.h"
30#include "qgssettings.h"
35#include "qgslayoutmanager.h"
36#include "qgsproject.h"
37#include "qgslayoutcombobox.h"
39#include "qgsprintlayout.h"
40#include "qgsscalewidget.h"
41#include "qgssnapindicator.h"
42#include "qgsmapmouseevent.h"
43#include "qgsfilterlineedit.h"
44#include "qgsmapcanvas.h"
45#include "qgsmessagebar.h"
46#include "qgscolorbutton.h"
49#include "qgsfieldcombobox.h"
51#include "qgsdatetimeedit.h"
55#include "qgsextentwidget.h"
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.userType() == QMetaType::Type::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.userType() == QMetaType::Type::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 {
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;
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;
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.userType() == QMetaType::Type::QVariantList ? 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()
2548}
2549
2550QStringList QgsProcessingExpressionWidgetWrapper::compatibleOutputTypes() const
2551{
2552 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.userType() == QMetaType::Type::QVariantList ? 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.userType() == QMetaType::Type::QVariantList ? 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.userType() == QMetaType::Type::QVariantList )
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()
3168}
3169
3170QStringList QgsProcessingLayoutWidgetWrapper::compatibleOutputTypes() const
3171{
3172 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{
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( mLineEdit, &QLineEdit::textChanged, this, &QgsProcessingPointPanel::textChanged );
3478 connect( mButton, &QToolButton::clicked, this, &QgsProcessingPointPanel::selectOnCanvas );
3479 mButton->setVisible( false );
3480}
3481
3482void QgsProcessingPointPanel::setMapCanvas( QgsMapCanvas *canvas )
3483{
3484 mCanvas = canvas;
3485 mButton->setVisible( true );
3486
3487 mCrs = canvas->mapSettings().destinationCrs();
3488 mTool = std::make_unique< QgsProcessingPointMapTool >( mCanvas );
3489 connect( mTool.get(), &QgsProcessingPointMapTool::clicked, this, &QgsProcessingPointPanel::updatePoint );
3490 connect( mTool.get(), &QgsProcessingPointMapTool::complete, this, &QgsProcessingPointPanel::pointPicked );
3491}
3492
3493void QgsProcessingPointPanel::setAllowNull( bool allowNull )
3494{
3495 mLineEdit->setShowClearButton( allowNull );
3496}
3497
3498void QgsProcessingPointPanel::setShowPointOnCanvas( bool show )
3499{
3500 if ( mShowPointOnCanvas == show )
3501 return;
3502
3503 mShowPointOnCanvas = show;
3504 if ( mShowPointOnCanvas )
3505 {
3506 updateRubberBand();
3507 }
3508 else
3509 {
3510 mMapPointRubberBand.reset();
3511 }
3512}
3513
3514QVariant QgsProcessingPointPanel::value() const
3515{
3516 return mLineEdit->showClearButton() && mLineEdit->text().trimmed().isEmpty() ? QVariant() : QVariant( mLineEdit->text() );
3517}
3518
3519void QgsProcessingPointPanel::clear()
3520{
3521 mLineEdit->clear();
3522}
3523
3524void QgsProcessingPointPanel::setValue( const QgsPointXY &point, const QgsCoordinateReferenceSystem &crs )
3525{
3526 mPoint = point;
3527 QString newText = QStringLiteral( "%1,%2" )
3528 .arg( QString::number( point.x(), 'f' ),
3529 QString::number( point.y(), 'f' ) );
3530
3531 mCrs = crs;
3532 if ( mCrs.isValid() )
3533 {
3534 newText += QStringLiteral( " [%1]" ).arg( mCrs.authid() );
3535 }
3536 mLineEdit->setText( newText );
3537 updateRubberBand();
3538}
3539
3540void QgsProcessingPointPanel::selectOnCanvas()
3541{
3542 if ( !mCanvas )
3543 return;
3544
3545 mPrevTool = mCanvas->mapTool();
3546 mCanvas->setMapTool( mTool.get() );
3547
3548 emit toggleDialogVisibility( false );
3549}
3550
3551void QgsProcessingPointPanel::updatePoint( const QgsPointXY &point )
3552{
3553 setValue( point, mCanvas->mapSettings().destinationCrs() );
3554}
3555
3556void QgsProcessingPointPanel::pointPicked()
3557{
3558 if ( !mCanvas )
3559 return;
3560
3561 mCanvas->setMapTool( mPrevTool );
3562
3563 emit toggleDialogVisibility( true );
3564}
3565
3566void QgsProcessingPointPanel::textChanged( const QString &text )
3567{
3568 const thread_local QRegularExpression rx( QStringLiteral( "^\\s*\\(?\\s*(.*?)\\s*,\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*\\)?\\s*$" ) );
3569
3570 const QRegularExpressionMatch match = rx.match( text );
3571 if ( match.hasMatch() )
3572 {
3573 bool xOk = false;
3574 const double x = match.captured( 1 ).toDouble( &xOk );
3575 bool yOk = false;
3576 const double y = match.captured( 2 ).toDouble( &yOk );
3577
3578 if ( xOk && yOk )
3579 {
3580 mPoint = QgsPointXY( x, y );
3581
3582 const QgsCoordinateReferenceSystem pointCrs( match.captured( 3 ) );
3583 if ( pointCrs.isValid() )
3584 {
3585 mCrs = pointCrs;
3586 }
3587 }
3588 else
3589 {
3590 mPoint = QgsPointXY();
3591 }
3592 }
3593 else
3594 {
3595 mPoint = QgsPointXY();
3596 }
3597
3598 updateRubberBand();
3599}
3600
3601void QgsProcessingPointPanel::updateRubberBand()
3602{
3603 if ( !mShowPointOnCanvas || !mCanvas )
3604 return;
3605
3606 if ( mPoint.isEmpty() )
3607 {
3608 mMapPointRubberBand.reset();
3609 return;
3610 }
3611
3612 if ( !mMapPointRubberBand )
3613 {
3614 mMapPointRubberBand.reset( new QgsRubberBand( mCanvas, Qgis::GeometryType::Point ) );
3615 mMapPointRubberBand->setZValue( 1000 );
3616 mMapPointRubberBand->setIcon( QgsRubberBand::ICON_X );
3617
3618 const double scaleFactor = mCanvas->fontMetrics().xHeight() * .4;
3619 mMapPointRubberBand->setWidth( scaleFactor );
3620 mMapPointRubberBand->setIconSize( scaleFactor * 5 );
3621
3622 mMapPointRubberBand->setSecondaryStrokeColor( QColor( 255, 255, 255, 100 ) );
3623 mMapPointRubberBand->setColor( QColor( 200, 0, 200 ) );
3624 }
3625
3626 mMapPointRubberBand->setToGeometry( QgsGeometry::fromPointXY( mPoint ), mCrs );
3627}
3628
3629
3630//
3631// QgsProcessingPointWidgetWrapper
3632//
3633
3634QgsProcessingPointParameterDefinitionWidget::QgsProcessingPointParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3635 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3636{
3637 QVBoxLayout *vlayout = new QVBoxLayout();
3638 vlayout->setContentsMargins( 0, 0, 0, 0 );
3639
3640 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3641
3642 mDefaultLineEdit = new QLineEdit();
3643 mDefaultLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3644 mDefaultLineEdit->setPlaceholderText( tr( "Point as 'x,y'" ) );
3645 if ( const QgsProcessingParameterPoint *pointParam = dynamic_cast<const QgsProcessingParameterPoint *>( definition ) )
3646 {
3647 QgsPointXY point = QgsProcessingParameters::parameterAsPoint( pointParam, pointParam->defaultValueForGui(), context );
3648 mDefaultLineEdit->setText( QStringLiteral( "%1,%2" ).arg( QString::number( point.x(), 'f' ), QString::number( point.y(), 'f' ) ) );
3649 }
3650
3651 vlayout->addWidget( mDefaultLineEdit );
3652 setLayout( vlayout );
3653}
3654
3655QgsProcessingParameterDefinition *QgsProcessingPointParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
3656{
3657 auto param = std::make_unique< QgsProcessingParameterPoint >( name, description, mDefaultLineEdit->text() );
3658 param->setFlags( flags );
3659 return param.release();
3660}
3661
3662QgsProcessingPointWidgetWrapper::QgsProcessingPointWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3663 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3664{
3665
3666}
3667
3668QWidget *QgsProcessingPointWidgetWrapper::createWidget()
3669{
3670 const QgsProcessingParameterPoint *pointParam = dynamic_cast< const QgsProcessingParameterPoint *>( parameterDefinition() );
3671 switch ( type() )
3672 {
3675 {
3676 mPanel = new QgsProcessingPointPanel( nullptr );
3677 if ( widgetContext().mapCanvas() )
3678 mPanel->setMapCanvas( widgetContext().mapCanvas() );
3679
3680 if ( pointParam->flags() & Qgis::ProcessingParameterFlag::Optional )
3681 mPanel->setAllowNull( true );
3682
3683 if ( type() == QgsProcessingGui::Standard )
3684 mPanel->setShowPointOnCanvas( true );
3685
3686 mPanel->setToolTip( parameterDefinition()->toolTip() );
3687
3688 connect( mPanel, &QgsProcessingPointPanel::changed, this, [ = ]
3689 {
3690 emit widgetValueHasChanged( this );
3691 } );
3692
3693 if ( mDialog )
3694 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
3695 return mPanel;
3696 }
3697
3699 {
3700 mLineEdit = new QLineEdit();
3701 mLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3702 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3703 {
3704 emit widgetValueHasChanged( this );
3705 } );
3706 return mLineEdit;
3707 }
3708 }
3709 return nullptr;
3710}
3711
3712void QgsProcessingPointWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3713{
3715 if ( mPanel && context.mapCanvas() )
3716 mPanel->setMapCanvas( context.mapCanvas() );
3717}
3718
3719void QgsProcessingPointWidgetWrapper::setDialog( QDialog *dialog )
3720{
3721 mDialog = dialog;
3722 if ( mPanel )
3723 {
3724 connect( mPanel, &QgsProcessingPointPanel::toggleDialogVisibility, mDialog, [ = ]( bool visible )
3725 {
3726 if ( !visible )
3727 mDialog->showMinimized();
3728 else
3729 {
3730 mDialog->showNormal();
3731 mDialog->raise();
3732 mDialog->activateWindow();
3733 }
3734 } );
3735 }
3737}
3738
3739void QgsProcessingPointWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3740{
3741 if ( mPanel )
3742 {
3743 if ( !value.isValid() || ( value.userType() == QMetaType::Type::QString && value.toString().isEmpty() ) )
3744 mPanel->clear();
3745 else
3746 {
3747 QgsPointXY p = QgsProcessingParameters::parameterAsPoint( parameterDefinition(), value, context );
3748 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
3749 mPanel->setValue( p, crs );
3750 }
3751 }
3752 else if ( mLineEdit )
3753 {
3754 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3755 mLineEdit->setText( v );
3756 }
3757}
3758
3759QVariant QgsProcessingPointWidgetWrapper::widgetValue() const
3760{
3761 if ( mPanel )
3762 {
3763 return mPanel->value();
3764 }
3765 else if ( mLineEdit )
3766 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3767 else
3768 return QVariant();
3769}
3770
3771QStringList QgsProcessingPointWidgetWrapper::compatibleParameterTypes() const
3772{
3773 return QStringList()
3776}
3777
3778QStringList QgsProcessingPointWidgetWrapper::compatibleOutputTypes() const
3779{
3780 return QStringList()
3783}
3784
3785QString QgsProcessingPointWidgetWrapper::modelerExpressionFormatString() const
3786{
3787 return tr( "string of the format 'x,y' or a geometry value (centroid is used)" );
3788}
3789
3790QString QgsProcessingPointWidgetWrapper::parameterType() const
3791{
3793}
3794
3795QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3796{
3797 return new QgsProcessingPointWidgetWrapper( parameter, type );
3798}
3799
3800QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3801{
3802 return new QgsProcessingPointParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3803}
3804
3805
3806//
3807// QgsProcessingGeometryWidgetWrapper
3808//
3809
3810
3811QgsProcessingGeometryParameterDefinitionWidget::QgsProcessingGeometryParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3812 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3813{
3814 QVBoxLayout *vlayout = new QVBoxLayout();
3815 vlayout->setContentsMargins( 0, 0, 0, 0 );
3816
3817 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3818
3819 mDefaultLineEdit = new QLineEdit();
3820 mDefaultLineEdit->setToolTip( tr( "Geometry as WKT" ) );
3821 mDefaultLineEdit->setPlaceholderText( tr( "Geometry as WKT" ) );
3822 if ( const QgsProcessingParameterGeometry *geometryParam = dynamic_cast<const QgsProcessingParameterGeometry *>( definition ) )
3823 {
3824 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( geometryParam, geometryParam->defaultValueForGui(), context );
3825 if ( !g.isNull() )
3826 mDefaultLineEdit->setText( g.asWkt() );
3827 }
3828
3829 vlayout->addWidget( mDefaultLineEdit );
3830 setLayout( vlayout );
3831}
3832
3833QgsProcessingParameterDefinition *QgsProcessingGeometryParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
3834{
3835 auto param = std::make_unique< QgsProcessingParameterGeometry >( name, description, mDefaultLineEdit->text() );
3836 param->setFlags( flags );
3837 return param.release();
3838}
3839
3840QgsProcessingGeometryWidgetWrapper::QgsProcessingGeometryWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3841 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3842{
3843
3844}
3845
3846QWidget *QgsProcessingGeometryWidgetWrapper::createWidget()
3847{
3848 switch ( type() )
3849 {
3853 {
3854 mLineEdit = new QLineEdit();
3855 mLineEdit->setToolTip( parameterDefinition()->toolTip() );
3856 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3857 {
3858 emit widgetValueHasChanged( this );
3859 } );
3860 return mLineEdit;
3861 }
3862 }
3863 return nullptr;
3864}
3865
3866void QgsProcessingGeometryWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3867{
3868 if ( mLineEdit )
3869 {
3870 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( parameterDefinition(), value, context );
3871 if ( !g.isNull() )
3872 mLineEdit->setText( g.asWkt() );
3873 else
3874 mLineEdit->clear();
3875 }
3876}
3877
3878QVariant QgsProcessingGeometryWidgetWrapper::widgetValue() const
3879{
3880 if ( mLineEdit )
3881 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3882 else
3883 return QVariant();
3884}
3885
3886QStringList QgsProcessingGeometryWidgetWrapper::compatibleParameterTypes() const
3887{
3888 return QStringList()
3893}
3894
3895QStringList QgsProcessingGeometryWidgetWrapper::compatibleOutputTypes() const
3896{
3897 return QStringList()
3900}
3901
3902QString QgsProcessingGeometryWidgetWrapper::modelerExpressionFormatString() const
3903{
3904 return tr( "string in the Well-Known-Text format or a geometry value" );
3905}
3906
3907QString QgsProcessingGeometryWidgetWrapper::parameterType() const
3908{
3910}
3911
3912QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingGeometryWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3913{
3914 return new QgsProcessingGeometryWidgetWrapper( parameter, type );
3915}
3916
3917QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingGeometryWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3918{
3919 return new QgsProcessingGeometryParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3920}
3921
3922
3923//
3924// QgsProcessingColorWidgetWrapper
3925//
3926
3927
3928QgsProcessingColorParameterDefinitionWidget::QgsProcessingColorParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3929 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3930{
3931 QVBoxLayout *vlayout = new QVBoxLayout();
3932 vlayout->setContentsMargins( 0, 0, 0, 0 );
3933
3934 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3935
3936 mDefaultColorButton = new QgsColorButton();
3937 mDefaultColorButton->setShowNull( true );
3938 mAllowOpacity = new QCheckBox( tr( "Allow opacity control" ) );
3939
3940 if ( const QgsProcessingParameterColor *colorParam = dynamic_cast<const QgsProcessingParameterColor *>( definition ) )
3941 {
3942 const QColor c = QgsProcessingParameters::parameterAsColor( colorParam, colorParam->defaultValueForGui(), context );
3943 if ( !c.isValid() )
3944 mDefaultColorButton->setToNull();
3945 else
3946 mDefaultColorButton->setColor( c );
3947 mAllowOpacity->setChecked( colorParam->opacityEnabled() );
3948 }
3949 else
3950 {
3951 mDefaultColorButton->setToNull();
3952 mAllowOpacity->setChecked( true );
3953 }
3954
3955 vlayout->addWidget( mDefaultColorButton );
3956 vlayout->addWidget( mAllowOpacity );
3957 setLayout( vlayout );
3958}
3959
3960QgsProcessingParameterDefinition *QgsProcessingColorParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
3961{
3962 auto param = std::make_unique< QgsProcessingParameterColor >( name, description, mDefaultColorButton->color(), mAllowOpacity->isChecked() );
3963 param->setFlags( flags );
3964 return param.release();
3965}
3966
3967QgsProcessingColorWidgetWrapper::QgsProcessingColorWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3968 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3969{
3970
3971}
3972
3973QWidget *QgsProcessingColorWidgetWrapper::createWidget()
3974{
3975 const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor *>( parameterDefinition() );
3976 switch ( type() )
3977 {
3981 {
3982 mColorButton = new QgsColorButton( nullptr );
3983 mColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
3984
3985 if ( colorParam->flags() & Qgis::ProcessingParameterFlag::Optional )
3986 mColorButton->setShowNull( true );
3987
3988 mColorButton->setAllowOpacity( colorParam->opacityEnabled() );
3989 mColorButton->setToolTip( parameterDefinition()->toolTip() );
3990 mColorButton->setColorDialogTitle( parameterDefinition()->description() );
3991 if ( colorParam->defaultValueForGui().value< QColor >().isValid() )
3992 {
3993 mColorButton->setDefaultColor( colorParam->defaultValueForGui().value< QColor >() );
3994 }
3995
3996 connect( mColorButton, &QgsColorButton::colorChanged, this, [ = ]
3997 {
3998 emit widgetValueHasChanged( this );
3999 } );
4000
4001 return mColorButton;
4002 }
4003 }
4004 return nullptr;
4005}
4006
4007void QgsProcessingColorWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4008{
4009 if ( mColorButton )
4010 {
4011 if ( !value.isValid() ||
4012 ( value.userType() == QMetaType::Type::QString && value.toString().isEmpty() )
4013 || ( value.userType() == QMetaType::Type::QColor && !value.value< QColor >().isValid() ) )
4014 mColorButton->setToNull();
4015 else
4016 {
4017 const QColor c = QgsProcessingParameters::parameterAsColor( parameterDefinition(), value, context );
4018 if ( !c.isValid() && mColorButton->showNull() )
4019 mColorButton->setToNull();
4020 else
4021 mColorButton->setColor( c );
4022 }
4023 }
4024}
4025
4026QVariant QgsProcessingColorWidgetWrapper::widgetValue() const
4027{
4028 if ( mColorButton )
4029 return mColorButton->isNull() ? QVariant() : mColorButton->color();
4030 else
4031 return QVariant();
4032}
4033
4034QStringList QgsProcessingColorWidgetWrapper::compatibleParameterTypes() const
4035{
4036 return QStringList()
4039}
4040
4041QStringList QgsProcessingColorWidgetWrapper::compatibleOutputTypes() const
4042{
4043 return QStringList()
4046}
4047
4048QString QgsProcessingColorWidgetWrapper::modelerExpressionFormatString() const
4049{
4050 return tr( "color style string, e.g. #ff0000 or 255,0,0" );
4051}
4052
4053QString QgsProcessingColorWidgetWrapper::parameterType() const
4054{
4056}
4057
4058QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingColorWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4059{
4060 return new QgsProcessingColorWidgetWrapper( parameter, type );
4061}
4062
4063QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingColorWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4064{
4065 return new QgsProcessingColorParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4066}
4067
4068
4069//
4070// QgsProcessingCoordinateOperationWidgetWrapper
4071//
4072
4073QgsProcessingCoordinateOperationParameterDefinitionWidget::QgsProcessingCoordinateOperationParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4074 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4075{
4076 QVBoxLayout *vlayout = new QVBoxLayout();
4077 vlayout->setContentsMargins( 0, 0, 0, 0 );
4078
4079 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4080
4081 mDefaultLineEdit = new QLineEdit();
4082 if ( const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
4083 mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( coordParam, coordParam->defaultValueForGui(), context ) );
4084 vlayout->addWidget( mDefaultLineEdit );
4085
4086 mSourceParamComboBox = new QComboBox();
4087 mDestParamComboBox = new QComboBox();
4088 QString initialSource;
4089 QString initialDest;
4092 if ( const QgsProcessingParameterCoordinateOperation *itemParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
4093 {
4094 initialSource = itemParam->sourceCrsParameterName();
4095 initialDest = itemParam->destinationCrsParameterName();
4096 sourceCrs = QgsProcessingUtils::variantToCrs( itemParam->sourceCrs(), context );
4097 destCrs = QgsProcessingUtils::variantToCrs( itemParam->destinationCrs(), context );
4098 }
4099
4100 mSourceParamComboBox->addItem( QString(), QString() );
4101 mDestParamComboBox->addItem( QString(), QString() );
4102 if ( auto *lModel = widgetContext.model() )
4103 {
4104 // populate combo box with other model input choices
4105 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4106 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4107 {
4108 if ( definition && it->parameterName() == definition->name() )
4109 continue;
4110
4111 // TODO - we should probably filter this list?
4112 mSourceParamComboBox->addItem( it->parameterName(), it->parameterName() );
4113 mDestParamComboBox->addItem( it->parameterName(), it->parameterName() );
4114 if ( !initialSource.isEmpty() && initialSource == it->parameterName() )
4115 {
4116 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
4117 }
4118 if ( !initialDest.isEmpty() && initialDest == it->parameterName() )
4119 {
4120 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
4121 }
4122 }
4123 }
4124
4125 if ( mSourceParamComboBox->count() == 1 && !initialSource.isEmpty() )
4126 {
4127 // if no source candidates found, we just add the existing one as a placeholder
4128 mSourceParamComboBox->addItem( initialSource, initialSource );
4129 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
4130 }
4131 if ( mDestParamComboBox->count() == 1 && !initialDest.isEmpty() )
4132 {
4133 // if no dest candidates found, we just add the existing one as a placeholder
4134 mDestParamComboBox->addItem( initialDest, initialDest );
4135 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
4136 }
4137
4138 vlayout->addWidget( new QLabel( tr( "Source CRS parameter" ) ) );
4139 vlayout->addWidget( mSourceParamComboBox );
4140 vlayout->addWidget( new QLabel( tr( "Destination CRS parameter" ) ) );
4141 vlayout->addWidget( mDestParamComboBox );
4142
4143 mStaticSourceWidget = new QgsProjectionSelectionWidget();
4144 mStaticSourceWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
4145 mStaticSourceWidget->setCrs( sourceCrs );
4146 mStaticDestWidget = new QgsProjectionSelectionWidget();
4147 mStaticDestWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
4148 mStaticDestWidget->setCrs( destCrs );
4149
4150 vlayout->addWidget( new QLabel( tr( "Static source CRS" ) ) );
4151 vlayout->addWidget( mStaticSourceWidget );
4152 vlayout->addWidget( new QLabel( tr( "Static destination CRS" ) ) );
4153 vlayout->addWidget( mStaticDestWidget );
4154
4155 setLayout( vlayout );
4156}
4157
4158QgsProcessingParameterDefinition *QgsProcessingCoordinateOperationParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
4159{
4160 auto param = std::make_unique< QgsProcessingParameterCoordinateOperation >( name, description, mDefaultLineEdit->text(),
4161 mSourceParamComboBox->currentText(),
4162 mDestParamComboBox->currentText(),
4163 mStaticSourceWidget->crs().isValid() ? QVariant::fromValue( mStaticSourceWidget->crs() ) : QVariant(),
4164 mStaticDestWidget->crs().isValid() ? QVariant::fromValue( mStaticDestWidget->crs() ) : QVariant() );
4165 param->setFlags( flags );
4166 return param.release();
4167}
4168
4169QgsProcessingCoordinateOperationWidgetWrapper::QgsProcessingCoordinateOperationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4170 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4171{
4172
4173}
4174
4175QWidget *QgsProcessingCoordinateOperationWidgetWrapper::createWidget()
4176{
4177 const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast< const QgsProcessingParameterCoordinateOperation *>( parameterDefinition() );
4179 mSourceCrs = QgsProcessingUtils::variantToCrs( coordParam->sourceCrs(), c );
4180 mDestCrs = QgsProcessingUtils::variantToCrs( coordParam->destinationCrs(), c );
4181 switch ( type() )
4182 {
4184 {
4185 mOperationWidget = new QgsCoordinateOperationWidget( nullptr );
4186 mOperationWidget->setShowMakeDefault( false );
4187 mOperationWidget->setShowFallbackOption( false );
4188 mOperationWidget->setToolTip( parameterDefinition()->toolTip() );
4189 mOperationWidget->setSourceCrs( mSourceCrs );
4190 mOperationWidget->setDestinationCrs( mDestCrs );
4191 mOperationWidget->setMapCanvas( mCanvas );
4192 if ( !coordParam->defaultValueForGui().toString().isEmpty() )
4193 {
4195 deets.proj = coordParam->defaultValueForGui().toString();
4196 mOperationWidget->setSelectedOperation( deets );
4197 }
4198
4199 connect( mOperationWidget, &QgsCoordinateOperationWidget::operationChanged, this, [ = ]
4200 {
4201 emit widgetValueHasChanged( this );
4202 } );
4203
4204 return mOperationWidget;
4205 }
4206
4209 {
4210 mLineEdit = new QLineEdit();
4211 QHBoxLayout *layout = new QHBoxLayout();
4212 layout->addWidget( mLineEdit, 1 );
4213 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
4214 {
4215 emit widgetValueHasChanged( this );
4216 } );
4217
4218 QToolButton *button = new QToolButton();
4219 button->setText( QString( QChar( 0x2026 ) ) );
4220 connect( button, &QToolButton::clicked, this, [ = ]
4221 {
4222 QgsDatumTransformDialog dlg( mSourceCrs, mDestCrs, false, false, false, qMakePair( -1, -1 ), button, Qt::WindowFlags(), mLineEdit->text(), mCanvas );
4223 if ( dlg.exec() )
4224 {
4225 mLineEdit->setText( dlg.selectedDatumTransform().proj );
4226 emit widgetValueHasChanged( this );
4227 }
4228 } );
4229 layout->addWidget( button );
4230
4231 QWidget *w = new QWidget();
4232 layout->setContentsMargins( 0, 0, 0, 0 );
4233 w->setLayout( layout );
4234 return w;
4235 }
4236
4237 }
4238 return nullptr;
4239}
4240
4241void QgsProcessingCoordinateOperationWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
4242{
4244 switch ( type() )
4245 {
4248 {
4249 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
4250 {
4251 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->sourceCrsParameterName() )
4252 {
4253 setSourceCrsParameterValue( wrapper->parameterValue() );
4255 {
4256 setSourceCrsParameterValue( wrapper->parameterValue() );
4257 } );
4258 }
4259 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->destinationCrsParameterName() )
4260 {
4261 setDestinationCrsParameterValue( wrapper->parameterValue() );
4263 {
4264 setDestinationCrsParameterValue( wrapper->parameterValue() );
4265 } );
4266 }
4267 }
4268 break;
4269 }
4270
4272 break;
4273 }
4274}
4275
4276void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
4277{
4278 mCanvas = context.mapCanvas();
4279 if ( mOperationWidget )
4280 mOperationWidget->setMapCanvas( context.mapCanvas() );
4281}
4282
4283void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
4284{
4285 if ( mOperationWidget )
4286 {
4287 if ( !value.isValid() ||
4288 ( value.userType() == QMetaType::Type::QString ) )
4289 {
4291 deets.proj = value.toString();
4292 mOperationWidget->setSelectedOperation( deets );
4293 }
4294 }
4295 if ( mLineEdit )
4296 {
4297 if ( !value.isValid() ||
4298 ( value.userType() == QMetaType::Type::QString ) )
4299 {
4300 mLineEdit->setText( value.toString() );
4301 }
4302 }
4303}
4304
4305QVariant QgsProcessingCoordinateOperationWidgetWrapper::widgetValue() const
4306{
4307 if ( mOperationWidget )
4308 return mOperationWidget->selectedOperation().proj;
4309 else if ( mLineEdit )
4310 return mLineEdit->text();
4311 else
4312 return QVariant();
4313}
4314
4315QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleParameterTypes() const
4316{
4317 return QStringList()
4320}
4321
4322QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleOutputTypes() const
4323{
4324 return QStringList()
4327}
4328
4329QString QgsProcessingCoordinateOperationWidgetWrapper::modelerExpressionFormatString() const
4330{
4331 return tr( "Proj coordinate operation string, e.g. '+proj=pipeline +step +inv...'" );
4332}
4333
4334void QgsProcessingCoordinateOperationWidgetWrapper::setSourceCrsParameterValue( const QVariant &value )
4335{
4336 QgsProcessingContext *context = nullptr;
4337 std::unique_ptr< QgsProcessingContext > tmpContext;
4338 if ( mProcessingContextGenerator )
4339 context = mProcessingContextGenerator->processingContext();
4340
4341 if ( !context )
4342 {
4343 tmpContext = std::make_unique< QgsProcessingContext >();
4344 context = tmpContext.get();
4345 }
4346
4347 mSourceCrs = QgsProcessingUtils::variantToCrs( value, *context );
4348 if ( mOperationWidget )
4349 {
4350 mOperationWidget->setSourceCrs( mSourceCrs );
4351 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
4352 }
4353}
4354
4355void QgsProcessingCoordinateOperationWidgetWrapper::setDestinationCrsParameterValue( const QVariant &value )
4356{
4357 QgsProcessingContext *context = nullptr;
4358 std::unique_ptr< QgsProcessingContext > tmpContext;
4359 if ( mProcessingContextGenerator )
4360 context = mProcessingContextGenerator->processingContext();
4361
4362 if ( !context )
4363 {
4364 tmpContext = std::make_unique< QgsProcessingContext >();
4365 context = tmpContext.get();
4366 }
4367
4368 mDestCrs = QgsProcessingUtils::variantToCrs( value, *context );
4369 if ( mOperationWidget )
4370 {
4371 mOperationWidget->setDestinationCrs( mDestCrs );
4372 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
4373 }
4374}
4375
4376QString QgsProcessingCoordinateOperationWidgetWrapper::parameterType() const
4377{
4379}
4380
4381QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCoordinateOperationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4382{
4383 return new QgsProcessingCoordinateOperationWidgetWrapper( parameter, type );
4384}
4385
4386QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCoordinateOperationWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4387{
4388 return new QgsProcessingCoordinateOperationParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4389}
4390
4391
4392
4393//
4394// QgsProcessingFieldPanelWidget
4395//
4396
4397QgsProcessingFieldPanelWidget::QgsProcessingFieldPanelWidget( QWidget *parent, const QgsProcessingParameterField *param )
4398 : QWidget( parent )
4399 , mParam( param )
4400{
4401 QHBoxLayout *hl = new QHBoxLayout();
4402 hl->setContentsMargins( 0, 0, 0, 0 );
4403
4404 mLineEdit = new QLineEdit();
4405 mLineEdit->setEnabled( false );
4406 hl->addWidget( mLineEdit, 1 );
4407
4408 mToolButton = new QToolButton();
4409 mToolButton->setText( QString( QChar( 0x2026 ) ) );
4410 hl->addWidget( mToolButton );
4411
4412 setLayout( hl );
4413
4414 if ( mParam )
4415 {
4416 mLineEdit->setText( tr( "%n field(s) selected", nullptr, 0 ) );
4417 }
4418
4419 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingFieldPanelWidget::showDialog );
4420}
4421
4422void QgsProcessingFieldPanelWidget::setFields( const QgsFields &fields )
4423{
4424 mFields = fields;
4425}
4426
4427void QgsProcessingFieldPanelWidget::setValue( const QVariant &value )
4428{
4429 if ( value.isValid() )
4430 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
4431 else
4432 mValue.clear();
4433
4434 updateSummaryText();
4435 emit changed();
4436}
4437
4438void QgsProcessingFieldPanelWidget::showDialog()
4439{
4440 QVariantList availableOptions;
4441 availableOptions.reserve( mFields.size() );
4442 for ( const QgsField &field : std::as_const( mFields ) )
4443 {
4444 availableOptions << field.name();
4445 }
4446
4448 if ( panel && panel->dockMode() )
4449 {
4450 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
4451 widget->setPanelTitle( mParam->description() );
4452
4453 widget->setValueFormatter( []( const QVariant & v ) -> QString
4454 {
4455 return v.toString();
4456 } );
4457
4458 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
4459 {
4460 setValue( widget->selectedOptions() );
4461 } );
4462 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
4463 panel->openPanel( widget );
4464 }
4465 else
4466 {
4467 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
4468
4469 dlg.setValueFormatter( []( const QVariant & v ) -> QString
4470 {
4471 return v.toString();
4472 } );
4473 if ( dlg.exec() )
4474 {
4475 setValue( dlg.selectedOptions() );
4476 }
4477 }
4478}
4479
4480void QgsProcessingFieldPanelWidget::updateSummaryText()
4481{
4482 if ( !mParam )
4483 return;
4484
4485 if ( mValue.empty() )
4486 {
4487 mLineEdit->setText( tr( "%n field(s) selected", nullptr, 0 ) );
4488 }
4489 else
4490 {
4491 QStringList values;
4492 values.reserve( mValue.size() );
4493 for ( const QVariant &val : std::as_const( mValue ) )
4494 {
4495 values << val.toString();
4496 }
4497
4498 const QString concatenated = values.join( tr( "," ) );
4499 if ( concatenated.length() < 100 )
4500 mLineEdit->setText( concatenated );
4501 else
4502 mLineEdit->setText( tr( "%n field(s) selected", nullptr, mValue.count() ) );
4503 }
4504}
4505
4506
4507//
4508// QgsProcessingFieldWidgetWrapper
4509//
4510
4511QgsProcessingFieldParameterDefinitionWidget::QgsProcessingFieldParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4512 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4513{
4514 QVBoxLayout *vlayout = new QVBoxLayout();
4515 vlayout->setContentsMargins( 0, 0, 0, 0 );
4516
4517 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
4518 mParentLayerComboBox = new QComboBox();
4519
4520 QString initialParent;
4521 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4522 initialParent = fieldParam->parentLayerParameterName();
4523
4524 if ( auto *lModel = widgetContext.model() )
4525 {
4526 // populate combo box with other model input choices
4527 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4528 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4529 {
4530 if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4531 {
4532 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4533 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4534 {
4535 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4536 }
4537 }
4538 else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4539 {
4540 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4541 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4542 {
4543 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4544 }
4545 }
4546 else if ( const QgsProcessingParameterMultipleLayers *definition = dynamic_cast< const QgsProcessingParameterMultipleLayers * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4547 {
4548 if ( definition->layerType() == Qgis::ProcessingSourceType::Vector )
4549 {
4550 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4551 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4552 {
4553 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4554 }
4555 }
4556 }
4557 }
4558 }
4559
4560 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
4561 {
4562 // if no parent candidates found, we just add the existing one as a placeholder
4563 mParentLayerComboBox->addItem( initialParent, initialParent );
4564 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4565 }
4566
4567 vlayout->addWidget( mParentLayerComboBox );
4568
4569 vlayout->addWidget( new QLabel( tr( "Allowed data type" ) ) );
4570 mDataTypeComboBox = new QComboBox();
4571 mDataTypeComboBox->addItem( tr( "Any" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::Any ) );
4572 mDataTypeComboBox->addItem( tr( "Number" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::Numeric ) );
4573 mDataTypeComboBox->addItem( tr( "String" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::String ) );
4574 mDataTypeComboBox->addItem( tr( "Date/time" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::DateTime ) );
4575 mDataTypeComboBox->addItem( tr( "Binary" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::Binary ) );
4576 mDataTypeComboBox->addItem( tr( "Boolean" ), static_cast< int >( Qgis::ProcessingFieldParameterDataType::Boolean ) );
4577 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4578 mDataTypeComboBox->setCurrentIndex( mDataTypeComboBox->findData( static_cast< int >( fieldParam->dataType() ) ) );
4579
4580 vlayout->addWidget( mDataTypeComboBox );
4581
4582 mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple fields" ) );
4583 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4584 mAllowMultipleCheckBox->setChecked( fieldParam->allowMultiple() );
4585
4586 vlayout->addWidget( mAllowMultipleCheckBox );
4587
4588 mDefaultToAllCheckBox = new QCheckBox( tr( "Select all fields by default" ) );
4589 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4590 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4591 mDefaultToAllCheckBox->setChecked( fieldParam->defaultToAllFields() );
4592
4593 vlayout->addWidget( mDefaultToAllCheckBox );
4594
4595 connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
4596 {
4597 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4598 } );
4599
4600 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4601
4602 mDefaultLineEdit = new QLineEdit();
4603 mDefaultLineEdit->setToolTip( tr( "Default field name, or ; separated list of field names for multiple field parameters" ) );
4604 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4605 {
4606 const QStringList fields = QgsProcessingParameters::parameterAsStrings( fieldParam, fieldParam->defaultValueForGui(), context );
4607 mDefaultLineEdit->setText( fields.join( ';' ) );
4608 }
4609 vlayout->addWidget( mDefaultLineEdit );
4610
4611 setLayout( vlayout );
4612}
4613
4614QgsProcessingParameterDefinition *QgsProcessingFieldParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
4615{
4616 Qgis::ProcessingFieldParameterDataType dataType = static_cast< Qgis::ProcessingFieldParameterDataType >( mDataTypeComboBox->currentData().toInt() );
4617
4618 QVariant defaultValue;
4619 if ( !mDefaultLineEdit->text().trimmed().isEmpty() )
4620 {
4621 defaultValue = mDefaultLineEdit->text();
4622 }
4623 auto param = std::make_unique< QgsProcessingParameterField >( name, description, defaultValue, mParentLayerComboBox->currentData().toString(), dataType, mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
4624 param->setFlags( flags );
4625 return param.release();
4626}
4627
4628QgsProcessingFieldWidgetWrapper::QgsProcessingFieldWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4629 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4630{
4631
4632}
4633
4634QWidget *QgsProcessingFieldWidgetWrapper::createWidget()
4635{
4636 const QgsProcessingParameterField *fieldParam = dynamic_cast< const QgsProcessingParameterField *>( parameterDefinition() );
4637 switch ( type() )
4638 {
4641 {
4642 if ( fieldParam->allowMultiple() )
4643 {
4644 mPanel = new QgsProcessingFieldPanelWidget( nullptr, fieldParam );
4645 mPanel->setToolTip( parameterDefinition()->toolTip() );
4646 connect( mPanel, &QgsProcessingFieldPanelWidget::changed, this, [ = ]
4647 {
4648 emit widgetValueHasChanged( this );
4649 } );
4650 return mPanel;
4651 }
4652 else
4653 {
4654 mComboBox = new QgsFieldComboBox();
4655 mComboBox->setAllowEmptyFieldName( fieldParam->flags() & Qgis::ProcessingParameterFlag::Optional );
4656
4658 mComboBox->setFilters( QgsFieldProxyModel::Numeric );
4659 else if ( fieldParam->dataType() == Qgis::ProcessingFieldParameterDataType::String )
4660 mComboBox->setFilters( QgsFieldProxyModel::String );
4663 else if ( fieldParam->dataType() == Qgis::ProcessingFieldParameterDataType::Binary )
4664 mComboBox->setFilters( QgsFieldProxyModel::Binary );
4666 mComboBox->setFilters( QgsFieldProxyModel::Boolean );
4667
4668 mComboBox->setToolTip( parameterDefinition()->toolTip() );
4669 connect( mComboBox, &QgsFieldComboBox::fieldChanged, this, [ = ]( const QString & )
4670 {
4671 emit widgetValueHasChanged( this );
4672 } );
4673 return mComboBox;
4674 }
4675 }
4676
4678 {
4679 mLineEdit = new QLineEdit();
4680 mLineEdit->setToolTip( QObject::tr( "Name of field (separate field names with ; for multiple field parameters)" ) );
4681 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
4682 {
4683 emit widgetValueHasChanged( this );
4684 } );
4685 return mLineEdit;
4686 }
4687
4688 }
4689 return nullptr;
4690}
4691
4692void QgsProcessingFieldWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
4693{
4695 switch ( type() )
4696 {
4699 {
4700 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
4701 {
4702 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterField * >( parameterDefinition() )->parentLayerParameterName() )
4703 {
4704 setParentLayerWrapperValue( wrapper );
4706 {
4707 setParentLayerWrapperValue( wrapper );
4708 } );
4709 break;
4710 }
4711 }
4712 break;
4713 }
4714
4716 break;
4717 }
4718}
4719
4720void QgsProcessingFieldWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
4721{
4722 // evaluate value to layer
4723 QgsProcessingContext *context = nullptr;
4724 std::unique_ptr< QgsProcessingContext > tmpContext;
4725 if ( mProcessingContextGenerator )
4726 context = mProcessingContextGenerator->processingContext();
4727
4728 if ( !context )
4729 {
4730 tmpContext = std::make_unique< QgsProcessingContext >();
4731 context = tmpContext.get();
4732 }
4733
4734 QVariant value = parentWrapper->parameterValue();
4735
4736 if ( value.userType() == QMetaType::type( "QgsProcessingFeatureSourceDefinition" ) )
4737 {
4738 // input is a QgsProcessingFeatureSourceDefinition - source from it.
4739 // this is normally discouraged, and algorithms should NEVER do this -- but in this case we can make
4740 // certain assumptions due to the fact that we're calling this outside of algorithm/model execution and all sources
4741 // should be real map layers at this stage
4742 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
4743 value = fromVar.source;
4744 }
4745
4746 bool valueSet = false;
4747 const QList< QgsMapLayer * > layers = QgsProcessingParameters::parameterAsLayerList( parentWrapper->parameterDefinition(), value, *context );
4748
4749 // several layers, populate with intersection of layers fields
4750 if ( layers.count() > 1 )
4751 {
4752 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4753 QgsFields fields = vlayer && vlayer->isValid() ? vlayer->fields() : QgsFields();
4754 const QList< QgsMapLayer * > remainingLayers = layers.mid( 1 );
4755 for ( QgsMapLayer *layer : remainingLayers )
4756 {
4757 if ( fields.isEmpty() )
4758 break;
4759
4760 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer );
4761 if ( !vlayer || !vlayer->isValid() )
4762 {
4763 fields = QgsFields();
4764 break;
4765 }
4766
4767 for ( int fieldIdx = fields.count() - 1; fieldIdx >= 0; fieldIdx-- )
4768 {
4769 if ( vlayer->fields().lookupField( fields.at( fieldIdx ).name() ) < 0 )
4770 fields.remove( fieldIdx );
4771 }
4772 }
4773
4774 if ( mComboBox )
4775 mComboBox->setFields( fields );
4776 else if ( mPanel )
4777 mPanel->setFields( filterFields( fields ) );
4778
4779 valueSet = true;
4780 }
4781
4782 // only one layer
4783 if ( !valueSet && !layers.isEmpty() && layers.at( 0 )->isValid() )
4784 {
4785 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4786
4787 // need to grab ownership of layer if required - otherwise layer may be deleted when context
4788 // goes out of scope
4789 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
4790 if ( ownedLayer && ownedLayer->type() == Qgis::LayerType::Vector )
4791 {
4792 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
4793 layer = mParentLayer.get();
4794 }
4795 else
4796 {
4797 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
4798 }
4799
4800 if ( mComboBox )
4801 mComboBox->setLayer( layer );
4802 else if ( mPanel )
4803 mPanel->setFields( filterFields( layer->fields() ) );
4804
4805 valueSet = true;
4806 }
4807
4808 if ( !valueSet )
4809 {
4810 std::unique_ptr< QgsProcessingFeatureSource > source( QgsProcessingParameters::parameterAsSource( parentWrapper->parameterDefinition(), value, *context ) );
4811 if ( source )
4812 {
4813 const QgsFields fields = source->fields();
4814 if ( mComboBox )
4815 mComboBox->setFields( fields );
4816 else if ( mPanel )
4817 mPanel->setFields( filterFields( fields ) );
4818
4819 valueSet = true;
4820 }
4821 }
4822
4823 if ( !valueSet )
4824 {
4825 if ( mComboBox )
4826 mComboBox->setLayer( nullptr );
4827 else if ( mPanel )
4828 mPanel->setFields( QgsFields() );
4829
4830 if ( value.isValid() && widgetContext().messageBar() )
4831 {
4832 widgetContext().messageBar()->clearWidgets();
4833 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent field could not be populated" ),
4835 }
4836 return;
4837 }
4838
4839 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4840 if ( mPanel && fieldParam->defaultToAllFields() )
4841 {
4842 QVariantList val;
4843 val.reserve( mPanel->fields().size() );
4844 for ( const QgsField &field : mPanel->fields() )
4845 val << field.name();
4846 setWidgetValue( val, *context );
4847 }
4848 else if ( fieldParam->defaultValueForGui().isValid() )
4849 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
4850}
4851
4852void QgsProcessingFieldWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4853{
4854 if ( mComboBox )
4855 {
4856 if ( !value.isValid() )
4857 mComboBox->setField( QString() );
4858 else
4859 {
4860 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4861 mComboBox->setField( v );
4862 }
4863 }
4864 else if ( mPanel )
4865 {
4866 QVariantList opts;
4867 if ( value.isValid() )
4868 {
4869 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
4870 opts.reserve( v.size() );
4871 for ( const QString &i : v )
4872 opts << i;
4873 }
4874 if ( mPanel )
4875 mPanel->setValue( opts );
4876 }
4877 else if ( mLineEdit )
4878 {
4879 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4880 if ( fieldParam->allowMultiple() )
4881 {
4882 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
4883 mLineEdit->setText( v.join( ';' ) );
4884 }
4885 else
4886 {
4887 mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
4888 }
4889 }
4890}
4891
4892QVariant QgsProcessingFieldWidgetWrapper::widgetValue() const
4893{
4894 if ( mComboBox )
4895 return mComboBox->currentField();
4896 else if ( mPanel )
4897 return mPanel->value();
4898 else if ( mLineEdit )
4899 {
4900 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4901 if ( fieldParam->allowMultiple() )
4902 {
4903 return mLineEdit->text().split( ';' );
4904 }
4905 else
4906 return mLineEdit->text();
4907 }
4908 else
4909 return QVariant();
4910}
4911
4912QStringList QgsProcessingFieldWidgetWrapper::compatibleParameterTypes() const
4913{
4914 return QStringList()
4917}
4918
4919QStringList QgsProcessingFieldWidgetWrapper::compatibleOutputTypes() const
4920{
4921 return QStringList()
4924}
4925
4926QString QgsProcessingFieldWidgetWrapper::modelerExpressionFormatString() const
4927{
4928 return tr( "selected field names as an array of names, or semicolon separated string of options (e.g. 'fid;place_name')" );
4929}
4930
4931const QgsVectorLayer *QgsProcessingFieldWidgetWrapper::linkedVectorLayer() const
4932{
4933 if ( mComboBox && mComboBox->layer() )
4934 return mComboBox->layer();
4935
4937}
4938
4939QgsFields QgsProcessingFieldWidgetWrapper::filterFields( const QgsFields &fields ) const
4940{
4941 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4942 QgsFields res;
4943 for ( const QgsField &f : fields )
4944 {
4945 switch ( fieldParam->dataType() )
4946 {
4948 res.append( f );
4949 break;
4950
4952 if ( f.isNumeric() )
4953 res.append( f );
4954 break;
4955
4957 if ( f.type() == QMetaType::Type::QString )
4958 res.append( f );
4959 break;
4960
4962 if ( f.type() == QMetaType::Type::QDate || f.type() == QMetaType::Type::QTime || f.type() == QMetaType::Type::QDateTime )
4963 res.append( f );
4964 break;
4965
4967 if ( f.type() == QMetaType::Type::QByteArray )
4968 res.append( f );
4969 break;
4970
4972 if ( f.type() == QMetaType::Type::Bool )
4973 res.append( f );
4974 break;
4975 }
4976 }
4977
4978 return res;
4979}
4980
4981QString QgsProcessingFieldWidgetWrapper::parameterType() const
4982{
4984}
4985
4986QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFieldWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4987{
4988 return new QgsProcessingFieldWidgetWrapper( parameter, type );
4989}
4990
4991QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFieldWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4992{
4993 return new QgsProcessingFieldParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4994}
4995
4996//
4997// QgsProcessingMapThemeWidgetWrapper
4998//
4999
5000
5001QgsProcessingMapThemeParameterDefinitionWidget::QgsProcessingMapThemeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5002 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5003{
5004 QVBoxLayout *vlayout = new QVBoxLayout();
5005 vlayout->setContentsMargins( 0, 0, 0, 0 );
5006
5007 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5008
5009 mDefaultComboBox = new QComboBox();
5010 mDefaultComboBox->addItem( QString(), QVariant( -1 ) );
5011
5012 const QStringList mapThemes = widgetContext.project() ? widgetContext.project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
5013 for ( const QString &theme : mapThemes )
5014 {
5015 mDefaultComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
5016 }
5017 mDefaultComboBox->setEditable( true );
5018
5019 if ( const QgsProcessingParameterMapTheme *themeParam = dynamic_cast<const QgsProcessingParameterMapTheme *>( definition ) )
5020 {
5021 if ( themeParam->defaultValueForGui().isValid() )
5022 mDefaultComboBox->setCurrentText( QgsProcessingParameters::parameterAsString( themeParam, themeParam->defaultValueForGui(), context ) );
5023 else
5024 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
5025 }
5026 else
5027 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
5028
5029 vlayout->addWidget( mDefaultComboBox );
5030
5031 setLayout( vlayout );
5032}
5033
5034QgsProcessingParameterDefinition *QgsProcessingMapThemeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
5035{
5036 QVariant defaultVal;
5037 if ( mDefaultComboBox->currentText().isEmpty() )
5038 defaultVal = QVariant();
5039 else
5040 defaultVal = mDefaultComboBox->currentText();
5041 auto param = std::make_unique< QgsProcessingParameterMapTheme>( name, description, defaultVal );
5042 param->setFlags( flags );
5043 return param.release();
5044}
5045
5046
5047QgsProcessingMapThemeWidgetWrapper::QgsProcessingMapThemeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5048 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5049{
5050
5051}
5052
5053QWidget *QgsProcessingMapThemeWidgetWrapper::createWidget()
5054{
5055 const QgsProcessingParameterMapTheme *themeParam = dynamic_cast< const QgsProcessingParameterMapTheme *>( parameterDefinition() );
5056
5057 mComboBox = new QComboBox();
5058
5059 if ( themeParam->flags() & Qgis::ProcessingParameterFlag::Optional )
5060 mComboBox->addItem( tr( "[Not selected]" ), QVariant( -1 ) );
5061
5062 const QStringList mapThemes = widgetContext().project() ? widgetContext().project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
5063 for ( const QString &theme : mapThemes )
5064 {
5065 mComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
5066 }
5067
5068 switch ( type() )
5069 {
5072 break;
5073
5075 mComboBox->setEditable( true );
5076 break;
5077 }
5078
5079 mComboBox->setToolTip( parameterDefinition()->toolTip() );
5080 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
5081 {
5082 emit widgetValueHasChanged( this );
5083 } );
5084
5085 return mComboBox;
5086}
5087
5088void QgsProcessingMapThemeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5089{
5090 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
5091
5092 if ( !value.isValid() )
5093 mComboBox->setCurrentIndex( mComboBox->findData( QVariant( -1 ) ) );
5094 else
5095 {
5096 if ( mComboBox->isEditable() && mComboBox->findData( v ) == -1 )
5097 {
5098 const QString prev = mComboBox->currentText();
5099 mComboBox->setCurrentText( v );
5100 if ( prev != v )
5101 emit widgetValueHasChanged( this );
5102 }
5103 else
5104 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
5105 }
5106}
5107
5108QVariant QgsProcessingMapThemeWidgetWrapper::widgetValue() const
5109{
5110 if ( mComboBox )
5111 return mComboBox->currentData().toInt() == -1 ? QVariant() :
5112 !mComboBox->currentData().isValid() && mComboBox->isEditable() ? mComboBox->currentText().isEmpty() ? QVariant() : QVariant( mComboBox->currentText() )
5113 : mComboBox->currentData();
5114 else
5115 return QVariant();
5116}
5117
5118QStringList QgsProcessingMapThemeWidgetWrapper::compatibleParameterTypes() const
5119{
5120 return QStringList()
5123}
5124
5125QStringList QgsProcessingMapThemeWidgetWrapper::compatibleOutputTypes() const
5126{
5127 return QStringList()
5130}
5131
5132QString QgsProcessingMapThemeWidgetWrapper::modelerExpressionFormatString() const
5133{
5134 return tr( "map theme as a string value (e.g. 'base maps')" );
5135}
5136
5137QString QgsProcessingMapThemeWidgetWrapper::parameterType() const
5138{
5140}
5141
5142QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapThemeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5143{
5144 return new QgsProcessingMapThemeWidgetWrapper( parameter, type );
5145}
5146
5147QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapThemeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5148{
5149 return new QgsProcessingMapThemeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5150}
5151
5152
5153
5154//
5155// QgsProcessingDateTimeWidgetWrapper
5156//
5157
5158
5159QgsProcessingDateTimeParameterDefinitionWidget::QgsProcessingDateTimeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5160 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5161{
5162 QVBoxLayout *vlayout = new QVBoxLayout();
5163 vlayout->setContentsMargins( 0, 0, 0, 0 );
5164
5165 vlayout->addWidget( new QLabel( tr( "Type" ) ) );
5166
5167 mTypeComboBox = new QComboBox();
5168 mTypeComboBox->addItem( tr( "Date and Time" ), static_cast< int >( Qgis::ProcessingDateTimeParameterDataType::DateTime ) );
5169 mTypeComboBox->addItem( tr( "Date" ), static_cast< int >( Qgis::ProcessingDateTimeParameterDataType::Date ) );
5170 mTypeComboBox->addItem( tr( "Time" ), static_cast< int >( Qgis::ProcessingDateTimeParameterDataType::Time ) );
5171 if ( const QgsProcessingParameterDateTime *datetimeParam = dynamic_cast<const QgsProcessingParameterDateTime *>( definition ) )
5172 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( static_cast< int >( datetimeParam->dataType() ) ) );
5173 else
5174 mTypeComboBox->setCurrentIndex( 0 );
5175 vlayout->addWidget( mTypeComboBox );
5176
5177 setLayout( vlayout );
5178}
5179
5180QgsProcessingParameterDefinition *QgsProcessingDateTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
5181{
5182 auto param = std::make_unique< QgsProcessingParameterDateTime >( name, description );
5183 param->setDataType( static_cast< Qgis::ProcessingDateTimeParameterDataType >( mTypeComboBox->currentData().toInt() ) );
5184 param->setFlags( flags );
5185 return param.release();
5186}
5187
5188
5189QgsProcessingDateTimeWidgetWrapper::QgsProcessingDateTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5190 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5191{
5192
5193}
5194
5195QWidget *QgsProcessingDateTimeWidgetWrapper::createWidget()
5196{
5197 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
5198
5199 QgsDateTimeEdit *widget = nullptr;
5200 switch ( dateTimeParam->dataType() )
5201 {
5203 mDateTimeEdit = new QgsDateTimeEdit();
5204 widget = mDateTimeEdit;
5205 break;
5206
5208 mDateEdit = new QgsDateEdit();
5209 widget = mDateEdit;
5210 break;
5211
5213 mTimeEdit = new QgsTimeEdit();
5214 widget = mTimeEdit;
5215 break;
5216 }
5217
5218 if ( dateTimeParam->flags() & Qgis::ProcessingParameterFlag::Optional )
5219 {
5220 widget->setNullRepresentation( tr( "[Not selected]" ) );
5221 widget->setAllowNull( true );
5222 }
5223 else
5224 {
5225 widget->setAllowNull( false );
5226 }
5227 widget->setToolTip( parameterDefinition()->toolTip() );
5228
5229 if ( mDateTimeEdit )
5230 {
5231 connect( mDateTimeEdit, &QgsDateTimeEdit::valueChanged, this, [ = ]( const QDateTime & )
5232 {
5233 emit widgetValueHasChanged( this );
5234 } );
5235 }
5236 else if ( mDateEdit )
5237 {
5238 connect( mDateEdit, &QgsDateEdit::dateValueChanged, this, [ = ]( const QDate & )
5239 {
5240 emit widgetValueHasChanged( this );
5241 } );
5242 }
5243 else if ( mTimeEdit )
5244 {
5245 connect( mTimeEdit, &QgsTimeEdit::timeValueChanged, this, [ = ]( const QTime & )
5246 {
5247 emit widgetValueHasChanged( this );
5248 } );
5249 }
5250
5251 return widget;
5252}
5253
5254QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDateTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5255{
5256 return new QgsProcessingDateTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5257}
5258
5259void QgsProcessingDateTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5260{
5261 if ( mDateTimeEdit )
5262 {
5263 mDateTimeEdit->setDateTime( QgsProcessingParameters::parameterAsDateTime( parameterDefinition(), value, context ) );
5264 }
5265 else if ( mDateEdit )
5266 {
5267 mDateEdit->setDate( QgsProcessingParameters::parameterAsDate( parameterDefinition(), value, context ) );
5268 }
5269 else if ( mTimeEdit )
5270 {
5271 mTimeEdit->setTime( QgsProcessingParameters::parameterAsTime( parameterDefinition(), value, context ) );
5272 }
5273}
5274
5275QVariant QgsProcessingDateTimeWidgetWrapper::widgetValue() const
5276{
5277 if ( mDateTimeEdit )
5278 return !mDateTimeEdit->dateTime().isNull() && mDateTimeEdit->dateTime().isValid() ? QVariant( mDateTimeEdit->dateTime() ) : QVariant();
5279 else if ( mDateEdit )
5280 return !mDateEdit->date().isNull() && mDateEdit->date().isValid() ? QVariant( mDateEdit->date() ) : QVariant();
5281 else if ( mTimeEdit )
5282 return !mTimeEdit->time().isNull() && mTimeEdit->time().isValid() ? QVariant( mTimeEdit->time() ) : QVariant();
5283 else
5284 return QVariant();
5285}
5286
5287QStringList QgsProcessingDateTimeWidgetWrapper::compatibleParameterTypes() const
5288{
5289 return QStringList()
5292}
5293
5294QStringList QgsProcessingDateTimeWidgetWrapper::compatibleOutputTypes() const
5295{
5296 return QStringList()
5299}
5300
5301QString QgsProcessingDateTimeWidgetWrapper::modelerExpressionFormatString() const
5302{
5303 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
5304 if ( dateTimeParam )
5305 {
5306 switch ( dateTimeParam->dataType() )
5307 {
5309 return tr( "datetime value, or a ISO string representation of a datetime" );
5310
5312 return tr( "date value, or a ISO string representation of a date" );
5313
5315 return tr( "time value, or a ISO string representation of a time" );
5316 }
5317 }
5318 return QString();
5319}
5320
5321QString QgsProcessingDateTimeWidgetWrapper::parameterType() const
5322{
5324}
5325
5326QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDateTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5327{
5328 return new QgsProcessingDateTimeWidgetWrapper( parameter, type );
5329}
5330
5331
5332
5333//
5334// QgsProcessingProviderConnectionWidgetWrapper
5335//
5336
5337QgsProcessingProviderConnectionParameterDefinitionWidget::QgsProcessingProviderConnectionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5338 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5339{
5340 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( definition );
5341
5342 QVBoxLayout *vlayout = new QVBoxLayout();
5343 vlayout->setContentsMargins( 0, 0, 0, 0 );
5344
5345 vlayout->addWidget( new QLabel( tr( "Provider" ) ) );
5346 mProviderComboBox = new QComboBox();
5347 mProviderComboBox->addItem( QObject::tr( "Postgres" ), QStringLiteral( "postgres" ) );
5348 mProviderComboBox->addItem( QObject::tr( "GeoPackage" ), QStringLiteral( "ogr" ) );
5349 mProviderComboBox->addItem( QObject::tr( "Spatialite" ), QStringLiteral( "spatialite" ) );
5350
5351 vlayout->addWidget( mProviderComboBox );
5352
5353 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5354
5355 mDefaultEdit = new QLineEdit();
5356 vlayout->addWidget( mDefaultEdit );
5357 setLayout( vlayout );
5358
5359 if ( connectionParam )
5360 {
5361 mProviderComboBox->setCurrentIndex( mProviderComboBox->findData( connectionParam->providerId() ) );
5362 mDefaultEdit->setText( connectionParam->defaultValueForGui().toString() );
5363 }
5364}
5365
5366QgsProcessingParameterDefinition *QgsProcessingProviderConnectionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
5367{
5368 QVariant defaultVal;
5369 if ( mDefaultEdit->text().isEmpty() )
5370 defaultVal = QVariant();
5371 else
5372 defaultVal = mDefaultEdit->text();
5373 auto param = std::make_unique< QgsProcessingParameterProviderConnection>( name, description, mProviderComboBox->currentData().toString(), defaultVal );
5374 param->setFlags( flags );
5375 return param.release();
5376}
5377
5378
5379QgsProcessingProviderConnectionWidgetWrapper::QgsProcessingProviderConnectionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5380 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5381{
5382
5383}
5384
5385QWidget *QgsProcessingProviderConnectionWidgetWrapper::createWidget()
5386{
5387 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( parameterDefinition() );
5388
5389 mProviderComboBox = new QgsProviderConnectionComboBox( connectionParam->providerId() );
5390 if ( connectionParam->flags() & Qgis::ProcessingParameterFlag::Optional )
5391 mProviderComboBox->setAllowEmptyConnection( true );
5392
5393 switch ( type() )
5394 {
5397 break;
5399 mProviderComboBox->setEditable( true );
5400 break;
5401 }
5402
5403 mProviderComboBox->setToolTip( parameterDefinition()->toolTip() );
5404 connect( mProviderComboBox, &QgsProviderConnectionComboBox::currentTextChanged, this, [ = ]( const QString & )
5405 {
5406 if ( mBlockSignals )
5407 return;
5408
5409 emit widgetValueHasChanged( this );
5410 } );
5411
5412 return mProviderComboBox;
5413}
5414
5415QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingProviderConnectionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5416{
5417 return new QgsProcessingProviderConnectionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5418}
5419
5420void QgsProcessingProviderConnectionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5421{
5422 const QString v = QgsProcessingParameters::parameterAsConnectionName( parameterDefinition(), value, context );
5423
5424 if ( !value.isValid() )
5425 mProviderComboBox->setCurrentIndex( -1 );
5426 else
5427 {
5428 if ( mProviderComboBox->isEditable() )
5429 {
5430 const QString prev = mProviderComboBox->currentText();
5431 mBlockSignals++;
5432 mProviderComboBox->setConnection( v );
5433 mProviderComboBox->setCurrentText( v );
5434
5435 mBlockSignals--;
5436 if ( prev != v )
5437 emit widgetValueHasChanged( this );
5438 }
5439 else
5440 mProviderComboBox->setConnection( v );
5441 }
5442}
5443
5444QVariant QgsProcessingProviderConnectionWidgetWrapper::widgetValue() const
5445{
5446 if ( mProviderComboBox )
5447 if ( mProviderComboBox->isEditable() )
5448 return mProviderComboBox->currentText().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentText() );
5449 else
5450 return mProviderComboBox->currentConnection().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentConnection() );
5451 else
5452 return QVariant();
5453}
5454
5455QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleParameterTypes() const
5456{
5457 return QStringList()
5461}
5462
5463QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleOutputTypes() const
5464{
5465 return QStringList()
5468}
5469
5470QString QgsProcessingProviderConnectionWidgetWrapper::modelerExpressionFormatString() const
5471{
5472 return tr( "connection name as a string value" );
5473}
5474
5475QString QgsProcessingProviderConnectionWidgetWrapper::parameterType() const
5476{
5478}
5479
5480QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingProviderConnectionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5481{
5482 return new QgsProcessingProviderConnectionWidgetWrapper( parameter, type );
5483}
5484
5485
5486
5487
5488//
5489// QgsProcessingDatabaseSchemaWidgetWrapper
5490//
5491
5492QgsProcessingDatabaseSchemaParameterDefinitionWidget::QgsProcessingDatabaseSchemaParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5493 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5494{
5495 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( definition );
5496
5497 QVBoxLayout *vlayout = new QVBoxLayout();
5498 vlayout->setContentsMargins( 0, 0, 0, 0 );
5499
5500 mConnectionParamComboBox = new QComboBox();
5501 QString initialConnection;
5502 if ( schemaParam )
5503 {
5504 initialConnection = schemaParam->parentConnectionParameterName();
5505 }
5506
5507 if ( auto *lModel = widgetContext.model() )
5508 {
5509 // populate combo box with other model input choices
5510 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5511 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5512 {
5513 if ( definition && it->parameterName() == definition->name() )
5514 continue;
5515
5516 if ( !dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5517 continue;
5518
5519 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5520 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5521 {
5522 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5523 }
5524 }
5525 }
5526
5527 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5528 {
5529 // if no candidates found, we just add the existing one as a placeholder
5530 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5531 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5532 }
5533
5534 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5535 vlayout->addWidget( mConnectionParamComboBox );
5536
5537 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5538
5539 mDefaultEdit = new QLineEdit();
5540 vlayout->addWidget( mDefaultEdit );
5541 setLayout( vlayout );
5542
5543 if ( schemaParam )
5544 {
5545 mDefaultEdit->setText( schemaParam->defaultValueForGui().toString() );
5546 }
5547}
5548
5549QgsProcessingParameterDefinition *QgsProcessingDatabaseSchemaParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
5550{
5551 QVariant defaultVal;
5552 if ( mDefaultEdit->text().isEmpty() )
5553 defaultVal = QVariant();
5554 else
5555 defaultVal = mDefaultEdit->text();
5556 auto param = std::make_unique< QgsProcessingParameterDatabaseSchema>( name, description, mConnectionParamComboBox->currentData().toString(), defaultVal );
5557 param->setFlags( flags );
5558 return param.release();
5559}
5560
5561
5562QgsProcessingDatabaseSchemaWidgetWrapper::QgsProcessingDatabaseSchemaWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5563 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5564{
5565
5566}
5567
5568QWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createWidget()
5569{
5570 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( parameterDefinition() );
5571
5572 mSchemaComboBox = new QgsDatabaseSchemaComboBox( QString(), QString() );
5573 if ( schemaParam->flags() & Qgis::ProcessingParameterFlag::Optional )
5574 mSchemaComboBox->setAllowEmptySchema( true );
5575
5576 switch ( type() )
5577 {
5580 break;
5582 mSchemaComboBox->comboBox()->setEditable( true );
5583 break;
5584 }
5585
5586 mSchemaComboBox->setToolTip( parameterDefinition()->toolTip() );
5587 connect( mSchemaComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5588 {
5589 if ( mBlockSignals )
5590 return;
5591
5592 emit widgetValueHasChanged( this );
5593 } );
5594
5595 return mSchemaComboBox;
5596}
5597
5598QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5599{
5600 return new QgsProcessingDatabaseSchemaParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5601}
5602
5603void QgsProcessingDatabaseSchemaWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5604{
5605 // evaluate value to connection
5606 QgsProcessingContext *context = nullptr;
5607 std::unique_ptr< QgsProcessingContext > tmpContext;
5608 if ( mProcessingContextGenerator )
5609 context = mProcessingContextGenerator->processingContext();
5610
5611 if ( !context )
5612 {
5613 tmpContext = std::make_unique< QgsProcessingContext >();
5614 context = tmpContext.get();
5615 }
5616
5617 const QVariant value = parentWrapper->parameterValue();
5618 const QString connection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5619
5620 if ( mSchemaComboBox )
5621 mSchemaComboBox->setConnectionName( connection, qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId() );
5622
5623 const QgsProcessingParameterDatabaseSchema *schemaParam = qgis::down_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() );
5624 if ( schemaParam->defaultValueForGui().isValid() )
5625 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5626}
5627
5628void QgsProcessingDatabaseSchemaWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5629{
5630 const QString v = QgsProcessingParameters::parameterAsSchema( parameterDefinition(), value, context );
5631
5632 if ( !value.isValid() )
5633 mSchemaComboBox->comboBox()->setCurrentIndex( -1 );
5634 else
5635 {
5636 if ( mSchemaComboBox->comboBox()->isEditable() )
5637 {
5638 const QString prev = mSchemaComboBox->comboBox()->currentText();
5639 mBlockSignals++;
5640 mSchemaComboBox->setSchema( v );
5641 mSchemaComboBox->comboBox()->setCurrentText( v );
5642
5643 mBlockSignals--;
5644 if ( prev != v )
5645 emit widgetValueHasChanged( this );
5646 }
5647 else
5648 mSchemaComboBox->setSchema( v );
5649 }
5650}
5651
5652QVariant QgsProcessingDatabaseSchemaWidgetWrapper::widgetValue() const
5653{
5654 if ( mSchemaComboBox )
5655 if ( mSchemaComboBox->comboBox()->isEditable() )
5656 return mSchemaComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->comboBox()->currentText() );
5657 else
5658 return mSchemaComboBox->currentSchema().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->currentSchema() );
5659 else
5660 return QVariant();
5661}
5662
5663QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleParameterTypes() const
5664{
5665 return QStringList()
5669}
5670
5671QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleOutputTypes() const
5672{
5673 return QStringList()
5676}
5677
5678QString QgsProcessingDatabaseSchemaWidgetWrapper::modelerExpressionFormatString() const
5679{
5680 return tr( "database schema name as a string value" );
5681}
5682
5683QString QgsProcessingDatabaseSchemaWidgetWrapper::parameterType() const
5684{
5686}
5687
5688QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseSchemaWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5689{
5690 return new QgsProcessingDatabaseSchemaWidgetWrapper( parameter, type );
5691}
5692
5693void QgsProcessingDatabaseSchemaWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5694{
5696 switch ( type() )
5697 {
5700 {
5701 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5702 {
5703 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() )->parentConnectionParameterName() )
5704 {
5705 setParentConnectionWrapperValue( wrapper );
5707 {
5708 setParentConnectionWrapperValue( wrapper );
5709 } );
5710 break;
5711 }
5712 }
5713 break;
5714 }
5715
5717 break;
5718 }
5719}
5720
5721
5722
5723//
5724// QgsProcessingDatabaseTableWidgetWrapper
5725//
5726
5727QgsProcessingDatabaseTableParameterDefinitionWidget::QgsProcessingDatabaseTableParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5728 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5729{
5730 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( definition );
5731
5732 QVBoxLayout *vlayout = new QVBoxLayout();
5733 vlayout->setContentsMargins( 0, 0, 0, 0 );
5734
5735 mConnectionParamComboBox = new QComboBox();
5736 mSchemaParamComboBox = new QComboBox();
5737 QString initialConnection;
5738 QString initialSchema;
5739 if ( tableParam )
5740 {
5741 initialConnection = tableParam->parentConnectionParameterName();
5742 initialSchema = tableParam->parentSchemaParameterName();
5743 }
5744
5745 if ( auto *lModel = widgetContext.model() )
5746 {
5747 // populate combo box with other model input choices
5748 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5749 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5750 {
5751 if ( definition && it->parameterName() == definition->name() )
5752 continue;
5753
5754 if ( dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5755 {
5756 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5757 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5758 {
5759 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5760 }
5761 }
5762 else if ( dynamic_cast< const QgsProcessingParameterDatabaseSchema * >( lModel->parameterDefinition( it->parameterName() ) ) )
5763 {
5764 mSchemaParamComboBox->addItem( it->parameterName(), it->parameterName() );
5765 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5766 {
5767 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5768 }
5769 }
5770 }
5771 }
5772
5773 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5774 {
5775 // if no candidates found, we just add the existing one as a placeholder
5776 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5777 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5778 }
5779
5780 if ( mSchemaParamComboBox->count() == 0 && !initialSchema.isEmpty() )
5781 {
5782 // if no candidates found, we just add the existing one as a placeholder
5783 mSchemaParamComboBox->addItem( initialSchema, initialSchema );
5784 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5785 }
5786
5787 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5788 vlayout->addWidget( mConnectionParamComboBox );
5789
5790 vlayout->addWidget( new QLabel( tr( "Database schema parameter" ) ) );
5791 vlayout->addWidget( mSchemaParamComboBox );
5792
5793 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5794
5795 mDefaultEdit = new QLineEdit();
5796 vlayout->addWidget( mDefaultEdit );
5797 setLayout( vlayout );
5798
5799 if ( tableParam )
5800 {
5801 mDefaultEdit->setText( tableParam->defaultValueForGui().toString() );
5802 }
5803}
5804
5805QgsProcessingParameterDefinition *QgsProcessingDatabaseTableParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
5806{
5807 QVariant defaultVal;
5808 if ( mDefaultEdit->text().isEmpty() )
5809 defaultVal = QVariant();
5810 else
5811 defaultVal = mDefaultEdit->text();
5812 auto param = std::make_unique< QgsProcessingParameterDatabaseTable>( name, description,
5813 mConnectionParamComboBox->currentData().toString(),
5814 mSchemaParamComboBox->currentData().toString(),
5815 defaultVal );
5816 param->setFlags( flags );
5817 return param.release();
5818}
5819
5820
5821QgsProcessingDatabaseTableWidgetWrapper::QgsProcessingDatabaseTableWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5822 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5823{
5824
5825}
5826
5827QWidget *QgsProcessingDatabaseTableWidgetWrapper::createWidget()
5828{
5829 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( parameterDefinition() );
5830
5831 mTableComboBox = new QgsDatabaseTableComboBox( QString(), QString() );
5832 if ( tableParam->flags() & Qgis::ProcessingParameterFlag::Optional )
5833 mTableComboBox->setAllowEmptyTable( true );
5834
5835 if ( type() == QgsProcessingGui::Modeler || tableParam->allowNewTableNames() )
5836 mTableComboBox->comboBox()->setEditable( true );
5837
5838 mTableComboBox->setToolTip( parameterDefinition()->toolTip() );
5839 connect( mTableComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5840 {
5841 if ( mBlockSignals )
5842 return;
5843
5844 emit widgetValueHasChanged( this );
5845 } );
5846
5847 return mTableComboBox;
5848}
5849
5850QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseTableWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5851{
5852 return new QgsProcessingDatabaseTableParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5853}
5854
5855void QgsProcessingDatabaseTableWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5856{
5857 // evaluate value to connection
5858 QgsProcessingContext *context = nullptr;
5859 std::unique_ptr< QgsProcessingContext > tmpContext;
5860 if ( mProcessingContextGenerator )
5861 context = mProcessingContextGenerator->processingContext();
5862
5863 if ( !context )
5864 {
5865 tmpContext = std::make_unique< QgsProcessingContext >();
5866 context = tmpContext.get();
5867 }
5868
5869 QVariant value = parentWrapper->parameterValue();
5870 mConnection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5871 mProvider = qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId();
5872 if ( mTableComboBox && !mSchema.isEmpty() )
5873 {
5874 mTableComboBox->setSchema( mSchema );
5875 mTableComboBox->setConnectionName( mConnection, mProvider );
5876
5877 const QgsProcessingParameterDatabaseTable *tableParam = qgis::down_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5878 if ( tableParam->defaultValueForGui().isValid() )
5879 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5880 }
5881}
5882
5883void QgsProcessingDatabaseTableWidgetWrapper::setParentSchemaWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5884{
5885 // evaluate value to schema
5886 QgsProcessingContext *context = nullptr;
5887 std::unique_ptr< QgsProcessingContext > tmpContext;
5888 if ( mProcessingContextGenerator )
5889 context = mProcessingContextGenerator->processingContext();
5890
5891 if ( !context )
5892 {
5893 tmpContext = std::make_unique< QgsProcessingContext >();
5894 context = tmpContext.get();
5895 }
5896
5897 QVariant value = parentWrapper->parameterValue();
5898 mSchema = value.isValid() ? QgsProcessingParameters::parameterAsSchema( parentWrapper->parameterDefinition(), value, *context ) : QString();
5899
5900 if ( mTableComboBox && !mSchema.isEmpty() && !mConnection.isEmpty() )
5901 {
5902 mTableComboBox->setSchema( mSchema );
5903 mTableComboBox->setConnectionName( mConnection, mProvider );
5904
5905 const QgsProcessingParameterDatabaseTable *tableParam = static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5906 if ( tableParam->defaultValueForGui().isValid() )
5907 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5908 }
5909
5910}
5911
5912void QgsProcessingDatabaseTableWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5913{
5914 const QString v = QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition(), value, context );
5915
5916 if ( !value.isValid() )
5917 mTableComboBox->comboBox()->setCurrentIndex( -1 );
5918 else
5919 {
5920 if ( mTableComboBox->comboBox()->isEditable() )
5921 {
5922 const QString prev = mTableComboBox->comboBox()->currentText();
5923 mBlockSignals++;
5924 mTableComboBox->setTable( v );
5925 mTableComboBox->comboBox()->setCurrentText( v );
5926
5927 mBlockSignals--;
5928 if ( prev != v )
5929 emit widgetValueHasChanged( this );
5930 }
5931 else
5932 mTableComboBox->setTable( v );
5933 }
5934}
5935
5936QVariant QgsProcessingDatabaseTableWidgetWrapper::widgetValue() const
5937{
5938 if ( mTableComboBox )
5939 if ( mTableComboBox->comboBox()->isEditable() )
5940 return mTableComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mTableComboBox->comboBox()->currentText() );
5941 else
5942 return mTableComboBox->currentTable().isEmpty() ? QVariant() : QVariant( mTableComboBox->currentTable() );
5943 else
5944 return QVariant();
5945}
5946
5947QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleParameterTypes() const
5948{
5949 return QStringList()
5953}
5954
5955QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleOutputTypes() const
5956{
5957 return QStringList()
5960}
5961
5962QString QgsProcessingDatabaseTableWidgetWrapper::modelerExpressionFormatString() const
5963{
5964 return tr( "database table name as a string value" );
5965}
5966
5967QString QgsProcessingDatabaseTableWidgetWrapper::parameterType() const
5968{
5970}
5971
5972QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseTableWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5973{
5974 return new QgsProcessingDatabaseTableWidgetWrapper( parameter, type );
5975}
5976
5977void QgsProcessingDatabaseTableWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5978{
5980 switch ( type() )
5981 {
5984 {
5985 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5986 {
5987 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentConnectionParameterName() )
5988 {
5989 setParentConnectionWrapperValue( wrapper );
5991 {
5992 setParentConnectionWrapperValue( wrapper );
5993 } );
5994 }
5995 else if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentSchemaParameterName() )
5996 {
5997 setParentSchemaWrapperValue( wrapper );
5999 {
6000 setParentSchemaWrapperValue( wrapper );
6001 } );
6002 }
6003 }
6004 break;
6005 }
6006
6008 break;
6009 }
6010}
6011
6012
6013//
6014// QgsProcessingExtentWidgetWrapper
6015//
6016
6017QgsProcessingExtentParameterDefinitionWidget::QgsProcessingExtentParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6018 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6019{
6020 QVBoxLayout *vlayout = new QVBoxLayout();
6021 vlayout->setContentsMargins( 0, 0, 0, 0 );
6022
6023 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
6024
6025 mDefaultWidget = new QgsExtentWidget();
6026 mDefaultWidget->setNullValueAllowed( true, tr( "Not set" ) );
6027 if ( const QgsProcessingParameterExtent *extentParam = dynamic_cast<const QgsProcessingParameterExtent *>( definition ) )
6028 {
6029 if ( extentParam->defaultValueForGui().isValid() )
6030 {
6031 QgsRectangle rect = QgsProcessingParameters::parameterAsExtent( extentParam, extentParam->defaultValueForGui(), context );
6032 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsExtentCrs( extentParam, extentParam->defaultValueForGui(), context );
6033 mDefaultWidget->setCurrentExtent( rect, crs );
6034 mDefaultWidget->setOutputExtentFromCurrent();
6035 }
6036 else
6037 {
6038 mDefaultWidget->clear();
6039 }
6040 }
6041
6042 vlayout->addWidget( mDefaultWidget );
6043 setLayout( vlayout );
6044}
6045
6046QgsProcessingParameterDefinition *QgsProcessingExtentParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
6047{
6048 const QString defaultVal = mDefaultWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
6049 QString::number( mDefaultWidget->outputExtent().xMinimum(), 'f', 9 ),
6050 QString::number( mDefaultWidget->outputExtent().xMaximum(), 'f', 9 ),
6051 QString::number( mDefaultWidget->outputExtent().yMinimum(), 'f', 9 ),
6052 QString::number( mDefaultWidget->outputExtent().yMaximum(), 'f', 9 ),
6053 mDefaultWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mDefaultWidget->outputCrs().authid() ) : QString()
6054 ) : QString();
6055 auto param = std::make_unique< QgsProcessingParameterExtent >( name, description, !defaultVal.isEmpty() ? QVariant( defaultVal ) : QVariant() );
6056 param->setFlags( flags );
6057 return param.release();
6058}
6059
6060
6061
6062QgsProcessingExtentWidgetWrapper::QgsProcessingExtentWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6063 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6064{
6065
6066}
6067
6068QWidget *QgsProcessingExtentWidgetWrapper::createWidget()
6069{
6070 const QgsProcessingParameterExtent *extentParam = dynamic_cast< const QgsProcessingParameterExtent *>( parameterDefinition() );
6071 switch ( type() )
6072 {
6076 {
6077 mExtentWidget = new QgsExtentWidget( nullptr );
6078 if ( widgetContext().mapCanvas() )
6079 mExtentWidget->setMapCanvas( widgetContext().mapCanvas() );
6080
6081 if ( extentParam->flags() & Qgis::ProcessingParameterFlag::Optional )
6082 mExtentWidget->setNullValueAllowed( true, tr( "Not set" ) );
6083
6084 mExtentWidget->setToolTip( parameterDefinition()->toolTip() );
6085
6086 connect( mExtentWidget, &QgsExtentWidget::extentChanged, this, [ = ]
6087 {
6088 emit widgetValueHasChanged( this );
6089 } );
6090
6091 if ( mDialog && type() != QgsProcessingGui::Modeler )
6092 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
6093
6094 return mExtentWidget;
6095 }
6096 }
6097 return nullptr;
6098}
6099
6100void QgsProcessingExtentWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
6101{
6103 if ( mExtentWidget && context.mapCanvas() && type() != QgsProcessingGui::Modeler )
6104 mExtentWidget->setMapCanvas( context.mapCanvas() );
6105}
6106
6107void QgsProcessingExtentWidgetWrapper::setDialog( QDialog *dialog )
6108{
6109 mDialog = dialog;
6110 if ( mExtentWidget && mDialog && type() != QgsProcessingGui::Modeler )
6111 {
6112 connect( mExtentWidget, &QgsExtentWidget::toggleDialogVisibility, mDialog, [ = ]( bool visible )
6113 {
6114 if ( !visible )
6115 mDialog->showMinimized();
6116 else
6117 {
6118 mDialog->showNormal();
6119 mDialog->raise();
6120 mDialog->activateWindow();
6121 }
6122 } );
6123 }
6125}
6126
6127void QgsProcessingExtentWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6128{
6129 if ( mExtentWidget )
6130 {
6131 if ( !value.isValid() || ( value.userType() == QMetaType::Type::QString && value.toString().isEmpty() ) )
6132 mExtentWidget->clear();
6133 else
6134 {
6135 QgsRectangle r = QgsProcessingParameters::parameterAsExtent( parameterDefinition(), value, context );
6136 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
6137 mExtentWidget->setCurrentExtent( r, crs );
6138 mExtentWidget->setOutputExtentFromUser( r, crs );
6139 }
6140 }
6141}
6142
6143QVariant QgsProcessingExtentWidgetWrapper::widgetValue() const
6144{
6145 if ( mExtentWidget )
6146 {
6147 const QString val = mExtentWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
6148 QString::number( mExtentWidget->outputExtent().xMinimum(), 'f', 9 ),
6149 QString::number( mExtentWidget->outputExtent().xMaximum(), 'f', 9 ),
6150 QString::number( mExtentWidget->outputExtent().yMinimum(), 'f', 9 ),
6151 QString::number( mExtentWidget->outputExtent().yMaximum(), 'f', 9 ),
6152 mExtentWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mExtentWidget->outputCrs().authid() ) : QString()
6153 ) : QString();
6154
6155 return val.isEmpty() ? QVariant() : QVariant( val );
6156 }
6157 else
6158 return QVariant();
6159}
6160
6161QStringList QgsProcessingExtentWidgetWrapper::compatibleParameterTypes() const
6162{
6163 return QStringList()
6173}
6174
6175QStringList QgsProcessingExtentWidgetWrapper::compatibleOutputTypes() const
6176{
6177 return QStringList()
6183}
6184
6185QString QgsProcessingExtentWidgetWrapper::modelerExpressionFormatString() const
6186{
6187 return tr( "string of the format 'x min,x max,y min,y max' or a geometry value (bounding box is used)" );
6188}
6189
6190QString QgsProcessingExtentWidgetWrapper::parameterType() const
6191{
6193}
6194
6195QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExtentWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6196{
6197 return new QgsProcessingExtentWidgetWrapper( parameter, type );
6198}
6199
6200QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExtentWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6201{
6202 return new QgsProcessingExtentParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6203}
6204
6205
6206
6207//
6208// QgsProcessingMapLayerWidgetWrapper
6209//
6210
6211QgsProcessingMapLayerParameterDefinitionWidget::QgsProcessingMapLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6212 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6213{
6214 QVBoxLayout *vlayout = new QVBoxLayout();
6215 vlayout->setContentsMargins( 0, 0, 0, 0 );
6216
6217 vlayout->addWidget( new QLabel( tr( "Layer type" ) ) );
6218 mLayerTypeComboBox = new QgsCheckableComboBox();
6219 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), static_cast< int >( Qgis::ProcessingSourceType::MapLayer ) );
6220 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
6221 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
6222 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
6223 mLayerTypeComboBox->addItem( tr( "Vector (Any Geometry Type)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
6224 mLayerTypeComboBox->addItem( tr( "Raster" ), static_cast< int >( Qgis::ProcessingSourceType::Raster ) );
6225 mLayerTypeComboBox->addItem( tr( "Mesh" ), static_cast< int >( Qgis::ProcessingSourceType::Mesh ) );
6226 mLayerTypeComboBox->addItem( tr( "Plugin" ), static_cast< int >( Qgis::ProcessingSourceType::Plugin ) );
6227 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), static_cast< int >( Qgis::ProcessingSourceType::PointCloud ) );
6228 mLayerTypeComboBox->addItem( tr( "Annotation" ), static_cast< int >( Qgis::ProcessingSourceType::Annotation ) );
6229
6230 if ( const QgsProcessingParameterMapLayer *layerParam = dynamic_cast<const QgsProcessingParameterMapLayer *>( definition ) )
6231 {
6232 for ( int i : layerParam->dataTypes() )
6233 {
6234 mLayerTypeComboBox->setItemCheckState( mLayerTypeComboBox->findData( i ), Qt::Checked );
6235 }
6236 }
6237
6238 vlayout->addWidget( mLayerTypeComboBox );
6239
6240 setLayout( vlayout );
6241}
6242
6243QgsProcessingParameterDefinition *QgsProcessingMapLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
6244{
6245 QList< int > dataTypes;
6246 for ( const QVariant &v : mLayerTypeComboBox->checkedItemsData() )
6247 dataTypes << v.toInt();
6248
6249 auto param = std::make_unique< QgsProcessingParameterMapLayer >( name, description );
6250 param->setDataTypes( dataTypes );
6251 param->setFlags( flags );
6252 return param.release();
6253}
6254
6255QgsProcessingMapLayerWidgetWrapper::QgsProcessingMapLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6256 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6257{
6258
6259}
6260
6261QWidget *QgsProcessingMapLayerWidgetWrapper::createWidget()
6262{
6263 mComboBox = new QgsProcessingMapLayerComboBox( parameterDefinition(), type() );
6264
6265 switch ( type() )
6266 {
6269 break;
6271 mComboBox->setEditable( true );
6272 break;
6273 }
6274
6275 mComboBox->setToolTip( parameterDefinition()->toolTip() );
6276
6277 connect( mComboBox, &QgsProcessingMapLayerComboBox::valueChanged, this, [ = ]()
6278 {
6279 if ( mBlockSignals )
6280 return;
6281
6282 emit widgetValueHasChanged( this );
6283 } );
6284
6285 setWidgetContext( widgetContext() );
6286 return mComboBox;
6287}
6288
6289void QgsProcessingMapLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
6290{
6292 if ( mComboBox )
6293 {
6294 mComboBox->setWidgetContext( context );
6295
6296 if ( !( parameterDefinition()->flags() & Qgis::ProcessingParameterFlag::Optional ) )
6297 {
6298 // non optional parameter -- if no default value set, default to active layer
6299 if ( !parameterDefinition()->defaultValueForGui().isValid() )
6300 mComboBox->setLayer( context.activeLayer() );
6301 }
6302 }
6303}
6304
6305void QgsProcessingMapLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6306{
6307 if ( mComboBox )
6308 mComboBox->setValue( value, context );
6309}
6310
6311QVariant QgsProcessingMapLayerWidgetWrapper::widgetValue() const
6312{
6313 return mComboBox ? mComboBox->value() : QVariant();
6314}
6315
6316QStringList QgsProcessingMapLayerWidgetWrapper::compatibleParameterTypes() const
6317{
6318 return QStringList()
6327}
6328
6329QStringList QgsProcessingMapLayerWidgetWrapper::compatibleOutputTypes() const
6330{
6331 return QStringList()
6338}
6339
6340QString QgsProcessingMapLayerWidgetWrapper::modelerExpressionFormatString() const
6341{
6342 return tr( "path to a map layer" );
6343}
6344
6345Qgis::ProcessingModelChildParameterSource QgsProcessingMapLayerWidgetWrapper::defaultModelSource( const QgsProcessingParameterDefinition *parameter ) const
6346{
6347 // non-optional layer sources default to a matching model input layer, but optional layer parameters
6348 // should default to static values. We don't want all optional layer parameters to have values set by default!
6349 if ( !( parameter->flags() & Qgis::ProcessingParameterFlag::Optional ) )
6350 {
6352 }
6353 else
6354 {
6356 }
6357}
6358
6359QString QgsProcessingMapLayerWidgetWrapper::parameterType() const
6360{
6362}
6363
6364QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6365{
6366 return new QgsProcessingMapLayerWidgetWrapper( parameter, type );
6367}
6368
6369QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6370{
6371 return new QgsProcessingMapLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6372}
6373
6374
6375//
6376// QgsProcessingRasterLayerWidgetWrapper
6377//
6378
6379QgsProcessingRasterLayerWidgetWrapper::QgsProcessingRasterLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6380 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6381{
6382
6383}
6384
6385QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleParameterTypes() const
6386{
6387 return QStringList()
6392}
6393
6394QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleOutputTypes() const
6395{
6396 return QStringList()
6402}
6403
6404QString QgsProcessingRasterLayerWidgetWrapper::modelerExpressionFormatString() const
6405{
6406 return tr( "path to a raster layer" );
6407}
6408
6409QString QgsProcessingRasterLayerWidgetWrapper::parameterType() const
6410{
6412}
6413
6414QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6415{
6416 return new QgsProcessingRasterLayerWidgetWrapper( parameter, type );
6417}
6418
6419QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRasterLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6420{
6421 Q_UNUSED( context );
6422 Q_UNUSED( widgetContext );
6423 Q_UNUSED( definition );
6424 Q_UNUSED( algorithm );
6425
6426 return nullptr;
6427}
6428
6429
6430//
6431// QgsProcessingVectorLayerWidgetWrapper
6432//
6433
6434QgsProcessingVectorLayerParameterDefinitionWidget::QgsProcessingVectorLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6435 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6436{
6437 QVBoxLayout *vlayout = new QVBoxLayout();
6438 vlayout->setContentsMargins( 0, 0, 0, 0 );
6439
6440 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6441 mGeometryTypeComboBox = new QgsCheckableComboBox();
6442 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
6443 mGeometryTypeComboBox->addItem( tr( "Point" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
6444 mGeometryTypeComboBox->addItem( tr( "Line" ), static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
6445 mGeometryTypeComboBox->addItem( tr( "Polygon" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
6446 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
6447
6448 if ( const QgsProcessingParameterVectorLayer *vectorParam = dynamic_cast<const QgsProcessingParameterVectorLayer *>( definition ) )
6449 {
6450 for ( int i : vectorParam->dataTypes() )
6451 {
6452 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6453 }
6454 }
6455
6456 vlayout->addWidget( mGeometryTypeComboBox );
6457
6458 setLayout( vlayout );
6459}
6460
6461QgsProcessingParameterDefinition *QgsProcessingVectorLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
6462{
6463 QList< int > dataTypes;
6464 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6465 dataTypes << v.toInt();
6466
6467 auto param = std::make_unique< QgsProcessingParameterVectorLayer >( name, description, dataTypes );
6468 param->setFlags( flags );
6469 return param.release();
6470}
6471
6472
6473QgsProcessingVectorLayerWidgetWrapper::QgsProcessingVectorLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6474 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6475{
6476
6477}
6478
6479QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleParameterTypes() const
6480{
6481 return QStringList()
6486}
6487
6488QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleOutputTypes() const
6489{
6490 return QStringList()
6496}
6497
6498QString QgsProcessingVectorLayerWidgetWrapper::modelerExpressionFormatString() const
6499{
6500 return tr( "path to a vector layer" );
6501}
6502
6503QList<int> QgsProcessingVectorLayerWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6504{
6505 if ( const QgsProcessingParameterVectorLayer *param = dynamic_cast< const QgsProcessingParameterVectorLayer *>( parameter ) )
6506 return param->dataTypes();
6507 else
6508 return QList< int >();
6509}
6510
6511QString QgsProcessingVectorLayerWidgetWrapper::parameterType() const
6512{
6514}
6515
6516QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6517{
6518 return new QgsProcessingVectorLayerWidgetWrapper( parameter, type );
6519}
6520
6521QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingVectorLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6522{
6523 return new QgsProcessingVectorLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6524}
6525
6526
6527
6528//
6529// QgsProcessingFeatureSourceLayerWidgetWrapper
6530//
6531
6532QgsProcessingFeatureSourceParameterDefinitionWidget::QgsProcessingFeatureSourceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6533 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6534{
6535 QVBoxLayout *vlayout = new QVBoxLayout();
6536 vlayout->setContentsMargins( 0, 0, 0, 0 );
6537
6538 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6539 mGeometryTypeComboBox = new QgsCheckableComboBox();
6540 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
6541 mGeometryTypeComboBox->addItem( tr( "Point" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
6542 mGeometryTypeComboBox->addItem( tr( "Line" ), static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
6543 mGeometryTypeComboBox->addItem( tr( "Polygon" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
6544 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
6545
6546 if ( const QgsProcessingParameterFeatureSource *sourceParam = dynamic_cast<const QgsProcessingParameterFeatureSource *>( definition ) )
6547 {
6548 for ( int i : sourceParam->dataTypes() )
6549 {
6550 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6551 }
6552 }
6553 else
6554 {
6555 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) ), Qt::Checked );
6556 }
6557
6558 vlayout->addWidget( mGeometryTypeComboBox );
6559
6560 setLayout( vlayout );
6561}
6562
6563QgsProcessingParameterDefinition *QgsProcessingFeatureSourceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
6564{
6565 QList< int > dataTypes;
6566 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6567 dataTypes << v.toInt();
6568
6569 auto param = std::make_unique< QgsProcessingParameterFeatureSource >( name, description, dataTypes );
6570 param->setFlags( flags );
6571 return param.release();
6572}
6573
6574QgsProcessingFeatureSourceWidgetWrapper::QgsProcessingFeatureSourceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6575 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6576{
6577
6578}
6579
6580QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleParameterTypes() const
6581{
6582 return QStringList()
6588}
6589
6590QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleOutputTypes() const
6591{
6592 return QStringList()
6598}
6599
6600QString QgsProcessingFeatureSourceWidgetWrapper::modelerExpressionFormatString() const
6601{
6602 return tr( "path to a vector layer" );
6603}
6604
6605QList<int> QgsProcessingFeatureSourceWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6606{
6607 if ( const QgsProcessingParameterFeatureSource *param = dynamic_cast< const QgsProcessingParameterFeatureSource *>( parameter ) )
6608 return param->dataTypes();
6609 else
6610 return QList< int >();
6611}
6612
6613QString QgsProcessingFeatureSourceWidgetWrapper::parameterType() const
6614{
6616}
6617
6618QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSourceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6619{
6620 return new QgsProcessingFeatureSourceWidgetWrapper( parameter, type );
6621}
6622
6623QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFeatureSourceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6624{
6625 return new QgsProcessingFeatureSourceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6626}
6627
6628//
6629// QgsProcessingMeshLayerWidgetWrapper
6630//
6631
6632QgsProcessingMeshLayerWidgetWrapper::QgsProcessingMeshLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6633 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6634{
6635
6636}
6637
6638QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleParameterTypes() const
6639{
6640 return QStringList()
6645}
6646
6647QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleOutputTypes() const
6648{
6649 return QStringList()
6651 // TODO << QgsProcessingOutputMeshLayer::typeName()
6655}
6656
6657QString QgsProcessingMeshLayerWidgetWrapper::modelerExpressionFormatString() const
6658{
6659 return tr( "path to a mesh layer" );
6660}
6661
6662QString QgsProcessingMeshLayerWidgetWrapper::parameterType() const
6663{
6665}
6666
6667QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6668{
6669 return new QgsProcessingMeshLayerWidgetWrapper( parameter, type );
6670}
6671
6672QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6673{
6674 Q_UNUSED( context );
6675 Q_UNUSED( widgetContext );
6676 Q_UNUSED( definition );
6677 Q_UNUSED( algorithm );
6678
6679 return nullptr;
6680}
6681
6682
6683
6684//
6685// QgsProcessingRasterBandPanelWidget
6686//
6687
6688QgsProcessingRasterBandPanelWidget::QgsProcessingRasterBandPanelWidget( QWidget *parent, const QgsProcessingParameterBand *param )
6689 : QWidget( parent )
6690 , mParam( param )
6691{
6692 QHBoxLayout *hl = new QHBoxLayout();
6693 hl->setContentsMargins( 0, 0, 0, 0 );
6694
6695 mLineEdit = new QLineEdit();
6696 mLineEdit->setEnabled( false );
6697 hl->addWidget( mLineEdit, 1 );
6698
6699 mToolButton = new QToolButton();
6700 mToolButton->setText( QString( QChar( 0x2026 ) ) );
6701 hl->addWidget( mToolButton );
6702
6703 setLayout( hl );
6704
6705 if ( mParam )
6706 {
6707 mLineEdit->setText( tr( "%n band(s) selected", nullptr, 0 ) );
6708 }
6709
6710 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingRasterBandPanelWidget::showDialog );
6711}
6712
6713void QgsProcessingRasterBandPanelWidget::setBands( const QList< int > &bands )
6714{
6715 mBands = bands;
6716}
6717
6718void QgsProcessingRasterBandPanelWidget::setBandNames( const QHash<int, QString> &names )
6719{
6720 mBandNames = names;
6721}
6722
6723void QgsProcessingRasterBandPanelWidget::setValue( const QVariant &value )
6724{
6725 if ( value.isValid() )
6726 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
6727 else
6728 mValue.clear();
6729
6730 updateSummaryText();
6731 emit changed();
6732}
6733
6734void QgsProcessingRasterBandPanelWidget::showDialog()
6735{
6736 QVariantList availableOptions;
6737 availableOptions.reserve( mBands.size() );
6738 for ( int band : std::as_const( mBands ) )
6739 {
6740 availableOptions << band;
6741 }
6742
6744 if ( panel && panel->dockMode() )
6745 {
6746 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
6747 widget->setPanelTitle( mParam->description() );
6748
6749 widget->setValueFormatter( [this]( const QVariant & v ) -> QString
6750 {
6751 int band = v.toInt();
6752 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6753 } );
6754
6755 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
6756 {
6757 setValue( widget->selectedOptions() );
6758 } );
6759 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
6760 panel->openPanel( widget );
6761 }
6762 else
6763 {
6764 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
6765
6766 dlg.setValueFormatter( [this]( const QVariant & v ) -> QString
6767 {
6768 int band = v.toInt();
6769 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6770 } );
6771 if ( dlg.exec() )
6772 {
6773 setValue( dlg.selectedOptions() );
6774 }
6775 }
6776}
6777
6778void QgsProcessingRasterBandPanelWidget::updateSummaryText()
6779{
6780 if ( mParam )
6781 mLineEdit->setText( tr( "%n band(s) selected", nullptr, mValue.count() ) );
6782}
6783
6784
6785
6786//
6787// QgsProcessingBandWidgetWrapper
6788//
6789
6790QgsProcessingBandParameterDefinitionWidget::QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6791 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6792{
6793 QVBoxLayout *vlayout = new QVBoxLayout();
6794 vlayout->setContentsMargins( 0, 0, 0, 0 );
6795
6796 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
6797
6798 mDefaultLineEdit = new QLineEdit();
6799 mDefaultLineEdit->setToolTip( tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6800 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6801 {
6802 const QList< int > bands = QgsProcessingParameters::parameterAsInts( bandParam, bandParam->defaultValueForGui(), context );
6803 QStringList defVal;
6804 for ( int b : bands )
6805 {
6806 defVal << QString::number( b );
6807 }
6808
6809 mDefaultLineEdit->setText( defVal.join( ';' ) );
6810 }
6811 vlayout->addWidget( mDefaultLineEdit );
6812
6813 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
6814 mParentLayerComboBox = new QComboBox();
6815
6816 QString initialParent;
6817 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6818 initialParent = bandParam->parentLayerParameterName();
6819
6820 if ( auto *lModel = widgetContext.model() )
6821 {
6822 // populate combo box with other model input choices
6823 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
6824 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
6825 {
6826 if ( const QgsProcessingParameterRasterLayer *definition = dynamic_cast< const QgsProcessingParameterRasterLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
6827 {
6828 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
6829 if ( !initialParent.isEmpty() && initialParent == definition->name() )
6830 {
6831 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6832 }
6833 }
6834 }
6835 }
6836
6837 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
6838 {
6839 // if no parent candidates found, we just add the existing one as a placeholder
6840 mParentLayerComboBox->addItem( initialParent, initialParent );
6841 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6842 }
6843
6844 vlayout->addWidget( mParentLayerComboBox );
6845
6846 mAllowMultipleCheckBox = new QCheckBox( tr( "Allow multiple" ) );
6847 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6848 mAllowMultipleCheckBox->setChecked( bandParam->allowMultiple() );
6849
6850 vlayout->addWidget( mAllowMultipleCheckBox );
6851 setLayout( vlayout );
6852}
6853
6854QgsProcessingParameterDefinition *QgsProcessingBandParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
6855{
6856 auto param = std::make_unique< QgsProcessingParameterBand >( name, description, mDefaultLineEdit->text().split( ';' ), mParentLayerComboBox->currentData().toString(), false, mAllowMultipleCheckBox->isChecked() );
6857 param->setFlags( flags );
6858 return param.release();
6859}
6860
6861QgsProcessingBandWidgetWrapper::QgsProcessingBandWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6862 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6863{
6864
6865}
6866
6867QWidget *QgsProcessingBandWidgetWrapper::createWidget()
6868{
6869 const QgsProcessingParameterBand *bandParam = dynamic_cast< const QgsProcessingParameterBand *>( parameterDefinition() );
6870 switch ( type() )
6871 {
6874 {
6875 if ( bandParam->allowMultiple() )
6876 {
6877 mPanel = new QgsProcessingRasterBandPanelWidget( nullptr, bandParam );
6878 mPanel->setToolTip( parameterDefinition()->toolTip() );
6879 connect( mPanel, &QgsProcessingRasterBandPanelWidget::changed, this, [ = ]
6880 {
6881 emit widgetValueHasChanged( this );
6882 } );
6883 return mPanel;
6884 }
6885 else
6886 {
6887 mComboBox = new QgsRasterBandComboBox();
6888 mComboBox->setShowNotSetOption( bandParam->flags() & Qgis::ProcessingParameterFlag::Optional );
6889
6890 mComboBox->setToolTip( parameterDefinition()->toolTip() );
6891 connect( mComboBox, &QgsRasterBandComboBox::bandChanged, this, [ = ]( int )
6892 {
6893 emit widgetValueHasChanged( this );
6894 } );
6895 return mComboBox;
6896 }
6897 }
6898
6900 {
6901 mLineEdit = new QLineEdit();
6902 mLineEdit->setToolTip( QObject::tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6903 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
6904 {
6905 emit widgetValueHasChanged( this );
6906 } );
6907 return mLineEdit;
6908 }
6909
6910 }
6911 return nullptr;
6912}
6913
6914void QgsProcessingBandWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
6915{
6917 switch ( type() )
6918 {
6921 {
6922 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
6923 {
6924 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterBand * >( parameterDefinition() )->parentLayerParameterName() )
6925 {
6926 setParentLayerWrapperValue( wrapper );
6928 {
6929 setParentLayerWrapperValue( wrapper );
6930 } );
6931 break;
6932 }
6933 }
6934 break;
6935 }
6936
6938 break;
6939 }
6940}
6941
6942void QgsProcessingBandWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
6943{
6944 // evaluate value to layer
6945 QgsProcessingContext *context = nullptr;
6946 std::unique_ptr< QgsProcessingContext > tmpContext;
6947 if ( mProcessingContextGenerator )
6948 context = mProcessingContextGenerator->processingContext();
6949
6950 if ( !context )
6951 {
6952 tmpContext = std::make_unique< QgsProcessingContext >();
6953 context = tmpContext.get();
6954 }
6955
6956 QVariant value = parentWrapper->parameterValue();
6957
6958 QgsRasterLayer *layer = QgsProcessingParameters::parameterAsRasterLayer( parentWrapper->parameterDefinition(), value, *context );
6959 if ( layer && layer->isValid() )
6960 {
6961 // need to grab ownership of layer if required - otherwise layer may be deleted when context
6962 // goes out of scope
6963 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
6964 if ( ownedLayer && ownedLayer->type() == Qgis::LayerType::Raster )
6965 {
6966 mParentLayer.reset( qobject_cast< QgsRasterLayer * >( ownedLayer.release() ) );
6967 layer = mParentLayer.get();
6968 }
6969 else
6970 {
6971 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
6972 }
6973
6974 if ( mComboBox )
6975 mComboBox->setLayer( layer );
6976 else if ( mPanel )
6977 {
6978 QgsRasterDataProvider *provider = layer->dataProvider();
6979 if ( provider && layer->isValid() )
6980 {
6981 //fill available bands
6982 int nBands = provider->bandCount();
6983 QList< int > bands;
6984 QHash< int, QString > bandNames;
6985 for ( int i = 1; i <= nBands; ++i )
6986 {
6987 bandNames.insert( i, QgsRasterBandComboBox::displayBandName( provider, i ) );
6988 bands << i;
6989 }
6990 mPanel->setBands( bands );
6991 mPanel->setBandNames( bandNames );
6992 }
6993 }
6994 }
6995 else
6996 {
6997 if ( mComboBox )
6998 mComboBox->setLayer( nullptr );
6999 else if ( mPanel )
7000 mPanel->setBands( QList< int >() );
7001
7002 if ( value.isValid() && widgetContext().messageBar() )
7003 {
7004 widgetContext().messageBar()->clearWidgets();
7005 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent bands could not be populated" ),
7007 }
7008 }
7009
7010 if ( parameterDefinition()->defaultValueForGui().isValid() )
7011 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
7012}
7013
7014void QgsProcessingBandWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7015{
7016 if ( mComboBox )
7017 {
7018 if ( !value.isValid() )
7019 mComboBox->setBand( -1 );
7020 else
7021 {
7022 const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
7023 mComboBox->setBand( v );
7024 }
7025 }
7026 else if ( mPanel )
7027 {
7028 QVariantList opts;
7029 if ( value.isValid() )
7030 {
7031 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
7032 opts.reserve( v.size() );
7033 for ( int i : v )
7034 opts << i;
7035 }
7036 if ( mPanel )
7037 mPanel->setValue( value.isValid() ? opts : QVariant() );
7038 }
7039 else if ( mLineEdit )
7040 {
7041 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
7042 if ( bandParam->allowMultiple() )
7043 {
7044 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
7045 QStringList opts;
7046 opts.reserve( v.size() );
7047 for ( int i : v )
7048 opts << QString::number( i );
7049 mLineEdit->setText( value.isValid() && !opts.empty() ? opts.join( ';' ) : QString() );
7050 }
7051 else
7052 {
7053 if ( value.isValid() )
7054 mLineEdit->setText( QString::number( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) ) );
7055 else
7056 mLineEdit->clear();
7057 }
7058 }
7059}
7060
7061QVariant QgsProcessingBandWidgetWrapper::widgetValue() const
7062{
7063 if ( mComboBox )
7064 return mComboBox->currentBand() == -1 ? QVariant() : mComboBox->currentBand();
7065 else if ( mPanel )
7066 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
7067 else if ( mLineEdit )
7068 {
7069 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
7070 if ( bandParam->allowMultiple() )
7071 {
7072 const QStringList parts = mLineEdit->text().split( ';', Qt::SkipEmptyParts );
7073 QVariantList res;
7074 res.reserve( parts.count() );
7075 for ( const QString &s : parts )
7076 {
7077 bool ok = false;
7078 int band = s.toInt( &ok );
7079 if ( ok )
7080 res << band;
7081 }
7082 return res.isEmpty() ? QVariant() : res;
7083 }
7084 else
7085 {
7086 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
7087 }
7088 }
7089 else
7090 return QVariant();
7091}
7092
7093QStringList QgsProcessingBandWidgetWrapper::compatibleParameterTypes() const
7094{
7095 return QStringList()
7098}
7099
7100QStringList QgsProcessingBandWidgetWrapper::compatibleOutputTypes() const
7101{
7102 return QStringList()
7105}
7106
7107QString QgsProcessingBandWidgetWrapper::modelerExpressionFormatString() const
7108{
7109 return tr( "selected band numbers as an array of numbers, or semicolon separated string of options (e.g. '1;3')" );
7110}
7111
7112QString QgsProcessingBandWidgetWrapper::parameterType() const
7113{
7115}
7116
7117QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBandWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7118{
7119 return new QgsProcessingBandWidgetWrapper( parameter, type );
7120}
7121
7122QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBandWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7123{
7124 return new QgsProcessingBandParameterDefinitionWidget( context, widgetContext, definition, algorithm );
7125}
7126
7127
7128
7129//
7130// QgsProcessingMultipleLayerPanelWidget
7131//
7132
7133QgsProcessingMultipleLayerPanelWidget::QgsProcessingMultipleLayerPanelWidget( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
7134 : QWidget( parent )
7135 , mParam( param )
7136{
7137 QHBoxLayout *hl = new QHBoxLayout();
7138 hl->setContentsMargins( 0, 0, 0, 0 );
7139
7140 mLineEdit = new QLineEdit();
7141 mLineEdit->setEnabled( false );
7142 hl->addWidget( mLineEdit, 1 );
7143
7144 mToolButton = new QToolButton();
7145 mToolButton->setText( QString( QChar( 0x2026 ) ) );
7146 hl->addWidget( mToolButton );
7147
7148 setLayout( hl );
7149
7150 if ( mParam )
7151 {
7152 mLineEdit->setText( tr( "%n input(s) selected", nullptr, 0 ) );
7153 }
7154
7155 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMultipleLayerPanelWidget::showDialog );
7156}
7157
7158void QgsProcessingMultipleLayerPanelWidget::setValue( const QVariant &value )
7159{
7160 if ( value.isValid() )
7161 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
7162 else
7163 mValue.clear();
7164
7165 updateSummaryText();
7166 emit changed();
7167}
7168
7169void QgsProcessingMultipleLayerPanelWidget::setProject( QgsProject *project )
7170{
7171 mProject = project;
7172 if ( mProject )
7173 {
7174 connect( mProject, &QgsProject::layerRemoved, this, [&]( const QString & layerId )
7175 {
7176 if ( mValue.removeAll( layerId ) )
7177 {
7178 updateSummaryText();
7179 emit changed();
7180 }
7181 } );
7182 }
7183}
7184
7185void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorithm *model, const QString &modelChildAlgorithmID )
7186{
7187 mModel = model;
7188 if ( !model )
7189 return;
7190
7191 switch ( mParam->layerType() )
7192 {
7194 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFile::typeName(),
7195 QStringList() << QgsProcessingOutputFile::typeName() );
7196 break;
7197
7199 {
7200 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterRasterLayer::typeName()
7203 QStringList() << QgsProcessingOutputFile::typeName()
7207 break;
7208 }
7209
7211 {
7212 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMeshLayer::typeName()
7215 QStringList() << QgsProcessingOutputFile::typeName()
7218 break;
7219 }
7220
7222 {
7223 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
7226 QStringList() << QgsProcessingOutputFile::typeName()
7229 break;
7230 }
7231
7233 {
7234 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterPointCloudLayer::typeName()
7237 QStringList() << QgsProcessingOutputFile::typeName()
7240 break;
7241 }
7242
7244 {
7245 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterAnnotationLayer::typeName()
7247 QStringList() << QgsProcessingOutputMapLayer::typeName()
7249 break;
7250 }
7251
7253 {
7254 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
7256 QStringList() << QgsProcessingOutputMapLayer::typeName()
7258 break;
7259 }
7260
7262 {
7263 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7267 QStringList() << QgsProcessingOutputFile::typeName()
7271 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
7272 break;
7273 }
7274
7276 {
7277 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7281 QStringList() << QgsProcessingOutputFile::typeName()
7285 break;
7286 }
7287
7289 {
7290 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7294 QStringList() << QgsProcessingOutputFile::typeName()
7298 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
7299 break;
7300 }
7301
7303 {
7304 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7308 QStringList() << QgsProcessingOutputFile::typeName()
7312 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
7313 break;
7314 }
7315
7317 {
7318 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7322 QStringList() << QgsProcessingOutputFile::typeName()
7326 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
7327 break;
7328 }
7329
7331 {
7332 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7338 QStringList() << QgsProcessingOutputFile::typeName()
7342 // << QgsProcessingOutputMeshLayer::typeName()
7344 break;
7345 }
7346 }
7347}
7348
7349void QgsProcessingMultipleLayerPanelWidget::showDialog()
7350{
7352 if ( panel && panel->dockMode() )
7353 {
7354 QgsProcessingMultipleInputPanelWidget *widget = new QgsProcessingMultipleInputPanelWidget( mParam, mValue, mModelSources, mModel );
7355 widget->setPanelTitle( mParam->description() );
7356 widget->setProject( mProject );
7357 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
7358 {
7359 setValue( widget->selectedOptions() );
7360 } );
7361 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
7362 panel->openPanel( widget );
7363 }
7364 else
7365 {
7366 QgsProcessingMultipleInputDialog dlg( mParam, mValue, mModelSources, mModel, this, Qt::WindowFlags() );
7367 dlg.setProject( mProject );
7368 if ( dlg.exec() )
7369 {
7370 setValue( dlg.selectedOptions() );
7371 }
7372 }
7373}
7374
7375void QgsProcessingMultipleLayerPanelWidget::updateSummaryText()
7376{
7377 if ( mParam )
7378 mLineEdit->setText( tr( "%n input(s) selected", nullptr, mValue.count() ) );
7379}
7380
7381//
7382// QgsProcessingMultipleLayerWidgetWrapper
7383//
7384
7385QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
7386 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
7387{
7388 QVBoxLayout *vlayout = new QVBoxLayout();
7389 vlayout->setContentsMargins( 0, 0, 0, 0 );
7390
7391 vlayout->addWidget( new QLabel( tr( "Allowed layer type" ) ) );
7392 mLayerTypeComboBox = new QComboBox();
7393 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), static_cast< int >( Qgis::ProcessingSourceType::MapLayer ) );
7394 mLayerTypeComboBox->addItem( tr( "Vector (No Geometry Required)" ), static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
7395 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
7396 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
7397 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
7398 mLayerTypeComboBox->addItem( tr( "Any Geometry Type" ), static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
7399 mLayerTypeComboBox->addItem( tr( "Raster" ), static_cast< int >( Qgis::ProcessingSourceType::Raster ) );
7400 mLayerTypeComboBox->addItem( tr( "File" ), static_cast< int >( Qgis::ProcessingSourceType::File ) );
7401 mLayerTypeComboBox->addItem( tr( "Mesh" ), static_cast< int >( Qgis::ProcessingSourceType::Mesh ) );
7402 mLayerTypeComboBox->addItem( tr( "Plugin" ), static_cast< int >( Qgis::ProcessingSourceType::Plugin ) );
7403 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), static_cast< int >( Qgis::ProcessingSourceType::PointCloud ) );
7404 mLayerTypeComboBox->addItem( tr( "Annotation" ), static_cast< int >( Qgis::ProcessingSourceType::Annotation ) );
7405 if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
7406 mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( static_cast< int >( layersParam->layerType() ) ) );
7407
7408 vlayout->addWidget( mLayerTypeComboBox );
7409 setLayout( vlayout );
7410}
7411
7412QgsProcessingParameterDefinition *QgsProcessingMultipleLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
7413{
7414 auto param = std::make_unique< QgsProcessingParameterMultipleLayers >( name, description, static_cast< Qgis::ProcessingSourceType >( mLayerTypeComboBox->currentData().toInt() ) );
7415 param->setFlags( flags );
7416 return param.release();
7417}
7418
7419QgsProcessingMultipleLayerWidgetWrapper::QgsProcessingMultipleLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7420 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7421{
7422
7423}
7424
7425QWidget *QgsProcessingMultipleLayerWidgetWrapper::createWidget()
7426{
7427 const QgsProcessingParameterMultipleLayers *layerParam = dynamic_cast< const QgsProcessingParameterMultipleLayers *>( parameterDefinition() );
7428
7429 mPanel = new QgsProcessingMultipleLayerPanelWidget( nullptr, layerParam );
7430 mPanel->setToolTip( parameterDefinition()->toolTip() );
7431 mPanel->setProject( widgetContext().project() );
7432 if ( type() == QgsProcessingGui::Modeler )
7433 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7434 connect( mPanel, &QgsProcessingMultipleLayerPanelWidget::changed, this, [ = ]
7435 {
7436 emit widgetValueHasChanged( this );
7437 } );
7438 return mPanel;
7439}
7440
7441void QgsProcessingMultipleLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7442{
7444 if ( mPanel )
7445 {
7446 mPanel->setProject( context.project() );
7447 if ( type() == QgsProcessingGui::Modeler )
7448 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7449 }
7450}
7451
7452void QgsProcessingMultipleLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7453{
7454 if ( mPanel )
7455 {
7456 QVariantList opts;
7457 if ( value.isValid() )
7458 {
7459 const QList< QgsMapLayer * > v = QgsProcessingParameters::parameterAsLayerList( parameterDefinition(), value, context );
7460 opts.reserve( v.size() );
7461 for ( const QgsMapLayer *l : v )
7462 opts << l->source();
7463 }
7464
7465 for ( const QVariant &v : value.toList() )
7466 {
7467 if ( v.userType() == QMetaType::type( "QgsProcessingModelChildParameterSource" ) )
7468 {
7469 const QgsProcessingModelChildParameterSource source = v.value< QgsProcessingModelChildParameterSource >();
7470 opts << QVariant::fromValue( source );
7471 }
7472 }
7473
7474 if ( mPanel )
7475 mPanel->setValue( value.isValid() ? opts : QVariant() );
7476 }
7477}
7478
7479QVariant QgsProcessingMultipleLayerWidgetWrapper::widgetValue() const
7480{
7481 if ( mPanel )
7482 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
7483 else
7484 return QVariant();
7485}
7486
7487QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleParameterTypes() const
7488{
7489 return QStringList()
7498}
7499
7500QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleOutputTypes() const
7501{
7502 return QStringList()
7510}
7511
7512QString QgsProcessingMultipleLayerWidgetWrapper::modelerExpressionFormatString() const
7513{
7514 return tr( "an array of layer paths, or semicolon separated string of layer paths" );
7515}
7516
7517QString QgsProcessingMultipleLayerWidgetWrapper::parameterType() const
7518{
7520}
7521
7522QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMultipleLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7523{
7524 return new QgsProcessingMultipleLayerWidgetWrapper( parameter, type );
7525}
7526
7527QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMultipleLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7528{
7529 return new QgsProcessingMultipleLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
7530}
7531
7532
7533//
7534// QgsProcessingPointCloudLayerWidgetWrapper
7535//
7536
7537QgsProcessingPointCloudLayerWidgetWrapper::QgsProcessingPointCloudLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7538 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
7539{
7540
7541}
7542
7543QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleParameterTypes() const
7544{
7545 return QStringList()
7550}
7551
7552QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleOutputTypes() const
7553{
7554 return QStringList()
7556 // TODO << QgsProcessingOutputPointCloudLayer::typeName()
7560}
7561
7562QString QgsProcessingPointCloudLayerWidgetWrapper::modelerExpressionFormatString() const
7563{
7564 return tr( "path to a point cloud layer" );
7565}
7566
7567QString QgsProcessingPointCloudLayerWidgetWrapper::parameterType() const
7568{
7570}
7571
7572QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7573{
7574 return new QgsProcessingPointCloudLayerWidgetWrapper( parameter, type );
7575}
7576
7577QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7578{
7579 Q_UNUSED( context );
7580 Q_UNUSED( widgetContext );
7581 Q_UNUSED( definition );
7582 Q_UNUSED( algorithm );
7583
7584 return nullptr;
7585}
7586
7587
7588//
7589// QgsProcessingAnnotationLayerWidgetWrapper
7590//
7591
7592QgsProcessingAnnotationLayerWidgetWrapper::QgsProcessingAnnotationLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7593 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7594{
7595
7596}
7597
7598QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleParameterTypes() const
7599{
7600 return QStringList()
7605}
7606
7607QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleOutputTypes() const
7608{
7609 return QStringList()
7613}
7614
7615QString QgsProcessingAnnotationLayerWidgetWrapper::modelerExpressionFormatString() const
7616{
7617 return tr( "name of an annotation layer, or \"main\" for the main annotation layer" );
7618}
7619
7620QString QgsProcessingAnnotationLayerWidgetWrapper::parameterType() const
7621{
7623}
7624
7625QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAnnotationLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7626{
7627 return new QgsProcessingAnnotationLayerWidgetWrapper( parameter, type );
7628}
7629
7630QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingAnnotationLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7631{
7632 Q_UNUSED( context );
7633 Q_UNUSED( widgetContext );
7634 Q_UNUSED( definition );
7635 Q_UNUSED( algorithm );
7636
7637 return nullptr;
7638}
7639
7640void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7641{
7643 if ( mComboBox )
7644 {
7645 if ( mWidgetContext.project() )
7646 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7647 }
7648}
7649
7650QWidget *QgsProcessingAnnotationLayerWidgetWrapper::createWidget()
7651{
7652 mComboBox = new QgsMapLayerComboBox( );
7653 mComboBox->setFilters( Qgis::LayerFilter::AnnotationLayer );
7654
7655 switch ( type() )
7656 {
7659 break;
7661 mComboBox->setEditable( true );
7662 break;
7663 }
7664
7665 mComboBox->setToolTip( parameterDefinition()->toolTip() );
7666
7667 if ( mWidgetContext.project() )
7668 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7669
7670 if ( parameterDefinition()->flags() & Qgis::ProcessingParameterFlag::Optional )
7671 mComboBox->setAllowEmptyLayer( true );
7672
7673 connect( mComboBox, &QgsMapLayerComboBox::layerChanged, this, [ = ]()
7674 {
7675 if ( mBlockSignals )
7676 return;
7677
7678 emit widgetValueHasChanged( this );
7679 } );
7680
7681 setWidgetContext( widgetContext() );
7682 return mComboBox;
7683}
7684
7685void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7686{
7687 if ( mComboBox )
7688 {
7689 if ( !value.isValid() && parameterDefinition()->flags() & Qgis::ProcessingParameterFlag::Optional )
7690 {
7691 mComboBox->setLayer( nullptr );
7692 return;
7693 }
7694
7695 QVariant val = value;
7696 if ( val.userType() == QMetaType::type( "QgsProperty" ) )
7697 {
7698 if ( val.value< QgsProperty >().propertyType() == Qgis::PropertyType::Static )
7699 {
7700 val = val.value< QgsProperty >().staticValue();
7701 }
7702 else
7703 {
7704 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), parameterDefinition()->defaultValueForGui().toString() );
7705 }
7706 }
7707
7708 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
7709 if ( !layer && val.userType() == QMetaType::Type::QString )
7710 {
7712 }
7713
7714 if ( layer )
7715 {
7716 mComboBox->setLayer( layer );
7717 }
7718 }
7719}
7720
7721QVariant QgsProcessingAnnotationLayerWidgetWrapper::widgetValue() const
7722{
7723 return mComboBox && mComboBox->currentLayer() ?
7724 ( mWidgetContext.project() ? ( mComboBox->currentLayer() == mWidgetContext.project()->mainAnnotationLayer() ? QStringLiteral( "main" ) : mComboBox->currentLayer()->id() ) : mComboBox->currentLayer()->id() )
7725 : QVariant();
7726}
7727
7728
7729//
7730// QgsProcessingPointCloudAttributePanelWidget
7731//
7732
7733QgsProcessingPointCloudAttributePanelWidget::QgsProcessingPointCloudAttributePanelWidget( QWidget *parent, const QgsProcessingParameterPointCloudAttribute *param )
7734 : QWidget( parent )
7735 , mParam( param )
7736{
7737 QHBoxLayout *hl = new QHBoxLayout();
7738 hl->setContentsMargins( 0, 0, 0, 0 );
7739
7740 mLineEdit = new QLineEdit();
7741 mLineEdit->setEnabled( false );
7742 hl->addWidget( mLineEdit, 1 );
7743
7744 mToolButton = new QToolButton();
7745 mToolButton->setText( QString( QChar( 0x2026 ) ) );
7746 hl->addWidget( mToolButton );
7747
7748 setLayout( hl );
7749
7750 if ( mParam )
7751 {
7752 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, 0 ) );
7753 }
7754
7755 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingPointCloudAttributePanelWidget::showDialog );
7756}
7757
7758void QgsProcessingPointCloudAttributePanelWidget::setAttributes( const QgsPointCloudAttributeCollection &attributes )
7759{
7760 mAttributes = attributes;
7761}
7762
7763void QgsProcessingPointCloudAttributePanelWidget::setValue( const QVariant &value )
7764{
7765 if ( value.isValid() )
7766 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
7767 else
7768 mValue.clear();
7769
7770 updateSummaryText();
7771 emit changed();
7772}
7773
7774void QgsProcessingPointCloudAttributePanelWidget::showDialog()
7775{
7776 QVariantList availableOptions;
7777 availableOptions.reserve( mAttributes.count() );
7778 const QVector<QgsPointCloudAttribute> attributes = mAttributes.attributes();
7779 for ( const QgsPointCloudAttribute &attr : attributes )
7780 {
7781 availableOptions << attr.name();
7782 }
7783
7785 if ( panel && panel->dockMode() )
7786 {
7787 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
7788 widget->setPanelTitle( mParam->description() );
7789
7790 widget->setValueFormatter( []( const QVariant & v ) -> QString
7791 {
7792 return v.toString();
7793 } );
7794
7795 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
7796 {
7797 setValue( widget->selectedOptions() );
7798 } );
7799 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
7800 panel->openPanel( widget );
7801 }
7802 else
7803 {
7804 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
7805
7806 dlg.setValueFormatter( []( const QVariant & v ) -> QString
7807 {
7808 return v.toString();
7809 } );
7810 if ( dlg.exec() )
7811 {
7812 setValue( dlg.selectedOptions() );
7813 }
7814 }
7815}
7816
7817void QgsProcessingPointCloudAttributePanelWidget::updateSummaryText()
7818{
7819 if ( !mParam )
7820 return;
7821
7822 if ( mValue.empty() )
7823 {
7824 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, 0 ) );
7825 }
7826 else
7827 {
7828 QStringList values;
7829 values.reserve( mValue.size() );
7830 for ( const QVariant &val : std::as_const( mValue ) )
7831 {
7832 values << val.toString();
7833 }
7834
7835 const QString concatenated = values.join( tr( "," ) );
7836 if ( concatenated.length() < 100 )
7837 mLineEdit->setText( concatenated );
7838 else
7839 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, mValue.count() ) );
7840 }
7841}
7842
7843
7844//
7845// QgsProcessingPointCloudAttributeWidgetWrapper
7846//
7847
7848QgsProcessingPointCloudAttributeParameterDefinitionWidget::QgsProcessingPointCloudAttributeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
7849 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
7850{
7851 QVBoxLayout *vlayout = new QVBoxLayout();
7852 vlayout->setContentsMargins( 0, 0, 0, 0 );
7853
7854 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
7855 mParentLayerComboBox = new QComboBox();
7856
7857 QString initialParent;
7858 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7859 initialParent = attrParam->parentLayerParameterName();
7860
7861 if ( auto *lModel = widgetContext.model() )
7862 {
7863 // populate combo box with other model input choices
7864 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
7865 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
7866 {
7867 if ( const QgsProcessingParameterPointCloudLayer *definition = dynamic_cast< const QgsProcessingParameterPointCloudLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
7868 {
7869 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
7870 if ( !initialParent.isEmpty() && initialParent == definition->name() )
7871 {
7872 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
7873 }
7874 }
7875 }
7876 }
7877
7878 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
7879 {
7880 // if no parent candidates found, we just add the existing one as a placeholder
7881 mParentLayerComboBox->addItem( initialParent, initialParent );
7882 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
7883 }
7884
7885 vlayout->addWidget( mParentLayerComboBox );
7886
7887 mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple attributes" ) );
7888 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7889 mAllowMultipleCheckBox->setChecked( attrParam->allowMultiple() );
7890
7891 vlayout->addWidget( mAllowMultipleCheckBox );
7892
7893 mDefaultToAllCheckBox = new QCheckBox( tr( "Select all attributes by default" ) );
7894 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
7895 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7896 mDefaultToAllCheckBox->setChecked( attrParam->defaultToAllAttributes() );
7897
7898 vlayout->addWidget( mDefaultToAllCheckBox );
7899
7900 connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
7901 {
7902 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
7903 } );
7904
7905 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
7906
7907 mDefaultLineEdit = new QLineEdit();
7908 mDefaultLineEdit->setToolTip( tr( "Default attribute name, or ; separated list of attribute names for multiple attribute parameters" ) );
7909 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7910 {
7911 const QStringList attributes = QgsProcessingParameters::parameterAsStrings( attrParam, attrParam->defaultValueForGui(), context );
7912 mDefaultLineEdit->setText( attributes.join( ';' ) );
7913 }
7914 vlayout->addWidget( mDefaultLineEdit );
7915
7916 setLayout( vlayout );
7917}
7918
7919QgsProcessingParameterDefinition *QgsProcessingPointCloudAttributeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
7920{
7921 QVariant defaultValue;
7922 if ( !mDefaultLineEdit->text().trimmed().isEmpty() )
7923 {
7924 defaultValue = mDefaultLineEdit->text();
7925 }
7926 auto param = std::make_unique< QgsProcessingParameterPointCloudAttribute >( name, description, defaultValue, mParentLayerComboBox->currentData().toString(), mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
7927 param->setFlags( flags );
7928 return param.release();
7929}
7930
7931QgsProcessingPointCloudAttributeWidgetWrapper::QgsProcessingPointCloudAttributeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7932 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7933{
7934}
7935
7936QWidget *QgsProcessingPointCloudAttributeWidgetWrapper::createWidget()
7937{
7938 const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast< const QgsProcessingParameterPointCloudAttribute *>( parameterDefinition() );
7939 switch ( type() )
7940 {
7943 {
7944 if ( attrParam->allowMultiple() )
7945 {
7946 mPanel = new QgsProcessingPointCloudAttributePanelWidget( nullptr, attrParam );
7947 mPanel->setToolTip( parameterDefinition()->toolTip() );
7948 connect( mPanel, &QgsProcessingPointCloudAttributePanelWidget::changed, this, [ = ]
7949 {
7950 emit widgetValueHasChanged( this );
7951 } );
7952 return mPanel;
7953 }
7954 else
7955 {
7956 mComboBox = new QgsPointCloudAttributeComboBox();
7957 mComboBox->setAllowEmptyAttributeName( attrParam->flags() & Qgis::ProcessingParameterFlag::Optional );
7958 mComboBox->setToolTip( parameterDefinition()->toolTip() );
7959 connect( mComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, [ = ]( const QString & )
7960 {
7961 emit widgetValueHasChanged( this );
7962 } );
7963 return mComboBox;
7964 }
7965 }
7966
7968 {
7969 mLineEdit = new QLineEdit();
7970 mLineEdit->setToolTip( QObject::tr( "Name of attribute (separate attribute names with ; for multiple attribute parameters)" ) );
7971 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
7972 {
7973 emit widgetValueHasChanged( this );
7974 } );
7975 return mLineEdit;
7976 }
7977
7978 }
7979 return nullptr;
7980}
7981
7982void QgsProcessingPointCloudAttributeWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
7983{
7985 switch ( type() )
7986 {
7989 {
7990 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
7991 {
7992 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() )->parentLayerParameterName() )
7993 {
7994 setParentLayerWrapperValue( wrapper );
7996 {
7997 setParentLayerWrapperValue( wrapper );
7998 } );
7999 break;
8000 }
8001 }
8002 break;
8003 }
8004
8006 break;
8007 }
8008}
8009
8010void QgsProcessingPointCloudAttributeWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
8011{
8012 // evaluate value to layer
8013 QgsProcessingContext *context = nullptr;
8014 std::unique_ptr< QgsProcessingContext > tmpContext;
8015 if ( mProcessingContextGenerator )
8016 context = mProcessingContextGenerator->processingContext();
8017
8018 if ( !context )
8019 {
8020 tmpContext = std::make_unique< QgsProcessingContext >();
8021 context = tmpContext.get();
8022 }
8023
8024 QVariant value = parentWrapper->parameterValue();
8025
8027 if ( layer && layer->isValid() )
8028 {
8029 // need to grab ownership of layer if required - otherwise layer may be deleted when context
8030 // goes out of scope
8031 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
8032 if ( ownedLayer && ownedLayer->type() == Qgis::LayerType::PointCloud )
8033 {
8034 mParentLayer.reset( qobject_cast< QgsPointCloudLayer * >( ownedLayer.release() ) );
8035 layer = mParentLayer.get();
8036 }
8037 else
8038 {
8039 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
8040 }
8041
8042 if ( mComboBox )
8043 mComboBox->setLayer( layer );
8044 else if ( mPanel )
8045 {
8046 mPanel->setAttributes( layer->attributes() );
8047 }
8048 }
8049 else
8050 {
8051 if ( mComboBox )
8052 {
8053 mComboBox->setLayer( nullptr );
8054 }
8055 else if ( mPanel )
8056 mPanel->setAttributes( QgsPointCloudAttributeCollection() );
8057
8058 if ( value.isValid() && widgetContext().messageBar() )
8059 {
8060 widgetContext().messageBar()->clearWidgets();
8061 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent attributes could not be populated" ),
8063 }
8064 }
8065
8066 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8067 if ( mPanel && attrParam->defaultToAllAttributes() )
8068 {
8069 QVariantList val;
8070 val.reserve( mPanel->attributes().attributes().size() );
8071 for ( const QgsPointCloudAttribute &attr : mPanel->attributes().attributes() )
8072 val << attr.name();
8073 setWidgetValue( val, *context );
8074 }
8075 else if ( attrParam->defaultValueForGui().isValid() )
8076 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
8077}
8078
8079void QgsProcessingPointCloudAttributeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
8080{
8081 if ( mComboBox )
8082 {
8083 if ( !value.isValid() )
8084 mComboBox->setAttribute( QString() );
8085 else
8086 {
8087 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
8088 mComboBox->setAttribute( v );
8089 }
8090 }
8091 else if ( mPanel )
8092 {
8093 QVariantList opts;
8094 if ( value.isValid() )
8095 {
8096 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
8097 opts.reserve( v.size() );
8098 for ( const QString &i : v )
8099 opts << i;
8100 }
8101 if ( mPanel )
8102 mPanel->setValue( opts );
8103 }
8104 else if ( mLineEdit )
8105 {
8106 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8107 if ( attrParam->allowMultiple() )
8108 {
8109 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
8110 mLineEdit->setText( v.join( ';' ) );
8111 }
8112 else
8113 {
8114 mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
8115 }
8116 }
8117}
8118
8119QVariant QgsProcessingPointCloudAttributeWidgetWrapper::widgetValue() const
8120{
8121 if ( mComboBox )
8122 return mComboBox->currentAttribute();
8123 else if ( mPanel )
8124 return mPanel->value();
8125 else if ( mLineEdit )
8126 {
8127 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8128 if ( attrParam->allowMultiple() )
8129 {
8130 return mLineEdit->text().split( ';' );
8131 }
8132 else
8133 return mLineEdit->text();
8134 }
8135 else
8136 return QVariant();
8137}
8138
8139QStringList QgsProcessingPointCloudAttributeWidgetWrapper::compatibleParameterTypes() const
8140{
8141 return QStringList()
8144}
8145
8146QStringList QgsProcessingPointCloudAttributeWidgetWrapper::compatibleOutputTypes() const
8147{
8148 return QStringList()
8151}
8152
8153QString QgsProcessingPointCloudAttributeWidgetWrapper::modelerExpressionFormatString() const
8154{
8155 return tr( "selected attribute names as an array of names, or semicolon separated string of options (e.g. 'X;Intensity')" );
8156}
8157
8158QString QgsProcessingPointCloudAttributeWidgetWrapper::parameterType() const
8159{
8161}
8162
8163QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudAttributeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8164{
8165 return new QgsProcessingPointCloudAttributeWidgetWrapper( parameter, type );
8166}
8167
8168QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudAttributeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
8169{
8170 return new QgsProcessingPointCloudAttributeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
8171}
8172
8173
8174//
8175// QgsProcessingOutputWidgetWrapper
8176//
8177
8178QgsProcessingOutputWidgetWrapper::QgsProcessingOutputWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8179 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
8180{
8181
8182}
8183
8184QWidget *QgsProcessingOutputWidgetWrapper::createWidget()
8185{
8186 const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( parameterDefinition() );
8187 switch ( type() )
8188 {
8191 {
8192 mOutputWidget = new QgsProcessingLayerOutputDestinationWidget( destParam, false );
8193 if ( mProcessingContextGenerator )
8194 mOutputWidget->setContext( mProcessingContextGenerator->processingContext() );
8195 if ( mParametersGenerator )
8196 mOutputWidget->registerProcessingParametersGenerator( mParametersGenerator );
8197 mOutputWidget->setToolTip( parameterDefinition()->toolTip() );
8198
8199 connect( mOutputWidget, &QgsProcessingLayerOutputDestinationWidget::destinationChanged, this, [ = ]()
8200 {
8201 if ( mBlockSignals )
8202 return;
8203
8204 emit widgetValueHasChanged( this );
8205 } );
8206
8207 if ( type() == QgsProcessingGui::Standard
8213 mOutputWidget->addOpenAfterRunningOption();
8214
8215 return mOutputWidget;
8216 }
8218 break;
8219 }
8220
8221 return nullptr;
8222}
8223
8224
8225void QgsProcessingOutputWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
8226{
8227 if ( mOutputWidget )
8228 mOutputWidget->setValue( value );
8229}
8230
8231QVariant QgsProcessingOutputWidgetWrapper::widgetValue() const
8232{
8233 if ( mOutputWidget )
8234 return mOutputWidget->value();
8235
8236 return QVariant();
8237}
8238
8239QVariantMap QgsProcessingOutputWidgetWrapper::customProperties() const
8240{
8241 QVariantMap res;
8242 if ( mOutputWidget )
8243 res.insert( QStringLiteral( "OPEN_AFTER_RUNNING" ), mOutputWidget->openAfterRunning() );
8244 return res;
8245}
8246
8247QStringList QgsProcessingOutputWidgetWrapper::compatibleParameterTypes() const
8248{
8249 return QStringList()
8256}
8257
8258QStringList QgsProcessingOutputWidgetWrapper::compatibleOutputTypes() const
8259{
8260 return QStringList()
8265}
8266
8267//
8268// QgsProcessingFeatureSinkWidgetWrapper
8269//
8270
8271QgsProcessingFeatureSinkWidgetWrapper::QgsProcessingFeatureSinkWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8272 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8273{
8274
8275}
8276
8277QString QgsProcessingFeatureSinkWidgetWrapper::parameterType() const
8278{
8280}
8281
8282QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSinkWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8283{
8284 return new QgsProcessingFeatureSinkWidgetWrapper( parameter, type );
8285}
8286
8287QString QgsProcessingFeatureSinkWidgetWrapper::modelerExpressionFormatString() const
8288{
8289 return tr( "path to layer destination" );
8290}
8291
8292//
8293// QgsProcessingFeatureSinkWidgetWrapper
8294//
8295
8296QgsProcessingVectorDestinationWidgetWrapper::QgsProcessingVectorDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8297 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8298{
8299
8300}
8301
8302QString QgsProcessingVectorDestinationWidgetWrapper::parameterType() const
8303{
8305}
8306
8307QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8308{
8309 return new QgsProcessingVectorDestinationWidgetWrapper( parameter, type );
8310}
8311
8312QString QgsProcessingVectorDestinationWidgetWrapper::modelerExpressionFormatString() const
8313{
8314 return tr( "path to layer destination" );
8315}
8316
8317//
8318// QgsProcessingRasterDestinationWidgetWrapper
8319//
8320
8321QgsProcessingRasterDestinationWidgetWrapper::QgsProcessingRasterDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8322 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8323{
8324
8325}
8326
8327QString QgsProcessingRasterDestinationWidgetWrapper::parameterType() const
8328{
8330}
8331
8332QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8333{
8334 return new QgsProcessingRasterDestinationWidgetWrapper( parameter, type );
8335}
8336
8337QString QgsProcessingRasterDestinationWidgetWrapper::modelerExpressionFormatString() const
8338{
8339 return tr( "path to layer destination" );
8340}
8341
8342//
8343// QgsProcessingPointCloudDestinationWidgetWrapper
8344//
8345
8346QgsProcessingPointCloudDestinationWidgetWrapper::QgsProcessingPointCloudDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8347 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8348{
8349
8350}
8351
8352QString QgsProcessingPointCloudDestinationWidgetWrapper::parameterType() const
8353{
8355}
8356
8357QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8358{
8359 return new QgsProcessingPointCloudDestinationWidgetWrapper( parameter, type );
8360}
8361
8362QString QgsProcessingPointCloudDestinationWidgetWrapper::modelerExpressionFormatString() const
8363{
8364 return tr( "path to layer destination" );
8365}
8366
8367//
8368// QgsProcessingFileDestinationWidgetWrapper
8369//
8370
8371QgsProcessingFileDestinationWidgetWrapper::QgsProcessingFileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8372 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8373{
8374
8375}
8376
8377QString QgsProcessingFileDestinationWidgetWrapper::parameterType() const
8378{
8380}
8381
8382QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8383{
8384 return new QgsProcessingFileDestinationWidgetWrapper( parameter, type );
8385}
8386
8387QString QgsProcessingFileDestinationWidgetWrapper::modelerExpressionFormatString() const
8388{
8389 return tr( "path to file destination" );
8390}
8391
8392//
8393// QgsProcessingFolderDestinationWidgetWrapper
8394//
8395
8396QgsProcessingFolderDestinationWidgetWrapper::QgsProcessingFolderDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8397 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8398{
8399
8400}
8401
8402QString QgsProcessingFolderDestinationWidgetWrapper::parameterType() const
8403{
8405}
8406
8407QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFolderDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8408{
8409 return new QgsProcessingFolderDestinationWidgetWrapper( parameter, type );
8410}
8411
8412QString QgsProcessingFolderDestinationWidgetWrapper::modelerExpressionFormatString() const
8413{
8414 return tr( "path to folder destination" );
8415}
8416
8417//
8418// QgsProcessingVectorTileDestinationWidgetWrapper
8419//
8420
8421QgsProcessingVectorTileDestinationWidgetWrapper::QgsProcessingVectorTileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8422 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8423{
8424}
8425
8426QString QgsProcessingVectorTileDestinationWidgetWrapper::parameterType() const
8427{
8429}
8430
8431QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorTileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8432{
8433 return new QgsProcessingPointCloudDestinationWidgetWrapper( parameter, type );
8434}
8435
8436QString QgsProcessingVectorTileDestinationWidgetWrapper::modelerExpressionFormatString() const
8437{
8438 return tr( "path to layer destination" );
8439}
8440
@ Standard
Unit is a standard measurement unit.
ProcessingSourceType
Processing data source types.
Definition qgis.h:2995
@ 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:3214
@ File
Parameter is a single file.
@ Folder
Parameter is a folder.
ExpressionType
Expression types.
Definition qgis.h:4696
@ RasterCalculator
Raster calculator expression (since QGIS 3.34)
@ Qgis
Native QGIS expression.
@ PointCloud
Point cloud expression.
DistanceUnit
Units of distance.
Definition qgis.h:4358
@ 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:3242
@ Boolean
Accepts boolean fields, since QGIS 3.34.
@ Binary
Accepts binary fields, since QGIS 3.34.
@ Numeric
Accepts numeric fields.
@ DateTime
Accepts datetime fields.
@ Info
Information message.
Definition qgis.h:100
@ Static
Static property.
@ AnnotationLayer
QgsAnnotationLayer.
TemporalUnit
Temporal units.
Definition qgis.h:4465
@ 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:3203
ProcessingModelChildParameterSource
Processing model child parameter sources.
Definition qgis.h:3273
@ 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:3260
ProcessingNumberParameterType
Processing numeric parameter data types.
Definition qgis.h:3228
A widget wrapper for Processing parameter value widgets.
QVariant parameterValue() const
Returns the current value of the parameter.
virtual QLabel * createLabel()
Creates a new label to accompany widgets created by the wrapper.
virtual void registerProcessingContextGenerator(QgsProcessingContextGenerator *generator)
Registers a Processing context generator class that will be used to retrieve a Processing context for...
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
virtual void postInitialize(const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers)
Called after all wrappers have been created within a particular dialog or context,...
virtual const QgsVectorLayer * linkedVectorLayer() const
Returns the optional vector layer associated with this widget wrapper, or nullptr if no vector layer ...
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
virtual void setDialog(QDialog *dialog)
Sets the parent dialog in which the wrapper is shown.
virtual void setWidgetContext(const QgsProcessingParameterWidgetContext &context)
Sets the context in which the Processing parameter widget is shown, e.g., the parent model algorithm,...
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
@ CapturePoint
Select and capture a point or a feature.
Selector widget for authentication configs.
void selectedConfigIdChanged(const QString &authcfg)
Emitted when authentication config is changed or missing.
QComboBox subclass which allows selecting multiple items.
A cross platform button subclass for selecting colors.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
A widget for selecting the coordinate operation to use when transforming between a source and destina...
void operationChanged()
Emitted when the operation selected in the dialog is changed.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
The QgsDatabaseSchemaComboBox class is a combo box which displays the list of schemas for a specific ...
The QgsDatabaseTableComboBox class is a combo box which displays the list of tables for a specific da...
The QgsDateEdit class is a QDateEdit widget with the capability of setting/reading null dates.
void dateValueChanged(const QDate &date)
Signal emitted whenever the date changes.
The QgsDateTimeEdit class is a QDateTimeEdit with the capability of setting/reading null date/times.
void setAllowNull(bool allowNull)
Determines if the widget allows setting null date/time.
void setNullRepresentation(const QString &null)
Sets the widget's null representation, which defaults to QgsApplication::nullRepresentation().
void valueChanged(const QDateTime &date)
Signal emitted whenever the value changes.
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
A reusable widget that can be used to build a expression string.
void expressionParsed(bool isValid)
Emitted when the user changes the expression in the widget.
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
A widget for configuration of a map extent.
void toggleDialogVisibility(bool visible)
Emitted when the parent dialog visibility must be changed (e.g.
void extentChanged(const QgsRectangle &r)
Emitted when the widget's extent is changed.
The QgsFieldComboBox is a combo box which displays the list of fields of a given layer.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
The QgsFieldExpressionWidget class 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:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:60
int count
Definition qgsfields.h:50
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
bool isEmpty
Definition qgsfields.h:49
void remove(int fieldIdx)
Removes the field with the given index.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
The QgsFileWidget class creates a widget for selecting a file or a folder.
@ GetFile
Select a single file.
@ GetDirectory
Select a directory.
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
A geometry is the spatial representation of a feature.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
Q_INVOKABLE QString asWkt(int precision=17) const
Exports the geometry to WKT.
The QgsLayoutComboBox class is a combo box which displays available layouts from a QgsLayoutManager.
void layoutChanged(QgsMasterLayoutInterface *layout)
Emitted whenever the currently selected layout changes.
void setAllowEmptyLayout(bool allowEmpty)
Sets whether an optional empty layout ("not set") option is present in the combobox.
The QgsLayoutItemComboBox class is a combo box which displays items of a matching type from a layout.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
Base class for graphical items within a QgsLayout.
virtual QString uuid() const
Returns the item identification string.
@ FilterPrintLayouts
Includes print layouts.
QList< QgsPrintLayout * > printLayouts() const
Returns a list of all print layouts contained in the manager.
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
The QgsMapLayerComboBox class is a combo box which displays the list of layers.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
Definition qgsmaplayer.h:75
QString name
Definition qgsmaplayer.h:79
QString id
Definition qgsmaplayer.h:78
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
QgsPointLocator::Match mapPointMatch() const
Returns the matching data from the most recently snapped point.
QgsPointXY snapPoint()
snapPoint will snap the points using the map canvas snapping utils configuration
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Abstract base class for all map tools.
Definition qgsmaptool.h:71
virtual void deactivate()
called when map tool is being deactivated
Interface for master layout type objects, such as print layouts and reports.
virtual QString name() const =0
Returns the layout's name.
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
bool clearWidgets()
Removes all items from the bar.
Base class for any widget that can be shown as a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void acceptPanel()
Accept the panel.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
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
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.
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.
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.
A class for drawing transient features (e.g.
@ ICON_X
A cross is used to highlight points (x)
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.
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:5486
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5445
const QgsCoordinateReferenceSystem & crs
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.