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