QGIS API Documentation 3.39.0-Master (47f7b3a4989)
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// QgsProcessingMultipleLayerLineEdit
7129//
7130
7131QgsProcessingMultipleLayerLineEdit::QgsProcessingMultipleLayerLineEdit( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
7132 : QgsHighlightableLineEdit( parent )
7133 , mParam( param )
7134{
7135 setAcceptDrops( true );
7136}
7137
7138void QgsProcessingMultipleLayerLineEdit::dragEnterEvent( QDragEnterEvent *event )
7139{
7140 const QStringList uris = QgsProcessingMultipleInputPanelWidget::compatibleUrisFromMimeData( mParam, event->mimeData(), {} );
7141 if ( !uris.isEmpty() )
7142 {
7143 event->setDropAction( Qt::CopyAction );
7144 event->accept();
7145 setHighlighted( true );
7146 }
7147 else
7148 {
7149 event->ignore();
7150 }
7151}
7152
7153void QgsProcessingMultipleLayerLineEdit::dragLeaveEvent( QDragLeaveEvent *event )
7154{
7155 QgsHighlightableLineEdit::dragLeaveEvent( event );
7156 event->accept();
7157 setHighlighted( false );
7158}
7159
7160void QgsProcessingMultipleLayerLineEdit::dropEvent( QDropEvent *event )
7161{
7162 const QStringList uris = QgsProcessingMultipleInputPanelWidget::compatibleUrisFromMimeData( mParam, event->mimeData(), {} );
7163 if ( !uris.isEmpty() )
7164 {
7165 event->acceptProposedAction();
7166 QVariantList uriList;
7167 uriList.reserve( uris.size() );
7168 for ( const QString &uri : uris )
7169 uriList.append( QVariant( uri ) );
7170 emit layersDropped( uriList );
7171 }
7172
7173 setHighlighted( false );
7174}
7175
7176//
7177// QgsProcessingMultipleLayerPanelWidget
7178//
7179
7180QgsProcessingMultipleLayerPanelWidget::QgsProcessingMultipleLayerPanelWidget( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
7181 : QWidget( parent )
7182 , mParam( param )
7183{
7184 QHBoxLayout *hl = new QHBoxLayout();
7185 hl->setContentsMargins( 0, 0, 0, 0 );
7186
7187 mLineEdit = new QgsProcessingMultipleLayerLineEdit( nullptr, param );
7188 mLineEdit->setEnabled( true );
7189 mLineEdit->setReadOnly( true );
7190
7191 hl->addWidget( mLineEdit, 1 );
7192 connect( mLineEdit, &QgsProcessingMultipleLayerLineEdit::layersDropped, this, &QgsProcessingMultipleLayerPanelWidget::setValue );
7193
7194 mToolButton = new QToolButton();
7195 mToolButton->setText( QString( QChar( 0x2026 ) ) );
7196 hl->addWidget( mToolButton );
7197
7198 setLayout( hl );
7199
7200 if ( mParam )
7201 {
7202 mLineEdit->setText( tr( "%n input(s) selected", nullptr, 0 ) );
7203 }
7204
7205 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMultipleLayerPanelWidget::showDialog );
7206}
7207
7208void QgsProcessingMultipleLayerPanelWidget::setValue( const QVariant &value )
7209{
7210 if ( value.isValid() )
7211 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
7212 else
7213 mValue.clear();
7214
7215 updateSummaryText();
7216 emit changed();
7217}
7218
7219void QgsProcessingMultipleLayerPanelWidget::setProject( QgsProject *project )
7220{
7221 mProject = project;
7222 if ( mProject )
7223 {
7224 connect( mProject, &QgsProject::layerRemoved, this, [&]( const QString & layerId )
7225 {
7226 if ( mValue.removeAll( layerId ) )
7227 {
7228 updateSummaryText();
7229 emit changed();
7230 }
7231 } );
7232 }
7233}
7234
7235void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorithm *model, const QString &modelChildAlgorithmID )
7236{
7237 mModel = model;
7238 if ( !model )
7239 return;
7240
7241 switch ( mParam->layerType() )
7242 {
7244 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFile::typeName(),
7245 QStringList() << QgsProcessingOutputFile::typeName() );
7246 break;
7247
7249 {
7250 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterRasterLayer::typeName()
7253 QStringList() << QgsProcessingOutputFile::typeName()
7257 break;
7258 }
7259
7261 {
7262 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMeshLayer::typeName()
7265 QStringList() << QgsProcessingOutputFile::typeName()
7268 break;
7269 }
7270
7272 {
7273 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
7276 QStringList() << QgsProcessingOutputFile::typeName()
7279 break;
7280 }
7281
7283 {
7284 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterPointCloudLayer::typeName()
7287 QStringList() << QgsProcessingOutputFile::typeName()
7290 break;
7291 }
7292
7294 {
7295 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterAnnotationLayer::typeName()
7297 QStringList() << QgsProcessingOutputMapLayer::typeName()
7299 break;
7300 }
7301
7303 {
7304 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
7306 QStringList() << QgsProcessingOutputMapLayer::typeName()
7308 break;
7309 }
7310
7312 {
7313 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7317 QStringList() << QgsProcessingOutputFile::typeName()
7321 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
7322 break;
7323 }
7324
7326 {
7327 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7331 QStringList() << QgsProcessingOutputFile::typeName()
7335 break;
7336 }
7337
7339 {
7340 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7344 QStringList() << QgsProcessingOutputFile::typeName()
7348 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
7349 break;
7350 }
7351
7353 {
7354 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7358 QStringList() << QgsProcessingOutputFile::typeName()
7362 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
7363 break;
7364 }
7365
7367 {
7368 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7372 QStringList() << QgsProcessingOutputFile::typeName()
7376 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) << static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
7377 break;
7378 }
7379
7381 {
7382 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
7388 QStringList() << QgsProcessingOutputFile::typeName()
7392 // << QgsProcessingOutputMeshLayer::typeName()
7394 break;
7395 }
7396 }
7397}
7398
7399void QgsProcessingMultipleLayerPanelWidget::showDialog()
7400{
7402 if ( panel && panel->dockMode() )
7403 {
7404 QgsProcessingMultipleInputPanelWidget *widget = new QgsProcessingMultipleInputPanelWidget( mParam, mValue, mModelSources, mModel );
7405 widget->setPanelTitle( mParam->description() );
7406 widget->setProject( mProject );
7407 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
7408 {
7409 setValue( widget->selectedOptions() );
7410 } );
7411 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
7412 panel->openPanel( widget );
7413 }
7414 else
7415 {
7416 QgsProcessingMultipleInputDialog dlg( mParam, mValue, mModelSources, mModel, this, Qt::WindowFlags() );
7417 dlg.setProject( mProject );
7418 if ( dlg.exec() )
7419 {
7420 setValue( dlg.selectedOptions() );
7421 }
7422 }
7423}
7424
7425void QgsProcessingMultipleLayerPanelWidget::updateSummaryText()
7426{
7427 if ( mParam )
7428 mLineEdit->setText( tr( "%n input(s) selected", nullptr, mValue.count() ) );
7429}
7430
7431//
7432// QgsProcessingMultipleLayerWidgetWrapper
7433//
7434
7435QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
7436 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
7437{
7438 QVBoxLayout *vlayout = new QVBoxLayout();
7439 vlayout->setContentsMargins( 0, 0, 0, 0 );
7440
7441 vlayout->addWidget( new QLabel( tr( "Allowed layer type" ) ) );
7442 mLayerTypeComboBox = new QComboBox();
7443 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), static_cast< int >( Qgis::ProcessingSourceType::MapLayer ) );
7444 mLayerTypeComboBox->addItem( tr( "Vector (No Geometry Required)" ), static_cast< int >( Qgis::ProcessingSourceType::Vector ) );
7445 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPoint ) );
7446 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorLine ) );
7447 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) );
7448 mLayerTypeComboBox->addItem( tr( "Any Geometry Type" ), static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
7449 mLayerTypeComboBox->addItem( tr( "Raster" ), static_cast< int >( Qgis::ProcessingSourceType::Raster ) );
7450 mLayerTypeComboBox->addItem( tr( "File" ), static_cast< int >( Qgis::ProcessingSourceType::File ) );
7451 mLayerTypeComboBox->addItem( tr( "Mesh" ), static_cast< int >( Qgis::ProcessingSourceType::Mesh ) );
7452 mLayerTypeComboBox->addItem( tr( "Plugin" ), static_cast< int >( Qgis::ProcessingSourceType::Plugin ) );
7453 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), static_cast< int >( Qgis::ProcessingSourceType::PointCloud ) );
7454 mLayerTypeComboBox->addItem( tr( "Annotation" ), static_cast< int >( Qgis::ProcessingSourceType::Annotation ) );
7455 if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
7456 mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( static_cast< int >( layersParam->layerType() ) ) );
7457
7458 vlayout->addWidget( mLayerTypeComboBox );
7459 setLayout( vlayout );
7460}
7461
7462QgsProcessingParameterDefinition *QgsProcessingMultipleLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
7463{
7464 auto param = std::make_unique< QgsProcessingParameterMultipleLayers >( name, description, static_cast< Qgis::ProcessingSourceType >( mLayerTypeComboBox->currentData().toInt() ) );
7465 param->setFlags( flags );
7466 return param.release();
7467}
7468
7469QgsProcessingMultipleLayerWidgetWrapper::QgsProcessingMultipleLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7470 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7471{
7472
7473}
7474
7475QWidget *QgsProcessingMultipleLayerWidgetWrapper::createWidget()
7476{
7477 const QgsProcessingParameterMultipleLayers *layerParam = dynamic_cast< const QgsProcessingParameterMultipleLayers *>( parameterDefinition() );
7478
7479 mPanel = new QgsProcessingMultipleLayerPanelWidget( nullptr, layerParam );
7480 mPanel->setToolTip( parameterDefinition()->toolTip() );
7481 mPanel->setProject( widgetContext().project() );
7482 if ( type() == QgsProcessingGui::Modeler )
7483 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7484 connect( mPanel, &QgsProcessingMultipleLayerPanelWidget::changed, this, [ = ]
7485 {
7486 emit widgetValueHasChanged( this );
7487 } );
7488 return mPanel;
7489}
7490
7491void QgsProcessingMultipleLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7492{
7494 if ( mPanel )
7495 {
7496 mPanel->setProject( context.project() );
7497 if ( type() == QgsProcessingGui::Modeler )
7498 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7499 }
7500}
7501
7502void QgsProcessingMultipleLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7503{
7504 if ( mPanel )
7505 {
7506 QVariantList opts;
7507 if ( value.isValid() )
7508 {
7509 const QList< QgsMapLayer * > v = QgsProcessingParameters::parameterAsLayerList( parameterDefinition(), value, context );
7510 opts.reserve( v.size() );
7511 for ( const QgsMapLayer *l : v )
7512 opts << l->source();
7513 }
7514
7515 for ( const QVariant &v : value.toList() )
7516 {
7517 if ( v.userType() == QMetaType::type( "QgsProcessingModelChildParameterSource" ) )
7518 {
7519 const QgsProcessingModelChildParameterSource source = v.value< QgsProcessingModelChildParameterSource >();
7520 opts << QVariant::fromValue( source );
7521 }
7522 }
7523
7524 if ( mPanel )
7525 mPanel->setValue( value.isValid() ? opts : QVariant() );
7526 }
7527}
7528
7529QVariant QgsProcessingMultipleLayerWidgetWrapper::widgetValue() const
7530{
7531 if ( mPanel )
7532 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
7533 else
7534 return QVariant();
7535}
7536
7537QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleParameterTypes() const
7538{
7539 return QStringList()
7548}
7549
7550QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleOutputTypes() const
7551{
7552 return QStringList()
7560}
7561
7562QString QgsProcessingMultipleLayerWidgetWrapper::modelerExpressionFormatString() const
7563{
7564 return tr( "an array of layer paths, or semicolon separated string of layer paths" );
7565}
7566
7567QString QgsProcessingMultipleLayerWidgetWrapper::parameterType() const
7568{
7570}
7571
7572QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMultipleLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7573{
7574 return new QgsProcessingMultipleLayerWidgetWrapper( parameter, type );
7575}
7576
7577QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMultipleLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7578{
7579 return new QgsProcessingMultipleLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
7580}
7581
7582
7583//
7584// QgsProcessingPointCloudLayerWidgetWrapper
7585//
7586
7587QgsProcessingPointCloudLayerWidgetWrapper::QgsProcessingPointCloudLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7588 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
7589{
7590
7591}
7592
7593QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleParameterTypes() const
7594{
7595 return QStringList()
7600}
7601
7602QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleOutputTypes() const
7603{
7604 return QStringList()
7606 // TODO << QgsProcessingOutputPointCloudLayer::typeName()
7610}
7611
7612QString QgsProcessingPointCloudLayerWidgetWrapper::modelerExpressionFormatString() const
7613{
7614 return tr( "path to a point cloud layer" );
7615}
7616
7617QString QgsProcessingPointCloudLayerWidgetWrapper::parameterType() const
7618{
7620}
7621
7622QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7623{
7624 return new QgsProcessingPointCloudLayerWidgetWrapper( parameter, type );
7625}
7626
7627QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7628{
7629 Q_UNUSED( context );
7630 Q_UNUSED( widgetContext );
7631 Q_UNUSED( definition );
7632 Q_UNUSED( algorithm );
7633
7634 return nullptr;
7635}
7636
7637
7638//
7639// QgsProcessingAnnotationLayerWidgetWrapper
7640//
7641
7642QgsProcessingAnnotationLayerWidgetWrapper::QgsProcessingAnnotationLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7643 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7644{
7645
7646}
7647
7648QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleParameterTypes() const
7649{
7650 return QStringList()
7655}
7656
7657QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleOutputTypes() const
7658{
7659 return QStringList()
7663}
7664
7665QString QgsProcessingAnnotationLayerWidgetWrapper::modelerExpressionFormatString() const
7666{
7667 return tr( "name of an annotation layer, or \"main\" for the main annotation layer" );
7668}
7669
7670QString QgsProcessingAnnotationLayerWidgetWrapper::parameterType() const
7671{
7673}
7674
7675QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAnnotationLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7676{
7677 return new QgsProcessingAnnotationLayerWidgetWrapper( parameter, type );
7678}
7679
7680QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingAnnotationLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7681{
7682 Q_UNUSED( context );
7683 Q_UNUSED( widgetContext );
7684 Q_UNUSED( definition );
7685 Q_UNUSED( algorithm );
7686
7687 return nullptr;
7688}
7689
7690void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7691{
7693 if ( mComboBox )
7694 {
7695 if ( mWidgetContext.project() )
7696 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7697 }
7698}
7699
7700QWidget *QgsProcessingAnnotationLayerWidgetWrapper::createWidget()
7701{
7702 mComboBox = new QgsMapLayerComboBox( );
7703 mComboBox->setFilters( Qgis::LayerFilter::AnnotationLayer );
7704
7705 switch ( type() )
7706 {
7709 break;
7711 mComboBox->setEditable( true );
7712 break;
7713 }
7714
7715 mComboBox->setToolTip( parameterDefinition()->toolTip() );
7716
7717 if ( mWidgetContext.project() )
7718 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7719
7720 if ( parameterDefinition()->flags() & Qgis::ProcessingParameterFlag::Optional )
7721 mComboBox->setAllowEmptyLayer( true );
7722
7723 connect( mComboBox, &QgsMapLayerComboBox::layerChanged, this, [ = ]()
7724 {
7725 if ( mBlockSignals )
7726 return;
7727
7728 emit widgetValueHasChanged( this );
7729 } );
7730
7731 setWidgetContext( widgetContext() );
7732 return mComboBox;
7733}
7734
7735void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7736{
7737 if ( mComboBox )
7738 {
7739 if ( !value.isValid() && parameterDefinition()->flags() & Qgis::ProcessingParameterFlag::Optional )
7740 {
7741 mComboBox->setLayer( nullptr );
7742 return;
7743 }
7744
7745 QVariant val = value;
7746 if ( val.userType() == QMetaType::type( "QgsProperty" ) )
7747 {
7748 if ( val.value< QgsProperty >().propertyType() == Qgis::PropertyType::Static )
7749 {
7750 val = val.value< QgsProperty >().staticValue();
7751 }
7752 else
7753 {
7754 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), parameterDefinition()->defaultValueForGui().toString() );
7755 }
7756 }
7757
7758 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
7759 if ( !layer && val.userType() == QMetaType::Type::QString )
7760 {
7762 }
7763
7764 if ( layer )
7765 {
7766 mComboBox->setLayer( layer );
7767 }
7768 }
7769}
7770
7771QVariant QgsProcessingAnnotationLayerWidgetWrapper::widgetValue() const
7772{
7773 return mComboBox && mComboBox->currentLayer() ?
7774 ( mWidgetContext.project() ? ( mComboBox->currentLayer() == mWidgetContext.project()->mainAnnotationLayer() ? QStringLiteral( "main" ) : mComboBox->currentLayer()->id() ) : mComboBox->currentLayer()->id() )
7775 : QVariant();
7776}
7777
7778
7779//
7780// QgsProcessingPointCloudAttributePanelWidget
7781//
7782
7783QgsProcessingPointCloudAttributePanelWidget::QgsProcessingPointCloudAttributePanelWidget( QWidget *parent, const QgsProcessingParameterPointCloudAttribute *param )
7784 : QWidget( parent )
7785 , mParam( param )
7786{
7787 QHBoxLayout *hl = new QHBoxLayout();
7788 hl->setContentsMargins( 0, 0, 0, 0 );
7789
7790 mLineEdit = new QLineEdit();
7791 mLineEdit->setEnabled( false );
7792 hl->addWidget( mLineEdit, 1 );
7793
7794 mToolButton = new QToolButton();
7795 mToolButton->setText( QString( QChar( 0x2026 ) ) );
7796 hl->addWidget( mToolButton );
7797
7798 setLayout( hl );
7799
7800 if ( mParam )
7801 {
7802 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, 0 ) );
7803 }
7804
7805 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingPointCloudAttributePanelWidget::showDialog );
7806}
7807
7808void QgsProcessingPointCloudAttributePanelWidget::setAttributes( const QgsPointCloudAttributeCollection &attributes )
7809{
7810 mAttributes = attributes;
7811}
7812
7813void QgsProcessingPointCloudAttributePanelWidget::setValue( const QVariant &value )
7814{
7815 if ( value.isValid() )
7816 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
7817 else
7818 mValue.clear();
7819
7820 updateSummaryText();
7821 emit changed();
7822}
7823
7824void QgsProcessingPointCloudAttributePanelWidget::showDialog()
7825{
7826 QVariantList availableOptions;
7827 availableOptions.reserve( mAttributes.count() );
7828 const QVector<QgsPointCloudAttribute> attributes = mAttributes.attributes();
7829 for ( const QgsPointCloudAttribute &attr : attributes )
7830 {
7831 availableOptions << attr.name();
7832 }
7833
7835 if ( panel && panel->dockMode() )
7836 {
7837 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
7838 widget->setPanelTitle( mParam->description() );
7839
7840 widget->setValueFormatter( []( const QVariant & v ) -> QString
7841 {
7842 return v.toString();
7843 } );
7844
7845 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
7846 {
7847 setValue( widget->selectedOptions() );
7848 } );
7849 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
7850 panel->openPanel( widget );
7851 }
7852 else
7853 {
7854 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
7855
7856 dlg.setValueFormatter( []( const QVariant & v ) -> QString
7857 {
7858 return v.toString();
7859 } );
7860 if ( dlg.exec() )
7861 {
7862 setValue( dlg.selectedOptions() );
7863 }
7864 }
7865}
7866
7867void QgsProcessingPointCloudAttributePanelWidget::updateSummaryText()
7868{
7869 if ( !mParam )
7870 return;
7871
7872 if ( mValue.empty() )
7873 {
7874 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, 0 ) );
7875 }
7876 else
7877 {
7878 QStringList values;
7879 values.reserve( mValue.size() );
7880 for ( const QVariant &val : std::as_const( mValue ) )
7881 {
7882 values << val.toString();
7883 }
7884
7885 const QString concatenated = values.join( tr( "," ) );
7886 if ( concatenated.length() < 100 )
7887 mLineEdit->setText( concatenated );
7888 else
7889 mLineEdit->setText( tr( "%n attribute(s) selected", nullptr, mValue.count() ) );
7890 }
7891}
7892
7893
7894//
7895// QgsProcessingPointCloudAttributeWidgetWrapper
7896//
7897
7898QgsProcessingPointCloudAttributeParameterDefinitionWidget::QgsProcessingPointCloudAttributeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
7899 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
7900{
7901 QVBoxLayout *vlayout = new QVBoxLayout();
7902 vlayout->setContentsMargins( 0, 0, 0, 0 );
7903
7904 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
7905 mParentLayerComboBox = new QComboBox();
7906
7907 QString initialParent;
7908 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7909 initialParent = attrParam->parentLayerParameterName();
7910
7911 if ( auto *lModel = widgetContext.model() )
7912 {
7913 // populate combo box with other model input choices
7914 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
7915 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
7916 {
7917 if ( const QgsProcessingParameterPointCloudLayer *definition = dynamic_cast< const QgsProcessingParameterPointCloudLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
7918 {
7919 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
7920 if ( !initialParent.isEmpty() && initialParent == definition->name() )
7921 {
7922 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
7923 }
7924 }
7925 }
7926 }
7927
7928 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
7929 {
7930 // if no parent candidates found, we just add the existing one as a placeholder
7931 mParentLayerComboBox->addItem( initialParent, initialParent );
7932 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
7933 }
7934
7935 vlayout->addWidget( mParentLayerComboBox );
7936
7937 mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple attributes" ) );
7938 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7939 mAllowMultipleCheckBox->setChecked( attrParam->allowMultiple() );
7940
7941 vlayout->addWidget( mAllowMultipleCheckBox );
7942
7943 mDefaultToAllCheckBox = new QCheckBox( tr( "Select all attributes by default" ) );
7944 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
7945 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7946 mDefaultToAllCheckBox->setChecked( attrParam->defaultToAllAttributes() );
7947
7948 vlayout->addWidget( mDefaultToAllCheckBox );
7949
7950 connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
7951 {
7952 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
7953 } );
7954
7955 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
7956
7957 mDefaultLineEdit = new QLineEdit();
7958 mDefaultLineEdit->setToolTip( tr( "Default attribute name, or ; separated list of attribute names for multiple attribute parameters" ) );
7959 if ( const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast<const QgsProcessingParameterPointCloudAttribute *>( definition ) )
7960 {
7961 const QStringList attributes = QgsProcessingParameters::parameterAsStrings( attrParam, attrParam->defaultValueForGui(), context );
7962 mDefaultLineEdit->setText( attributes.join( ';' ) );
7963 }
7964 vlayout->addWidget( mDefaultLineEdit );
7965
7966 setLayout( vlayout );
7967}
7968
7969QgsProcessingParameterDefinition *QgsProcessingPointCloudAttributeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
7970{
7971 QVariant defaultValue;
7972 if ( !mDefaultLineEdit->text().trimmed().isEmpty() )
7973 {
7974 defaultValue = mDefaultLineEdit->text();
7975 }
7976 auto param = std::make_unique< QgsProcessingParameterPointCloudAttribute >( name, description, defaultValue, mParentLayerComboBox->currentData().toString(), mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
7977 param->setFlags( flags );
7978 return param.release();
7979}
7980
7981QgsProcessingPointCloudAttributeWidgetWrapper::QgsProcessingPointCloudAttributeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7982 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7983{
7984}
7985
7986QWidget *QgsProcessingPointCloudAttributeWidgetWrapper::createWidget()
7987{
7988 const QgsProcessingParameterPointCloudAttribute *attrParam = dynamic_cast< const QgsProcessingParameterPointCloudAttribute *>( parameterDefinition() );
7989 switch ( type() )
7990 {
7993 {
7994 if ( attrParam->allowMultiple() )
7995 {
7996 mPanel = new QgsProcessingPointCloudAttributePanelWidget( nullptr, attrParam );
7997 mPanel->setToolTip( parameterDefinition()->toolTip() );
7998 connect( mPanel, &QgsProcessingPointCloudAttributePanelWidget::changed, this, [ = ]
7999 {
8000 emit widgetValueHasChanged( this );
8001 } );
8002 return mPanel;
8003 }
8004 else
8005 {
8006 mComboBox = new QgsPointCloudAttributeComboBox();
8007 mComboBox->setAllowEmptyAttributeName( attrParam->flags() & Qgis::ProcessingParameterFlag::Optional );
8008 mComboBox->setToolTip( parameterDefinition()->toolTip() );
8009 connect( mComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, [ = ]( const QString & )
8010 {
8011 emit widgetValueHasChanged( this );
8012 } );
8013 return mComboBox;
8014 }
8015 }
8016
8018 {
8019 mLineEdit = new QLineEdit();
8020 mLineEdit->setToolTip( QObject::tr( "Name of attribute (separate attribute names with ; for multiple attribute parameters)" ) );
8021 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
8022 {
8023 emit widgetValueHasChanged( this );
8024 } );
8025 return mLineEdit;
8026 }
8027
8028 }
8029 return nullptr;
8030}
8031
8032void QgsProcessingPointCloudAttributeWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
8033{
8035 switch ( type() )
8036 {
8039 {
8040 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
8041 {
8042 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() )->parentLayerParameterName() )
8043 {
8044 setParentLayerWrapperValue( wrapper );
8046 {
8047 setParentLayerWrapperValue( wrapper );
8048 } );
8049 break;
8050 }
8051 }
8052 break;
8053 }
8054
8056 break;
8057 }
8058}
8059
8060void QgsProcessingPointCloudAttributeWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
8061{
8062 // evaluate value to layer
8063 QgsProcessingContext *context = nullptr;
8064 std::unique_ptr< QgsProcessingContext > tmpContext;
8065 if ( mProcessingContextGenerator )
8066 context = mProcessingContextGenerator->processingContext();
8067
8068 if ( !context )
8069 {
8070 tmpContext = std::make_unique< QgsProcessingContext >();
8071 context = tmpContext.get();
8072 }
8073
8074 QVariant value = parentWrapper->parameterValue();
8075
8077 if ( layer && layer->isValid() )
8078 {
8079 // need to grab ownership of layer if required - otherwise layer may be deleted when context
8080 // goes out of scope
8081 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
8082 if ( ownedLayer && ownedLayer->type() == Qgis::LayerType::PointCloud )
8083 {
8084 mParentLayer.reset( qobject_cast< QgsPointCloudLayer * >( ownedLayer.release() ) );
8085 layer = mParentLayer.get();
8086 }
8087 else
8088 {
8089 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
8090 }
8091
8092 if ( mComboBox )
8093 mComboBox->setLayer( layer );
8094 else if ( mPanel )
8095 {
8096 mPanel->setAttributes( layer->attributes() );
8097 }
8098 }
8099 else
8100 {
8101 if ( mComboBox )
8102 {
8103 mComboBox->setLayer( nullptr );
8104 }
8105 else if ( mPanel )
8106 mPanel->setAttributes( QgsPointCloudAttributeCollection() );
8107
8108 if ( value.isValid() && widgetContext().messageBar() )
8109 {
8110 widgetContext().messageBar()->clearWidgets();
8111 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent attributes could not be populated" ),
8113 }
8114 }
8115
8116 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8117 if ( mPanel && attrParam->defaultToAllAttributes() )
8118 {
8119 QVariantList val;
8120 val.reserve( mPanel->attributes().attributes().size() );
8121 for ( const QgsPointCloudAttribute &attr : mPanel->attributes().attributes() )
8122 val << attr.name();
8123 setWidgetValue( val, *context );
8124 }
8125 else if ( attrParam->defaultValueForGui().isValid() )
8126 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
8127}
8128
8129void QgsProcessingPointCloudAttributeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
8130{
8131 if ( mComboBox )
8132 {
8133 if ( !value.isValid() )
8134 mComboBox->setAttribute( QString() );
8135 else
8136 {
8137 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
8138 mComboBox->setAttribute( v );
8139 }
8140 }
8141 else if ( mPanel )
8142 {
8143 QVariantList opts;
8144 if ( value.isValid() )
8145 {
8146 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
8147 opts.reserve( v.size() );
8148 for ( const QString &i : v )
8149 opts << i;
8150 }
8151 if ( mPanel )
8152 mPanel->setValue( opts );
8153 }
8154 else if ( mLineEdit )
8155 {
8156 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8157 if ( attrParam->allowMultiple() )
8158 {
8159 const QStringList v = QgsProcessingParameters::parameterAsStrings( parameterDefinition(), value, context );
8160 mLineEdit->setText( v.join( ';' ) );
8161 }
8162 else
8163 {
8164 mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
8165 }
8166 }
8167}
8168
8169QVariant QgsProcessingPointCloudAttributeWidgetWrapper::widgetValue() const
8170{
8171 if ( mComboBox )
8172 return mComboBox->currentAttribute();
8173 else if ( mPanel )
8174 return mPanel->value();
8175 else if ( mLineEdit )
8176 {
8177 const QgsProcessingParameterPointCloudAttribute *attrParam = static_cast< const QgsProcessingParameterPointCloudAttribute * >( parameterDefinition() );
8178 if ( attrParam->allowMultiple() )
8179 {
8180 return mLineEdit->text().split( ';' );
8181 }
8182 else
8183 return mLineEdit->text();
8184 }
8185 else
8186 return QVariant();
8187}
8188
8189QStringList QgsProcessingPointCloudAttributeWidgetWrapper::compatibleParameterTypes() const
8190{
8191 return QStringList()
8194}
8195
8196QStringList QgsProcessingPointCloudAttributeWidgetWrapper::compatibleOutputTypes() const
8197{
8198 return QStringList()
8201}
8202
8203QString QgsProcessingPointCloudAttributeWidgetWrapper::modelerExpressionFormatString() const
8204{
8205 return tr( "selected attribute names as an array of names, or semicolon separated string of options (e.g. 'X;Intensity')" );
8206}
8207
8208QString QgsProcessingPointCloudAttributeWidgetWrapper::parameterType() const
8209{
8211}
8212
8213QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudAttributeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8214{
8215 return new QgsProcessingPointCloudAttributeWidgetWrapper( parameter, type );
8216}
8217
8218QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudAttributeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
8219{
8220 return new QgsProcessingPointCloudAttributeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
8221}
8222
8223
8224//
8225// QgsProcessingOutputWidgetWrapper
8226//
8227
8228QgsProcessingOutputWidgetWrapper::QgsProcessingOutputWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8229 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
8230{
8231
8232}
8233
8234QWidget *QgsProcessingOutputWidgetWrapper::createWidget()
8235{
8236 const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( parameterDefinition() );
8237 switch ( type() )
8238 {
8241 {
8242 mOutputWidget = new QgsProcessingLayerOutputDestinationWidget( destParam, false );
8243 if ( mProcessingContextGenerator )
8244 mOutputWidget->setContext( mProcessingContextGenerator->processingContext() );
8245 if ( mParametersGenerator )
8246 mOutputWidget->registerProcessingParametersGenerator( mParametersGenerator );
8247 mOutputWidget->setToolTip( parameterDefinition()->toolTip() );
8248
8249 connect( mOutputWidget, &QgsProcessingLayerOutputDestinationWidget::destinationChanged, this, [ = ]()
8250 {
8251 if ( mBlockSignals )
8252 return;
8253
8254 emit widgetValueHasChanged( this );
8255 } );
8256
8257 if ( type() == QgsProcessingGui::Standard
8263 mOutputWidget->addOpenAfterRunningOption();
8264
8265 return mOutputWidget;
8266 }
8268 break;
8269 }
8270
8271 return nullptr;
8272}
8273
8274
8275void QgsProcessingOutputWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
8276{
8277 if ( mOutputWidget )
8278 mOutputWidget->setValue( value );
8279}
8280
8281QVariant QgsProcessingOutputWidgetWrapper::widgetValue() const
8282{
8283 if ( mOutputWidget )
8284 return mOutputWidget->value();
8285
8286 return QVariant();
8287}
8288
8289QVariantMap QgsProcessingOutputWidgetWrapper::customProperties() const
8290{
8291 QVariantMap res;
8292 if ( mOutputWidget )
8293 res.insert( QStringLiteral( "OPEN_AFTER_RUNNING" ), mOutputWidget->openAfterRunning() );
8294 return res;
8295}
8296
8297QStringList QgsProcessingOutputWidgetWrapper::compatibleParameterTypes() const
8298{
8299 return QStringList()
8306}
8307
8308QStringList QgsProcessingOutputWidgetWrapper::compatibleOutputTypes() const
8309{
8310 return QStringList()
8315}
8316
8317//
8318// QgsProcessingFeatureSinkWidgetWrapper
8319//
8320
8321QgsProcessingFeatureSinkWidgetWrapper::QgsProcessingFeatureSinkWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8322 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8323{
8324
8325}
8326
8327QString QgsProcessingFeatureSinkWidgetWrapper::parameterType() const
8328{
8330}
8331
8332QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSinkWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8333{
8334 return new QgsProcessingFeatureSinkWidgetWrapper( parameter, type );
8335}
8336
8337QString QgsProcessingFeatureSinkWidgetWrapper::modelerExpressionFormatString() const
8338{
8339 return tr( "path to layer destination" );
8340}
8341
8342//
8343// QgsProcessingFeatureSinkWidgetWrapper
8344//
8345
8346QgsProcessingVectorDestinationWidgetWrapper::QgsProcessingVectorDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8347 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8348{
8349
8350}
8351
8352QString QgsProcessingVectorDestinationWidgetWrapper::parameterType() const
8353{
8355}
8356
8357QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8358{
8359 return new QgsProcessingVectorDestinationWidgetWrapper( parameter, type );
8360}
8361
8362QString QgsProcessingVectorDestinationWidgetWrapper::modelerExpressionFormatString() const
8363{
8364 return tr( "path to layer destination" );
8365}
8366
8367//
8368// QgsProcessingRasterDestinationWidgetWrapper
8369//
8370
8371QgsProcessingRasterDestinationWidgetWrapper::QgsProcessingRasterDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8372 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8373{
8374
8375}
8376
8377QString QgsProcessingRasterDestinationWidgetWrapper::parameterType() const
8378{
8380}
8381
8382QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8383{
8384 return new QgsProcessingRasterDestinationWidgetWrapper( parameter, type );
8385}
8386
8387QString QgsProcessingRasterDestinationWidgetWrapper::modelerExpressionFormatString() const
8388{
8389 return tr( "path to layer destination" );
8390}
8391
8392//
8393// QgsProcessingPointCloudDestinationWidgetWrapper
8394//
8395
8396QgsProcessingPointCloudDestinationWidgetWrapper::QgsProcessingPointCloudDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8397 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8398{
8399
8400}
8401
8402QString QgsProcessingPointCloudDestinationWidgetWrapper::parameterType() const
8403{
8405}
8406
8407QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8408{
8409 return new QgsProcessingPointCloudDestinationWidgetWrapper( parameter, type );
8410}
8411
8412QString QgsProcessingPointCloudDestinationWidgetWrapper::modelerExpressionFormatString() const
8413{
8414 return tr( "path to layer destination" );
8415}
8416
8417//
8418// QgsProcessingFileDestinationWidgetWrapper
8419//
8420
8421QgsProcessingFileDestinationWidgetWrapper::QgsProcessingFileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8422 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8423{
8424
8425}
8426
8427QString QgsProcessingFileDestinationWidgetWrapper::parameterType() const
8428{
8430}
8431
8432QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8433{
8434 return new QgsProcessingFileDestinationWidgetWrapper( parameter, type );
8435}
8436
8437QString QgsProcessingFileDestinationWidgetWrapper::modelerExpressionFormatString() const
8438{
8439 return tr( "path to file destination" );
8440}
8441
8442//
8443// QgsProcessingFolderDestinationWidgetWrapper
8444//
8445
8446QgsProcessingFolderDestinationWidgetWrapper::QgsProcessingFolderDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8447 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8448{
8449
8450}
8451
8452QString QgsProcessingFolderDestinationWidgetWrapper::parameterType() const
8453{
8455}
8456
8457QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFolderDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8458{
8459 return new QgsProcessingFolderDestinationWidgetWrapper( parameter, type );
8460}
8461
8462QString QgsProcessingFolderDestinationWidgetWrapper::modelerExpressionFormatString() const
8463{
8464 return tr( "path to folder destination" );
8465}
8466
8467//
8468// QgsProcessingVectorTileDestinationWidgetWrapper
8469//
8470
8471QgsProcessingVectorTileDestinationWidgetWrapper::QgsProcessingVectorTileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
8472 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
8473{
8474}
8475
8476QString QgsProcessingVectorTileDestinationWidgetWrapper::parameterType() const
8477{
8479}
8480
8481QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorTileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
8482{
8483 return new QgsProcessingPointCloudDestinationWidgetWrapper( parameter, type );
8484}
8485
8486QString QgsProcessingVectorTileDestinationWidgetWrapper::modelerExpressionFormatString() const
8487{
8488 return tr( "path to layer destination" );
8489}
8490
@ Standard
Unit is a standard measurement unit.
ProcessingSourceType
Processing data source types.
Definition qgis.h:3000
@ 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:3219
@ File
Parameter is a single file.
@ Folder
Parameter is a folder.
ExpressionType
Expression types.
Definition qgis.h:4701
@ RasterCalculator
Raster calculator expression (since QGIS 3.34)
@ Qgis
Native QGIS expression.
@ PointCloud
Point cloud expression.
DistanceUnit
Units of distance.
Definition qgis.h:4363
@ 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:3247
@ 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:4470
@ 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:3208
ProcessingModelChildParameterSource
Processing model child parameter sources.
Definition qgis.h:3278
@ 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:3265
ProcessingNumberParameterType
Processing numeric parameter data types.
Definition qgis.h:3233
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.
A QgsFilterLineEdit subclass with the ability to "highlight" the edges of the widget.
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:5506
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5465
const QgsCoordinateReferenceSystem & crs
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.