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