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
18 #include "qgsprocessingwidgetwrapperimpl.h"
19 #include "qgsprocessingparameters.h"
20 #include "processing/models/qgsprocessingmodelalgorithm.h"
21 #include "qgsprocessingoutputs.h"
22 #include "qgsprojectionselectionwidget.h"
23 #include "qgsprocessingmatrixparameterdialog.h"
24 #include "qgsspinbox.h"
25 #include "qgsdoublespinbox.h"
26 #include "qgsprocessingcontext.h"
27 #include "qgsauthconfigselect.h"
28 #include "qgsapplication.h"
29 #include "qgsfilewidget.h"
30 #include "qgssettings.h"
31 #include "qgsexpressionlineedit.h"
32 #include "qgsfieldexpressionwidget.h"
33 #include "qgsexpressionbuilderwidget.h"
34 #include "qgsprocessingmultipleselectiondialog.h"
35 #include "qgslayoutmanager.h"
36 #include "qgsproject.h"
37 #include "qgslayoutcombobox.h"
38 #include "qgslayoutitemcombobox.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"
47 #include "qgscoordinateoperationwidget.h"
48 #include "qgsdatumtransformdialog.h"
49 #include "qgsfieldcombobox.h"
50 #include "qgsmapthemecollection.h"
51 #include "qgsdatetimeedit.h"
52 #include "qgsproviderconnectioncombobox.h"
53 #include "qgsdatabaseschemacombobox.h"
54 #include "qgsdatabasetablecombobox.h"
55 #include "qgsextentwidget.h"
56 #include "qgsprocessingenummodelerwidget.h"
57 #include "qgsprocessingmatrixmodelerwidget.h"
58 #include "qgsprocessingmaplayercombobox.h"
59 #include "qgsrasterbandcombobox.h"
60 #include "qgsprocessingoutputdestinationwidget.h"
61 #include "qgscheckablecombobox.h"
62 #include "qgsexpressioncontext.h"
63 #include "qgsexpressioncontextutils.h"
64 #include "qgsdoublevalidator.h"
65 #include "qgsmaplayercombobox.h"
66 #include "qgsannotationlayer.h"
67 #include <QToolButton>
68 #include <QLabel>
69 #include <QHBoxLayout>
70 #include <QVBoxLayout>
71 #include <QCheckBox>
72 #include <QComboBox>
73 #include <QLineEdit>
74 #include <QPlainTextEdit>
75 #include <QRadioButton>
76 #include <QButtonGroup>
77 #include <QMenu>
78 #include <QFileDialog>
79
80 ///@cond PRIVATE
81
82 //
83 // QgsProcessingBooleanWidgetWrapper
84 //
85
86
QgsProcessingBooleanParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)87 QgsProcessingBooleanParameterDefinitionWidget::QgsProcessingBooleanParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
88 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
89 {
90 QVBoxLayout *vlayout = new QVBoxLayout();
91 vlayout->setContentsMargins( 0, 0, 0, 0 );
92
93 mDefaultCheckBox = new QCheckBox( tr( "Checked" ) );
94 if ( const QgsProcessingParameterBoolean *boolParam = dynamic_cast<const QgsProcessingParameterBoolean *>( definition ) )
95 mDefaultCheckBox->setChecked( QgsProcessingParameters::parameterAsBool( boolParam, boolParam->defaultValueForGui(), context ) );
96 else
97 mDefaultCheckBox->setChecked( false );
98 vlayout->addWidget( mDefaultCheckBox );
99 setLayout( vlayout );
100 }
101
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const102 QgsProcessingParameterDefinition *QgsProcessingBooleanParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
103 {
104 auto param = std::make_unique< QgsProcessingParameterBoolean >( name, description, mDefaultCheckBox->isChecked() );
105 param->setFlags( flags );
106 return param.release();
107 }
108
109
QgsProcessingBooleanWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)110 QgsProcessingBooleanWidgetWrapper::QgsProcessingBooleanWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
111 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
112 {
113
114 }
115
createWidget()116 QWidget *QgsProcessingBooleanWidgetWrapper::createWidget()
117 {
118 switch ( type() )
119 {
120 case QgsProcessingGui::Standard:
121 {
122 QString description = parameterDefinition()->description();
123 if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
124 description = QObject::tr( "%1 [optional]" ).arg( description );
125
126 mCheckBox = new QCheckBox( description );
127 mCheckBox->setToolTip( parameterDefinition()->toolTip() );
128
129 connect( mCheckBox, &QCheckBox::toggled, this, [ = ]
130 {
131 emit widgetValueHasChanged( this );
132 } );
133 return mCheckBox;
134 }
135
136 case QgsProcessingGui::Batch:
137 case QgsProcessingGui::Modeler:
138 {
139 mComboBox = new QComboBox();
140 mComboBox->addItem( tr( "Yes" ), true );
141 mComboBox->addItem( tr( "No" ), false );
142 mComboBox->setToolTip( parameterDefinition()->toolTip() );
143
144 connect( mComboBox, qOverload< int>( &QComboBox::currentIndexChanged ), this, [ = ]
145 {
146 emit widgetValueHasChanged( this );
147 } );
148
149 return mComboBox;
150 }
151 }
152 return nullptr;
153 }
154
createLabel()155 QLabel *QgsProcessingBooleanWidgetWrapper::createLabel()
156 {
157 // avoid creating labels in standard dialogs
158 if ( type() == QgsProcessingGui::Standard )
159 return nullptr;
160 else
161 return QgsAbstractProcessingParameterWidgetWrapper::createLabel();
162 }
163
setWidgetValue(const QVariant & value,QgsProcessingContext & context)164 void QgsProcessingBooleanWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
165 {
166 switch ( type() )
167 {
168 case QgsProcessingGui::Standard:
169 {
170 const bool v = QgsProcessingParameters::parameterAsBool( parameterDefinition(), value, context );
171 mCheckBox->setChecked( v );
172 break;
173 }
174
175 case QgsProcessingGui::Batch:
176 case QgsProcessingGui::Modeler:
177 {
178 const bool v = QgsProcessingParameters::parameterAsBool( parameterDefinition(), value, context );
179 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
180 break;
181 }
182 }
183 }
184
widgetValue() const185 QVariant QgsProcessingBooleanWidgetWrapper::widgetValue() const
186 {
187 switch ( type() )
188 {
189 case QgsProcessingGui::Standard:
190 return mCheckBox->isChecked();
191
192 case QgsProcessingGui::Batch:
193 case QgsProcessingGui::Modeler:
194 return mComboBox->currentData();
195 }
196 return QVariant();
197 }
198
compatibleParameterTypes() const199 QStringList QgsProcessingBooleanWidgetWrapper::compatibleParameterTypes() const
200 {
201 //pretty much everything is compatible here and can be converted to a bool!
202 return QStringList() << QgsProcessingParameterBoolean::typeName()
203 << QgsProcessingParameterString::typeName()
204 << QgsProcessingParameterNumber::typeName()
205 << QgsProcessingParameterDistance::typeName()
206 << QgsProcessingParameterDuration::typeName()
207 << QgsProcessingParameterScale::typeName()
208 << QgsProcessingParameterFile::typeName()
209 << QgsProcessingParameterField::typeName()
210 << QgsProcessingParameterFeatureSource::typeName()
211 << QgsProcessingParameterMapLayer::typeName()
212 << QgsProcessingParameterRasterLayer::typeName()
213 << QgsProcessingParameterVectorLayer::typeName()
214 << QgsProcessingParameterMeshLayer::typeName()
215 << QgsProcessingParameterExpression::typeName()
216 << QgsProcessingParameterProviderConnection::typeName()
217 << QgsProcessingParameterPointCloudLayer::typeName()
218 << QgsProcessingParameterAnnotationLayer::typeName();
219 }
220
compatibleOutputTypes() const221 QStringList QgsProcessingBooleanWidgetWrapper::compatibleOutputTypes() const
222 {
223 return QStringList() << QgsProcessingOutputNumber::typeName()
224 << QgsProcessingOutputMapLayer::typeName()
225 << QgsProcessingOutputFile::typeName()
226 << QgsProcessingOutputRasterLayer::typeName()
227 << QgsProcessingOutputVectorLayer::typeName()
228 << QgsProcessingOutputString::typeName()
229 << QgsProcessingOutputBoolean::typeName();
230 }
231
parameterType() const232 QString QgsProcessingBooleanWidgetWrapper::parameterType() const
233 {
234 return QgsProcessingParameterBoolean::typeName();
235 }
236
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)237 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBooleanWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
238 {
239 return new QgsProcessingBooleanWidgetWrapper( parameter, type );
240 }
241
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)242 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBooleanWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
243 {
244 return new QgsProcessingBooleanParameterDefinitionWidget( context, widgetContext, definition, algorithm );
245 }
246
247
248 //
249 // QgsProcessingCrsWidgetWrapper
250 //
251
QgsProcessingCrsParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)252 QgsProcessingCrsParameterDefinitionWidget::QgsProcessingCrsParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
253 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
254 {
255 QVBoxLayout *vlayout = new QVBoxLayout();
256 vlayout->setContentsMargins( 0, 0, 0, 0 );
257
258 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
259
260 mCrsSelector = new QgsProjectionSelectionWidget();
261
262 // possibly we should expose this for parameter by parameter control
263 mCrsSelector->setShowAccuracyWarnings( true );
264
265 if ( const QgsProcessingParameterCrs *crsParam = dynamic_cast<const QgsProcessingParameterCrs *>( definition ) )
266 mCrsSelector->setCrs( QgsProcessingParameters::parameterAsCrs( crsParam, crsParam->defaultValueForGui(), context ) );
267 else
268 mCrsSelector->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
269
270 vlayout->addWidget( mCrsSelector );
271 setLayout( vlayout );
272 }
273
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const274 QgsProcessingParameterDefinition *QgsProcessingCrsParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
275 {
276 auto param = std::make_unique< QgsProcessingParameterCrs >( name, description, mCrsSelector->crs().authid() );
277 param->setFlags( flags );
278 return param.release();
279 }
280
QgsProcessingCrsWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)281 QgsProcessingCrsWidgetWrapper::QgsProcessingCrsWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
282 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
283 {
284
285 }
286
createWidget()287 QWidget *QgsProcessingCrsWidgetWrapper::createWidget()
288 {
289 Q_ASSERT( mProjectionSelectionWidget == nullptr );
290 mProjectionSelectionWidget = new QgsProjectionSelectionWidget();
291 mProjectionSelectionWidget->setToolTip( parameterDefinition()->toolTip() );
292
293 if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
294 mProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
295 else
296 mProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, false );
297
298 connect( mProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, [ = ]
299 {
300 emit widgetValueHasChanged( this );
301 } );
302
303 switch ( type() )
304 {
305 case QgsProcessingGui::Standard:
306 case QgsProcessingGui::Batch:
307 {
308 return mProjectionSelectionWidget;
309 }
310
311 case QgsProcessingGui::Modeler:
312 {
313 QWidget *w = new QWidget();
314 w->setToolTip( parameterDefinition()->toolTip() );
315
316 QVBoxLayout *vl = new QVBoxLayout();
317 vl->setContentsMargins( 0, 0, 0, 0 );
318 w->setLayout( vl );
319
320 mUseProjectCrsCheckBox = new QCheckBox( tr( "Use project CRS" ) );
321 mUseProjectCrsCheckBox->setToolTip( tr( "Always use the current project CRS when running the model" ) );
322 vl->addWidget( mUseProjectCrsCheckBox );
323 connect( mUseProjectCrsCheckBox, &QCheckBox::toggled, mProjectionSelectionWidget, &QgsProjectionSelectionWidget::setDisabled );
324 connect( mUseProjectCrsCheckBox, &QCheckBox::toggled, this, [ = ]
325 {
326 emit widgetValueHasChanged( this );
327 } );
328
329 vl->addWidget( mProjectionSelectionWidget );
330
331 return w;
332 }
333 }
334 return nullptr;
335 }
336
setWidgetValue(const QVariant & value,QgsProcessingContext & context)337 void QgsProcessingCrsWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
338 {
339 if ( mUseProjectCrsCheckBox )
340 {
341 if ( value.toString().compare( QLatin1String( "ProjectCrs" ), Qt::CaseInsensitive ) == 0 )
342 {
343 mUseProjectCrsCheckBox->setChecked( true );
344 return;
345 }
346 else
347 {
348 mUseProjectCrsCheckBox->setChecked( false );
349 }
350 }
351
352 const QgsCoordinateReferenceSystem v = QgsProcessingParameters::parameterAsCrs( parameterDefinition(), value, context );
353 if ( mProjectionSelectionWidget )
354 mProjectionSelectionWidget->setCrs( v );
355 }
356
widgetValue() const357 QVariant QgsProcessingCrsWidgetWrapper::widgetValue() const
358 {
359 if ( mUseProjectCrsCheckBox && mUseProjectCrsCheckBox->isChecked() )
360 return QStringLiteral( "ProjectCrs" );
361 else if ( mProjectionSelectionWidget )
362 return mProjectionSelectionWidget->crs().isValid() ? mProjectionSelectionWidget->crs() : QVariant();
363 else
364 return QVariant();
365 }
366
compatibleParameterTypes() const367 QStringList QgsProcessingCrsWidgetWrapper::compatibleParameterTypes() const
368 {
369 return QStringList()
370 << QgsProcessingParameterCrs::typeName()
371 << QgsProcessingParameterExpression::typeName()
372 << QgsProcessingParameterString::typeName()
373 << QgsProcessingParameterRasterLayer::typeName()
374 << QgsProcessingParameterVectorLayer::typeName()
375 << QgsProcessingParameterMeshLayer::typeName()
376 << QgsProcessingParameterFeatureSource::typeName()
377 << QgsProcessingParameterPointCloudLayer::typeName()
378 << QgsProcessingParameterAnnotationLayer::typeName();
379 }
380
compatibleOutputTypes() const381 QStringList QgsProcessingCrsWidgetWrapper::compatibleOutputTypes() const
382 {
383 return QStringList() << QgsProcessingOutputVectorLayer::typeName()
384 << QgsProcessingOutputRasterLayer::typeName()
385 << QgsProcessingOutputMapLayer::typeName()
386 << QgsProcessingOutputString::typeName();
387 }
388
modelerExpressionFormatString() const389 QString QgsProcessingCrsWidgetWrapper::modelerExpressionFormatString() const
390 {
391 return tr( "string as EPSG code, WKT or PROJ format, or a string identifying a map layer" );
392 }
393
parameterType() const394 QString QgsProcessingCrsWidgetWrapper::parameterType() const
395 {
396 return QgsProcessingParameterCrs::typeName();
397 }
398
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)399 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCrsWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
400 {
401 return new QgsProcessingCrsWidgetWrapper( parameter, type );
402 }
403
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)404 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCrsWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
405 {
406 return new QgsProcessingCrsParameterDefinitionWidget( context, widgetContext, definition, algorithm );
407 }
408
409
410
411 //
412 // QgsProcessingStringWidgetWrapper
413 //
414
415
QgsProcessingStringParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)416 QgsProcessingStringParameterDefinitionWidget::QgsProcessingStringParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
417 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
418 {
419 QVBoxLayout *vlayout = new QVBoxLayout();
420 vlayout->setContentsMargins( 0, 0, 0, 0 );
421
422 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
423
424 mDefaultLineEdit = new QLineEdit();
425 if ( const QgsProcessingParameterString *stringParam = dynamic_cast<const QgsProcessingParameterString *>( definition ) )
426 mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( stringParam, stringParam->defaultValueForGui(), context ) );
427 vlayout->addWidget( mDefaultLineEdit );
428
429 mMultiLineCheckBox = new QCheckBox( tr( "Multiline input" ) );
430 if ( const QgsProcessingParameterString *stringParam = dynamic_cast<const QgsProcessingParameterString *>( definition ) )
431 mMultiLineCheckBox->setChecked( stringParam->multiLine() );
432 vlayout->addWidget( mMultiLineCheckBox );
433
434 setLayout( vlayout );
435 }
436
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const437 QgsProcessingParameterDefinition *QgsProcessingStringParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
438 {
439 auto param = std::make_unique< QgsProcessingParameterString >( name, description, mDefaultLineEdit->text(), mMultiLineCheckBox->isChecked() );
440 param->setFlags( flags );
441 return param.release();
442 }
443
444
445
QgsProcessingStringWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)446 QgsProcessingStringWidgetWrapper::QgsProcessingStringWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
447 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
448 {
449
450 }
451
createWidget()452 QWidget *QgsProcessingStringWidgetWrapper::createWidget()
453 {
454 const QVariantMap metadata = parameterDefinition()->metadata();
455 const QVariant valueHintsVariant = metadata.value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "value_hints" ) );
456
457 if ( valueHintsVariant.isValid() )
458 {
459 const QVariantList valueList = valueHintsVariant.toList();
460 mComboBox = new QComboBox();
461 mComboBox->setToolTip( parameterDefinition()->toolTip() );
462
463 if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
464 {
465 mComboBox->addItem( QString() );
466 }
467 for ( const QVariant &entry : valueList )
468 {
469 mComboBox->addItem( entry.toString(), entry.toString() );
470 }
471 mComboBox->setCurrentIndex( 0 );
472
473 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
474 {
475 emit widgetValueHasChanged( this );
476 } );
477 return mComboBox;
478 }
479 else
480 {
481 switch ( type() )
482 {
483 case QgsProcessingGui::Standard:
484 case QgsProcessingGui::Modeler:
485 {
486 if ( static_cast< const QgsProcessingParameterString * >( parameterDefinition() )->multiLine() )
487 {
488 mPlainTextEdit = new QPlainTextEdit();
489 mPlainTextEdit->setToolTip( parameterDefinition()->toolTip() );
490
491 connect( mPlainTextEdit, &QPlainTextEdit::textChanged, this, [ = ]
492 {
493 emit widgetValueHasChanged( this );
494 } );
495 return mPlainTextEdit;
496 }
497 else
498 {
499 mLineEdit = new QLineEdit();
500 mLineEdit->setToolTip( parameterDefinition()->toolTip() );
501
502 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
503 {
504 emit widgetValueHasChanged( this );
505 } );
506 return mLineEdit;
507 }
508 }
509
510 case QgsProcessingGui::Batch:
511 {
512 mLineEdit = new QLineEdit();
513 mLineEdit->setToolTip( parameterDefinition()->toolTip() );
514
515 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
516 {
517 emit widgetValueHasChanged( this );
518 } );
519 return mLineEdit;
520 }
521 }
522 }
523
524 return nullptr;
525 }
526
setWidgetValue(const QVariant & value,QgsProcessingContext & context)527 void QgsProcessingStringWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
528 {
529 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
530 if ( mLineEdit )
531 mLineEdit->setText( v );
532 if ( mPlainTextEdit )
533 mPlainTextEdit->setPlainText( v );
534 if ( mComboBox )
535 {
536 int index = -1;
537 if ( !value.isValid() )
538 index = mComboBox->findData( QVariant() );
539 else
540 index = mComboBox->findData( v );
541
542 if ( index >= 0 )
543 mComboBox->setCurrentIndex( index );
544 else
545 mComboBox->setCurrentIndex( 0 );
546 }
547 }
548
widgetValue() const549 QVariant QgsProcessingStringWidgetWrapper::widgetValue() const
550 {
551 if ( mLineEdit )
552 return mLineEdit->text();
553 else if ( mPlainTextEdit )
554 return mPlainTextEdit->toPlainText();
555 else if ( mComboBox )
556 return mComboBox->currentData();
557 else
558 return QVariant();
559 }
560
compatibleParameterTypes() const561 QStringList QgsProcessingStringWidgetWrapper::compatibleParameterTypes() const
562 {
563 return QStringList()
564 << QgsProcessingParameterString::typeName()
565 << QgsProcessingParameterAuthConfig::typeName()
566 << QgsProcessingParameterNumber::typeName()
567 << QgsProcessingParameterDistance::typeName()
568 << QgsProcessingParameterDuration::typeName()
569 << QgsProcessingParameterScale::typeName()
570 << QgsProcessingParameterFile::typeName()
571 << QgsProcessingParameterField::typeName()
572 << QgsProcessingParameterExpression::typeName()
573 << QgsProcessingParameterCoordinateOperation::typeName()
574 << QgsProcessingParameterProviderConnection::typeName();
575 }
576
compatibleOutputTypes() const577 QStringList QgsProcessingStringWidgetWrapper::compatibleOutputTypes() const
578 {
579 return QStringList() << QgsProcessingOutputNumber::typeName()
580 << QgsProcessingOutputFile::typeName()
581 << QgsProcessingOutputFolder::typeName()
582 << QgsProcessingOutputString::typeName();
583 }
584
parameterType() const585 QString QgsProcessingStringWidgetWrapper::parameterType() const
586 {
587 return QgsProcessingParameterString::typeName();
588 }
589
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)590 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingStringWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
591 {
592 return new QgsProcessingStringWidgetWrapper( parameter, type );
593 }
594
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)595 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingStringWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
596 {
597 return new QgsProcessingStringParameterDefinitionWidget( context, widgetContext, definition, algorithm );
598 }
599
600
601
602 //
603 // QgsProcessingAuthConfigWidgetWrapper
604 //
605
QgsProcessingAuthConfigWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)606 QgsProcessingAuthConfigWidgetWrapper::QgsProcessingAuthConfigWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
607 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
608 {
609
610 }
611
createWidget()612 QWidget *QgsProcessingAuthConfigWidgetWrapper::createWidget()
613 {
614 switch ( type() )
615 {
616 case QgsProcessingGui::Standard:
617 case QgsProcessingGui::Modeler:
618 case QgsProcessingGui::Batch:
619 {
620 mAuthConfigSelect = new QgsAuthConfigSelect();
621 mAuthConfigSelect->setToolTip( parameterDefinition()->toolTip() );
622
623 connect( mAuthConfigSelect, &QgsAuthConfigSelect::selectedConfigIdChanged, this, [ = ]
624 {
625 emit widgetValueHasChanged( this );
626 } );
627 return mAuthConfigSelect;
628 }
629 }
630 return nullptr;
631 }
632
setWidgetValue(const QVariant & value,QgsProcessingContext & context)633 void QgsProcessingAuthConfigWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
634 {
635 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
636 if ( mAuthConfigSelect )
637 mAuthConfigSelect->setConfigId( v );
638 }
639
widgetValue() const640 QVariant QgsProcessingAuthConfigWidgetWrapper::widgetValue() const
641 {
642 if ( mAuthConfigSelect )
643 return mAuthConfigSelect->configId();
644 else
645 return QVariant();
646 }
647
compatibleParameterTypes() const648 QStringList QgsProcessingAuthConfigWidgetWrapper::compatibleParameterTypes() const
649 {
650 return QStringList()
651 << QgsProcessingParameterAuthConfig::typeName()
652 << QgsProcessingParameterString::typeName()
653 << QgsProcessingParameterExpression::typeName();
654 }
655
compatibleOutputTypes() const656 QStringList QgsProcessingAuthConfigWidgetWrapper::compatibleOutputTypes() const
657 {
658 return QStringList() << QgsProcessingOutputString::typeName();
659 }
660
parameterType() const661 QString QgsProcessingAuthConfigWidgetWrapper::parameterType() const
662 {
663 return QgsProcessingParameterAuthConfig::typeName();
664 }
665
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)666 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAuthConfigWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
667 {
668 return new QgsProcessingAuthConfigWidgetWrapper( parameter, type );
669 }
670
671 //
672 // QgsProcessingNumericWidgetWrapper
673 //
674
QgsProcessingNumberParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)675 QgsProcessingNumberParameterDefinitionWidget::QgsProcessingNumberParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
676 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
677 {
678 QVBoxLayout *vlayout = new QVBoxLayout();
679 vlayout->setContentsMargins( 0, 0, 0, 0 );
680
681 vlayout->addWidget( new QLabel( tr( "Number type" ) ) );
682
683 mTypeComboBox = new QComboBox();
684 mTypeComboBox->addItem( tr( "Float" ), QgsProcessingParameterNumber::Double );
685 mTypeComboBox->addItem( tr( "Integer" ), QgsProcessingParameterNumber::Integer );
686 vlayout->addWidget( mTypeComboBox );
687
688 vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
689 mMinLineEdit = new QLineEdit();
690 vlayout->addWidget( mMinLineEdit );
691
692 vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
693 mMaxLineEdit = new QLineEdit();
694 vlayout->addWidget( mMaxLineEdit );
695
696 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
697 mDefaultLineEdit = new QLineEdit();
698 vlayout->addWidget( mDefaultLineEdit );
699
700 if ( const QgsProcessingParameterNumber *numberParam = dynamic_cast<const QgsProcessingParameterNumber *>( definition ) )
701 {
702 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( numberParam->dataType() ) );
703 mMinLineEdit->setText( QLocale().toString( numberParam->minimum() ) );
704 mMaxLineEdit->setText( QLocale().toString( numberParam->maximum() ) );
705 mDefaultLineEdit->setText( numberParam->defaultValueForGui().toString() );
706 }
707
708 setLayout( vlayout );
709 }
710
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const711 QgsProcessingParameterDefinition *QgsProcessingNumberParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
712 {
713 bool ok;
714 double val = QgsDoubleValidator::toDouble( mDefaultLineEdit->text(), &ok );
715
716 QgsProcessingParameterNumber::Type dataType = static_cast< QgsProcessingParameterNumber::Type >( mTypeComboBox->currentData().toInt() );
717 auto param = std::make_unique< QgsProcessingParameterNumber >( name, description, dataType, ok ? val : QVariant() );
718
719 val = QgsDoubleValidator::toDouble( mMinLineEdit->text( ), &ok );
720 if ( ok )
721 {
722 param->setMinimum( val );
723 }
724
725 val = QgsDoubleValidator::toDouble( mMaxLineEdit->text(), &ok );
726 if ( ok )
727 {
728 param->setMaximum( val );
729 }
730
731 param->setFlags( flags );
732 return param.release();
733 }
734
QgsProcessingNumericWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)735 QgsProcessingNumericWidgetWrapper::QgsProcessingNumericWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
736 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
737 {
738
739 }
740
createWidget()741 QWidget *QgsProcessingNumericWidgetWrapper::createWidget()
742 {
743 const QgsProcessingParameterNumber *numberDef = static_cast< const QgsProcessingParameterNumber * >( parameterDefinition() );
744 const QVariantMap metadata = numberDef->metadata();
745 const int decimals = metadata.value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "decimals" ), 6 ).toInt();
746 switch ( type() )
747 {
748 case QgsProcessingGui::Standard:
749 case QgsProcessingGui::Modeler:
750 case QgsProcessingGui::Batch:
751 {
752 // lots of duplicate code here -- but there's no common interface between QSpinBox/QDoubleSpinBox which would allow us to avoid this
753 QAbstractSpinBox *spinBox = nullptr;
754 switch ( numberDef->dataType() )
755 {
756 case QgsProcessingParameterNumber::Double:
757 mDoubleSpinBox = new QgsDoubleSpinBox();
758 mDoubleSpinBox->setExpressionsEnabled( true );
759 mDoubleSpinBox->setDecimals( decimals );
760
761 // guess reasonable step value for double spin boxes
762 if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) &&
763 !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() + 1 ) )
764 {
765 double singleStep = calculateStep( numberDef->minimum(), numberDef->maximum() );
766 singleStep = std::max( singleStep, std::pow( 10, -decimals ) );
767 mDoubleSpinBox->setSingleStep( singleStep );
768 }
769
770 spinBox = mDoubleSpinBox;
771 break;
772
773 case QgsProcessingParameterNumber::Integer:
774 mSpinBox = new QgsSpinBox();
775 mSpinBox->setExpressionsEnabled( true );
776 spinBox = mSpinBox;
777 break;
778 }
779 spinBox->setToolTip( parameterDefinition()->toolTip() );
780
781 double max = 999999999;
782 if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) )
783 {
784 max = numberDef->maximum();
785 }
786 double min = -999999999;
787 if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) )
788 {
789 min = numberDef->minimum();
790 }
791 if ( mDoubleSpinBox )
792 {
793 mDoubleSpinBox->setMinimum( min );
794 mDoubleSpinBox->setMaximum( max );
795 }
796 else
797 {
798 mSpinBox->setMinimum( static_cast< int >( min ) );
799 mSpinBox->setMaximum( static_cast< int >( max ) );
800 }
801
802 if ( numberDef->flags() & QgsProcessingParameterDefinition::FlagOptional )
803 {
804 mAllowingNull = true;
805 if ( mDoubleSpinBox )
806 {
807 mDoubleSpinBox->setShowClearButton( true );
808 const double min = mDoubleSpinBox->minimum() - 1;
809 mDoubleSpinBox->setMinimum( min );
810 mDoubleSpinBox->setValue( min );
811 }
812 else
813 {
814 mSpinBox->setShowClearButton( true );
815 const int min = mSpinBox->minimum() - 1;
816 mSpinBox->setMinimum( min );
817 mSpinBox->setValue( min );
818 }
819 spinBox->setSpecialValueText( tr( "Not set" ) );
820 }
821 else
822 {
823 if ( numberDef->defaultValueForGui().isValid() )
824 {
825 // if default value for parameter, we clear to that
826 bool ok = false;
827 if ( mDoubleSpinBox )
828 {
829 double defaultVal = numberDef->defaultValueForGui().toDouble( &ok );
830 if ( ok )
831 mDoubleSpinBox->setClearValue( defaultVal );
832 }
833 else
834 {
835 int intVal = numberDef->defaultValueForGui().toInt( &ok );
836 if ( ok )
837 mSpinBox->setClearValue( intVal );
838 }
839 }
840 else if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) )
841 {
842 // otherwise we clear to the minimum, if it's set
843 if ( mDoubleSpinBox )
844 mDoubleSpinBox->setClearValue( numberDef->minimum() );
845 else
846 mSpinBox->setClearValue( static_cast< int >( numberDef->minimum() ) );
847 }
848 else
849 {
850 // last resort, we clear to 0
851 if ( mDoubleSpinBox )
852 {
853 mDoubleSpinBox->setValue( 0 );
854 mDoubleSpinBox->setClearValue( 0 );
855 }
856 else
857 {
858 mSpinBox->setValue( 0 );
859 mSpinBox->setClearValue( 0 );
860 }
861 }
862 }
863
864 if ( mDoubleSpinBox )
865 connect( mDoubleSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );
866 else if ( mSpinBox )
867 connect( mSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );
868
869 return spinBox;
870 }
871 }
872 return nullptr;
873 }
874
setWidgetValue(const QVariant & value,QgsProcessingContext & context)875 void QgsProcessingNumericWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
876 {
877 if ( mDoubleSpinBox )
878 {
879 if ( mAllowingNull && !value.isValid() )
880 mDoubleSpinBox->clear();
881 else
882 {
883 const double v = QgsProcessingParameters::parameterAsDouble( parameterDefinition(), value, context );
884 mDoubleSpinBox->setValue( v );
885 }
886 }
887 else if ( mSpinBox )
888 {
889 if ( mAllowingNull && !value.isValid() )
890 mSpinBox->clear();
891 else
892 {
893 const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
894 mSpinBox->setValue( v );
895 }
896 }
897 }
898
widgetValue() const899 QVariant QgsProcessingNumericWidgetWrapper::widgetValue() const
900 {
901 if ( mDoubleSpinBox )
902 {
903 if ( mAllowingNull && qgsDoubleNear( mDoubleSpinBox->value(), mDoubleSpinBox->minimum() ) )
904 return QVariant();
905 else
906 return mDoubleSpinBox->value();
907 }
908 else if ( mSpinBox )
909 {
910 if ( mAllowingNull && mSpinBox->value() == mSpinBox->minimum() )
911 return QVariant();
912 else
913 return mSpinBox->value();
914 }
915 else
916 return QVariant();
917 }
918
compatibleParameterTypes() const919 QStringList QgsProcessingNumericWidgetWrapper::compatibleParameterTypes() const
920 {
921 return QStringList()
922 << QgsProcessingParameterString::typeName()
923 << QgsProcessingParameterNumber::typeName()
924 << QgsProcessingParameterDistance::typeName()
925 << QgsProcessingParameterDuration::typeName()
926 << QgsProcessingParameterScale::typeName();
927 }
928
compatibleOutputTypes() const929 QStringList QgsProcessingNumericWidgetWrapper::compatibleOutputTypes() const
930 {
931 return QStringList() << QgsProcessingOutputNumber::typeName()
932 << QgsProcessingOutputString::typeName();
933 }
934
calculateStep(const double minimum,const double maximum)935 double QgsProcessingNumericWidgetWrapper::calculateStep( const double minimum, const double maximum )
936 {
937 const double valueRange = maximum - minimum;
938 if ( valueRange <= 1.0 )
939 {
940 const double step = valueRange / 10.0;
941 // round to 1 significant figure
942 return qgsRound( step, -std::floor( std::log( step ) ) );
943 }
944 else
945 {
946 return 1.0;
947 }
948 }
949
parameterType() const950 QString QgsProcessingNumericWidgetWrapper::parameterType() const
951 {
952 return QgsProcessingParameterNumber::typeName();
953 }
954
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)955 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingNumericWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
956 {
957 return new QgsProcessingNumericWidgetWrapper( parameter, type );
958 }
959
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)960 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingNumericWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
961 {
962 return new QgsProcessingNumberParameterDefinitionWidget( context, widgetContext, definition, algorithm );
963 }
964
965 //
966 // QgsProcessingDistanceWidgetWrapper
967 //
968
QgsProcessingDistanceParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)969 QgsProcessingDistanceParameterDefinitionWidget::QgsProcessingDistanceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
970 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
971 {
972 QVBoxLayout *vlayout = new QVBoxLayout();
973 vlayout->setContentsMargins( 0, 0, 0, 0 );
974
975 vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
976
977 mParentLayerComboBox = new QComboBox();
978
979 QString initialParent;
980 if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
981 initialParent = distParam->parentParameterName();
982
983 if ( auto *lModel = widgetContext.model() )
984 {
985 // populate combo box with other model input choices
986 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
987 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
988 {
989 if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
990 {
991 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
992 if ( !initialParent.isEmpty() && initialParent == definition->name() )
993 {
994 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
995 }
996 }
997 else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
998 {
999 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
1000 if ( !initialParent.isEmpty() && initialParent == definition->name() )
1001 {
1002 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1003 }
1004 }
1005 else if ( const QgsProcessingParameterMapLayer *definition = dynamic_cast< const QgsProcessingParameterMapLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
1006 {
1007 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
1008 if ( !initialParent.isEmpty() && initialParent == definition->name() )
1009 {
1010 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1011 }
1012 }
1013 else if ( const QgsProcessingParameterCrs *definition = dynamic_cast< const QgsProcessingParameterCrs * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
1014 {
1015 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
1016 if ( !initialParent.isEmpty() && initialParent == definition->name() )
1017 {
1018 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1019 }
1020 }
1021 }
1022 }
1023
1024 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
1025 {
1026 // if no parent candidates found, we just add the existing one as a placeholder
1027 mParentLayerComboBox->addItem( initialParent, initialParent );
1028 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
1029 }
1030
1031 vlayout->addWidget( mParentLayerComboBox );
1032
1033 vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
1034 mMinLineEdit = new QLineEdit();
1035 vlayout->addWidget( mMinLineEdit );
1036
1037 vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
1038 mMaxLineEdit = new QLineEdit();
1039 vlayout->addWidget( mMaxLineEdit );
1040
1041 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1042 mDefaultLineEdit = new QLineEdit();
1043 vlayout->addWidget( mDefaultLineEdit );
1044
1045 if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
1046 {
1047 mMinLineEdit->setText( QLocale().toString( distParam->minimum() ) );
1048 mMaxLineEdit->setText( QLocale().toString( distParam->maximum() ) );
1049 mDefaultLineEdit->setText( distParam->defaultValueForGui().toString() );
1050 }
1051
1052 setLayout( vlayout );
1053 }
1054
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1055 QgsProcessingParameterDefinition *QgsProcessingDistanceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1056 {
1057 bool ok;
1058 double val = QgsDoubleValidator::toDouble( mDefaultLineEdit->text(), &ok );
1059
1060 auto param = std::make_unique< QgsProcessingParameterDistance >( name, description, ok ? val : QVariant(), mParentLayerComboBox->currentData().toString() );
1061
1062 val = QgsDoubleValidator::toDouble( mMinLineEdit->text(), &ok );
1063 if ( ok )
1064 {
1065 param->setMinimum( val );
1066 }
1067
1068 val = QgsDoubleValidator::toDouble( mMaxLineEdit->text(), &ok );
1069 if ( ok )
1070 {
1071 param->setMaximum( val );
1072 }
1073
1074 param->setFlags( flags );
1075 return param.release();
1076 }
1077
QgsProcessingDistanceWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1078 QgsProcessingDistanceWidgetWrapper::QgsProcessingDistanceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1079 : QgsProcessingNumericWidgetWrapper( parameter, type, parent )
1080 {
1081
1082 }
1083
parameterType() const1084 QString QgsProcessingDistanceWidgetWrapper::parameterType() const
1085 {
1086 return QgsProcessingParameterDistance::typeName();
1087 }
1088
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)1089 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDistanceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1090 {
1091 return new QgsProcessingDistanceWidgetWrapper( parameter, type );
1092 }
1093
createWidget()1094 QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
1095 {
1096 const QgsProcessingParameterDistance *distanceDef = static_cast< const QgsProcessingParameterDistance * >( parameterDefinition() );
1097
1098 QWidget *spin = QgsProcessingNumericWidgetWrapper::createWidget();
1099 switch ( type() )
1100 {
1101 case QgsProcessingGui::Standard:
1102 {
1103 mLabel = new QLabel();
1104 mUnitsCombo = new QComboBox();
1105
1106 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMeters ), QgsUnitTypes::DistanceMeters );
1107 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceKilometers ), QgsUnitTypes::DistanceKilometers );
1108 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceFeet ), QgsUnitTypes::DistanceFeet );
1109 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMiles ), QgsUnitTypes::DistanceMiles );
1110 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceYards ), QgsUnitTypes::DistanceYards );
1111
1112 const int labelMargin = static_cast< int >( std::round( mUnitsCombo->fontMetrics().horizontalAdvance( 'X' ) ) );
1113 QHBoxLayout *layout = new QHBoxLayout();
1114 layout->addWidget( spin, 1 );
1115 layout->insertSpacing( 1, labelMargin / 2 );
1116 layout->insertWidget( 2, mLabel );
1117 layout->insertWidget( 3, mUnitsCombo );
1118
1119 // bit of fiddlyness here -- we want the initial spacing to only be visible
1120 // when the warning label is shown, so it's embedded inside mWarningLabel
1121 // instead of outside it
1122 mWarningLabel = new QWidget();
1123 QHBoxLayout *warningLayout = new QHBoxLayout();
1124 warningLayout->setContentsMargins( 0, 0, 0, 0 );
1125 QLabel *warning = new QLabel();
1126 QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
1127 const int size = static_cast< int >( std::max( 24.0, spin->minimumSize().height() * 0.5 ) );
1128 warning->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
1129 warning->setToolTip( tr( "Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results." ) );
1130 warningLayout->insertSpacing( 0, labelMargin / 2 );
1131 warningLayout->insertWidget( 1, warning );
1132 mWarningLabel->setLayout( warningLayout );
1133 layout->insertWidget( 4, mWarningLabel );
1134
1135 QWidget *w = new QWidget();
1136 layout->setContentsMargins( 0, 0, 0, 0 );
1137 w->setLayout( layout );
1138
1139 setUnits( distanceDef->defaultUnit() );
1140
1141 return w;
1142 }
1143
1144 case QgsProcessingGui::Batch:
1145 case QgsProcessingGui::Modeler:
1146 return spin;
1147
1148 }
1149 return nullptr;
1150 }
1151
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)1152 void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
1153 {
1154 QgsProcessingNumericWidgetWrapper::postInitialize( wrappers );
1155 switch ( type() )
1156 {
1157 case QgsProcessingGui::Standard:
1158 {
1159 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
1160 {
1161 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDistance * >( parameterDefinition() )->parentParameterName() )
1162 {
1163 setUnitParameterValue( wrapper->parameterValue() );
1164 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
1165 {
1166 setUnitParameterValue( wrapper->parameterValue() );
1167 } );
1168 break;
1169 }
1170 }
1171 break;
1172 }
1173
1174 case QgsProcessingGui::Batch:
1175 case QgsProcessingGui::Modeler:
1176 break;
1177 }
1178 }
1179
setUnitParameterValue(const QVariant & value)1180 void QgsProcessingDistanceWidgetWrapper::setUnitParameterValue( const QVariant &value )
1181 {
1182 QgsUnitTypes::DistanceUnit units = QgsUnitTypes::DistanceUnknownUnit;
1183
1184 // evaluate value to layer
1185 QgsProcessingContext *context = nullptr;
1186 std::unique_ptr< QgsProcessingContext > tmpContext;
1187 if ( mProcessingContextGenerator )
1188 context = mProcessingContextGenerator->processingContext();
1189
1190 if ( !context )
1191 {
1192 tmpContext = std::make_unique< QgsProcessingContext >();
1193 context = tmpContext.get();
1194 }
1195
1196 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsCrs( parameterDefinition(), value, *context );
1197 if ( crs.isValid() )
1198 {
1199 units = crs.mapUnits();
1200 }
1201
1202 setUnits( units );
1203 }
1204
setUnits(const QgsUnitTypes::DistanceUnit units)1205 void QgsProcessingDistanceWidgetWrapper::setUnits( const QgsUnitTypes::DistanceUnit units )
1206 {
1207 mLabel->setText( QgsUnitTypes::toString( units ) );
1208 if ( QgsUnitTypes::unitType( units ) != QgsUnitTypes::Standard )
1209 {
1210 mUnitsCombo->hide();
1211 mLabel->show();
1212 }
1213 else
1214 {
1215 mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( units ) );
1216 mUnitsCombo->show();
1217 mLabel->hide();
1218 }
1219 mWarningLabel->setVisible( units == QgsUnitTypes::DistanceDegrees );
1220 mBaseUnit = units;
1221 }
1222
widgetValue() const1223 QVariant QgsProcessingDistanceWidgetWrapper::widgetValue() const
1224 {
1225 const QVariant val = QgsProcessingNumericWidgetWrapper::widgetValue();
1226 if ( val.type() == QVariant::Double && mUnitsCombo && mUnitsCombo->isVisible() )
1227 {
1228 QgsUnitTypes::DistanceUnit displayUnit = static_cast<QgsUnitTypes::DistanceUnit >( mUnitsCombo->currentData().toInt() );
1229 return val.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( displayUnit, mBaseUnit );
1230 }
1231 else
1232 {
1233 return val;
1234 }
1235 }
1236
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)1237 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDistanceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1238 {
1239 return new QgsProcessingDistanceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1240 }
1241
1242
1243 //
1244 // QgsProcessingDurationWidgetWrapper
1245 //
1246
QgsProcessingDurationParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)1247 QgsProcessingDurationParameterDefinitionWidget::QgsProcessingDurationParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1248 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1249 {
1250 QVBoxLayout *vlayout = new QVBoxLayout();
1251 vlayout->setContentsMargins( 0, 0, 0, 0 );
1252
1253 vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
1254 mMinLineEdit = new QLineEdit();
1255 vlayout->addWidget( mMinLineEdit );
1256
1257 vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
1258 mMaxLineEdit = new QLineEdit();
1259 vlayout->addWidget( mMaxLineEdit );
1260
1261 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1262 mDefaultLineEdit = new QLineEdit();
1263 vlayout->addWidget( mDefaultLineEdit );
1264
1265 vlayout->addWidget( new QLabel( tr( "Default unit type" ) ) );
1266
1267 mUnitsCombo = new QComboBox();
1268 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalMilliseconds ), QgsUnitTypes::TemporalMilliseconds );
1269 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalSeconds ), QgsUnitTypes::TemporalSeconds );
1270 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalMinutes ), QgsUnitTypes::TemporalMinutes );
1271 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalHours ), QgsUnitTypes::TemporalHours );
1272 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalDays ), QgsUnitTypes::TemporalDays );
1273 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalWeeks ), QgsUnitTypes::TemporalWeeks );
1274 mUnitsCombo->addItem( tr( "years (365.25 days)" ), QgsUnitTypes::TemporalYears );
1275 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalDecades ), QgsUnitTypes::TemporalDecades );
1276 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalCenturies ), QgsUnitTypes::TemporalCenturies );
1277 vlayout->addWidget( mUnitsCombo );
1278
1279 if ( const QgsProcessingParameterDuration *durationParam = dynamic_cast<const QgsProcessingParameterDuration *>( definition ) )
1280 {
1281 mMinLineEdit->setText( QLocale().toString( durationParam->minimum() ) );
1282 mMaxLineEdit->setText( QLocale().toString( durationParam->maximum() ) );
1283 mDefaultLineEdit->setText( durationParam->defaultValueForGui().toString() );
1284 mUnitsCombo->setCurrentIndex( durationParam->defaultUnit() );
1285 }
1286
1287 setLayout( vlayout );
1288 }
1289
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1290 QgsProcessingParameterDefinition *QgsProcessingDurationParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1291 {
1292 bool ok;
1293 double val = QgsDoubleValidator::toDouble( mDefaultLineEdit->text(), &ok );
1294
1295 auto param = std::make_unique< QgsProcessingParameterDuration >( name, description, ok ? val : QVariant() );
1296
1297 val = QgsDoubleValidator::toDouble( mMinLineEdit->text(), &ok );
1298 if ( ok )
1299 {
1300 param->setMinimum( val );
1301 }
1302
1303 val = QgsDoubleValidator::toDouble( mMaxLineEdit->text(), &ok );
1304 if ( ok )
1305 {
1306 param->setMaximum( val );
1307 }
1308
1309 param->setDefaultUnit( static_cast<QgsUnitTypes::TemporalUnit >( mUnitsCombo->currentData().toInt() ) );
1310
1311 param->setFlags( flags );
1312 return param.release();
1313 }
1314
QgsProcessingDurationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1315 QgsProcessingDurationWidgetWrapper::QgsProcessingDurationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1316 : QgsProcessingNumericWidgetWrapper( parameter, type, parent )
1317 {
1318
1319 }
1320
parameterType() const1321 QString QgsProcessingDurationWidgetWrapper::parameterType() const
1322 {
1323 return QgsProcessingParameterDuration::typeName();
1324 }
1325
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)1326 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDurationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1327 {
1328 return new QgsProcessingDurationWidgetWrapper( parameter, type );
1329 }
1330
createWidget()1331 QWidget *QgsProcessingDurationWidgetWrapper::createWidget()
1332 {
1333 const QgsProcessingParameterDuration *durationDef = static_cast< const QgsProcessingParameterDuration * >( parameterDefinition() );
1334
1335 QWidget *spin = QgsProcessingNumericWidgetWrapper::createWidget();
1336 switch ( type() )
1337 {
1338 case QgsProcessingGui::Standard:
1339 {
1340 mUnitsCombo = new QComboBox();
1341
1342 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalMilliseconds ), QgsUnitTypes::TemporalMilliseconds );
1343 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalSeconds ), QgsUnitTypes::TemporalSeconds );
1344 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalMinutes ), QgsUnitTypes::TemporalMinutes );
1345 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalHours ), QgsUnitTypes::TemporalHours );
1346 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalDays ), QgsUnitTypes::TemporalDays );
1347 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalWeeks ), QgsUnitTypes::TemporalWeeks );
1348 mUnitsCombo->addItem( tr( "years (365.25 days)" ), QgsUnitTypes::TemporalYears );
1349 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalDecades ), QgsUnitTypes::TemporalDecades );
1350 mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::TemporalCenturies ), QgsUnitTypes::TemporalCenturies );
1351
1352 QHBoxLayout *layout = new QHBoxLayout();
1353 layout->addWidget( spin, 1 );
1354 layout->insertWidget( 1, mUnitsCombo );
1355
1356 QWidget *w = new QWidget();
1357 layout->setContentsMargins( 0, 0, 0, 0 );
1358 w->setLayout( layout );
1359
1360 mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( durationDef->defaultUnit() ) );
1361 mUnitsCombo->show();
1362
1363 return w;
1364 }
1365
1366 case QgsProcessingGui::Batch:
1367 case QgsProcessingGui::Modeler:
1368 return spin;
1369
1370 }
1371 return nullptr;
1372 }
1373
createLabel()1374 QLabel *QgsProcessingDurationWidgetWrapper::createLabel()
1375 {
1376 QLabel *label = QgsAbstractProcessingParameterWidgetWrapper::createLabel();
1377
1378 if ( type() == QgsProcessingGui::Modeler )
1379 {
1380 label->setText( QStringLiteral( "%1 [%2]" ).arg( label->text(), QgsUnitTypes::toString( mBaseUnit ) ) );
1381 }
1382
1383 return label;
1384 }
1385
widgetValue() const1386 QVariant QgsProcessingDurationWidgetWrapper::widgetValue() const
1387 {
1388 const QVariant val = QgsProcessingNumericWidgetWrapper::widgetValue();
1389 if ( val.type() == QVariant::Double && mUnitsCombo )
1390 {
1391 QgsUnitTypes::TemporalUnit displayUnit = static_cast<QgsUnitTypes::TemporalUnit >( mUnitsCombo->currentData().toInt() );
1392 return val.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( displayUnit, mBaseUnit );
1393 }
1394 else
1395 {
1396 return val;
1397 }
1398 }
1399
setWidgetValue(const QVariant & value,QgsProcessingContext & context)1400 void QgsProcessingDurationWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1401 {
1402 if ( mUnitsCombo )
1403 {
1404 QgsUnitTypes::TemporalUnit displayUnit = static_cast<QgsUnitTypes::TemporalUnit >( mUnitsCombo->currentData().toInt() );
1405 const QVariant val = value.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( mBaseUnit, displayUnit );
1406 QgsProcessingNumericWidgetWrapper::setWidgetValue( val, context );
1407 }
1408 else
1409 {
1410 QgsProcessingNumericWidgetWrapper::setWidgetValue( value, context );
1411 }
1412 }
1413
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)1414 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDurationWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1415 {
1416 return new QgsProcessingDurationParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1417 }
1418
1419 //
1420 // QgsProcessingScaleWidgetWrapper
1421 //
1422
QgsProcessingScaleParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)1423 QgsProcessingScaleParameterDefinitionWidget::QgsProcessingScaleParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1424 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1425 {
1426 QVBoxLayout *vlayout = new QVBoxLayout();
1427 vlayout->setContentsMargins( 0, 0, 0, 0 );
1428
1429 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1430
1431 mDefaultLineEdit = new QLineEdit();
1432
1433 if ( const QgsProcessingParameterScale *scaleParam = dynamic_cast<const QgsProcessingParameterScale *>( definition ) )
1434 {
1435 mDefaultLineEdit->setText( scaleParam->defaultValueForGui().toString() );
1436 }
1437
1438 vlayout->addWidget( mDefaultLineEdit );
1439
1440 setLayout( vlayout );
1441 }
1442
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1443 QgsProcessingParameterDefinition *QgsProcessingScaleParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1444 {
1445 bool ok;
1446 double val = mDefaultLineEdit->text().toDouble( &ok );
1447 auto param = std::make_unique< QgsProcessingParameterScale >( name, description, ok ? val : QVariant() );
1448 param->setFlags( flags );
1449 return param.release();
1450 }
1451
QgsProcessingScaleWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1452 QgsProcessingScaleWidgetWrapper::QgsProcessingScaleWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1453 : QgsProcessingNumericWidgetWrapper( parameter, type, parent )
1454 {
1455
1456 }
1457
parameterType() const1458 QString QgsProcessingScaleWidgetWrapper::parameterType() const
1459 {
1460 return QgsProcessingParameterScale::typeName();
1461 }
1462
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)1463 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingScaleWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1464 {
1465 return new QgsProcessingScaleWidgetWrapper( parameter, type );
1466 }
1467
createWidget()1468 QWidget *QgsProcessingScaleWidgetWrapper::createWidget()
1469 {
1470 const QgsProcessingParameterScale *scaleDef = static_cast< const QgsProcessingParameterScale * >( parameterDefinition() );
1471
1472 switch ( type() )
1473 {
1474 case QgsProcessingGui::Standard:
1475 case QgsProcessingGui::Batch:
1476 case QgsProcessingGui::Modeler:
1477 {
1478 mScaleWidget = new QgsScaleWidget( nullptr );
1479 if ( scaleDef->flags() & QgsProcessingParameterDefinition::FlagOptional )
1480 mScaleWidget->setAllowNull( true );
1481
1482 mScaleWidget->setMapCanvas( widgetContext().mapCanvas() );
1483 mScaleWidget->setShowCurrentScaleButton( true );
1484
1485 mScaleWidget->setToolTip( parameterDefinition()->toolTip() );
1486 connect( mScaleWidget, &QgsScaleWidget::scaleChanged, this, [ = ]( double )
1487 {
1488 emit widgetValueHasChanged( this );
1489 } );
1490 return mScaleWidget;
1491 }
1492 }
1493 return nullptr;
1494 }
1495
setWidgetContext(const QgsProcessingParameterWidgetContext & context)1496 void QgsProcessingScaleWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
1497 {
1498 if ( mScaleWidget )
1499 mScaleWidget->setMapCanvas( context.mapCanvas() );
1500 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
1501 }
1502
1503
widgetValue() const1504 QVariant QgsProcessingScaleWidgetWrapper::widgetValue() const
1505 {
1506 return mScaleWidget && !mScaleWidget->isNull() ? QVariant( mScaleWidget->scale() ) : QVariant();
1507 }
1508
setWidgetValue(const QVariant & value,QgsProcessingContext & context)1509 void QgsProcessingScaleWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1510 {
1511 if ( mScaleWidget )
1512 {
1513 if ( mScaleWidget->allowNull() && !value.isValid() )
1514 mScaleWidget->setNull();
1515 else
1516 {
1517 const double v = QgsProcessingParameters::parameterAsDouble( parameterDefinition(), value, context );
1518 mScaleWidget->setScale( v );
1519 }
1520 }
1521 }
1522
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)1523 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingScaleWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1524 {
1525 return new QgsProcessingScaleParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1526 }
1527
1528
1529 //
1530 // QgsProcessingRangeWidgetWrapper
1531 //
1532
QgsProcessingRangeParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)1533 QgsProcessingRangeParameterDefinitionWidget::QgsProcessingRangeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1534 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1535 {
1536 QVBoxLayout *vlayout = new QVBoxLayout();
1537 vlayout->setContentsMargins( 0, 0, 0, 0 );
1538
1539 vlayout->addWidget( new QLabel( tr( "Number type" ) ) );
1540
1541 mTypeComboBox = new QComboBox();
1542 mTypeComboBox->addItem( tr( "Float" ), QgsProcessingParameterNumber::Double );
1543 mTypeComboBox->addItem( tr( "Integer" ), QgsProcessingParameterNumber::Integer );
1544 vlayout->addWidget( mTypeComboBox );
1545
1546 vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
1547 mMinLineEdit = new QLineEdit();
1548 vlayout->addWidget( mMinLineEdit );
1549
1550 vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
1551 mMaxLineEdit = new QLineEdit();
1552 vlayout->addWidget( mMaxLineEdit );
1553
1554 if ( const QgsProcessingParameterRange *rangeParam = dynamic_cast<const QgsProcessingParameterRange *>( definition ) )
1555 {
1556 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( rangeParam->dataType() ) );
1557 const QList< double > range = QgsProcessingParameters::parameterAsRange( rangeParam, rangeParam->defaultValueForGui(), context );
1558 mMinLineEdit->setText( QLocale().toString( range.at( 0 ) ) );
1559 mMaxLineEdit->setText( QLocale().toString( range.at( 1 ) ) );
1560 }
1561
1562 setLayout( vlayout );
1563 }
1564
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1565 QgsProcessingParameterDefinition *QgsProcessingRangeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1566 {
1567 QString defaultValue;
1568 if ( mMinLineEdit->text().isEmpty() )
1569 {
1570 defaultValue = QStringLiteral( "None" );
1571 }
1572 else
1573 {
1574 bool ok;
1575 defaultValue = QString::number( QgsDoubleValidator::toDouble( mMinLineEdit->text(), &ok ) );
1576 if ( ! ok )
1577 {
1578 defaultValue = QStringLiteral( "None" );
1579 }
1580 }
1581
1582 if ( mMaxLineEdit->text().isEmpty() )
1583 {
1584 defaultValue += QLatin1String( ",None" );
1585 }
1586 else
1587 {
1588 bool ok;
1589 const double val { QgsDoubleValidator::toDouble( mMaxLineEdit->text(), &ok ) };
1590 defaultValue += QStringLiteral( ",%1" ).arg( ok ? QString::number( val ) : QLatin1String( "None" ) );
1591 }
1592
1593 QgsProcessingParameterNumber::Type dataType = static_cast< QgsProcessingParameterNumber::Type >( mTypeComboBox->currentData().toInt() );
1594 auto param = std::make_unique< QgsProcessingParameterRange >( name, description, dataType, defaultValue );
1595 param->setFlags( flags );
1596 return param.release();
1597 }
1598
1599
QgsProcessingRangeWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1600 QgsProcessingRangeWidgetWrapper::QgsProcessingRangeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1601 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1602 {
1603
1604 }
1605
createWidget()1606 QWidget *QgsProcessingRangeWidgetWrapper::createWidget()
1607 {
1608 const QgsProcessingParameterRange *rangeDef = static_cast< const QgsProcessingParameterRange * >( parameterDefinition() );
1609 switch ( type() )
1610 {
1611 case QgsProcessingGui::Standard:
1612 case QgsProcessingGui::Modeler:
1613 case QgsProcessingGui::Batch:
1614 {
1615 QHBoxLayout *layout = new QHBoxLayout();
1616
1617 mMinSpinBox = new QgsDoubleSpinBox();
1618 mMaxSpinBox = new QgsDoubleSpinBox();
1619
1620 mMinSpinBox->setExpressionsEnabled( true );
1621 mMinSpinBox->setShowClearButton( false );
1622 mMaxSpinBox->setExpressionsEnabled( true );
1623 mMaxSpinBox->setShowClearButton( false );
1624
1625 QLabel *minLabel = new QLabel( tr( "Min" ) );
1626 layout->addWidget( minLabel );
1627 layout->addWidget( mMinSpinBox, 1 );
1628
1629 QLabel *maxLabel = new QLabel( tr( "Max" ) );
1630 layout->addWidget( maxLabel );
1631 layout->addWidget( mMaxSpinBox, 1 );
1632
1633 QWidget *w = new QWidget();
1634 layout->setContentsMargins( 0, 0, 0, 0 );
1635 w->setLayout( layout );
1636
1637 if ( rangeDef->dataType() == QgsProcessingParameterNumber::Double )
1638 {
1639 mMinSpinBox->setDecimals( 6 );
1640 mMaxSpinBox->setDecimals( 6 );
1641 }
1642 else
1643 {
1644 mMinSpinBox->setDecimals( 0 );
1645 mMaxSpinBox->setDecimals( 0 );
1646 }
1647
1648 mMinSpinBox->setMinimum( -99999999.999999 );
1649 mMaxSpinBox->setMinimum( -99999999.999999 );
1650 mMinSpinBox->setMaximum( 99999999.999999 );
1651 mMaxSpinBox->setMaximum( 99999999.999999 );
1652
1653 if ( rangeDef->flags() & QgsProcessingParameterDefinition::FlagOptional )
1654 {
1655 mAllowingNull = true;
1656
1657 const double min = mMinSpinBox->minimum() - 1;
1658 mMinSpinBox->setMinimum( min );
1659 mMaxSpinBox->setMinimum( min );
1660 mMinSpinBox->setValue( min );
1661 mMaxSpinBox->setValue( min );
1662
1663 mMinSpinBox->setShowClearButton( true );
1664 mMaxSpinBox->setShowClearButton( true );
1665 mMinSpinBox->setSpecialValueText( tr( "Not set" ) );
1666 mMaxSpinBox->setSpecialValueText( tr( "Not set" ) );
1667 }
1668
1669 w->setToolTip( parameterDefinition()->toolTip() );
1670
1671 connect( mMinSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( const double v )
1672 {
1673 mBlockChangedSignal++;
1674 if ( !mAllowingNull && v > mMaxSpinBox->value() )
1675 mMaxSpinBox->setValue( v );
1676 mBlockChangedSignal--;
1677
1678 if ( !mBlockChangedSignal )
1679 emit widgetValueHasChanged( this );
1680 } );
1681 connect( mMaxSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( const double v )
1682 {
1683 mBlockChangedSignal++;
1684 if ( !mAllowingNull && v < mMinSpinBox->value() )
1685 mMinSpinBox->setValue( v );
1686 mBlockChangedSignal--;
1687
1688 if ( !mBlockChangedSignal )
1689 emit widgetValueHasChanged( this );
1690 } );
1691
1692 return w;
1693 }
1694 }
1695 return nullptr;
1696 }
1697
setWidgetValue(const QVariant & value,QgsProcessingContext & context)1698 void QgsProcessingRangeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1699 {
1700 const QList< double > v = QgsProcessingParameters::parameterAsRange( parameterDefinition(), value, context );
1701 if ( mAllowingNull && v.empty() )
1702 {
1703 mMinSpinBox->clear();
1704 mMaxSpinBox->clear();
1705 }
1706 else
1707 {
1708 if ( v.empty() )
1709 return;
1710
1711 if ( mAllowingNull )
1712 {
1713 mBlockChangedSignal++;
1714 if ( std::isnan( v.at( 0 ) ) )
1715 mMinSpinBox->clear();
1716 else
1717 mMinSpinBox->setValue( v.at( 0 ) );
1718
1719 if ( v.count() >= 2 )
1720 {
1721 if ( std::isnan( v.at( 1 ) ) )
1722 mMaxSpinBox->clear();
1723 else
1724 mMaxSpinBox->setValue( v.at( 1 ) );
1725 }
1726 mBlockChangedSignal--;
1727 }
1728 else
1729 {
1730 mBlockChangedSignal++;
1731 mMinSpinBox->setValue( v.at( 0 ) );
1732 if ( v.count() >= 2 )
1733 mMaxSpinBox->setValue( v.at( 1 ) );
1734 mBlockChangedSignal--;
1735 }
1736 }
1737
1738 if ( !mBlockChangedSignal )
1739 emit widgetValueHasChanged( this );
1740 }
1741
widgetValue() const1742 QVariant QgsProcessingRangeWidgetWrapper::widgetValue() const
1743 {
1744 if ( mAllowingNull )
1745 {
1746 QString value;
1747 if ( qgsDoubleNear( mMinSpinBox->value(), mMinSpinBox->minimum() ) )
1748 value = QStringLiteral( "None" );
1749 else
1750 value = QString::number( mMinSpinBox->value() );
1751
1752 if ( qgsDoubleNear( mMaxSpinBox->value(), mMaxSpinBox->minimum() ) )
1753 value += QLatin1String( ",None" );
1754 else
1755 value += QStringLiteral( ",%1" ).arg( mMaxSpinBox->value() );
1756
1757 return value;
1758 }
1759 else
1760 return QStringLiteral( "%1,%2" ).arg( mMinSpinBox->value() ).arg( mMaxSpinBox->value() );
1761 }
1762
compatibleParameterTypes() const1763 QStringList QgsProcessingRangeWidgetWrapper::compatibleParameterTypes() const
1764 {
1765 return QStringList()
1766 << QgsProcessingParameterRange::typeName()
1767 << QgsProcessingParameterString::typeName();
1768 }
1769
compatibleOutputTypes() const1770 QStringList QgsProcessingRangeWidgetWrapper::compatibleOutputTypes() const
1771 {
1772 return QStringList() << QgsProcessingOutputString::typeName();
1773 }
1774
modelerExpressionFormatString() const1775 QString QgsProcessingRangeWidgetWrapper::modelerExpressionFormatString() const
1776 {
1777 return tr( "string as two comma delimited floats, e.g. '1,10'" );
1778 }
1779
parameterType() const1780 QString QgsProcessingRangeWidgetWrapper::parameterType() const
1781 {
1782 return QgsProcessingParameterRange::typeName();
1783 }
1784
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)1785 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRangeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1786 {
1787 return new QgsProcessingRangeWidgetWrapper( parameter, type );
1788 }
1789
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)1790 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRangeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1791 {
1792 return new QgsProcessingRangeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1793 }
1794
1795
1796 //
1797 // QgsProcessingMatrixWidgetWrapper
1798 //
1799
QgsProcessingMatrixParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)1800 QgsProcessingMatrixParameterDefinitionWidget::QgsProcessingMatrixParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1801 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1802 {
1803 QVBoxLayout *vlayout = new QVBoxLayout();
1804 vlayout->setContentsMargins( 0, 0, 0, 0 );
1805
1806 mMatrixWidget = new QgsProcessingMatrixModelerWidget();
1807 if ( const QgsProcessingParameterMatrix *matrixParam = dynamic_cast<const QgsProcessingParameterMatrix *>( definition ) )
1808 {
1809 mMatrixWidget->setValue( matrixParam->headers(), matrixParam->defaultValueForGui() );
1810 mMatrixWidget->setFixedRows( matrixParam->hasFixedNumberRows() );
1811 }
1812 vlayout->addWidget( mMatrixWidget );
1813 setLayout( vlayout );
1814 }
1815
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1816 QgsProcessingParameterDefinition *QgsProcessingMatrixParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1817 {
1818 auto param = std::make_unique< QgsProcessingParameterMatrix >( name, description, 1, mMatrixWidget->fixedRows(), mMatrixWidget->headers(), mMatrixWidget->value() );
1819 param->setFlags( flags );
1820 return param.release();
1821 }
1822
1823
QgsProcessingMatrixWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1824 QgsProcessingMatrixWidgetWrapper::QgsProcessingMatrixWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1825 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1826 {
1827
1828 }
1829
createWidget()1830 QWidget *QgsProcessingMatrixWidgetWrapper::createWidget()
1831 {
1832 mMatrixWidget = new QgsProcessingMatrixParameterPanel( nullptr, dynamic_cast< const QgsProcessingParameterMatrix *>( parameterDefinition() ) );
1833 mMatrixWidget->setToolTip( parameterDefinition()->toolTip() );
1834
1835 connect( mMatrixWidget, &QgsProcessingMatrixParameterPanel::changed, this, [ = ]
1836 {
1837 emit widgetValueHasChanged( this );
1838 } );
1839
1840 switch ( type() )
1841 {
1842 case QgsProcessingGui::Standard:
1843 case QgsProcessingGui::Batch:
1844 case QgsProcessingGui::Modeler:
1845 {
1846 return mMatrixWidget;
1847 }
1848 }
1849 return nullptr;
1850 }
1851
setWidgetValue(const QVariant & value,QgsProcessingContext & context)1852 void QgsProcessingMatrixWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
1853 {
1854 const QVariantList v = QgsProcessingParameters::parameterAsMatrix( parameterDefinition(), value, context );
1855 if ( mMatrixWidget )
1856 mMatrixWidget->setValue( v );
1857 }
1858
widgetValue() const1859 QVariant QgsProcessingMatrixWidgetWrapper::widgetValue() const
1860 {
1861 if ( mMatrixWidget )
1862 return mMatrixWidget->value().isEmpty() ? QVariant() : mMatrixWidget->value();
1863 else
1864 return QVariant();
1865 }
1866
compatibleParameterTypes() const1867 QStringList QgsProcessingMatrixWidgetWrapper::compatibleParameterTypes() const
1868 {
1869 return QStringList()
1870 << QgsProcessingParameterMatrix::typeName();
1871 }
1872
compatibleOutputTypes() const1873 QStringList QgsProcessingMatrixWidgetWrapper::compatibleOutputTypes() const
1874 {
1875 return QStringList();
1876 }
1877
modelerExpressionFormatString() const1878 QString QgsProcessingMatrixWidgetWrapper::modelerExpressionFormatString() const
1879 {
1880 return tr( "comma delimited string of values, or an array of values" );
1881 }
1882
parameterType() const1883 QString QgsProcessingMatrixWidgetWrapper::parameterType() const
1884 {
1885 return QgsProcessingParameterMatrix::typeName();
1886 }
1887
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)1888 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMatrixWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
1889 {
1890 return new QgsProcessingMatrixWidgetWrapper( parameter, type );
1891 }
1892
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)1893 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMatrixWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
1894 {
1895 return new QgsProcessingMatrixParameterDefinitionWidget( context, widgetContext, definition, algorithm );
1896 }
1897
1898
1899 //
1900 // QgsProcessingFileWidgetWrapper
1901 //
1902
1903
QgsProcessingFileParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)1904 QgsProcessingFileParameterDefinitionWidget::QgsProcessingFileParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
1905 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
1906 {
1907 QVBoxLayout *vlayout = new QVBoxLayout();
1908 vlayout->setContentsMargins( 0, 0, 0, 0 );
1909
1910 vlayout->addWidget( new QLabel( tr( "Type" ) ) );
1911
1912 mTypeComboBox = new QComboBox();
1913 mTypeComboBox->addItem( tr( "File" ), QgsProcessingParameterFile::File );
1914 mTypeComboBox->addItem( tr( "Folder" ), QgsProcessingParameterFile::Folder );
1915 if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1916 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( fileParam->behavior() ) );
1917 else
1918 mTypeComboBox->setCurrentIndex( 0 );
1919 vlayout->addWidget( mTypeComboBox );
1920
1921 vlayout->addWidget( new QLabel( tr( "File filter" ) ) );
1922
1923 mFilterComboBox = new QComboBox();
1924 mFilterComboBox->setEditable( true );
1925 // add some standard ones -- these also act as a demonstration of the required format
1926 mFilterComboBox->addItem( tr( "All Files (*.*)" ) );
1927 mFilterComboBox->addItem( tr( "CSV Files (*.csv)" ) );
1928 mFilterComboBox->addItem( tr( "HTML Files (*.html *.htm)" ) );
1929 mFilterComboBox->addItem( tr( "Text Files (*.txt)" ) );
1930 if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1931 mFilterComboBox->setCurrentText( fileParam->fileFilter() );
1932 else
1933 mFilterComboBox->setCurrentIndex( 0 );
1934 vlayout->addWidget( mFilterComboBox );
1935
1936 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
1937
1938 mDefaultFileWidget = new QgsFileWidget();
1939 mDefaultFileWidget->lineEdit()->setShowClearButton( true );
1940 if ( const QgsProcessingParameterFile *fileParam = dynamic_cast<const QgsProcessingParameterFile *>( definition ) )
1941 {
1942 mDefaultFileWidget->setStorageMode( fileParam->behavior() == QgsProcessingParameterFile::File ? QgsFileWidget::GetFile : QgsFileWidget::GetDirectory );
1943 mDefaultFileWidget->setFilePath( fileParam->defaultValueForGui().toString() );
1944 }
1945 else
1946 mDefaultFileWidget->setStorageMode( QgsFileWidget::GetFile );
1947 vlayout->addWidget( mDefaultFileWidget );
1948
1949 connect( mTypeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
1950 {
1951 QgsProcessingParameterFile::Behavior behavior = static_cast< QgsProcessingParameterFile::Behavior >( mTypeComboBox->currentData().toInt() );
1952 mFilterComboBox->setEnabled( behavior == QgsProcessingParameterFile::File );
1953 mDefaultFileWidget->setStorageMode( behavior == QgsProcessingParameterFile::File ? QgsFileWidget::GetFile : QgsFileWidget::GetDirectory );
1954 } );
1955 mFilterComboBox->setEnabled( static_cast< QgsProcessingParameterFile::Behavior >( mTypeComboBox->currentData().toInt() ) == QgsProcessingParameterFile::File );
1956
1957
1958 setLayout( vlayout );
1959 }
1960
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const1961 QgsProcessingParameterDefinition *QgsProcessingFileParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
1962 {
1963 auto param = std::make_unique< QgsProcessingParameterFile >( name, description );
1964 param->setBehavior( static_cast< QgsProcessingParameterFile::Behavior>( mTypeComboBox->currentData().toInt() ) );
1965 if ( param->behavior() == QgsProcessingParameterFile::File )
1966 param->setFileFilter( mFilterComboBox->currentText() );
1967 if ( !mDefaultFileWidget->filePath().isEmpty() )
1968 param->setDefaultValue( mDefaultFileWidget->filePath() );
1969 param->setFlags( flags );
1970 return param.release();
1971 }
1972
1973
QgsProcessingFileWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)1974 QgsProcessingFileWidgetWrapper::QgsProcessingFileWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
1975 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
1976 {
1977
1978 }
1979
createWidget()1980 QWidget *QgsProcessingFileWidgetWrapper::createWidget()
1981 {
1982 const QgsProcessingParameterFile *fileParam = dynamic_cast< const QgsProcessingParameterFile *>( parameterDefinition() );
1983 switch ( type() )
1984 {
1985 case QgsProcessingGui::Standard:
1986 case QgsProcessingGui::Modeler:
1987 case QgsProcessingGui::Batch:
1988 {
1989 mFileWidget = new QgsFileWidget();
1990 mFileWidget->setToolTip( parameterDefinition()->toolTip() );
1991 mFileWidget->setDialogTitle( parameterDefinition()->description() );
1992
1993 mFileWidget->setDefaultRoot( QgsSettings().value( QStringLiteral( "/Processing/LastInputPath" ), QDir::homePath() ).toString() );
1994
1995 switch ( fileParam->behavior() )
1996 {
1997 case QgsProcessingParameterFile::File:
1998 mFileWidget->setStorageMode( QgsFileWidget::GetFile );
1999 if ( !fileParam->fileFilter().isEmpty() )
2000 mFileWidget->setFilter( fileParam->fileFilter() );
2001 else if ( !fileParam->extension().isEmpty() )
2002 mFileWidget->setFilter( tr( "%1 files" ).arg( fileParam->extension().toUpper() ) + QStringLiteral( " (*." ) + fileParam->extension().toLower() + ')' );
2003 break;
2004
2005 case QgsProcessingParameterFile::Folder:
2006 mFileWidget->setStorageMode( QgsFileWidget::GetDirectory );
2007 break;
2008 }
2009
2010 connect( mFileWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & path )
2011 {
2012 QgsSettings().setValue( QStringLiteral( "/Processing/LastInputPath" ), QFileInfo( path ).canonicalPath() );
2013 emit widgetValueHasChanged( this );
2014 } );
2015 return mFileWidget;
2016 }
2017 }
2018 return nullptr;
2019 }
2020
setWidgetValue(const QVariant & value,QgsProcessingContext & context)2021 void QgsProcessingFileWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2022 {
2023 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2024 if ( mFileWidget )
2025 mFileWidget->setFilePath( v );
2026 }
2027
widgetValue() const2028 QVariant QgsProcessingFileWidgetWrapper::widgetValue() const
2029 {
2030 if ( mFileWidget )
2031 return mFileWidget->filePath();
2032 else
2033 return QVariant();
2034 }
2035
compatibleParameterTypes() const2036 QStringList QgsProcessingFileWidgetWrapper::compatibleParameterTypes() const
2037 {
2038 return QStringList()
2039 << QgsProcessingParameterString::typeName()
2040 << QgsProcessingParameterFile::typeName();
2041 }
2042
compatibleOutputTypes() const2043 QStringList QgsProcessingFileWidgetWrapper::compatibleOutputTypes() const
2044 {
2045 return QStringList() << QgsProcessingOutputFile::typeName()
2046 << QgsProcessingOutputFolder::typeName()
2047 << QgsProcessingOutputString::typeName()
2048 << QgsProcessingOutputRasterLayer::typeName()
2049 << QgsProcessingOutputVectorLayer::typeName()
2050 << QgsProcessingOutputMapLayer::typeName();
2051 }
2052
modelerExpressionFormatString() const2053 QString QgsProcessingFileWidgetWrapper::modelerExpressionFormatString() const
2054 {
2055 return tr( "string representing a path to a file or folder" );
2056 }
2057
parameterType() const2058 QString QgsProcessingFileWidgetWrapper::parameterType() const
2059 {
2060 return QgsProcessingParameterFile::typeName();
2061 }
2062
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)2063 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2064 {
2065 return new QgsProcessingFileWidgetWrapper( parameter, type );
2066 }
2067
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)2068 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFileWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2069 {
2070 return new QgsProcessingFileParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2071 }
2072
2073
2074
2075 //
2076 // QgsProcessingExpressionWidgetWrapper
2077 //
2078
QgsProcessingExpressionParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)2079 QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2080 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2081 {
2082 QVBoxLayout *vlayout = new QVBoxLayout();
2083 vlayout->setContentsMargins( 0, 0, 0, 0 );
2084 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
2085
2086 mDefaultLineEdit = new QgsExpressionLineEdit();
2087 mDefaultLineEdit->registerExpressionContextGenerator( this );
2088
2089 if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
2090 mDefaultLineEdit->setExpression( QgsProcessingParameters::parameterAsExpression( expParam, expParam->defaultValueForGui(), context ) );
2091 vlayout->addWidget( mDefaultLineEdit );
2092
2093 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
2094
2095 mParentLayerComboBox = new QComboBox();
2096 mParentLayerComboBox->addItem( tr( "None" ), QVariant() );
2097
2098 QString initialParent;
2099 if ( const QgsProcessingParameterExpression *expParam = dynamic_cast<const QgsProcessingParameterExpression *>( definition ) )
2100 initialParent = expParam->parentLayerParameterName();
2101
2102 if ( QgsProcessingModelAlgorithm *model = widgetContext.model() )
2103 {
2104 // populate combo box with other model input choices
2105 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
2106 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
2107 {
2108 if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( model->parameterDefinition( it.value().parameterName() ) ) )
2109 {
2110 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
2111 if ( !initialParent.isEmpty() && initialParent == definition->name() )
2112 {
2113 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
2114 }
2115 }
2116 else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( model->parameterDefinition( it.value().parameterName() ) ) )
2117 {
2118 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
2119 if ( !initialParent.isEmpty() && initialParent == definition->name() )
2120 {
2121 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
2122 }
2123 }
2124 }
2125 }
2126
2127 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
2128 {
2129 // if no parent candidates found, we just add the existing one as a placeholder
2130 mParentLayerComboBox->addItem( initialParent, initialParent );
2131 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
2132 }
2133
2134 vlayout->addWidget( mParentLayerComboBox );
2135 setLayout( vlayout );
2136 }
2137
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const2138 QgsProcessingParameterDefinition *QgsProcessingExpressionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2139 {
2140 auto param = std::make_unique< QgsProcessingParameterExpression >( name, description, mDefaultLineEdit->expression(), mParentLayerComboBox->currentData().toString() );
2141 param->setFlags( flags );
2142 return param.release();
2143 }
2144
QgsProcessingExpressionWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)2145 QgsProcessingExpressionWidgetWrapper::QgsProcessingExpressionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2146 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2147 {
2148
2149 }
2150
createWidget()2151 QWidget *QgsProcessingExpressionWidgetWrapper::createWidget()
2152 {
2153 const QgsProcessingParameterExpression *expParam = dynamic_cast< const QgsProcessingParameterExpression *>( parameterDefinition() );
2154 switch ( type() )
2155 {
2156 case QgsProcessingGui::Standard:
2157 case QgsProcessingGui::Modeler:
2158 case QgsProcessingGui::Batch:
2159 {
2160 if ( expParam->parentLayerParameterName().isEmpty() )
2161 {
2162 mExpLineEdit = new QgsExpressionLineEdit();
2163 mExpLineEdit->setToolTip( parameterDefinition()->toolTip() );
2164 mExpLineEdit->setExpressionDialogTitle( parameterDefinition()->description() );
2165 mExpLineEdit->registerExpressionContextGenerator( this );
2166 connect( mExpLineEdit, &QgsExpressionLineEdit::expressionChanged, this, [ = ]( const QString & )
2167 {
2168 emit widgetValueHasChanged( this );
2169 } );
2170 return mExpLineEdit;
2171 }
2172 else
2173 {
2174 if ( expParam->metadata().value( QStringLiteral( "inlineEditor" ) ).toBool() )
2175 {
2176 mExpBuilderWidget = new QgsExpressionBuilderWidget();
2177 mExpBuilderWidget->setToolTip( parameterDefinition()->toolTip() );
2178 mExpBuilderWidget->init( createExpressionContext() );
2179 connect( mExpBuilderWidget, &QgsExpressionBuilderWidget::expressionParsed, this, [ = ]( bool changed )
2180 {
2181 Q_UNUSED( changed );
2182 emit widgetValueHasChanged( this );
2183 } );
2184 return mExpBuilderWidget;
2185 }
2186 else
2187 {
2188 mFieldExpWidget = new QgsFieldExpressionWidget();
2189 mFieldExpWidget->setToolTip( parameterDefinition()->toolTip() );
2190 mFieldExpWidget->setExpressionDialogTitle( parameterDefinition()->description() );
2191 mFieldExpWidget->registerExpressionContextGenerator( this );
2192 if ( expParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
2193 mFieldExpWidget->setAllowEmptyFieldName( true );
2194
2195 connect( mFieldExpWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ]( const QString & )
2196 {
2197 emit widgetValueHasChanged( this );
2198 } );
2199 return mFieldExpWidget;
2200 }
2201 }
2202 }
2203 }
2204 return nullptr;
2205 }
2206
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)2207 void QgsProcessingExpressionWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
2208 {
2209 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
2210 switch ( type() )
2211 {
2212 case QgsProcessingGui::Standard:
2213 case QgsProcessingGui::Batch:
2214 {
2215 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
2216 {
2217 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterExpression * >( parameterDefinition() )->parentLayerParameterName() )
2218 {
2219 setParentLayerWrapperValue( wrapper );
2220 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
2221 {
2222 setParentLayerWrapperValue( wrapper );
2223 } );
2224 break;
2225 }
2226 }
2227 break;
2228 }
2229
2230 case QgsProcessingGui::Modeler:
2231 break;
2232 }
2233 }
2234
registerProcessingContextGenerator(QgsProcessingContextGenerator * generator)2235 void QgsProcessingExpressionWidgetWrapper::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator )
2236 {
2237 QgsAbstractProcessingParameterWidgetWrapper::registerProcessingContextGenerator( generator );
2238 if ( mExpBuilderWidget )
2239 {
2240 // we need to regenerate the expression context for use by this widget -- it doesn't fetch automatically on demand
2241 mExpBuilderWidget->setExpressionContext( createExpressionContext() );
2242 }
2243 }
2244
setParentLayerWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)2245 void QgsProcessingExpressionWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
2246 {
2247 // evaluate value to layer
2248 QgsProcessingContext *context = nullptr;
2249 std::unique_ptr< QgsProcessingContext > tmpContext;
2250 if ( mProcessingContextGenerator )
2251 context = mProcessingContextGenerator->processingContext();
2252
2253 if ( !context )
2254 {
2255 tmpContext = std::make_unique< QgsProcessingContext >();
2256 context = tmpContext.get();
2257 }
2258
2259 QVariant val = parentWrapper->parameterValue();
2260 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
2261 {
2262 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
2263 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
2264 val = fromVar.source;
2265 }
2266
2267 QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), val, *context );
2268 if ( !layer )
2269 {
2270 if ( mFieldExpWidget )
2271 mFieldExpWidget->setLayer( nullptr );
2272 else if ( mExpBuilderWidget )
2273 mExpBuilderWidget->setLayer( nullptr );
2274 else if ( mExpLineEdit )
2275 mExpLineEdit->setLayer( nullptr );
2276 return;
2277 }
2278
2279 // need to grab ownership of layer if required - otherwise layer may be deleted when context
2280 // goes out of scope
2281 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
2282 if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
2283 {
2284 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
2285 layer = mParentLayer.get();
2286 }
2287 else
2288 {
2289 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
2290 }
2291
2292 if ( mFieldExpWidget )
2293 mFieldExpWidget->setLayer( layer );
2294 if ( mExpBuilderWidget )
2295 mExpBuilderWidget->setLayer( layer );
2296 else if ( mExpLineEdit )
2297 mExpLineEdit->setLayer( layer );
2298 }
2299
setWidgetValue(const QVariant & value,QgsProcessingContext & context)2300 void QgsProcessingExpressionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2301 {
2302 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2303 if ( mFieldExpWidget )
2304 mFieldExpWidget->setExpression( v );
2305 else if ( mExpBuilderWidget )
2306 mExpBuilderWidget->setExpressionText( v );
2307 else if ( mExpLineEdit )
2308 mExpLineEdit->setExpression( v );
2309 }
2310
widgetValue() const2311 QVariant QgsProcessingExpressionWidgetWrapper::widgetValue() const
2312 {
2313 if ( mFieldExpWidget )
2314 return mFieldExpWidget->expression();
2315 if ( mExpBuilderWidget )
2316 return mExpBuilderWidget->expressionText();
2317 else if ( mExpLineEdit )
2318 return mExpLineEdit->expression();
2319 else
2320 return QVariant();
2321 }
2322
compatibleParameterTypes() const2323 QStringList QgsProcessingExpressionWidgetWrapper::compatibleParameterTypes() const
2324 {
2325 return QStringList()
2326 << QgsProcessingParameterExpression::typeName()
2327 << QgsProcessingParameterString::typeName()
2328 << QgsProcessingParameterNumber::typeName()
2329 << QgsProcessingParameterDistance::typeName()
2330 << QgsProcessingParameterScale::typeName()
2331 << QgsProcessingParameterProviderConnection::typeName();
2332 }
2333
compatibleOutputTypes() const2334 QStringList QgsProcessingExpressionWidgetWrapper::compatibleOutputTypes() const
2335 {
2336 return QStringList()
2337 << QgsProcessingOutputString::typeName()
2338 << QgsProcessingOutputNumber::typeName();
2339 }
2340
modelerExpressionFormatString() const2341 QString QgsProcessingExpressionWidgetWrapper::modelerExpressionFormatString() const
2342 {
2343 return tr( "string representation of an expression" );
2344 }
2345
linkedVectorLayer() const2346 const QgsVectorLayer *QgsProcessingExpressionWidgetWrapper::linkedVectorLayer() const
2347 {
2348 if ( mFieldExpWidget && mFieldExpWidget->layer() )
2349 return mFieldExpWidget->layer();
2350
2351 if ( mExpBuilderWidget && mExpBuilderWidget->layer() )
2352 return mExpBuilderWidget->layer();
2353
2354 return QgsAbstractProcessingParameterWidgetWrapper::linkedVectorLayer();
2355 }
2356
parameterType() const2357 QString QgsProcessingExpressionWidgetWrapper::parameterType() const
2358 {
2359 return QgsProcessingParameterExpression::typeName();
2360 }
2361
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)2362 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExpressionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2363 {
2364 return new QgsProcessingExpressionWidgetWrapper( parameter, type );
2365 }
2366
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)2367 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExpressionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2368 {
2369 return new QgsProcessingExpressionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2370 }
2371
2372
2373
2374 //
2375 // QgsProcessingEnumPanelWidget
2376 //
2377
QgsProcessingEnumPanelWidget(QWidget * parent,const QgsProcessingParameterEnum * param)2378 QgsProcessingEnumPanelWidget::QgsProcessingEnumPanelWidget( QWidget *parent, const QgsProcessingParameterEnum *param )
2379 : QWidget( parent )
2380 , mParam( param )
2381 {
2382 QHBoxLayout *hl = new QHBoxLayout();
2383 hl->setContentsMargins( 0, 0, 0, 0 );
2384
2385 mLineEdit = new QLineEdit();
2386 mLineEdit->setEnabled( false );
2387 hl->addWidget( mLineEdit, 1 );
2388
2389 mToolButton = new QToolButton();
2390 mToolButton->setText( QString( QChar( 0x2026 ) ) );
2391 hl->addWidget( mToolButton );
2392
2393 setLayout( hl );
2394
2395 if ( mParam )
2396 {
2397 mLineEdit->setText( tr( "%1 options selected" ).arg( 0 ) );
2398 }
2399
2400 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingEnumPanelWidget::showDialog );
2401 }
2402
setValue(const QVariant & value)2403 void QgsProcessingEnumPanelWidget::setValue( const QVariant &value )
2404 {
2405 if ( value.isValid() )
2406 {
2407 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
2408
2409 if ( mParam->usesStaticStrings() && mValue.count() == 1 && mValue.at( 0 ).toString().isEmpty() )
2410 mValue.clear();
2411 }
2412 else
2413 mValue.clear();
2414
2415 updateSummaryText();
2416 emit changed();
2417 }
2418
showDialog()2419 void QgsProcessingEnumPanelWidget::showDialog()
2420 {
2421 QVariantList availableOptions;
2422 if ( mParam )
2423 {
2424 availableOptions.reserve( mParam->options().size() );
2425 for ( int i = 0; i < mParam->options().count(); ++i )
2426 availableOptions << i;
2427 }
2428
2429 const QStringList options = mParam ? mParam->options() : QStringList();
2430 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
2431 if ( panel && panel->dockMode() )
2432 {
2433 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
2434 widget->setPanelTitle( mParam->description() );
2435
2436 if ( mParam->usesStaticStrings() )
2437 {
2438 widget->setValueFormatter( [options]( const QVariant & v ) -> QString
2439 {
2440 const QString i = v.toString();
2441 return options.contains( i ) ? i : QString();
2442 } );
2443 }
2444 else
2445 {
2446 widget->setValueFormatter( [options]( const QVariant & v ) -> QString
2447 {
2448 const int i = v.toInt();
2449 return options.size() > i ? options.at( i ) : QString();
2450 } );
2451 }
2452
2453 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
2454 {
2455 setValue( widget->selectedOptions() );
2456 } );
2457 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
2458 panel->openPanel( widget );
2459 }
2460 else
2461 {
2462 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
2463
2464 dlg.setValueFormatter( [options]( const QVariant & v ) -> QString
2465 {
2466 const int i = v.toInt();
2467 return options.size() > i ? options.at( i ) : QString();
2468 } );
2469 if ( dlg.exec() )
2470 {
2471 setValue( dlg.selectedOptions() );
2472 }
2473 }
2474 }
2475
updateSummaryText()2476 void QgsProcessingEnumPanelWidget::updateSummaryText()
2477 {
2478 if ( mParam )
2479 mLineEdit->setText( tr( "%1 options selected" ).arg( mValue.count() ) );
2480 }
2481
2482
2483 //
2484 // QgsProcessingEnumCheckboxPanelWidget
2485 //
QgsProcessingEnumCheckboxPanelWidget(QWidget * parent,const QgsProcessingParameterEnum * param,int columns)2486 QgsProcessingEnumCheckboxPanelWidget::QgsProcessingEnumCheckboxPanelWidget( QWidget *parent, const QgsProcessingParameterEnum *param, int columns )
2487 : QWidget( parent )
2488 , mParam( param )
2489 , mButtonGroup( new QButtonGroup( this ) )
2490 , mColumns( columns )
2491 {
2492 mButtonGroup->setExclusive( !mParam->allowMultiple() );
2493
2494 QGridLayout *l = new QGridLayout();
2495 l->setContentsMargins( 0, 0, 0, 0 );
2496
2497 int rows = static_cast< int >( std::ceil( mParam->options().count() / static_cast< double >( mColumns ) ) );
2498 for ( int i = 0; i < mParam->options().count(); ++i )
2499 {
2500 QAbstractButton *button = nullptr;
2501 if ( mParam->allowMultiple() )
2502 button = new QCheckBox( mParam->options().at( i ) );
2503 else
2504 button = new QRadioButton( mParam->options().at( i ) );
2505
2506 connect( button, &QAbstractButton::toggled, this, [ = ]
2507 {
2508 if ( !mBlockChangedSignal )
2509 emit changed();
2510 } );
2511
2512 mButtons.insert( i, button );
2513
2514 mButtonGroup->addButton( button, i );
2515 l->addWidget( button, i % rows, i / rows );
2516 }
2517 l->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, mColumns );
2518 setLayout( l );
2519
2520 if ( mParam->allowMultiple() )
2521 {
2522 setContextMenuPolicy( Qt::CustomContextMenu );
2523 connect( this, &QWidget::customContextMenuRequested, this, &QgsProcessingEnumCheckboxPanelWidget::showPopupMenu );
2524 }
2525 }
2526
value() const2527 QVariant QgsProcessingEnumCheckboxPanelWidget::value() const
2528 {
2529 if ( mParam->allowMultiple() )
2530 {
2531 QVariantList value;
2532 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2533 {
2534 if ( it.value()->isChecked() )
2535 value.append( mParam->usesStaticStrings() ? mParam->options().at( it.key().toInt() ) : it.key() );
2536 }
2537 return value;
2538 }
2539 else
2540 {
2541 if ( mParam->usesStaticStrings() )
2542 return mButtonGroup->checkedId() >= 0 ? mParam->options().at( mButtonGroup->checkedId() ) : QVariant();
2543 else
2544 return mButtonGroup->checkedId() >= 0 ? mButtonGroup->checkedId() : QVariant();
2545 }
2546 }
2547
setValue(const QVariant & value)2548 void QgsProcessingEnumCheckboxPanelWidget::setValue( const QVariant &value )
2549 {
2550 mBlockChangedSignal = true;
2551 if ( mParam->allowMultiple() )
2552 {
2553 QVariantList selected;
2554 if ( value.isValid() )
2555 selected = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
2556 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2557 {
2558 QVariant v = mParam->usesStaticStrings() ? mParam->options().at( it.key().toInt() ) : it.key();
2559 it.value()->setChecked( selected.contains( v ) );
2560 }
2561 }
2562 else
2563 {
2564 QVariant v = value;
2565 if ( v.type() == QVariant::List )
2566 v = v.toList().value( 0 );
2567
2568 v = mParam->usesStaticStrings() ? mParam->options().indexOf( v.toString() ) : v;
2569 if ( mButtons.contains( v ) )
2570 mButtons.value( v )->setChecked( true );
2571 }
2572 mBlockChangedSignal = false;
2573 emit changed();
2574 }
2575
showPopupMenu()2576 void QgsProcessingEnumCheckboxPanelWidget::showPopupMenu()
2577 {
2578 QMenu popupMenu;
2579 QAction *selectAllAction = new QAction( tr( "Select All" ), &popupMenu );
2580 connect( selectAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::selectAll );
2581 QAction *clearAllAction = new QAction( tr( "Clear Selection" ), &popupMenu );
2582 connect( clearAllAction, &QAction::triggered, this, &QgsProcessingEnumCheckboxPanelWidget::deselectAll );
2583 popupMenu.addAction( selectAllAction );
2584 popupMenu.addAction( clearAllAction );
2585 popupMenu.exec( QCursor::pos() );
2586 }
2587
selectAll()2588 void QgsProcessingEnumCheckboxPanelWidget::selectAll()
2589 {
2590 mBlockChangedSignal = true;
2591 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2592 it.value()->setChecked( true );
2593 mBlockChangedSignal = false;
2594 emit changed();
2595 }
2596
deselectAll()2597 void QgsProcessingEnumCheckboxPanelWidget::deselectAll()
2598 {
2599 mBlockChangedSignal = true;
2600 for ( auto it = mButtons.constBegin(); it != mButtons.constEnd(); ++it )
2601 it.value()->setChecked( false );
2602 mBlockChangedSignal = false;
2603 emit changed();
2604 }
2605
2606
2607 //
2608 // QgsProcessingEnumWidgetWrapper
2609 //
2610
QgsProcessingEnumParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)2611 QgsProcessingEnumParameterDefinitionWidget::QgsProcessingEnumParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2612 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2613 {
2614 QVBoxLayout *vlayout = new QVBoxLayout();
2615 vlayout->setContentsMargins( 0, 0, 0, 0 );
2616
2617 mEnumWidget = new QgsProcessingEnumModelerWidget();
2618 if ( const QgsProcessingParameterEnum *enumParam = dynamic_cast<const QgsProcessingParameterEnum *>( definition ) )
2619 {
2620 mEnumWidget->setAllowMultiple( enumParam->allowMultiple() );
2621 mEnumWidget->setOptions( enumParam->options() );
2622 mEnumWidget->setDefaultOptions( enumParam->defaultValueForGui() );
2623 }
2624 vlayout->addWidget( mEnumWidget );
2625 setLayout( vlayout );
2626 }
2627
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const2628 QgsProcessingParameterDefinition *QgsProcessingEnumParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2629 {
2630 auto param = std::make_unique< QgsProcessingParameterEnum >( name, description, mEnumWidget->options(), mEnumWidget->allowMultiple(), mEnumWidget->defaultOptions() );
2631 param->setFlags( flags );
2632 return param.release();
2633 }
2634
2635
QgsProcessingEnumWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)2636 QgsProcessingEnumWidgetWrapper::QgsProcessingEnumWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2637 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2638 {
2639
2640 }
2641
createWidget()2642 QWidget *QgsProcessingEnumWidgetWrapper::createWidget()
2643 {
2644 const QgsProcessingParameterEnum *expParam = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2645 switch ( type() )
2646 {
2647 case QgsProcessingGui::Standard:
2648 {
2649 // checkbox panel only for use outside in standard gui!
2650 if ( expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "useCheckBoxes" ), false ).toBool() )
2651 {
2652 const int columns = expParam->metadata().value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "columns" ), 2 ).toInt();
2653 mCheckboxPanel = new QgsProcessingEnumCheckboxPanelWidget( nullptr, expParam, columns );
2654 mCheckboxPanel->setToolTip( parameterDefinition()->toolTip() );
2655 connect( mCheckboxPanel, &QgsProcessingEnumCheckboxPanelWidget::changed, this, [ = ]
2656 {
2657 emit widgetValueHasChanged( this );
2658 } );
2659 return mCheckboxPanel;
2660 }
2661 }
2662 FALLTHROUGH
2663 case QgsProcessingGui::Modeler:
2664 case QgsProcessingGui::Batch:
2665 {
2666 if ( expParam->allowMultiple() )
2667 {
2668 mPanel = new QgsProcessingEnumPanelWidget( nullptr, expParam );
2669 mPanel->setToolTip( parameterDefinition()->toolTip() );
2670 connect( mPanel, &QgsProcessingEnumPanelWidget::changed, this, [ = ]
2671 {
2672 emit widgetValueHasChanged( this );
2673 } );
2674 return mPanel;
2675 }
2676 else
2677 {
2678 mComboBox = new QComboBox();
2679
2680 if ( expParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
2681 mComboBox->addItem( tr( "[Not selected]" ), QVariant() );
2682 const QStringList options = expParam->options();
2683 for ( int i = 0; i < options.count(); ++i )
2684 {
2685 if ( expParam->usesStaticStrings() )
2686 mComboBox->addItem( options.at( i ), options.at( i ) );
2687 else
2688 mComboBox->addItem( options.at( i ), i );
2689 }
2690
2691 mComboBox->setToolTip( parameterDefinition()->toolTip() );
2692 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
2693 {
2694 emit widgetValueHasChanged( this );
2695 } );
2696 return mComboBox;
2697 }
2698 }
2699 }
2700 return nullptr;
2701 }
2702
setWidgetValue(const QVariant & value,QgsProcessingContext & context)2703 void QgsProcessingEnumWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2704 {
2705 if ( mComboBox )
2706 {
2707 if ( !value.isValid() )
2708 mComboBox->setCurrentIndex( mComboBox->findData( QVariant() ) );
2709 else
2710 {
2711 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2712 if ( enumDef->usesStaticStrings() )
2713 {
2714 const QString v = QgsProcessingParameters::parameterAsEnumString( parameterDefinition(), value, context );
2715 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
2716 }
2717 else
2718 {
2719 const int v = QgsProcessingParameters::parameterAsEnum( parameterDefinition(), value, context );
2720 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
2721 }
2722 }
2723 }
2724 else if ( mPanel || mCheckboxPanel )
2725 {
2726 QVariantList opts;
2727 if ( value.isValid() )
2728 {
2729 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( parameterDefinition() );
2730 if ( enumDef->usesStaticStrings() )
2731 {
2732 const QStringList v = QgsProcessingParameters::parameterAsEnumStrings( parameterDefinition(), value, context );
2733 opts.reserve( v.size() );
2734 for ( QString i : v )
2735 opts << i;
2736 }
2737 else
2738 {
2739 const QList< int > v = QgsProcessingParameters::parameterAsEnums( parameterDefinition(), value, context );
2740 opts.reserve( v.size() );
2741 for ( int i : v )
2742 opts << i;
2743 }
2744 }
2745 if ( mPanel )
2746 mPanel->setValue( opts );
2747 else if ( mCheckboxPanel )
2748 mCheckboxPanel->setValue( opts );
2749 }
2750 }
2751
widgetValue() const2752 QVariant QgsProcessingEnumWidgetWrapper::widgetValue() const
2753 {
2754 if ( mComboBox )
2755 return mComboBox->currentData();
2756 else if ( mPanel )
2757 return mPanel->value();
2758 else if ( mCheckboxPanel )
2759 return mCheckboxPanel->value();
2760 else
2761 return QVariant();
2762 }
2763
compatibleParameterTypes() const2764 QStringList QgsProcessingEnumWidgetWrapper::compatibleParameterTypes() const
2765 {
2766 return QStringList()
2767 << QgsProcessingParameterEnum::typeName()
2768 << QgsProcessingParameterString::typeName()
2769 << QgsProcessingParameterNumber::typeName();
2770 }
2771
compatibleOutputTypes() const2772 QStringList QgsProcessingEnumWidgetWrapper::compatibleOutputTypes() const
2773 {
2774 return QStringList()
2775 << QgsProcessingOutputString::typeName()
2776 << QgsProcessingOutputNumber::typeName();
2777 }
2778
modelerExpressionFormatString() const2779 QString QgsProcessingEnumWidgetWrapper::modelerExpressionFormatString() const
2780 {
2781 return tr( "selected option index (starting from 0), array of indices, or comma separated string of options (e.g. '1,3')" );
2782 }
2783
parameterType() const2784 QString QgsProcessingEnumWidgetWrapper::parameterType() const
2785 {
2786 return QgsProcessingParameterEnum::typeName();
2787 }
2788
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)2789 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingEnumWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2790 {
2791 return new QgsProcessingEnumWidgetWrapper( parameter, type );
2792 }
2793
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)2794 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingEnumWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
2795 {
2796 return new QgsProcessingEnumParameterDefinitionWidget( context, widgetContext, definition, algorithm );
2797 }
2798
2799 //
2800 // QgsProcessingLayoutWidgetWrapper
2801 //
2802
QgsProcessingLayoutWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)2803 QgsProcessingLayoutWidgetWrapper::QgsProcessingLayoutWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2804 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2805 {
2806
2807 }
2808
createWidget()2809 QWidget *QgsProcessingLayoutWidgetWrapper::createWidget()
2810 {
2811 const QgsProcessingParameterLayout *layoutParam = dynamic_cast< const QgsProcessingParameterLayout *>( parameterDefinition() );
2812 switch ( type() )
2813 {
2814 case QgsProcessingGui::Standard:
2815 case QgsProcessingGui::Batch:
2816 {
2817 // combobox only for use outside modeler!
2818 mComboBox = new QgsLayoutComboBox( nullptr, widgetContext().project() ? widgetContext().project()->layoutManager() : nullptr );
2819 if ( layoutParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
2820 mComboBox->setAllowEmptyLayout( true );
2821 mComboBox->setFilters( QgsLayoutManagerProxyModel::FilterPrintLayouts );
2822
2823 mComboBox->setToolTip( parameterDefinition()->toolTip() );
2824 connect( mComboBox, &QgsLayoutComboBox::layoutChanged, this, [ = ]( QgsMasterLayoutInterface * )
2825 {
2826 emit widgetValueHasChanged( this );
2827 } );
2828 return mComboBox;
2829 }
2830
2831 case QgsProcessingGui::Modeler:
2832 {
2833 mPlainComboBox = new QComboBox();
2834 mPlainComboBox->setEditable( true );
2835 mPlainComboBox->setToolTip( tr( "Name of an existing print layout" ) );
2836 if ( widgetContext().project() )
2837 {
2838 const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2839 for ( const QgsPrintLayout *layout : layouts )
2840 mPlainComboBox->addItem( layout->name() );
2841 }
2842
2843 connect( mPlainComboBox, &QComboBox::currentTextChanged, this, [ = ]( const QString & )
2844 {
2845 emit widgetValueHasChanged( this );
2846 } );
2847 return mPlainComboBox;
2848 }
2849 }
2850 return nullptr;
2851 }
2852
setWidgetValue(const QVariant & value,QgsProcessingContext & context)2853 void QgsProcessingLayoutWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
2854 {
2855 if ( mComboBox )
2856 {
2857 if ( !value.isValid() )
2858 mComboBox->setCurrentLayout( nullptr );
2859 else
2860 {
2861 if ( QgsPrintLayout *l = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, context ) )
2862 mComboBox->setCurrentLayout( l );
2863 else
2864 mComboBox->setCurrentLayout( nullptr );
2865 }
2866 }
2867 else if ( mPlainComboBox )
2868 {
2869 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
2870 mPlainComboBox->setCurrentText( v );
2871 }
2872 }
2873
widgetValue() const2874 QVariant QgsProcessingLayoutWidgetWrapper::widgetValue() const
2875 {
2876 if ( mComboBox )
2877 {
2878 const QgsMasterLayoutInterface *l = mComboBox->currentLayout();
2879 return l ? l->name() : QVariant();
2880 }
2881 else if ( mPlainComboBox )
2882 return mPlainComboBox->currentText().isEmpty() ? QVariant() : mPlainComboBox->currentText();
2883 else
2884 return QVariant();
2885 }
2886
setWidgetContext(const QgsProcessingParameterWidgetContext & context)2887 void QgsProcessingLayoutWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
2888 {
2889 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
2890 if ( mPlainComboBox && context.project() )
2891 {
2892 const QList< QgsPrintLayout * > layouts = widgetContext().project()->layoutManager()->printLayouts();
2893 for ( const QgsPrintLayout *layout : layouts )
2894 mPlainComboBox->addItem( layout->name() );
2895 }
2896 }
2897
compatibleParameterTypes() const2898 QStringList QgsProcessingLayoutWidgetWrapper::compatibleParameterTypes() const
2899 {
2900 return QStringList()
2901 << QgsProcessingParameterLayout::typeName()
2902 << QgsProcessingParameterString::typeName();
2903 }
2904
compatibleOutputTypes() const2905 QStringList QgsProcessingLayoutWidgetWrapper::compatibleOutputTypes() const
2906 {
2907 return QStringList()
2908 << QgsProcessingOutputString::typeName();
2909 }
2910
modelerExpressionFormatString() const2911 QString QgsProcessingLayoutWidgetWrapper::modelerExpressionFormatString() const
2912 {
2913 return tr( "string representing the name of an existing print layout" );
2914 }
2915
parameterType() const2916 QString QgsProcessingLayoutWidgetWrapper::parameterType() const
2917 {
2918 return QgsProcessingParameterLayout::typeName();
2919 }
2920
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)2921 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
2922 {
2923 return new QgsProcessingLayoutWidgetWrapper( parameter, type );
2924 }
2925
2926
2927
2928
2929 //
2930 // QgsProcessingLayoutItemWidgetWrapper
2931 //
2932
2933
QgsProcessingLayoutItemParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)2934 QgsProcessingLayoutItemParameterDefinitionWidget::QgsProcessingLayoutItemParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
2935 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
2936 {
2937 QVBoxLayout *vlayout = new QVBoxLayout();
2938 vlayout->setContentsMargins( 0, 0, 0, 0 );
2939
2940 vlayout->addWidget( new QLabel( tr( "Parent layout" ) ) );
2941
2942 mParentLayoutComboBox = new QComboBox();
2943 QString initialParent;
2944 if ( const QgsProcessingParameterLayoutItem *itemParam = dynamic_cast<const QgsProcessingParameterLayoutItem *>( definition ) )
2945 initialParent = itemParam->parentLayoutParameterName();
2946
2947 if ( auto *lModel = widgetContext.model() )
2948 {
2949 // populate combo box with other model input choices
2950 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
2951 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
2952 {
2953 if ( const QgsProcessingParameterLayout *definition = dynamic_cast< const QgsProcessingParameterLayout * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
2954 {
2955 mParentLayoutComboBox-> addItem( definition->description(), definition->name() );
2956 if ( !initialParent.isEmpty() && initialParent == definition->name() )
2957 {
2958 mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
2959 }
2960 }
2961 }
2962 }
2963
2964 if ( mParentLayoutComboBox->count() == 0 && !initialParent.isEmpty() )
2965 {
2966 // if no parent candidates found, we just add the existing one as a placeholder
2967 mParentLayoutComboBox->addItem( initialParent, initialParent );
2968 mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 );
2969 }
2970
2971 vlayout->addWidget( mParentLayoutComboBox );
2972 setLayout( vlayout );
2973 }
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const2974 QgsProcessingParameterDefinition *QgsProcessingLayoutItemParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
2975 {
2976 auto param = std::make_unique< QgsProcessingParameterLayoutItem >( name, description, QVariant(), mParentLayoutComboBox->currentData().toString() );
2977 param->setFlags( flags );
2978 return param.release();
2979 }
2980
2981
QgsProcessingLayoutItemWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)2982 QgsProcessingLayoutItemWidgetWrapper::QgsProcessingLayoutItemWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
2983 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
2984 {
2985
2986 }
2987
createWidget()2988 QWidget *QgsProcessingLayoutItemWidgetWrapper::createWidget()
2989 {
2990 const QgsProcessingParameterLayoutItem *layoutParam = dynamic_cast< const QgsProcessingParameterLayoutItem *>( parameterDefinition() );
2991 switch ( type() )
2992 {
2993 case QgsProcessingGui::Standard:
2994 case QgsProcessingGui::Batch:
2995 {
2996 // combobox only for use outside modeler!
2997 mComboBox = new QgsLayoutItemComboBox( nullptr, nullptr );
2998 if ( layoutParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
2999 mComboBox->setAllowEmptyItem( true );
3000 if ( layoutParam->itemType() >= 0 )
3001 mComboBox->setItemType( static_cast< QgsLayoutItemRegistry::ItemType >( layoutParam->itemType() ) );
3002
3003 mComboBox->setToolTip( parameterDefinition()->toolTip() );
3004 connect( mComboBox, &QgsLayoutItemComboBox::itemChanged, this, [ = ]( QgsLayoutItem * )
3005 {
3006 emit widgetValueHasChanged( this );
3007 } );
3008 return mComboBox;
3009 }
3010
3011 case QgsProcessingGui::Modeler:
3012 {
3013 mLineEdit = new QLineEdit();
3014 mLineEdit->setToolTip( tr( "UUID or ID of an existing print layout item" ) );
3015 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3016 {
3017 emit widgetValueHasChanged( this );
3018 } );
3019 return mLineEdit;
3020 }
3021 }
3022 return nullptr;
3023 }
3024
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)3025 void QgsProcessingLayoutItemWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3026 {
3027 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
3028 switch ( type() )
3029 {
3030 case QgsProcessingGui::Standard:
3031 case QgsProcessingGui::Batch:
3032 {
3033 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3034 {
3035 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterLayoutItem * >( parameterDefinition() )->parentLayoutParameterName() )
3036 {
3037 setLayoutParameterValue( wrapper->parameterValue() );
3038 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
3039 {
3040 setLayoutParameterValue( wrapper->parameterValue() );
3041 } );
3042 break;
3043 }
3044 }
3045 break;
3046 }
3047
3048 case QgsProcessingGui::Modeler:
3049 break;
3050 }
3051 }
3052
setLayoutParameterValue(const QVariant & value)3053 void QgsProcessingLayoutItemWidgetWrapper::setLayoutParameterValue( const QVariant &value )
3054 {
3055 QgsPrintLayout *layout = nullptr;
3056
3057 // evaluate value to layout
3058 QgsProcessingContext *context = nullptr;
3059 std::unique_ptr< QgsProcessingContext > tmpContext;
3060 if ( mProcessingContextGenerator )
3061 context = mProcessingContextGenerator->processingContext();
3062
3063 if ( !context )
3064 {
3065 tmpContext = std::make_unique< QgsProcessingContext >();
3066 context = tmpContext.get();
3067 }
3068
3069 layout = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, *context );
3070 setLayout( layout );
3071 }
3072
setLayout(QgsPrintLayout * layout)3073 void QgsProcessingLayoutItemWidgetWrapper::setLayout( QgsPrintLayout *layout )
3074 {
3075 if ( mComboBox )
3076 mComboBox->setCurrentLayout( layout );
3077 }
3078
setWidgetValue(const QVariant & value,QgsProcessingContext & context)3079 void QgsProcessingLayoutItemWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3080 {
3081 if ( mComboBox )
3082 {
3083 if ( !value.isValid() )
3084 mComboBox->setItem( nullptr );
3085 else
3086 {
3087 QgsLayoutItem *item = QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition(), value, context, qobject_cast< QgsPrintLayout * >( mComboBox->currentLayout() ) );
3088 mComboBox->setItem( item );
3089 }
3090 }
3091 else if ( mLineEdit )
3092 {
3093 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3094 mLineEdit->setText( v );
3095 }
3096 }
3097
widgetValue() const3098 QVariant QgsProcessingLayoutItemWidgetWrapper::widgetValue() const
3099 {
3100 if ( mComboBox )
3101 {
3102 const QgsLayoutItem *i = mComboBox->currentItem();
3103 return i ? i->uuid() : QVariant();
3104 }
3105 else if ( mLineEdit )
3106 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3107 else
3108 return QVariant();
3109 }
3110
compatibleParameterTypes() const3111 QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleParameterTypes() const
3112 {
3113 return QStringList()
3114 << QgsProcessingParameterLayoutItem::typeName()
3115 << QgsProcessingParameterString::typeName();
3116 }
3117
compatibleOutputTypes() const3118 QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleOutputTypes() const
3119 {
3120 return QStringList()
3121 << QgsProcessingOutputString::typeName();
3122 }
3123
modelerExpressionFormatString() const3124 QString QgsProcessingLayoutItemWidgetWrapper::modelerExpressionFormatString() const
3125 {
3126 return tr( "string representing the UUID or ID of an existing print layout item" );
3127 }
3128
parameterType() const3129 QString QgsProcessingLayoutItemWidgetWrapper::parameterType() const
3130 {
3131 return QgsProcessingParameterLayoutItem::typeName();
3132 }
3133
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)3134 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutItemWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3135 {
3136 return new QgsProcessingLayoutItemWidgetWrapper( parameter, type );
3137 }
3138
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)3139 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingLayoutItemWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3140 {
3141 return new QgsProcessingLayoutItemParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3142 }
3143
3144 //
3145 // QgsProcessingPointMapTool
3146 //
3147
QgsProcessingPointMapTool(QgsMapCanvas * canvas)3148 QgsProcessingPointMapTool::QgsProcessingPointMapTool( QgsMapCanvas *canvas )
3149 : QgsMapTool( canvas )
3150 {
3151 setCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::CapturePoint ) );
3152 mSnapIndicator.reset( new QgsSnapIndicator( canvas ) );
3153 }
3154
3155 QgsProcessingPointMapTool::~QgsProcessingPointMapTool() = default;
3156
deactivate()3157 void QgsProcessingPointMapTool::deactivate()
3158 {
3159 mSnapIndicator->setMatch( QgsPointLocator::Match() );
3160 QgsMapTool::deactivate();
3161 }
3162
canvasMoveEvent(QgsMapMouseEvent * e)3163 void QgsProcessingPointMapTool::canvasMoveEvent( QgsMapMouseEvent *e )
3164 {
3165 e->snapPoint();
3166 mSnapIndicator->setMatch( e->mapPointMatch() );
3167 }
3168
canvasPressEvent(QgsMapMouseEvent * e)3169 void QgsProcessingPointMapTool::canvasPressEvent( QgsMapMouseEvent *e )
3170 {
3171 if ( e->button() == Qt::LeftButton )
3172 {
3173 QgsPointXY point = e->snapPoint();
3174 emit clicked( point );
3175 emit complete();
3176 }
3177 }
3178
keyPressEvent(QKeyEvent * e)3179 void QgsProcessingPointMapTool::keyPressEvent( QKeyEvent *e )
3180 {
3181 if ( e->key() == Qt::Key_Escape )
3182 {
3183
3184 // Override default shortcut management in MapCanvas
3185 e->ignore();
3186 emit complete();
3187 }
3188 }
3189
3190
3191
3192 //
3193 // QgsProcessingPointPanel
3194 //
3195
QgsProcessingPointPanel(QWidget * parent)3196 QgsProcessingPointPanel::QgsProcessingPointPanel( QWidget *parent )
3197 : QWidget( parent )
3198 {
3199 QHBoxLayout *l = new QHBoxLayout();
3200 l->setContentsMargins( 0, 0, 0, 0 );
3201 mLineEdit = new QgsFilterLineEdit( );
3202 mLineEdit->setShowClearButton( false );
3203 l->addWidget( mLineEdit, 1 );
3204 mButton = new QToolButton();
3205 mButton->setText( QString( QChar( 0x2026 ) ) );
3206 l->addWidget( mButton );
3207 setLayout( l );
3208
3209 connect( mLineEdit, &QLineEdit::textChanged, this, &QgsProcessingPointPanel::changed );
3210 connect( mButton, &QToolButton::clicked, this, &QgsProcessingPointPanel::selectOnCanvas );
3211 mButton->setVisible( false );
3212 }
3213
setMapCanvas(QgsMapCanvas * canvas)3214 void QgsProcessingPointPanel::setMapCanvas( QgsMapCanvas *canvas )
3215 {
3216 mCanvas = canvas;
3217 mButton->setVisible( true );
3218
3219 mCrs = canvas->mapSettings().destinationCrs();
3220 mTool = std::make_unique< QgsProcessingPointMapTool >( mCanvas );
3221 connect( mTool.get(), &QgsProcessingPointMapTool::clicked, this, &QgsProcessingPointPanel::updatePoint );
3222 connect( mTool.get(), &QgsProcessingPointMapTool::complete, this, &QgsProcessingPointPanel::pointPicked );
3223 }
3224
setAllowNull(bool allowNull)3225 void QgsProcessingPointPanel::setAllowNull( bool allowNull )
3226 {
3227 mLineEdit->setShowClearButton( allowNull );
3228 }
3229
value() const3230 QVariant QgsProcessingPointPanel::value() const
3231 {
3232 return mLineEdit->showClearButton() && mLineEdit->text().trimmed().isEmpty() ? QVariant() : QVariant( mLineEdit->text() );
3233 }
3234
clear()3235 void QgsProcessingPointPanel::clear()
3236 {
3237 mLineEdit->clear();
3238 }
3239
setValue(const QgsPointXY & point,const QgsCoordinateReferenceSystem & crs)3240 void QgsProcessingPointPanel::setValue( const QgsPointXY &point, const QgsCoordinateReferenceSystem &crs )
3241 {
3242 QString newText = QStringLiteral( "%1,%2" )
3243 .arg( QString::number( point.x(), 'f' ),
3244 QString::number( point.y(), 'f' ) );
3245
3246 mCrs = crs;
3247 if ( mCrs.isValid() )
3248 {
3249 newText += QStringLiteral( " [%1]" ).arg( mCrs.authid() );
3250 }
3251 mLineEdit->setText( newText );
3252 }
3253
selectOnCanvas()3254 void QgsProcessingPointPanel::selectOnCanvas()
3255 {
3256 if ( !mCanvas )
3257 return;
3258
3259 mPrevTool = mCanvas->mapTool();
3260 mCanvas->setMapTool( mTool.get() );
3261
3262 emit toggleDialogVisibility( false );
3263 }
3264
updatePoint(const QgsPointXY & point)3265 void QgsProcessingPointPanel::updatePoint( const QgsPointXY &point )
3266 {
3267 setValue( point, mCanvas->mapSettings().destinationCrs() );
3268 }
3269
pointPicked()3270 void QgsProcessingPointPanel::pointPicked()
3271 {
3272 if ( !mCanvas )
3273 return;
3274
3275 mCanvas->setMapTool( mPrevTool );
3276
3277 emit toggleDialogVisibility( true );
3278 }
3279
3280
3281
3282 //
3283 // QgsProcessingPointWidgetWrapper
3284 //
3285
QgsProcessingPointParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)3286 QgsProcessingPointParameterDefinitionWidget::QgsProcessingPointParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3287 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3288 {
3289 QVBoxLayout *vlayout = new QVBoxLayout();
3290 vlayout->setContentsMargins( 0, 0, 0, 0 );
3291
3292 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3293
3294 mDefaultLineEdit = new QLineEdit();
3295 mDefaultLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3296 mDefaultLineEdit->setPlaceholderText( tr( "Point as 'x,y'" ) );
3297 if ( const QgsProcessingParameterPoint *pointParam = dynamic_cast<const QgsProcessingParameterPoint *>( definition ) )
3298 {
3299 QgsPointXY point = QgsProcessingParameters::parameterAsPoint( pointParam, pointParam->defaultValueForGui(), context );
3300 mDefaultLineEdit->setText( QStringLiteral( "%1,%2" ).arg( QString::number( point.x(), 'f' ), QString::number( point.y(), 'f' ) ) );
3301 }
3302
3303 vlayout->addWidget( mDefaultLineEdit );
3304 setLayout( vlayout );
3305 }
3306
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const3307 QgsProcessingParameterDefinition *QgsProcessingPointParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3308 {
3309 auto param = std::make_unique< QgsProcessingParameterPoint >( name, description, mDefaultLineEdit->text() );
3310 param->setFlags( flags );
3311 return param.release();
3312 }
3313
QgsProcessingPointWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)3314 QgsProcessingPointWidgetWrapper::QgsProcessingPointWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3315 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3316 {
3317
3318 }
3319
createWidget()3320 QWidget *QgsProcessingPointWidgetWrapper::createWidget()
3321 {
3322 const QgsProcessingParameterPoint *pointParam = dynamic_cast< const QgsProcessingParameterPoint *>( parameterDefinition() );
3323 switch ( type() )
3324 {
3325 case QgsProcessingGui::Standard:
3326 case QgsProcessingGui::Batch:
3327 {
3328 mPanel = new QgsProcessingPointPanel( nullptr );
3329 if ( widgetContext().mapCanvas() )
3330 mPanel->setMapCanvas( widgetContext().mapCanvas() );
3331
3332 if ( pointParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
3333 mPanel->setAllowNull( true );
3334
3335 mPanel->setToolTip( parameterDefinition()->toolTip() );
3336
3337 connect( mPanel, &QgsProcessingPointPanel::changed, this, [ = ]
3338 {
3339 emit widgetValueHasChanged( this );
3340 } );
3341
3342 if ( mDialog )
3343 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
3344 return mPanel;
3345 }
3346
3347 case QgsProcessingGui::Modeler:
3348 {
3349 mLineEdit = new QLineEdit();
3350 mLineEdit->setToolTip( tr( "Point as 'x,y'" ) );
3351 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
3352 {
3353 emit widgetValueHasChanged( this );
3354 } );
3355 return mLineEdit;
3356 }
3357 }
3358 return nullptr;
3359 }
3360
setWidgetContext(const QgsProcessingParameterWidgetContext & context)3361 void QgsProcessingPointWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3362 {
3363 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
3364 if ( mPanel && context.mapCanvas() )
3365 mPanel->setMapCanvas( context.mapCanvas() );
3366 }
3367
setDialog(QDialog * dialog)3368 void QgsProcessingPointWidgetWrapper::setDialog( QDialog *dialog )
3369 {
3370 mDialog = dialog;
3371 if ( mPanel )
3372 {
3373 connect( mPanel, &QgsProcessingPointPanel::toggleDialogVisibility, mDialog, [ = ]( bool visible )
3374 {
3375 if ( !visible )
3376 mDialog->showMinimized();
3377 else
3378 {
3379 mDialog->showNormal();
3380 mDialog->raise();
3381 mDialog->activateWindow();
3382 }
3383 } );
3384 }
3385 QgsAbstractProcessingParameterWidgetWrapper::setDialog( dialog );
3386 }
3387
setWidgetValue(const QVariant & value,QgsProcessingContext & context)3388 void QgsProcessingPointWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3389 {
3390 if ( mPanel )
3391 {
3392 if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
3393 mPanel->clear();
3394 else
3395 {
3396 QgsPointXY p = QgsProcessingParameters::parameterAsPoint( parameterDefinition(), value, context );
3397 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
3398 mPanel->setValue( p, crs );
3399 }
3400 }
3401 else if ( mLineEdit )
3402 {
3403 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
3404 mLineEdit->setText( v );
3405 }
3406 }
3407
widgetValue() const3408 QVariant QgsProcessingPointWidgetWrapper::widgetValue() const
3409 {
3410 if ( mPanel )
3411 {
3412 return mPanel->value();
3413 }
3414 else if ( mLineEdit )
3415 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3416 else
3417 return QVariant();
3418 }
3419
compatibleParameterTypes() const3420 QStringList QgsProcessingPointWidgetWrapper::compatibleParameterTypes() const
3421 {
3422 return QStringList()
3423 << QgsProcessingParameterPoint::typeName()
3424 << QgsProcessingParameterString::typeName();
3425 }
3426
compatibleOutputTypes() const3427 QStringList QgsProcessingPointWidgetWrapper::compatibleOutputTypes() const
3428 {
3429 return QStringList()
3430 << QgsProcessingOutputString::typeName();
3431 }
3432
modelerExpressionFormatString() const3433 QString QgsProcessingPointWidgetWrapper::modelerExpressionFormatString() const
3434 {
3435 return tr( "string of the format 'x,y' or a geometry value (centroid is used)" );
3436 }
3437
parameterType() const3438 QString QgsProcessingPointWidgetWrapper::parameterType() const
3439 {
3440 return QgsProcessingParameterPoint::typeName();
3441 }
3442
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)3443 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3444 {
3445 return new QgsProcessingPointWidgetWrapper( parameter, type );
3446 }
3447
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)3448 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3449 {
3450 return new QgsProcessingPointParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3451 }
3452
3453
3454 //
3455 // QgsProcessingGeometryWidgetWrapper
3456 //
3457
3458
QgsProcessingGeometryParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)3459 QgsProcessingGeometryParameterDefinitionWidget::QgsProcessingGeometryParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3460 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3461 {
3462 QVBoxLayout *vlayout = new QVBoxLayout();
3463 vlayout->setContentsMargins( 0, 0, 0, 0 );
3464
3465 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3466
3467 mDefaultLineEdit = new QLineEdit();
3468 mDefaultLineEdit->setToolTip( tr( "Geometry as WKT" ) );
3469 mDefaultLineEdit->setPlaceholderText( tr( "Geometry as WKT" ) );
3470 if ( const QgsProcessingParameterGeometry *geometryParam = dynamic_cast<const QgsProcessingParameterGeometry *>( definition ) )
3471 {
3472 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( geometryParam, geometryParam->defaultValueForGui(), context );
3473 if ( !g.isNull() )
3474 mDefaultLineEdit->setText( g.asWkt() );
3475 }
3476
3477 vlayout->addWidget( mDefaultLineEdit );
3478 setLayout( vlayout );
3479 }
3480
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const3481 QgsProcessingParameterDefinition *QgsProcessingGeometryParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3482 {
3483 auto param = std::make_unique< QgsProcessingParameterGeometry >( name, description, mDefaultLineEdit->text() );
3484 param->setFlags( flags );
3485 return param.release();
3486 }
3487
QgsProcessingGeometryWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)3488 QgsProcessingGeometryWidgetWrapper::QgsProcessingGeometryWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3489 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3490 {
3491
3492 }
3493
createWidget()3494 QWidget *QgsProcessingGeometryWidgetWrapper::createWidget()
3495 {
3496 switch ( type() )
3497 {
3498 case QgsProcessingGui::Standard:
3499 case QgsProcessingGui::Modeler:
3500 case QgsProcessingGui::Batch:
3501 {
3502 mLineEdit = new QLineEdit();
3503 mLineEdit->setToolTip( parameterDefinition()->toolTip() );
3504 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3505 {
3506 emit widgetValueHasChanged( this );
3507 } );
3508 return mLineEdit;
3509 }
3510 }
3511 return nullptr;
3512 }
3513
setWidgetValue(const QVariant & value,QgsProcessingContext & context)3514 void QgsProcessingGeometryWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3515 {
3516 if ( mLineEdit )
3517 {
3518 QgsGeometry g = QgsProcessingParameters::parameterAsGeometry( parameterDefinition(), value, context );
3519 if ( !g.isNull() )
3520 mLineEdit->setText( g.asWkt() );
3521 else
3522 mLineEdit->clear();
3523 }
3524 }
3525
widgetValue() const3526 QVariant QgsProcessingGeometryWidgetWrapper::widgetValue() const
3527 {
3528 if ( mLineEdit )
3529 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
3530 else
3531 return QVariant();
3532 }
3533
compatibleParameterTypes() const3534 QStringList QgsProcessingGeometryWidgetWrapper::compatibleParameterTypes() const
3535 {
3536 return QStringList()
3537 << QgsProcessingParameterGeometry::typeName()
3538 << QgsProcessingParameterString::typeName()
3539 << QgsProcessingParameterPoint::typeName()
3540 << QgsProcessingParameterExtent::typeName();
3541 }
3542
compatibleOutputTypes() const3543 QStringList QgsProcessingGeometryWidgetWrapper::compatibleOutputTypes() const
3544 {
3545 return QStringList()
3546 << QgsProcessingOutputString::typeName();
3547 }
3548
modelerExpressionFormatString() const3549 QString QgsProcessingGeometryWidgetWrapper::modelerExpressionFormatString() const
3550 {
3551 return tr( "string in the Well-Known-Text format or a geometry value" );
3552 }
3553
parameterType() const3554 QString QgsProcessingGeometryWidgetWrapper::parameterType() const
3555 {
3556 return QgsProcessingParameterGeometry::typeName();
3557 }
3558
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)3559 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingGeometryWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3560 {
3561 return new QgsProcessingGeometryWidgetWrapper( parameter, type );
3562 }
3563
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)3564 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingGeometryWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3565 {
3566 return new QgsProcessingGeometryParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3567 }
3568
3569
3570 //
3571 // QgsProcessingColorWidgetWrapper
3572 //
3573
3574
QgsProcessingColorParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)3575 QgsProcessingColorParameterDefinitionWidget::QgsProcessingColorParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3576 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3577 {
3578 QVBoxLayout *vlayout = new QVBoxLayout();
3579 vlayout->setContentsMargins( 0, 0, 0, 0 );
3580
3581 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3582
3583 mDefaultColorButton = new QgsColorButton();
3584 mDefaultColorButton->setShowNull( true );
3585 mAllowOpacity = new QCheckBox( tr( "Allow opacity control" ) );
3586
3587 if ( const QgsProcessingParameterColor *colorParam = dynamic_cast<const QgsProcessingParameterColor *>( definition ) )
3588 {
3589 const QColor c = QgsProcessingParameters::parameterAsColor( colorParam, colorParam->defaultValueForGui(), context );
3590 if ( !c.isValid() )
3591 mDefaultColorButton->setToNull();
3592 else
3593 mDefaultColorButton->setColor( c );
3594 mAllowOpacity->setChecked( colorParam->opacityEnabled() );
3595 }
3596 else
3597 {
3598 mDefaultColorButton->setToNull();
3599 mAllowOpacity->setChecked( true );
3600 }
3601
3602 vlayout->addWidget( mDefaultColorButton );
3603 vlayout->addWidget( mAllowOpacity );
3604 setLayout( vlayout );
3605 }
3606
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const3607 QgsProcessingParameterDefinition *QgsProcessingColorParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3608 {
3609 auto param = std::make_unique< QgsProcessingParameterColor >( name, description, mDefaultColorButton->color(), mAllowOpacity->isChecked() );
3610 param->setFlags( flags );
3611 return param.release();
3612 }
3613
QgsProcessingColorWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)3614 QgsProcessingColorWidgetWrapper::QgsProcessingColorWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3615 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3616 {
3617
3618 }
3619
createWidget()3620 QWidget *QgsProcessingColorWidgetWrapper::createWidget()
3621 {
3622 const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor *>( parameterDefinition() );
3623 switch ( type() )
3624 {
3625 case QgsProcessingGui::Standard:
3626 case QgsProcessingGui::Batch:
3627 case QgsProcessingGui::Modeler:
3628 {
3629 mColorButton = new QgsColorButton( nullptr );
3630 mColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
3631
3632 if ( colorParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
3633 mColorButton->setShowNull( true );
3634
3635 mColorButton->setAllowOpacity( colorParam->opacityEnabled() );
3636 mColorButton->setToolTip( parameterDefinition()->toolTip() );
3637 mColorButton->setColorDialogTitle( parameterDefinition()->description() );
3638 if ( colorParam->defaultValueForGui().value< QColor >().isValid() )
3639 {
3640 mColorButton->setDefaultColor( colorParam->defaultValueForGui().value< QColor >() );
3641 }
3642
3643 connect( mColorButton, &QgsColorButton::colorChanged, this, [ = ]
3644 {
3645 emit widgetValueHasChanged( this );
3646 } );
3647
3648 return mColorButton;
3649 }
3650 }
3651 return nullptr;
3652 }
3653
setWidgetValue(const QVariant & value,QgsProcessingContext & context)3654 void QgsProcessingColorWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
3655 {
3656 if ( mColorButton )
3657 {
3658 if ( !value.isValid() ||
3659 ( value.type() == QVariant::String && value.toString().isEmpty() )
3660 || ( value.type() == QVariant::Color && !value.value< QColor >().isValid() ) )
3661 mColorButton->setToNull();
3662 else
3663 {
3664 const QColor c = QgsProcessingParameters::parameterAsColor( parameterDefinition(), value, context );
3665 if ( !c.isValid() && mColorButton->showNull() )
3666 mColorButton->setToNull();
3667 else
3668 mColorButton->setColor( c );
3669 }
3670 }
3671 }
3672
widgetValue() const3673 QVariant QgsProcessingColorWidgetWrapper::widgetValue() const
3674 {
3675 if ( mColorButton )
3676 return mColorButton->isNull() ? QVariant() : mColorButton->color();
3677 else
3678 return QVariant();
3679 }
3680
compatibleParameterTypes() const3681 QStringList QgsProcessingColorWidgetWrapper::compatibleParameterTypes() const
3682 {
3683 return QStringList()
3684 << QgsProcessingParameterColor::typeName()
3685 << QgsProcessingParameterString::typeName();
3686 }
3687
compatibleOutputTypes() const3688 QStringList QgsProcessingColorWidgetWrapper::compatibleOutputTypes() const
3689 {
3690 return QStringList()
3691 << QgsProcessingOutputString::typeName();
3692 }
3693
modelerExpressionFormatString() const3694 QString QgsProcessingColorWidgetWrapper::modelerExpressionFormatString() const
3695 {
3696 return tr( "color style string, e.g. #ff0000 or 255,0,0" );
3697 }
3698
parameterType() const3699 QString QgsProcessingColorWidgetWrapper::parameterType() const
3700 {
3701 return QgsProcessingParameterColor::typeName();
3702 }
3703
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)3704 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingColorWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
3705 {
3706 return new QgsProcessingColorWidgetWrapper( parameter, type );
3707 }
3708
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)3709 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingColorWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
3710 {
3711 return new QgsProcessingColorParameterDefinitionWidget( context, widgetContext, definition, algorithm );
3712 }
3713
3714
3715 //
3716 // QgsProcessingCoordinateOperationWidgetWrapper
3717 //
3718
QgsProcessingCoordinateOperationParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)3719 QgsProcessingCoordinateOperationParameterDefinitionWidget::QgsProcessingCoordinateOperationParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
3720 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
3721 {
3722 QVBoxLayout *vlayout = new QVBoxLayout();
3723 vlayout->setContentsMargins( 0, 0, 0, 0 );
3724
3725 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
3726
3727 mDefaultLineEdit = new QLineEdit();
3728 if ( const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3729 mDefaultLineEdit->setText( QgsProcessingParameters::parameterAsString( coordParam, coordParam->defaultValueForGui(), context ) );
3730 vlayout->addWidget( mDefaultLineEdit );
3731
3732 mSourceParamComboBox = new QComboBox();
3733 mDestParamComboBox = new QComboBox();
3734 QString initialSource;
3735 QString initialDest;
3736 QgsCoordinateReferenceSystem sourceCrs;
3737 QgsCoordinateReferenceSystem destCrs;
3738 if ( const QgsProcessingParameterCoordinateOperation *itemParam = dynamic_cast<const QgsProcessingParameterCoordinateOperation *>( definition ) )
3739 {
3740 initialSource = itemParam->sourceCrsParameterName();
3741 initialDest = itemParam->destinationCrsParameterName();
3742 sourceCrs = QgsProcessingUtils::variantToCrs( itemParam->sourceCrs(), context );
3743 destCrs = QgsProcessingUtils::variantToCrs( itemParam->destinationCrs(), context );
3744 }
3745
3746 mSourceParamComboBox->addItem( QString(), QString() );
3747 mDestParamComboBox->addItem( QString(), QString() );
3748 if ( auto *lModel = widgetContext.model() )
3749 {
3750 // populate combo box with other model input choices
3751 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
3752 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
3753 {
3754 if ( definition && it->parameterName() == definition->name() )
3755 continue;
3756
3757 // TODO - we should probably filter this list?
3758 mSourceParamComboBox->addItem( it->parameterName(), it->parameterName() );
3759 mDestParamComboBox->addItem( it->parameterName(), it->parameterName() );
3760 if ( !initialSource.isEmpty() && initialSource == it->parameterName() )
3761 {
3762 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3763 }
3764 if ( !initialDest.isEmpty() && initialDest == it->parameterName() )
3765 {
3766 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3767 }
3768 }
3769 }
3770
3771 if ( mSourceParamComboBox->count() == 1 && !initialSource.isEmpty() )
3772 {
3773 // if no source candidates found, we just add the existing one as a placeholder
3774 mSourceParamComboBox->addItem( initialSource, initialSource );
3775 mSourceParamComboBox->setCurrentIndex( mSourceParamComboBox->count() - 1 );
3776 }
3777 if ( mDestParamComboBox->count() == 1 && !initialDest.isEmpty() )
3778 {
3779 // if no dest candidates found, we just add the existing one as a placeholder
3780 mDestParamComboBox->addItem( initialDest, initialDest );
3781 mDestParamComboBox->setCurrentIndex( mDestParamComboBox->count() - 1 );
3782 }
3783
3784 vlayout->addWidget( new QLabel( tr( "Source CRS parameter" ) ) );
3785 vlayout->addWidget( mSourceParamComboBox );
3786 vlayout->addWidget( new QLabel( tr( "Destination CRS parameter" ) ) );
3787 vlayout->addWidget( mDestParamComboBox );
3788
3789 mStaticSourceWidget = new QgsProjectionSelectionWidget();
3790 mStaticSourceWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3791 mStaticSourceWidget->setCrs( sourceCrs );
3792 mStaticDestWidget = new QgsProjectionSelectionWidget();
3793 mStaticDestWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
3794 mStaticDestWidget->setCrs( destCrs );
3795
3796 vlayout->addWidget( new QLabel( tr( "Static source CRS" ) ) );
3797 vlayout->addWidget( mStaticSourceWidget );
3798 vlayout->addWidget( new QLabel( tr( "Static destination CRS" ) ) );
3799 vlayout->addWidget( mStaticDestWidget );
3800
3801 setLayout( vlayout );
3802 }
3803
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const3804 QgsProcessingParameterDefinition *QgsProcessingCoordinateOperationParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
3805 {
3806 auto param = std::make_unique< QgsProcessingParameterCoordinateOperation >( name, description, mDefaultLineEdit->text(),
3807 mSourceParamComboBox->currentText(),
3808 mDestParamComboBox->currentText(),
3809 mStaticSourceWidget->crs().isValid() ? QVariant::fromValue( mStaticSourceWidget->crs() ) : QVariant(),
3810 mStaticDestWidget->crs().isValid() ? QVariant::fromValue( mStaticDestWidget->crs() ) : QVariant() );
3811 param->setFlags( flags );
3812 return param.release();
3813 }
3814
QgsProcessingCoordinateOperationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)3815 QgsProcessingCoordinateOperationWidgetWrapper::QgsProcessingCoordinateOperationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
3816 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
3817 {
3818
3819 }
3820
createWidget()3821 QWidget *QgsProcessingCoordinateOperationWidgetWrapper::createWidget()
3822 {
3823 const QgsProcessingParameterCoordinateOperation *coordParam = dynamic_cast< const QgsProcessingParameterCoordinateOperation *>( parameterDefinition() );
3824 QgsProcessingContext c;
3825 mSourceCrs = QgsProcessingUtils::variantToCrs( coordParam->sourceCrs(), c );
3826 mDestCrs = QgsProcessingUtils::variantToCrs( coordParam->destinationCrs(), c );
3827 switch ( type() )
3828 {
3829 case QgsProcessingGui::Standard:
3830 {
3831 mOperationWidget = new QgsCoordinateOperationWidget( nullptr );
3832 mOperationWidget->setShowMakeDefault( false );
3833 mOperationWidget->setShowFallbackOption( false );
3834 mOperationWidget->setToolTip( parameterDefinition()->toolTip() );
3835 mOperationWidget->setSourceCrs( mSourceCrs );
3836 mOperationWidget->setDestinationCrs( mDestCrs );
3837 mOperationWidget->setMapCanvas( mCanvas );
3838 if ( !coordParam->defaultValueForGui().toString().isEmpty() )
3839 {
3840 QgsCoordinateOperationWidget::OperationDetails deets;
3841 deets.proj = coordParam->defaultValueForGui().toString();
3842 mOperationWidget->setSelectedOperation( deets );
3843 }
3844
3845 connect( mOperationWidget, &QgsCoordinateOperationWidget::operationChanged, this, [ = ]
3846 {
3847 emit widgetValueHasChanged( this );
3848 } );
3849
3850 return mOperationWidget;
3851 }
3852
3853 case QgsProcessingGui::Batch:
3854 case QgsProcessingGui::Modeler:
3855 {
3856 mLineEdit = new QLineEdit();
3857 QHBoxLayout *layout = new QHBoxLayout();
3858 layout->addWidget( mLineEdit, 1 );
3859 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
3860 {
3861 emit widgetValueHasChanged( this );
3862 } );
3863
3864 QToolButton *button = new QToolButton();
3865 button->setText( QString( QChar( 0x2026 ) ) );
3866 connect( button, &QToolButton::clicked, this, [ = ]
3867 {
3868 QgsDatumTransformDialog dlg( mSourceCrs, mDestCrs, false, false, false, qMakePair( -1, -1 ), button, Qt::WindowFlags(), mLineEdit->text(), mCanvas );
3869 if ( dlg.exec() )
3870 {
3871 mLineEdit->setText( dlg.selectedDatumTransform().proj );
3872 emit widgetValueHasChanged( this );
3873 }
3874 } );
3875 layout->addWidget( button );
3876
3877 QWidget *w = new QWidget();
3878 layout->setContentsMargins( 0, 0, 0, 0 );
3879 w->setLayout( layout );
3880 return w;
3881 }
3882
3883 }
3884 return nullptr;
3885 }
3886
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)3887 void QgsProcessingCoordinateOperationWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
3888 {
3889 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
3890 switch ( type() )
3891 {
3892 case QgsProcessingGui::Standard:
3893 case QgsProcessingGui::Batch:
3894 {
3895 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
3896 {
3897 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->sourceCrsParameterName() )
3898 {
3899 setSourceCrsParameterValue( wrapper->parameterValue() );
3900 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
3901 {
3902 setSourceCrsParameterValue( wrapper->parameterValue() );
3903 } );
3904 }
3905 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterCoordinateOperation * >( parameterDefinition() )->destinationCrsParameterName() )
3906 {
3907 setDestinationCrsParameterValue( wrapper->parameterValue() );
3908 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
3909 {
3910 setDestinationCrsParameterValue( wrapper->parameterValue() );
3911 } );
3912 }
3913 }
3914 break;
3915 }
3916
3917 case QgsProcessingGui::Modeler:
3918 break;
3919 }
3920 }
3921
setWidgetContext(const QgsProcessingParameterWidgetContext & context)3922 void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
3923 {
3924 mCanvas = context.mapCanvas();
3925 if ( mOperationWidget )
3926 mOperationWidget->setMapCanvas( context.mapCanvas() );
3927 }
3928
setWidgetValue(const QVariant & value,QgsProcessingContext &)3929 void QgsProcessingCoordinateOperationWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
3930 {
3931 if ( mOperationWidget )
3932 {
3933 if ( !value.isValid() ||
3934 ( value.type() == QVariant::String ) )
3935 {
3936 QgsCoordinateOperationWidget::OperationDetails deets;
3937 deets.proj = value.toString();
3938 mOperationWidget->setSelectedOperation( deets );
3939 }
3940 }
3941 if ( mLineEdit )
3942 {
3943 if ( !value.isValid() ||
3944 ( value.type() == QVariant::String ) )
3945 {
3946 mLineEdit->setText( value.toString() );
3947 }
3948 }
3949 }
3950
widgetValue() const3951 QVariant QgsProcessingCoordinateOperationWidgetWrapper::widgetValue() const
3952 {
3953 if ( mOperationWidget )
3954 return mOperationWidget->selectedOperation().proj;
3955 else if ( mLineEdit )
3956 return mLineEdit->text();
3957 else
3958 return QVariant();
3959 }
3960
compatibleParameterTypes() const3961 QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleParameterTypes() const
3962 {
3963 return QStringList()
3964 << QgsProcessingParameterCoordinateOperation::typeName()
3965 << QgsProcessingParameterString::typeName();
3966 }
3967
compatibleOutputTypes() const3968 QStringList QgsProcessingCoordinateOperationWidgetWrapper::compatibleOutputTypes() const
3969 {
3970 return QStringList()
3971 << QgsProcessingOutputString::typeName();
3972 }
3973
modelerExpressionFormatString() const3974 QString QgsProcessingCoordinateOperationWidgetWrapper::modelerExpressionFormatString() const
3975 {
3976 return tr( "Proj coordinate operation string, e.g. '+proj=pipeline +step +inv...'" );
3977 }
3978
setSourceCrsParameterValue(const QVariant & value)3979 void QgsProcessingCoordinateOperationWidgetWrapper::setSourceCrsParameterValue( const QVariant &value )
3980 {
3981 QgsProcessingContext *context = nullptr;
3982 std::unique_ptr< QgsProcessingContext > tmpContext;
3983 if ( mProcessingContextGenerator )
3984 context = mProcessingContextGenerator->processingContext();
3985
3986 if ( !context )
3987 {
3988 tmpContext = std::make_unique< QgsProcessingContext >();
3989 context = tmpContext.get();
3990 }
3991
3992 mSourceCrs = QgsProcessingUtils::variantToCrs( value, *context );
3993 if ( mOperationWidget )
3994 {
3995 mOperationWidget->setSourceCrs( mSourceCrs );
3996 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
3997 }
3998 }
3999
setDestinationCrsParameterValue(const QVariant & value)4000 void QgsProcessingCoordinateOperationWidgetWrapper::setDestinationCrsParameterValue( const QVariant &value )
4001 {
4002 QgsProcessingContext *context = nullptr;
4003 std::unique_ptr< QgsProcessingContext > tmpContext;
4004 if ( mProcessingContextGenerator )
4005 context = mProcessingContextGenerator->processingContext();
4006
4007 if ( !context )
4008 {
4009 tmpContext = std::make_unique< QgsProcessingContext >();
4010 context = tmpContext.get();
4011 }
4012
4013 mDestCrs = QgsProcessingUtils::variantToCrs( value, *context );
4014 if ( mOperationWidget )
4015 {
4016 mOperationWidget->setDestinationCrs( mDestCrs );
4017 mOperationWidget->setSelectedOperationUsingContext( context->transformContext() );
4018 }
4019 }
4020
parameterType() const4021 QString QgsProcessingCoordinateOperationWidgetWrapper::parameterType() const
4022 {
4023 return QgsProcessingParameterCoordinateOperation::typeName();
4024 }
4025
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)4026 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingCoordinateOperationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4027 {
4028 return new QgsProcessingCoordinateOperationWidgetWrapper( parameter, type );
4029 }
4030
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)4031 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingCoordinateOperationWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4032 {
4033 return new QgsProcessingCoordinateOperationParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4034 }
4035
4036
4037
4038 //
4039 // QgsProcessingFieldPanelWidget
4040 //
4041
QgsProcessingFieldPanelWidget(QWidget * parent,const QgsProcessingParameterField * param)4042 QgsProcessingFieldPanelWidget::QgsProcessingFieldPanelWidget( QWidget *parent, const QgsProcessingParameterField *param )
4043 : QWidget( parent )
4044 , mParam( param )
4045 {
4046 QHBoxLayout *hl = new QHBoxLayout();
4047 hl->setContentsMargins( 0, 0, 0, 0 );
4048
4049 mLineEdit = new QLineEdit();
4050 mLineEdit->setEnabled( false );
4051 hl->addWidget( mLineEdit, 1 );
4052
4053 mToolButton = new QToolButton();
4054 mToolButton->setText( QString( QChar( 0x2026 ) ) );
4055 hl->addWidget( mToolButton );
4056
4057 setLayout( hl );
4058
4059 if ( mParam )
4060 {
4061 mLineEdit->setText( tr( "%1 options selected" ).arg( 0 ) );
4062 }
4063
4064 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingFieldPanelWidget::showDialog );
4065 }
4066
setFields(const QgsFields & fields)4067 void QgsProcessingFieldPanelWidget::setFields( const QgsFields &fields )
4068 {
4069 mFields = fields;
4070 }
4071
setValue(const QVariant & value)4072 void QgsProcessingFieldPanelWidget::setValue( const QVariant &value )
4073 {
4074 if ( value.isValid() )
4075 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
4076 else
4077 mValue.clear();
4078
4079 updateSummaryText();
4080 emit changed();
4081 }
4082
showDialog()4083 void QgsProcessingFieldPanelWidget::showDialog()
4084 {
4085 QVariantList availableOptions;
4086 QStringList fieldNames;
4087 availableOptions.reserve( mFields.size() );
4088 for ( const QgsField &field : std::as_const( mFields ) )
4089 {
4090 availableOptions << field.name();
4091 }
4092
4093 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
4094 if ( panel && panel->dockMode() )
4095 {
4096 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
4097 widget->setPanelTitle( mParam->description() );
4098
4099 widget->setValueFormatter( []( const QVariant & v ) -> QString
4100 {
4101 return v.toString();
4102 } );
4103
4104 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
4105 {
4106 setValue( widget->selectedOptions() );
4107 } );
4108 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
4109 panel->openPanel( widget );
4110 }
4111 else
4112 {
4113 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
4114
4115 dlg.setValueFormatter( []( const QVariant & v ) -> QString
4116 {
4117 return v.toString();
4118 } );
4119 if ( dlg.exec() )
4120 {
4121 setValue( dlg.selectedOptions() );
4122 }
4123 }
4124 }
4125
updateSummaryText()4126 void QgsProcessingFieldPanelWidget::updateSummaryText()
4127 {
4128 if ( mParam )
4129 mLineEdit->setText( tr( "%1 options selected" ).arg( mValue.count() ) );
4130 }
4131
4132
4133 //
4134 // QgsProcessingFieldWidgetWrapper
4135 //
4136
QgsProcessingFieldParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)4137 QgsProcessingFieldParameterDefinitionWidget::QgsProcessingFieldParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4138 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4139 {
4140 QVBoxLayout *vlayout = new QVBoxLayout();
4141 vlayout->setContentsMargins( 0, 0, 0, 0 );
4142
4143 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
4144 mParentLayerComboBox = new QComboBox();
4145
4146 QString initialParent;
4147 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4148 initialParent = fieldParam->parentLayerParameterName();
4149
4150 if ( auto *lModel = widgetContext.model() )
4151 {
4152 // populate combo box with other model input choices
4153 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
4154 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
4155 {
4156 if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4157 {
4158 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4159 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4160 {
4161 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4162 }
4163 }
4164 else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4165 {
4166 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4167 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4168 {
4169 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4170 }
4171 }
4172 else if ( const QgsProcessingParameterMultipleLayers *definition = dynamic_cast< const QgsProcessingParameterMultipleLayers * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
4173 {
4174 if ( definition->layerType() == QgsProcessing::TypeVector )
4175 {
4176 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
4177 if ( !initialParent.isEmpty() && initialParent == definition->name() )
4178 {
4179 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4180 }
4181 }
4182 }
4183 }
4184 }
4185
4186 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
4187 {
4188 // if no parent candidates found, we just add the existing one as a placeholder
4189 mParentLayerComboBox->addItem( initialParent, initialParent );
4190 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
4191 }
4192
4193 vlayout->addWidget( mParentLayerComboBox );
4194
4195 vlayout->addWidget( new QLabel( tr( "Allowed data type" ) ) );
4196 mDataTypeComboBox = new QComboBox();
4197 mDataTypeComboBox->addItem( tr( "Any" ), QgsProcessingParameterField::Any );
4198 mDataTypeComboBox->addItem( tr( "Number" ), QgsProcessingParameterField::Numeric );
4199 mDataTypeComboBox->addItem( tr( "String" ), QgsProcessingParameterField::String );
4200 mDataTypeComboBox->addItem( tr( "Date/time" ), QgsProcessingParameterField::DateTime );
4201 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4202 mDataTypeComboBox->setCurrentIndex( mDataTypeComboBox->findData( fieldParam->dataType() ) );
4203
4204 vlayout->addWidget( mDataTypeComboBox );
4205
4206 mAllowMultipleCheckBox = new QCheckBox( tr( "Accept multiple fields" ) );
4207 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4208 mAllowMultipleCheckBox->setChecked( fieldParam->allowMultiple() );
4209
4210 vlayout->addWidget( mAllowMultipleCheckBox );
4211
4212 mDefaultToAllCheckBox = new QCheckBox( tr( "Select all fields by default" ) );
4213 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4214 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4215 mDefaultToAllCheckBox->setChecked( fieldParam->defaultToAllFields() );
4216
4217 vlayout->addWidget( mDefaultToAllCheckBox );
4218
4219 connect( mAllowMultipleCheckBox, &QCheckBox::stateChanged, this, [ = ]
4220 {
4221 mDefaultToAllCheckBox->setEnabled( mAllowMultipleCheckBox->isChecked() );
4222 } );
4223
4224 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4225
4226 mDefaultLineEdit = new QLineEdit();
4227 mDefaultLineEdit->setToolTip( tr( "Default field name, or ; separated list of field names for multiple field parameters" ) );
4228 if ( const QgsProcessingParameterField *fieldParam = dynamic_cast<const QgsProcessingParameterField *>( definition ) )
4229 {
4230 const QStringList fields = QgsProcessingParameters::parameterAsFields( fieldParam, fieldParam->defaultValueForGui(), context );
4231 mDefaultLineEdit->setText( fields.join( ';' ) );
4232 }
4233 vlayout->addWidget( mDefaultLineEdit );
4234
4235 setLayout( vlayout );
4236 }
4237
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const4238 QgsProcessingParameterDefinition *QgsProcessingFieldParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4239 {
4240 QgsProcessingParameterField::DataType dataType = static_cast< QgsProcessingParameterField::DataType >( mDataTypeComboBox->currentData().toInt() );
4241
4242 QVariant defaultValue;
4243 if ( !mDefaultLineEdit->text().trimmed().isEmpty() )
4244 {
4245 defaultValue = mDefaultLineEdit->text();
4246 }
4247 auto param = std::make_unique< QgsProcessingParameterField >( name, description, defaultValue, mParentLayerComboBox->currentData().toString(), dataType, mAllowMultipleCheckBox->isChecked(), false, mDefaultToAllCheckBox->isChecked() );
4248 param->setFlags( flags );
4249 return param.release();
4250 }
4251
QgsProcessingFieldWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)4252 QgsProcessingFieldWidgetWrapper::QgsProcessingFieldWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4253 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4254 {
4255
4256 }
4257
createWidget()4258 QWidget *QgsProcessingFieldWidgetWrapper::createWidget()
4259 {
4260 const QgsProcessingParameterField *fieldParam = dynamic_cast< const QgsProcessingParameterField *>( parameterDefinition() );
4261 switch ( type() )
4262 {
4263 case QgsProcessingGui::Standard:
4264 case QgsProcessingGui::Batch:
4265 {
4266 if ( fieldParam->allowMultiple() )
4267 {
4268 mPanel = new QgsProcessingFieldPanelWidget( nullptr, fieldParam );
4269 mPanel->setToolTip( parameterDefinition()->toolTip() );
4270 connect( mPanel, &QgsProcessingFieldPanelWidget::changed, this, [ = ]
4271 {
4272 emit widgetValueHasChanged( this );
4273 } );
4274 return mPanel;
4275 }
4276 else
4277 {
4278 mComboBox = new QgsFieldComboBox();
4279 mComboBox->setAllowEmptyFieldName( fieldParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
4280
4281 if ( fieldParam->dataType() == QgsProcessingParameterField::Numeric )
4282 mComboBox->setFilters( QgsFieldProxyModel::Numeric );
4283 else if ( fieldParam->dataType() == QgsProcessingParameterField::String )
4284 mComboBox->setFilters( QgsFieldProxyModel::String );
4285 else if ( fieldParam->dataType() == QgsProcessingParameterField::DateTime )
4286 mComboBox->setFilters( QgsFieldProxyModel::Date | QgsFieldProxyModel::Time | QgsFieldProxyModel::DateTime );
4287
4288 mComboBox->setToolTip( parameterDefinition()->toolTip() );
4289 connect( mComboBox, &QgsFieldComboBox::fieldChanged, this, [ = ]( const QString & )
4290 {
4291 emit widgetValueHasChanged( this );
4292 } );
4293 return mComboBox;
4294 }
4295 }
4296
4297 case QgsProcessingGui::Modeler:
4298 {
4299 mLineEdit = new QLineEdit();
4300 mLineEdit->setToolTip( QObject::tr( "Name of field (separate field names with ; for multiple field parameters)" ) );
4301 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
4302 {
4303 emit widgetValueHasChanged( this );
4304 } );
4305 return mLineEdit;
4306 }
4307
4308 }
4309 return nullptr;
4310 }
4311
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)4312 void QgsProcessingFieldWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
4313 {
4314 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
4315 switch ( type() )
4316 {
4317 case QgsProcessingGui::Standard:
4318 case QgsProcessingGui::Batch:
4319 {
4320 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
4321 {
4322 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterField * >( parameterDefinition() )->parentLayerParameterName() )
4323 {
4324 setParentLayerWrapperValue( wrapper );
4325 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
4326 {
4327 setParentLayerWrapperValue( wrapper );
4328 } );
4329 break;
4330 }
4331 }
4332 break;
4333 }
4334
4335 case QgsProcessingGui::Modeler:
4336 break;
4337 }
4338 }
4339
setParentLayerWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)4340 void QgsProcessingFieldWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
4341 {
4342 // evaluate value to layer
4343 QgsProcessingContext *context = nullptr;
4344 std::unique_ptr< QgsProcessingContext > tmpContext;
4345 if ( mProcessingContextGenerator )
4346 context = mProcessingContextGenerator->processingContext();
4347
4348 if ( !context )
4349 {
4350 tmpContext = std::make_unique< QgsProcessingContext >();
4351 context = tmpContext.get();
4352 }
4353
4354 QVariant value = parentWrapper->parameterValue();
4355
4356 if ( value.canConvert<QgsProcessingFeatureSourceDefinition>() )
4357 {
4358 // input is a QgsProcessingFeatureSourceDefinition - source from it.
4359 // this is normally discouraged, and algorithms should NEVER do this -- but in this case we can make
4360 // certain assumptions due to the fact that we're calling this outside of algorithm/model execution and all sources
4361 // should be real map layers at this stage
4362 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
4363 value = fromVar.source;
4364 }
4365
4366 bool valueSet = false;
4367 const QList< QgsMapLayer * > layers = QgsProcessingParameters::parameterAsLayerList( parentWrapper->parameterDefinition(), value, *context );
4368
4369 // several layers, populate with intersection of layers fields
4370 if ( layers.count() > 1 )
4371 {
4372 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4373 QgsFields fields = vlayer && vlayer->isValid() ? vlayer->fields() : QgsFields();
4374 const QList< QgsMapLayer * > remainingLayers = layers.mid( 1 );
4375 for ( QgsMapLayer *layer : remainingLayers )
4376 {
4377 if ( fields.isEmpty() )
4378 break;
4379
4380 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer );
4381 if ( !vlayer || !vlayer->isValid() )
4382 {
4383 fields = QgsFields();
4384 break;
4385 }
4386
4387 for ( int fieldIdx = fields.count() - 1; fieldIdx >= 0; fieldIdx-- )
4388 {
4389 if ( vlayer->fields().lookupField( fields.at( fieldIdx ).name() ) < 0 )
4390 fields.remove( fieldIdx );
4391 }
4392 }
4393
4394 if ( mComboBox )
4395 mComboBox->setFields( fields );
4396 else if ( mPanel )
4397 mPanel->setFields( filterFields( fields ) );
4398
4399 valueSet = true;
4400 }
4401
4402 // only one layer
4403 if ( !valueSet && !layers.isEmpty() && layers.at( 0 )->isValid() )
4404 {
4405 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( layers.at( 0 ) );
4406
4407 // need to grab ownership of layer if required - otherwise layer may be deleted when context
4408 // goes out of scope
4409 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
4410 if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
4411 {
4412 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
4413 layer = mParentLayer.get();
4414 }
4415 else
4416 {
4417 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
4418 }
4419
4420 if ( mComboBox )
4421 mComboBox->setLayer( layer );
4422 else if ( mPanel )
4423 mPanel->setFields( filterFields( layer->fields() ) );
4424
4425 valueSet = true;
4426 }
4427
4428 if ( !valueSet )
4429 {
4430 std::unique_ptr< QgsProcessingFeatureSource > source( QgsProcessingParameters::parameterAsSource( parentWrapper->parameterDefinition(), value, *context ) );
4431 if ( source )
4432 {
4433 const QgsFields fields = source->fields();
4434 if ( mComboBox )
4435 mComboBox->setFields( fields );
4436 else if ( mPanel )
4437 mPanel->setFields( filterFields( fields ) );
4438
4439 valueSet = true;
4440 }
4441 }
4442
4443 if ( !valueSet )
4444 {
4445 if ( mComboBox )
4446 mComboBox->setLayer( nullptr );
4447 else if ( mPanel )
4448 mPanel->setFields( QgsFields() );
4449
4450 if ( value.isValid() && widgetContext().messageBar() )
4451 {
4452 widgetContext().messageBar()->clearWidgets();
4453 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent field could not be populated" ),
4454 Qgis::MessageLevel::Info );
4455 }
4456 return;
4457 }
4458
4459 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4460 if ( mPanel && fieldParam->defaultToAllFields() )
4461 {
4462 QVariantList val;
4463 val.reserve( mPanel->fields().size() );
4464 for ( const QgsField &field : mPanel->fields() )
4465 val << field.name();
4466 setWidgetValue( val, *context );
4467 }
4468 else if ( fieldParam->defaultValueForGui().isValid() )
4469 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
4470 }
4471
setWidgetValue(const QVariant & value,QgsProcessingContext & context)4472 void QgsProcessingFieldWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4473 {
4474 if ( mComboBox )
4475 {
4476 if ( !value.isValid() )
4477 mComboBox->setField( QString() );
4478 else
4479 {
4480 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4481 mComboBox->setField( v );
4482 }
4483 }
4484 else if ( mPanel )
4485 {
4486 QVariantList opts;
4487 if ( value.isValid() )
4488 {
4489 const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4490 opts.reserve( v.size() );
4491 for ( const QString &i : v )
4492 opts << i;
4493 }
4494 if ( mPanel )
4495 mPanel->setValue( opts );
4496 }
4497 else if ( mLineEdit )
4498 {
4499 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4500 if ( fieldParam->allowMultiple() )
4501 {
4502 const QStringList v = QgsProcessingParameters::parameterAsFields( parameterDefinition(), value, context );
4503 mLineEdit->setText( v.join( ';' ) );
4504 }
4505 else
4506 {
4507 mLineEdit->setText( QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context ) );
4508 }
4509 }
4510 }
4511
widgetValue() const4512 QVariant QgsProcessingFieldWidgetWrapper::widgetValue() const
4513 {
4514 if ( mComboBox )
4515 return mComboBox->currentField();
4516 else if ( mPanel )
4517 return mPanel->value();
4518 else if ( mLineEdit )
4519 {
4520 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4521 if ( fieldParam->allowMultiple() )
4522 {
4523 return mLineEdit->text().split( ';' );
4524 }
4525 else
4526 return mLineEdit->text();
4527 }
4528 else
4529 return QVariant();
4530 }
4531
compatibleParameterTypes() const4532 QStringList QgsProcessingFieldWidgetWrapper::compatibleParameterTypes() const
4533 {
4534 return QStringList()
4535 << QgsProcessingParameterField::typeName()
4536 << QgsProcessingParameterString::typeName();
4537 }
4538
compatibleOutputTypes() const4539 QStringList QgsProcessingFieldWidgetWrapper::compatibleOutputTypes() const
4540 {
4541 return QStringList()
4542 << QgsProcessingOutputString::typeName();
4543 }
4544
modelerExpressionFormatString() const4545 QString QgsProcessingFieldWidgetWrapper::modelerExpressionFormatString() const
4546 {
4547 return tr( "selected field names as an array of names, or semicolon separated string of options (e.g. 'fid;place_name')" );
4548 }
4549
linkedVectorLayer() const4550 const QgsVectorLayer *QgsProcessingFieldWidgetWrapper::linkedVectorLayer() const
4551 {
4552 if ( mComboBox && mComboBox->layer() )
4553 return mComboBox->layer();
4554
4555 return QgsAbstractProcessingParameterWidgetWrapper::linkedVectorLayer();
4556 }
4557
filterFields(const QgsFields & fields) const4558 QgsFields QgsProcessingFieldWidgetWrapper::filterFields( const QgsFields &fields ) const
4559 {
4560 const QgsProcessingParameterField *fieldParam = static_cast< const QgsProcessingParameterField * >( parameterDefinition() );
4561 QgsFields res;
4562 for ( const QgsField &f : fields )
4563 {
4564 switch ( fieldParam->dataType() )
4565 {
4566 case QgsProcessingParameterField::Any:
4567 res.append( f );
4568 break;
4569
4570 case QgsProcessingParameterField::Numeric:
4571 if ( f.isNumeric() )
4572 res.append( f );
4573 break;
4574
4575 case QgsProcessingParameterField::String:
4576 if ( f.type() == QVariant::String )
4577 res.append( f );
4578 break;
4579
4580 case QgsProcessingParameterField::DateTime:
4581 if ( f.type() == QVariant::Date || f.type() == QVariant::Time || f.type() == QVariant::DateTime )
4582 res.append( f );
4583 break;
4584 }
4585 }
4586
4587 return res;
4588 }
4589
parameterType() const4590 QString QgsProcessingFieldWidgetWrapper::parameterType() const
4591 {
4592 return QgsProcessingParameterField::typeName();
4593 }
4594
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)4595 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFieldWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4596 {
4597 return new QgsProcessingFieldWidgetWrapper( parameter, type );
4598 }
4599
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)4600 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFieldWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4601 {
4602 return new QgsProcessingFieldParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4603 }
4604
4605 //
4606 // QgsProcessingMapThemeWidgetWrapper
4607 //
4608
4609
QgsProcessingMapThemeParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)4610 QgsProcessingMapThemeParameterDefinitionWidget::QgsProcessingMapThemeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4611 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4612 {
4613 QVBoxLayout *vlayout = new QVBoxLayout();
4614 vlayout->setContentsMargins( 0, 0, 0, 0 );
4615
4616 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4617
4618 mDefaultComboBox = new QComboBox();
4619 mDefaultComboBox->addItem( QString(), QVariant( -1 ) );
4620
4621 const QStringList mapThemes = widgetContext.project() ? widgetContext.project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
4622 for ( const QString &theme : mapThemes )
4623 {
4624 mDefaultComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4625 }
4626 mDefaultComboBox->setEditable( true );
4627
4628 if ( const QgsProcessingParameterMapTheme *themeParam = dynamic_cast<const QgsProcessingParameterMapTheme *>( definition ) )
4629 {
4630 if ( themeParam->defaultValueForGui().isValid() )
4631 mDefaultComboBox->setCurrentText( QgsProcessingParameters::parameterAsString( themeParam, themeParam->defaultValueForGui(), context ) );
4632 else
4633 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4634 }
4635 else
4636 mDefaultComboBox->setCurrentIndex( mDefaultComboBox->findData( -1 ) );
4637
4638 vlayout->addWidget( mDefaultComboBox );
4639
4640 setLayout( vlayout );
4641 }
4642
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const4643 QgsProcessingParameterDefinition *QgsProcessingMapThemeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4644 {
4645 QVariant defaultVal;
4646 if ( mDefaultComboBox->currentText().isEmpty() )
4647 defaultVal = QVariant();
4648 else
4649 defaultVal = mDefaultComboBox->currentText();
4650 auto param = std::make_unique< QgsProcessingParameterMapTheme>( name, description, defaultVal );
4651 param->setFlags( flags );
4652 return param.release();
4653 }
4654
4655
QgsProcessingMapThemeWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)4656 QgsProcessingMapThemeWidgetWrapper::QgsProcessingMapThemeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4657 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4658 {
4659
4660 }
4661
createWidget()4662 QWidget *QgsProcessingMapThemeWidgetWrapper::createWidget()
4663 {
4664 const QgsProcessingParameterMapTheme *themeParam = dynamic_cast< const QgsProcessingParameterMapTheme *>( parameterDefinition() );
4665
4666 mComboBox = new QComboBox();
4667
4668 if ( themeParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
4669 mComboBox->addItem( tr( "[Not selected]" ), QVariant( -1 ) );
4670
4671 const QStringList mapThemes = widgetContext().project() ? widgetContext().project()->mapThemeCollection()->mapThemes() : QgsProject::instance()->mapThemeCollection()->mapThemes();
4672 for ( const QString &theme : mapThemes )
4673 {
4674 mComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), theme, theme );
4675 }
4676
4677 switch ( type() )
4678 {
4679 case QgsProcessingGui::Standard:
4680 case QgsProcessingGui::Batch:
4681 break;
4682
4683 case QgsProcessingGui::Modeler:
4684 mComboBox->setEditable( true );
4685 break;
4686 }
4687
4688 mComboBox->setToolTip( parameterDefinition()->toolTip() );
4689 connect( mComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
4690 {
4691 emit widgetValueHasChanged( this );
4692 } );
4693
4694 return mComboBox;
4695 }
4696
setWidgetValue(const QVariant & value,QgsProcessingContext & context)4697 void QgsProcessingMapThemeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4698 {
4699 const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
4700
4701 if ( !value.isValid() )
4702 mComboBox->setCurrentIndex( mComboBox->findData( QVariant( -1 ) ) );
4703 else
4704 {
4705 if ( mComboBox->isEditable() && mComboBox->findData( v ) == -1 )
4706 {
4707 const QString prev = mComboBox->currentText();
4708 mComboBox->setCurrentText( v );
4709 if ( prev != v )
4710 emit widgetValueHasChanged( this );
4711 }
4712 else
4713 mComboBox->setCurrentIndex( mComboBox->findData( v ) );
4714 }
4715 }
4716
widgetValue() const4717 QVariant QgsProcessingMapThemeWidgetWrapper::widgetValue() const
4718 {
4719 if ( mComboBox )
4720 return mComboBox->currentData().toInt() == -1 ? QVariant() :
4721 !mComboBox->currentData().isValid() && mComboBox->isEditable() ? mComboBox->currentText().isEmpty() ? QVariant() : QVariant( mComboBox->currentText() )
4722 : mComboBox->currentData();
4723 else
4724 return QVariant();
4725 }
4726
compatibleParameterTypes() const4727 QStringList QgsProcessingMapThemeWidgetWrapper::compatibleParameterTypes() const
4728 {
4729 return QStringList()
4730 << QgsProcessingParameterString::typeName()
4731 << QgsProcessingParameterExpression::typeName();
4732 }
4733
compatibleOutputTypes() const4734 QStringList QgsProcessingMapThemeWidgetWrapper::compatibleOutputTypes() const
4735 {
4736 return QStringList()
4737 << QgsProcessingOutputString::typeName();
4738 }
4739
modelerExpressionFormatString() const4740 QString QgsProcessingMapThemeWidgetWrapper::modelerExpressionFormatString() const
4741 {
4742 return tr( "map theme as a string value (e.g. 'base maps')" );
4743 }
4744
parameterType() const4745 QString QgsProcessingMapThemeWidgetWrapper::parameterType() const
4746 {
4747 return QgsProcessingParameterMapTheme::typeName();
4748 }
4749
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)4750 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapThemeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4751 {
4752 return new QgsProcessingMapThemeWidgetWrapper( parameter, type );
4753 }
4754
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)4755 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapThemeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4756 {
4757 return new QgsProcessingMapThemeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4758 }
4759
4760
4761
4762 //
4763 // QgsProcessingDateTimeWidgetWrapper
4764 //
4765
4766
QgsProcessingDateTimeParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)4767 QgsProcessingDateTimeParameterDefinitionWidget::QgsProcessingDateTimeParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4768 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4769 {
4770 QVBoxLayout *vlayout = new QVBoxLayout();
4771 vlayout->setContentsMargins( 0, 0, 0, 0 );
4772
4773 vlayout->addWidget( new QLabel( tr( "Type" ) ) );
4774
4775 mTypeComboBox = new QComboBox();
4776 mTypeComboBox->addItem( tr( "Date and Time" ), QgsProcessingParameterDateTime::DateTime );
4777 mTypeComboBox->addItem( tr( "Date" ), QgsProcessingParameterDateTime::Date );
4778 mTypeComboBox->addItem( tr( "Time" ), QgsProcessingParameterDateTime::Time );
4779 if ( const QgsProcessingParameterDateTime *datetimeParam = dynamic_cast<const QgsProcessingParameterDateTime *>( definition ) )
4780 mTypeComboBox->setCurrentIndex( mTypeComboBox->findData( datetimeParam->dataType() ) );
4781 else
4782 mTypeComboBox->setCurrentIndex( 0 );
4783 vlayout->addWidget( mTypeComboBox );
4784
4785 setLayout( vlayout );
4786 }
4787
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const4788 QgsProcessingParameterDefinition *QgsProcessingDateTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4789 {
4790 auto param = std::make_unique< QgsProcessingParameterDateTime >( name, description );
4791 param->setDataType( static_cast< QgsProcessingParameterDateTime::Type >( mTypeComboBox->currentData().toInt() ) );
4792 param->setFlags( flags );
4793 return param.release();
4794 }
4795
4796
QgsProcessingDateTimeWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)4797 QgsProcessingDateTimeWidgetWrapper::QgsProcessingDateTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4798 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4799 {
4800
4801 }
4802
createWidget()4803 QWidget *QgsProcessingDateTimeWidgetWrapper::createWidget()
4804 {
4805 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
4806
4807 QgsDateTimeEdit *widget = nullptr;
4808 switch ( dateTimeParam->dataType() )
4809 {
4810 case QgsProcessingParameterDateTime::DateTime:
4811 mDateTimeEdit = new QgsDateTimeEdit();
4812 widget = mDateTimeEdit;
4813 break;
4814
4815 case QgsProcessingParameterDateTime::Date:
4816 mDateEdit = new QgsDateEdit();
4817 widget = mDateEdit;
4818 break;
4819
4820 case QgsProcessingParameterDateTime::Time:
4821 mTimeEdit = new QgsTimeEdit();
4822 widget = mTimeEdit;
4823 break;
4824 }
4825
4826 if ( dateTimeParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
4827 {
4828 widget->setNullRepresentation( tr( "[Not selected]" ) );
4829 widget->setAllowNull( true );
4830 }
4831 else
4832 {
4833 widget->setAllowNull( false );
4834 }
4835 widget->setToolTip( parameterDefinition()->toolTip() );
4836
4837 if ( mDateTimeEdit )
4838 {
4839 connect( mDateTimeEdit, &QgsDateTimeEdit::valueChanged, this, [ = ]( const QDateTime & )
4840 {
4841 emit widgetValueHasChanged( this );
4842 } );
4843 }
4844 else if ( mDateEdit )
4845 {
4846 connect( mDateEdit, &QgsDateEdit::dateValueChanged, this, [ = ]( const QDate & )
4847 {
4848 emit widgetValueHasChanged( this );
4849 } );
4850 }
4851 else if ( mTimeEdit )
4852 {
4853 connect( mTimeEdit, &QgsTimeEdit::timeValueChanged, this, [ = ]( const QTime & )
4854 {
4855 emit widgetValueHasChanged( this );
4856 } );
4857 }
4858
4859 return widget;
4860 }
4861
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)4862 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDateTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
4863 {
4864 return new QgsProcessingDateTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
4865 }
4866
setWidgetValue(const QVariant & value,QgsProcessingContext & context)4867 void QgsProcessingDateTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
4868 {
4869 if ( mDateTimeEdit )
4870 {
4871 mDateTimeEdit->setDateTime( QgsProcessingParameters::parameterAsDateTime( parameterDefinition(), value, context ) );
4872 }
4873 else if ( mDateEdit )
4874 {
4875 mDateEdit->setDate( QgsProcessingParameters::parameterAsDate( parameterDefinition(), value, context ) );
4876 }
4877 else if ( mTimeEdit )
4878 {
4879 mTimeEdit->setTime( QgsProcessingParameters::parameterAsTime( parameterDefinition(), value, context ) );
4880 }
4881 }
4882
widgetValue() const4883 QVariant QgsProcessingDateTimeWidgetWrapper::widgetValue() const
4884 {
4885 if ( mDateTimeEdit )
4886 return !mDateTimeEdit->dateTime().isNull() && mDateTimeEdit->dateTime().isValid() ? QVariant( mDateTimeEdit->dateTime() ) : QVariant();
4887 else if ( mDateEdit )
4888 return !mDateEdit->date().isNull() && mDateEdit->date().isValid() ? QVariant( mDateEdit->date() ) : QVariant();
4889 else if ( mTimeEdit )
4890 return !mTimeEdit->time().isNull() && mTimeEdit->time().isValid() ? QVariant( mTimeEdit->time() ) : QVariant();
4891 else
4892 return QVariant();
4893 }
4894
compatibleParameterTypes() const4895 QStringList QgsProcessingDateTimeWidgetWrapper::compatibleParameterTypes() const
4896 {
4897 return QStringList()
4898 << QgsProcessingParameterDateTime::typeName()
4899 << QgsProcessingParameterString::typeName();
4900 }
4901
compatibleOutputTypes() const4902 QStringList QgsProcessingDateTimeWidgetWrapper::compatibleOutputTypes() const
4903 {
4904 return QStringList()
4905 << QgsProcessingOutputString::typeName();
4906 }
4907
modelerExpressionFormatString() const4908 QString QgsProcessingDateTimeWidgetWrapper::modelerExpressionFormatString() const
4909 {
4910 const QgsProcessingParameterDateTime *dateTimeParam = dynamic_cast< const QgsProcessingParameterDateTime *>( parameterDefinition() );
4911 if ( dateTimeParam )
4912 {
4913 switch ( dateTimeParam->dataType() )
4914 {
4915 case QgsProcessingParameterDateTime::DateTime:
4916 return tr( "datetime value, or a ISO string representation of a datetime" );
4917
4918 case QgsProcessingParameterDateTime::Date:
4919 return tr( "date value, or a ISO string representation of a date" );
4920
4921 case QgsProcessingParameterDateTime::Time:
4922 return tr( "time value, or a ISO string representation of a time" );
4923 }
4924 }
4925 return QString();
4926 }
4927
parameterType() const4928 QString QgsProcessingDateTimeWidgetWrapper::parameterType() const
4929 {
4930 return QgsProcessingParameterDateTime::typeName();
4931 }
4932
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)4933 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDateTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
4934 {
4935 return new QgsProcessingDateTimeWidgetWrapper( parameter, type );
4936 }
4937
4938
4939
4940 //
4941 // QgsProcessingProviderConnectionWidgetWrapper
4942 //
4943
QgsProcessingProviderConnectionParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)4944 QgsProcessingProviderConnectionParameterDefinitionWidget::QgsProcessingProviderConnectionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
4945 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
4946 {
4947 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( definition );
4948
4949 QVBoxLayout *vlayout = new QVBoxLayout();
4950 vlayout->setContentsMargins( 0, 0, 0, 0 );
4951
4952 vlayout->addWidget( new QLabel( tr( "Provider" ) ) );
4953 mProviderComboBox = new QComboBox();
4954 mProviderComboBox->addItem( QObject::tr( "Postgres" ), QStringLiteral( "postgres" ) );
4955 mProviderComboBox->addItem( QObject::tr( "GeoPackage" ), QStringLiteral( "ogr" ) );
4956 mProviderComboBox->addItem( QObject::tr( "Spatialite" ), QStringLiteral( "spatialite" ) );
4957
4958 vlayout->addWidget( mProviderComboBox );
4959
4960 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
4961
4962 mDefaultEdit = new QLineEdit();
4963 vlayout->addWidget( mDefaultEdit );
4964 setLayout( vlayout );
4965
4966 if ( connectionParam )
4967 {
4968 mProviderComboBox->setCurrentIndex( mProviderComboBox->findData( connectionParam->providerId() ) );
4969 mDefaultEdit->setText( connectionParam->defaultValueForGui().toString() );
4970 }
4971 }
4972
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const4973 QgsProcessingParameterDefinition *QgsProcessingProviderConnectionParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
4974 {
4975 QVariant defaultVal;
4976 if ( mDefaultEdit->text().isEmpty() )
4977 defaultVal = QVariant();
4978 else
4979 defaultVal = mDefaultEdit->text();
4980 auto param = std::make_unique< QgsProcessingParameterProviderConnection>( name, description, mProviderComboBox->currentData().toString(), defaultVal );
4981 param->setFlags( flags );
4982 return param.release();
4983 }
4984
4985
QgsProcessingProviderConnectionWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)4986 QgsProcessingProviderConnectionWidgetWrapper::QgsProcessingProviderConnectionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
4987 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
4988 {
4989
4990 }
4991
createWidget()4992 QWidget *QgsProcessingProviderConnectionWidgetWrapper::createWidget()
4993 {
4994 const QgsProcessingParameterProviderConnection *connectionParam = dynamic_cast< const QgsProcessingParameterProviderConnection *>( parameterDefinition() );
4995
4996 mProviderComboBox = new QgsProviderConnectionComboBox( connectionParam->providerId() );
4997 if ( connectionParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
4998 mProviderComboBox->setAllowEmptyConnection( true );
4999
5000 switch ( type() )
5001 {
5002 case QgsProcessingGui::Standard:
5003 case QgsProcessingGui::Batch:
5004 break;
5005 case QgsProcessingGui::Modeler:
5006 mProviderComboBox->setEditable( true );
5007 break;
5008 }
5009
5010 mProviderComboBox->setToolTip( parameterDefinition()->toolTip() );
5011 connect( mProviderComboBox, &QgsProviderConnectionComboBox::currentTextChanged, this, [ = ]( const QString & )
5012 {
5013 if ( mBlockSignals )
5014 return;
5015
5016 emit widgetValueHasChanged( this );
5017 } );
5018
5019 return mProviderComboBox;
5020 }
5021
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)5022 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingProviderConnectionWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5023 {
5024 return new QgsProcessingProviderConnectionParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5025 }
5026
setWidgetValue(const QVariant & value,QgsProcessingContext & context)5027 void QgsProcessingProviderConnectionWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5028 {
5029 const QString v = QgsProcessingParameters::parameterAsConnectionName( parameterDefinition(), value, context );
5030
5031 if ( !value.isValid() )
5032 mProviderComboBox->setCurrentIndex( -1 );
5033 else
5034 {
5035 if ( mProviderComboBox->isEditable() )
5036 {
5037 const QString prev = mProviderComboBox->currentText();
5038 mBlockSignals++;
5039 mProviderComboBox->setConnection( v );
5040 mProviderComboBox->setCurrentText( v );
5041
5042 mBlockSignals--;
5043 if ( prev != v )
5044 emit widgetValueHasChanged( this );
5045 }
5046 else
5047 mProviderComboBox->setConnection( v );
5048 }
5049 }
5050
widgetValue() const5051 QVariant QgsProcessingProviderConnectionWidgetWrapper::widgetValue() const
5052 {
5053 if ( mProviderComboBox )
5054 if ( mProviderComboBox->isEditable() )
5055 return mProviderComboBox->currentText().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentText() );
5056 else
5057 return mProviderComboBox->currentConnection().isEmpty() ? QVariant() : QVariant( mProviderComboBox->currentConnection() );
5058 else
5059 return QVariant();
5060 }
5061
compatibleParameterTypes() const5062 QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleParameterTypes() const
5063 {
5064 return QStringList()
5065 << QgsProcessingParameterProviderConnection::typeName()
5066 << QgsProcessingParameterString::typeName()
5067 << QgsProcessingParameterExpression::typeName();
5068 }
5069
compatibleOutputTypes() const5070 QStringList QgsProcessingProviderConnectionWidgetWrapper::compatibleOutputTypes() const
5071 {
5072 return QStringList()
5073 << QgsProcessingOutputString::typeName();
5074 }
5075
modelerExpressionFormatString() const5076 QString QgsProcessingProviderConnectionWidgetWrapper::modelerExpressionFormatString() const
5077 {
5078 return tr( "connection name as a string value" );
5079 }
5080
parameterType() const5081 QString QgsProcessingProviderConnectionWidgetWrapper::parameterType() const
5082 {
5083 return QgsProcessingParameterProviderConnection::typeName();
5084 }
5085
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)5086 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingProviderConnectionWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5087 {
5088 return new QgsProcessingProviderConnectionWidgetWrapper( parameter, type );
5089 }
5090
5091
5092
5093
5094 //
5095 // QgsProcessingDatabaseSchemaWidgetWrapper
5096 //
5097
QgsProcessingDatabaseSchemaParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)5098 QgsProcessingDatabaseSchemaParameterDefinitionWidget::QgsProcessingDatabaseSchemaParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5099 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5100 {
5101 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( definition );
5102
5103 QVBoxLayout *vlayout = new QVBoxLayout();
5104 vlayout->setContentsMargins( 0, 0, 0, 0 );
5105
5106 mConnectionParamComboBox = new QComboBox();
5107 QString initialConnection;
5108 if ( schemaParam )
5109 {
5110 initialConnection = schemaParam->parentConnectionParameterName();
5111 }
5112
5113 if ( auto *lModel = widgetContext.model() )
5114 {
5115 // populate combo box with other model input choices
5116 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5117 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5118 {
5119 if ( definition && it->parameterName() == definition->name() )
5120 continue;
5121
5122 if ( !dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5123 continue;
5124
5125 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5126 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5127 {
5128 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5129 }
5130 }
5131 }
5132
5133 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5134 {
5135 // if no candidates found, we just add the existing one as a placeholder
5136 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5137 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5138 }
5139
5140 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5141 vlayout->addWidget( mConnectionParamComboBox );
5142
5143 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5144
5145 mDefaultEdit = new QLineEdit();
5146 vlayout->addWidget( mDefaultEdit );
5147 setLayout( vlayout );
5148
5149 if ( schemaParam )
5150 {
5151 mDefaultEdit->setText( schemaParam->defaultValueForGui().toString() );
5152 }
5153 }
5154
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const5155 QgsProcessingParameterDefinition *QgsProcessingDatabaseSchemaParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5156 {
5157 QVariant defaultVal;
5158 if ( mDefaultEdit->text().isEmpty() )
5159 defaultVal = QVariant();
5160 else
5161 defaultVal = mDefaultEdit->text();
5162 auto param = std::make_unique< QgsProcessingParameterDatabaseSchema>( name, description, mConnectionParamComboBox->currentData().toString(), defaultVal );
5163 param->setFlags( flags );
5164 return param.release();
5165 }
5166
5167
QgsProcessingDatabaseSchemaWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)5168 QgsProcessingDatabaseSchemaWidgetWrapper::QgsProcessingDatabaseSchemaWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5169 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5170 {
5171
5172 }
5173
createWidget()5174 QWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createWidget()
5175 {
5176 const QgsProcessingParameterDatabaseSchema *schemaParam = dynamic_cast< const QgsProcessingParameterDatabaseSchema *>( parameterDefinition() );
5177
5178 mSchemaComboBox = new QgsDatabaseSchemaComboBox( QString(), QString() );
5179 if ( schemaParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
5180 mSchemaComboBox->setAllowEmptySchema( true );
5181
5182 switch ( type() )
5183 {
5184 case QgsProcessingGui::Standard:
5185 case QgsProcessingGui::Batch:
5186 break;
5187 case QgsProcessingGui::Modeler:
5188 mSchemaComboBox->comboBox()->setEditable( true );
5189 break;
5190 }
5191
5192 mSchemaComboBox->setToolTip( parameterDefinition()->toolTip() );
5193 connect( mSchemaComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5194 {
5195 if ( mBlockSignals )
5196 return;
5197
5198 emit widgetValueHasChanged( this );
5199 } );
5200
5201 return mSchemaComboBox;
5202 }
5203
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)5204 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseSchemaWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5205 {
5206 return new QgsProcessingDatabaseSchemaParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5207 }
5208
setParentConnectionWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)5209 void QgsProcessingDatabaseSchemaWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5210 {
5211 // evaluate value to connection
5212 QgsProcessingContext *context = nullptr;
5213 std::unique_ptr< QgsProcessingContext > tmpContext;
5214 if ( mProcessingContextGenerator )
5215 context = mProcessingContextGenerator->processingContext();
5216
5217 if ( !context )
5218 {
5219 tmpContext = std::make_unique< QgsProcessingContext >();
5220 context = tmpContext.get();
5221 }
5222
5223 const QVariant value = parentWrapper->parameterValue();
5224 const QString connection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5225
5226 if ( mSchemaComboBox )
5227 mSchemaComboBox->setConnectionName( connection, qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId() );
5228
5229 const QgsProcessingParameterDatabaseSchema *schemaParam = qgis::down_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() );
5230 if ( schemaParam->defaultValueForGui().isValid() )
5231 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5232 }
5233
setWidgetValue(const QVariant & value,QgsProcessingContext & context)5234 void QgsProcessingDatabaseSchemaWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5235 {
5236 const QString v = QgsProcessingParameters::parameterAsSchema( parameterDefinition(), value, context );
5237
5238 if ( !value.isValid() )
5239 mSchemaComboBox->comboBox()->setCurrentIndex( -1 );
5240 else
5241 {
5242 if ( mSchemaComboBox->comboBox()->isEditable() )
5243 {
5244 const QString prev = mSchemaComboBox->comboBox()->currentText();
5245 mBlockSignals++;
5246 mSchemaComboBox->setSchema( v );
5247 mSchemaComboBox->comboBox()->setCurrentText( v );
5248
5249 mBlockSignals--;
5250 if ( prev != v )
5251 emit widgetValueHasChanged( this );
5252 }
5253 else
5254 mSchemaComboBox->setSchema( v );
5255 }
5256 }
5257
widgetValue() const5258 QVariant QgsProcessingDatabaseSchemaWidgetWrapper::widgetValue() const
5259 {
5260 if ( mSchemaComboBox )
5261 if ( mSchemaComboBox->comboBox()->isEditable() )
5262 return mSchemaComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->comboBox()->currentText() );
5263 else
5264 return mSchemaComboBox->currentSchema().isEmpty() ? QVariant() : QVariant( mSchemaComboBox->currentSchema() );
5265 else
5266 return QVariant();
5267 }
5268
compatibleParameterTypes() const5269 QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleParameterTypes() const
5270 {
5271 return QStringList()
5272 << QgsProcessingParameterProviderConnection::typeName()
5273 << QgsProcessingParameterString::typeName()
5274 << QgsProcessingParameterExpression::typeName();
5275 }
5276
compatibleOutputTypes() const5277 QStringList QgsProcessingDatabaseSchemaWidgetWrapper::compatibleOutputTypes() const
5278 {
5279 return QStringList()
5280 << QgsProcessingOutputString::typeName();
5281 }
5282
modelerExpressionFormatString() const5283 QString QgsProcessingDatabaseSchemaWidgetWrapper::modelerExpressionFormatString() const
5284 {
5285 return tr( "database schema name as a string value" );
5286 }
5287
parameterType() const5288 QString QgsProcessingDatabaseSchemaWidgetWrapper::parameterType() const
5289 {
5290 return QgsProcessingParameterDatabaseSchema::typeName();
5291 }
5292
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)5293 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseSchemaWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5294 {
5295 return new QgsProcessingDatabaseSchemaWidgetWrapper( parameter, type );
5296 }
5297
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)5298 void QgsProcessingDatabaseSchemaWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5299 {
5300 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
5301 switch ( type() )
5302 {
5303 case QgsProcessingGui::Standard:
5304 case QgsProcessingGui::Batch:
5305 {
5306 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5307 {
5308 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseSchema * >( parameterDefinition() )->parentConnectionParameterName() )
5309 {
5310 setParentConnectionWrapperValue( wrapper );
5311 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
5312 {
5313 setParentConnectionWrapperValue( wrapper );
5314 } );
5315 break;
5316 }
5317 }
5318 break;
5319 }
5320
5321 case QgsProcessingGui::Modeler:
5322 break;
5323 }
5324 }
5325
5326
5327
5328 //
5329 // QgsProcessingDatabaseTableWidgetWrapper
5330 //
5331
QgsProcessingDatabaseTableParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)5332 QgsProcessingDatabaseTableParameterDefinitionWidget::QgsProcessingDatabaseTableParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5333 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5334 {
5335 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( definition );
5336
5337 QVBoxLayout *vlayout = new QVBoxLayout();
5338 vlayout->setContentsMargins( 0, 0, 0, 0 );
5339
5340 mConnectionParamComboBox = new QComboBox();
5341 mSchemaParamComboBox = new QComboBox();
5342 QString initialConnection;
5343 QString initialSchema;
5344 if ( tableParam )
5345 {
5346 initialConnection = tableParam->parentConnectionParameterName();
5347 initialSchema = tableParam->parentSchemaParameterName();
5348 }
5349
5350 if ( auto *lModel = widgetContext.model() )
5351 {
5352 // populate combo box with other model input choices
5353 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
5354 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
5355 {
5356 if ( definition && it->parameterName() == definition->name() )
5357 continue;
5358
5359 if ( dynamic_cast< const QgsProcessingParameterProviderConnection * >( lModel->parameterDefinition( it->parameterName() ) ) )
5360 {
5361 mConnectionParamComboBox->addItem( it->parameterName(), it->parameterName() );
5362 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5363 {
5364 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5365 }
5366 }
5367 else if ( dynamic_cast< const QgsProcessingParameterDatabaseSchema * >( lModel->parameterDefinition( it->parameterName() ) ) )
5368 {
5369 mSchemaParamComboBox->addItem( it->parameterName(), it->parameterName() );
5370 if ( !initialConnection.isEmpty() && initialConnection == it->parameterName() )
5371 {
5372 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5373 }
5374 }
5375 }
5376 }
5377
5378 if ( mConnectionParamComboBox->count() == 0 && !initialConnection.isEmpty() )
5379 {
5380 // if no candidates found, we just add the existing one as a placeholder
5381 mConnectionParamComboBox->addItem( initialConnection, initialConnection );
5382 mConnectionParamComboBox->setCurrentIndex( mConnectionParamComboBox->count() - 1 );
5383 }
5384
5385 if ( mSchemaParamComboBox->count() == 0 && !initialSchema.isEmpty() )
5386 {
5387 // if no candidates found, we just add the existing one as a placeholder
5388 mSchemaParamComboBox->addItem( initialSchema, initialSchema );
5389 mSchemaParamComboBox->setCurrentIndex( mSchemaParamComboBox->count() - 1 );
5390 }
5391
5392 vlayout->addWidget( new QLabel( tr( "Provider connection parameter" ) ) );
5393 vlayout->addWidget( mConnectionParamComboBox );
5394
5395 vlayout->addWidget( new QLabel( tr( "Database schema parameter" ) ) );
5396 vlayout->addWidget( mSchemaParamComboBox );
5397
5398 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5399
5400 mDefaultEdit = new QLineEdit();
5401 vlayout->addWidget( mDefaultEdit );
5402 setLayout( vlayout );
5403
5404 if ( tableParam )
5405 {
5406 mDefaultEdit->setText( tableParam->defaultValueForGui().toString() );
5407 }
5408 }
5409
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const5410 QgsProcessingParameterDefinition *QgsProcessingDatabaseTableParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5411 {
5412 QVariant defaultVal;
5413 if ( mDefaultEdit->text().isEmpty() )
5414 defaultVal = QVariant();
5415 else
5416 defaultVal = mDefaultEdit->text();
5417 auto param = std::make_unique< QgsProcessingParameterDatabaseTable>( name, description,
5418 mConnectionParamComboBox->currentData().toString(),
5419 mSchemaParamComboBox->currentData().toString(),
5420 defaultVal );
5421 param->setFlags( flags );
5422 return param.release();
5423 }
5424
5425
QgsProcessingDatabaseTableWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)5426 QgsProcessingDatabaseTableWidgetWrapper::QgsProcessingDatabaseTableWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5427 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5428 {
5429
5430 }
5431
createWidget()5432 QWidget *QgsProcessingDatabaseTableWidgetWrapper::createWidget()
5433 {
5434 const QgsProcessingParameterDatabaseTable *tableParam = dynamic_cast< const QgsProcessingParameterDatabaseTable *>( parameterDefinition() );
5435
5436 mTableComboBox = new QgsDatabaseTableComboBox( QString(), QString() );
5437 if ( tableParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
5438 mTableComboBox->setAllowEmptyTable( true );
5439
5440 if ( type() == QgsProcessingGui::Modeler || tableParam->allowNewTableNames() )
5441 mTableComboBox->comboBox()->setEditable( true );
5442
5443 mTableComboBox->setToolTip( parameterDefinition()->toolTip() );
5444 connect( mTableComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
5445 {
5446 if ( mBlockSignals )
5447 return;
5448
5449 emit widgetValueHasChanged( this );
5450 } );
5451
5452 return mTableComboBox;
5453 }
5454
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)5455 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingDatabaseTableWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5456 {
5457 return new QgsProcessingDatabaseTableParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5458 }
5459
setParentConnectionWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)5460 void QgsProcessingDatabaseTableWidgetWrapper::setParentConnectionWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5461 {
5462 // evaluate value to connection
5463 QgsProcessingContext *context = nullptr;
5464 std::unique_ptr< QgsProcessingContext > tmpContext;
5465 if ( mProcessingContextGenerator )
5466 context = mProcessingContextGenerator->processingContext();
5467
5468 if ( !context )
5469 {
5470 tmpContext = std::make_unique< QgsProcessingContext >();
5471 context = tmpContext.get();
5472 }
5473
5474 QVariant value = parentWrapper->parameterValue();
5475 mConnection = value.isValid() ? QgsProcessingParameters::parameterAsConnectionName( parentWrapper->parameterDefinition(), value, *context ) : QString();
5476 mProvider = qgis::down_cast< const QgsProcessingParameterProviderConnection * >( parentWrapper->parameterDefinition() )->providerId();
5477 if ( mTableComboBox && !mSchema.isEmpty() )
5478 {
5479 mTableComboBox->setSchema( mSchema );
5480 mTableComboBox->setConnectionName( mConnection, mProvider );
5481
5482 const QgsProcessingParameterDatabaseTable *tableParam = qgis::down_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5483 if ( tableParam->defaultValueForGui().isValid() )
5484 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5485 }
5486 }
5487
setParentSchemaWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)5488 void QgsProcessingDatabaseTableWidgetWrapper::setParentSchemaWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
5489 {
5490 // evaluate value to schema
5491 QgsProcessingContext *context = nullptr;
5492 std::unique_ptr< QgsProcessingContext > tmpContext;
5493 if ( mProcessingContextGenerator )
5494 context = mProcessingContextGenerator->processingContext();
5495
5496 if ( !context )
5497 {
5498 tmpContext = std::make_unique< QgsProcessingContext >();
5499 context = tmpContext.get();
5500 }
5501
5502 QVariant value = parentWrapper->parameterValue();
5503 mSchema = value.isValid() ? QgsProcessingParameters::parameterAsSchema( parentWrapper->parameterDefinition(), value, *context ) : QString();
5504
5505 if ( mTableComboBox && !mSchema.isEmpty() && !mConnection.isEmpty() )
5506 {
5507 mTableComboBox->setSchema( mSchema );
5508 mTableComboBox->setConnectionName( mConnection, mProvider );
5509
5510 const QgsProcessingParameterDatabaseTable *tableParam = static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() );
5511 if ( tableParam->defaultValueForGui().isValid() )
5512 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
5513 }
5514
5515 }
5516
setWidgetValue(const QVariant & value,QgsProcessingContext & context)5517 void QgsProcessingDatabaseTableWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5518 {
5519 const QString v = QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition(), value, context );
5520
5521 if ( !value.isValid() )
5522 mTableComboBox->comboBox()->setCurrentIndex( -1 );
5523 else
5524 {
5525 if ( mTableComboBox->comboBox()->isEditable() )
5526 {
5527 const QString prev = mTableComboBox->comboBox()->currentText();
5528 mBlockSignals++;
5529 mTableComboBox->setTable( v );
5530 mTableComboBox->comboBox()->setCurrentText( v );
5531
5532 mBlockSignals--;
5533 if ( prev != v )
5534 emit widgetValueHasChanged( this );
5535 }
5536 else
5537 mTableComboBox->setTable( v );
5538 }
5539 }
5540
widgetValue() const5541 QVariant QgsProcessingDatabaseTableWidgetWrapper::widgetValue() const
5542 {
5543 if ( mTableComboBox )
5544 if ( mTableComboBox->comboBox()->isEditable() )
5545 return mTableComboBox->comboBox()->currentText().isEmpty() ? QVariant() : QVariant( mTableComboBox->comboBox()->currentText() );
5546 else
5547 return mTableComboBox->currentTable().isEmpty() ? QVariant() : QVariant( mTableComboBox->currentTable() );
5548 else
5549 return QVariant();
5550 }
5551
compatibleParameterTypes() const5552 QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleParameterTypes() const
5553 {
5554 return QStringList()
5555 << QgsProcessingParameterProviderConnection::typeName()
5556 << QgsProcessingParameterString::typeName()
5557 << QgsProcessingParameterExpression::typeName();
5558 }
5559
compatibleOutputTypes() const5560 QStringList QgsProcessingDatabaseTableWidgetWrapper::compatibleOutputTypes() const
5561 {
5562 return QStringList()
5563 << QgsProcessingOutputString::typeName();
5564 }
5565
modelerExpressionFormatString() const5566 QString QgsProcessingDatabaseTableWidgetWrapper::modelerExpressionFormatString() const
5567 {
5568 return tr( "database table name as a string value" );
5569 }
5570
parameterType() const5571 QString QgsProcessingDatabaseTableWidgetWrapper::parameterType() const
5572 {
5573 return QgsProcessingParameterDatabaseTable::typeName();
5574 }
5575
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)5576 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDatabaseTableWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5577 {
5578 return new QgsProcessingDatabaseTableWidgetWrapper( parameter, type );
5579 }
5580
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)5581 void QgsProcessingDatabaseTableWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
5582 {
5583 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
5584 switch ( type() )
5585 {
5586 case QgsProcessingGui::Standard:
5587 case QgsProcessingGui::Batch:
5588 {
5589 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
5590 {
5591 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentConnectionParameterName() )
5592 {
5593 setParentConnectionWrapperValue( wrapper );
5594 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
5595 {
5596 setParentConnectionWrapperValue( wrapper );
5597 } );
5598 }
5599 else if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDatabaseTable * >( parameterDefinition() )->parentSchemaParameterName() )
5600 {
5601 setParentSchemaWrapperValue( wrapper );
5602 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
5603 {
5604 setParentSchemaWrapperValue( wrapper );
5605 } );
5606 }
5607 }
5608 break;
5609 }
5610
5611 case QgsProcessingGui::Modeler:
5612 break;
5613 }
5614 }
5615
5616
5617 //
5618 // QgsProcessingExtentWidgetWrapper
5619 //
5620
QgsProcessingExtentParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)5621 QgsProcessingExtentParameterDefinitionWidget::QgsProcessingExtentParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5622 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5623 {
5624 QVBoxLayout *vlayout = new QVBoxLayout();
5625 vlayout->setContentsMargins( 0, 0, 0, 0 );
5626
5627 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
5628
5629 mDefaultWidget = new QgsExtentWidget();
5630 mDefaultWidget->setNullValueAllowed( true, tr( "Not set" ) );
5631 if ( const QgsProcessingParameterExtent *extentParam = dynamic_cast<const QgsProcessingParameterExtent *>( definition ) )
5632 {
5633 if ( extentParam->defaultValueForGui().isValid() )
5634 {
5635 QgsRectangle rect = QgsProcessingParameters::parameterAsExtent( extentParam, extentParam->defaultValueForGui(), context );
5636 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsExtentCrs( extentParam, extentParam->defaultValueForGui(), context );
5637 mDefaultWidget->setCurrentExtent( rect, crs );
5638 mDefaultWidget->setOutputExtentFromCurrent();
5639 }
5640 else
5641 {
5642 mDefaultWidget->clear();
5643 }
5644 }
5645
5646 vlayout->addWidget( mDefaultWidget );
5647 setLayout( vlayout );
5648 }
5649
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const5650 QgsProcessingParameterDefinition *QgsProcessingExtentParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5651 {
5652 const QString defaultVal = mDefaultWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5653 QString::number( mDefaultWidget->outputExtent().xMinimum(), 'f', 9 ),
5654 QString::number( mDefaultWidget->outputExtent().xMaximum(), 'f', 9 ),
5655 QString::number( mDefaultWidget->outputExtent().yMinimum(), 'f', 9 ),
5656 QString::number( mDefaultWidget->outputExtent().yMaximum(), 'f', 9 ),
5657 mDefaultWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mDefaultWidget->outputCrs().authid() ) : QString()
5658 ) : QString();
5659 auto param = std::make_unique< QgsProcessingParameterExtent >( name, description, !defaultVal.isEmpty() ? QVariant( defaultVal ) : QVariant() );
5660 param->setFlags( flags );
5661 return param.release();
5662 }
5663
5664
5665
QgsProcessingExtentWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)5666 QgsProcessingExtentWidgetWrapper::QgsProcessingExtentWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5667 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5668 {
5669
5670 }
5671
createWidget()5672 QWidget *QgsProcessingExtentWidgetWrapper::createWidget()
5673 {
5674 const QgsProcessingParameterExtent *extentParam = dynamic_cast< const QgsProcessingParameterExtent *>( parameterDefinition() );
5675 switch ( type() )
5676 {
5677 case QgsProcessingGui::Standard:
5678 case QgsProcessingGui::Batch:
5679 case QgsProcessingGui::Modeler:
5680 {
5681 mExtentWidget = new QgsExtentWidget( nullptr );
5682 if ( widgetContext().mapCanvas() )
5683 mExtentWidget->setMapCanvas( widgetContext().mapCanvas() );
5684
5685 if ( extentParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
5686 mExtentWidget->setNullValueAllowed( true, tr( "Not set" ) );
5687
5688 mExtentWidget->setToolTip( parameterDefinition()->toolTip() );
5689
5690 connect( mExtentWidget, &QgsExtentWidget::extentChanged, this, [ = ]
5691 {
5692 emit widgetValueHasChanged( this );
5693 } );
5694
5695 if ( mDialog && type() != QgsProcessingGui::Modeler )
5696 setDialog( mDialog ); // setup connections to panel - dialog was previously set before the widget was created
5697
5698 return mExtentWidget;
5699 }
5700 }
5701 return nullptr;
5702 }
5703
setWidgetContext(const QgsProcessingParameterWidgetContext & context)5704 void QgsProcessingExtentWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5705 {
5706 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
5707 if ( mExtentWidget && context.mapCanvas() && type() != QgsProcessingGui::Modeler )
5708 mExtentWidget->setMapCanvas( context.mapCanvas() );
5709 }
5710
setDialog(QDialog * dialog)5711 void QgsProcessingExtentWidgetWrapper::setDialog( QDialog *dialog )
5712 {
5713 mDialog = dialog;
5714 if ( mExtentWidget && mDialog && type() != QgsProcessingGui::Modeler )
5715 {
5716 connect( mExtentWidget, &QgsExtentWidget::toggleDialogVisibility, mDialog, [ = ]( bool visible )
5717 {
5718 if ( !visible )
5719 mDialog->showMinimized();
5720 else
5721 {
5722 mDialog->showNormal();
5723 mDialog->raise();
5724 mDialog->activateWindow();
5725 }
5726 } );
5727 }
5728 QgsAbstractProcessingParameterWidgetWrapper::setDialog( dialog );
5729 }
5730
setWidgetValue(const QVariant & value,QgsProcessingContext & context)5731 void QgsProcessingExtentWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5732 {
5733 if ( mExtentWidget )
5734 {
5735 if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
5736 mExtentWidget->clear();
5737 else
5738 {
5739 QgsRectangle r = QgsProcessingParameters::parameterAsExtent( parameterDefinition(), value, context );
5740 QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsPointCrs( parameterDefinition(), value, context );
5741 mExtentWidget->setCurrentExtent( r, crs );
5742 mExtentWidget->setOutputExtentFromUser( r, crs );
5743 }
5744 }
5745 }
5746
widgetValue() const5747 QVariant QgsProcessingExtentWidgetWrapper::widgetValue() const
5748 {
5749 if ( mExtentWidget )
5750 {
5751 const QString val = mExtentWidget->isValid() ? QStringLiteral( "%1,%2,%3,%4%5" ).arg(
5752 QString::number( mExtentWidget->outputExtent().xMinimum(), 'f', 9 ),
5753 QString::number( mExtentWidget->outputExtent().xMaximum(), 'f', 9 ),
5754 QString::number( mExtentWidget->outputExtent().yMinimum(), 'f', 9 ),
5755 QString::number( mExtentWidget->outputExtent().yMaximum(), 'f', 9 ),
5756 mExtentWidget->outputCrs().isValid() ? QStringLiteral( " [%1]" ).arg( mExtentWidget->outputCrs().authid() ) : QString()
5757 ) : QString();
5758
5759 return val.isEmpty() ? QVariant() : QVariant( val );
5760 }
5761 else
5762 return QVariant();
5763 }
5764
compatibleParameterTypes() const5765 QStringList QgsProcessingExtentWidgetWrapper::compatibleParameterTypes() const
5766 {
5767 return QStringList()
5768 << QgsProcessingParameterExtent::typeName()
5769 << QgsProcessingParameterString::typeName()
5770 << QgsProcessingParameterMapLayer::typeName()
5771 << QgsProcessingParameterFeatureSource::typeName()
5772 << QgsProcessingParameterRasterLayer::typeName()
5773 << QgsProcessingParameterVectorLayer::typeName()
5774 << QgsProcessingParameterMeshLayer::typeName()
5775 << QgsProcessingParameterPointCloudLayer::typeName()
5776 << QgsProcessingParameterAnnotationLayer::typeName();
5777 }
5778
compatibleOutputTypes() const5779 QStringList QgsProcessingExtentWidgetWrapper::compatibleOutputTypes() const
5780 {
5781 return QStringList()
5782 << QgsProcessingOutputString::typeName()
5783 << QgsProcessingOutputRasterLayer::typeName()
5784 << QgsProcessingOutputVectorLayer::typeName()
5785 << QgsProcessingOutputMapLayer::typeName();
5786 }
5787
modelerExpressionFormatString() const5788 QString QgsProcessingExtentWidgetWrapper::modelerExpressionFormatString() const
5789 {
5790 return tr( "string of the format 'x min,x max,y min,y max' or a geometry value (bounding box is used)" );
5791 }
5792
parameterType() const5793 QString QgsProcessingExtentWidgetWrapper::parameterType() const
5794 {
5795 return QgsProcessingParameterExtent::typeName();
5796 }
5797
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)5798 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingExtentWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5799 {
5800 return new QgsProcessingExtentWidgetWrapper( parameter, type );
5801 }
5802
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)5803 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingExtentWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5804 {
5805 return new QgsProcessingExtentParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5806 }
5807
5808
5809
5810 //
5811 // QgsProcessingMapLayerWidgetWrapper
5812 //
5813
QgsProcessingMapLayerParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)5814 QgsProcessingMapLayerParameterDefinitionWidget::QgsProcessingMapLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
5815 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
5816 {
5817 QVBoxLayout *vlayout = new QVBoxLayout();
5818 vlayout->setContentsMargins( 0, 0, 0, 0 );
5819
5820 vlayout->addWidget( new QLabel( tr( "Layer type" ) ) );
5821 mLayerTypeComboBox = new QgsCheckableComboBox();
5822 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
5823 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
5824 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
5825 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
5826 mLayerTypeComboBox->addItem( tr( "Vector (Any Geometry Type)" ), QgsProcessing::TypeVectorAnyGeometry );
5827 mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
5828 mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
5829 mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );
5830 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), QgsProcessing::TypePointCloud );
5831 mLayerTypeComboBox->addItem( tr( "Annotation" ), QgsProcessing::TypeAnnotation );
5832
5833 if ( const QgsProcessingParameterMapLayer *layerParam = dynamic_cast<const QgsProcessingParameterMapLayer *>( definition ) )
5834 {
5835 for ( int i : layerParam->dataTypes() )
5836 {
5837 mLayerTypeComboBox->setItemCheckState( mLayerTypeComboBox->findData( i ), Qt::Checked );
5838 }
5839 }
5840
5841 vlayout->addWidget( mLayerTypeComboBox );
5842
5843 setLayout( vlayout );
5844 }
5845
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const5846 QgsProcessingParameterDefinition *QgsProcessingMapLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
5847 {
5848 QList< int > dataTypes;
5849 for ( const QVariant &v : mLayerTypeComboBox->checkedItemsData() )
5850 dataTypes << v.toInt();
5851
5852 auto param = std::make_unique< QgsProcessingParameterMapLayer >( name, description );
5853 param->setDataTypes( dataTypes );
5854 param->setFlags( flags );
5855 return param.release();
5856 }
5857
QgsProcessingMapLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)5858 QgsProcessingMapLayerWidgetWrapper::QgsProcessingMapLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5859 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
5860 {
5861
5862 }
5863
createWidget()5864 QWidget *QgsProcessingMapLayerWidgetWrapper::createWidget()
5865 {
5866 mComboBox = new QgsProcessingMapLayerComboBox( parameterDefinition(), type() );
5867
5868 switch ( type() )
5869 {
5870 case QgsProcessingGui::Standard:
5871 case QgsProcessingGui::Batch:
5872 break;
5873 case QgsProcessingGui::Modeler:
5874 mComboBox->setEditable( true );
5875 break;
5876 }
5877
5878 mComboBox->setToolTip( parameterDefinition()->toolTip() );
5879
5880 connect( mComboBox, &QgsProcessingMapLayerComboBox::valueChanged, this, [ = ]()
5881 {
5882 if ( mBlockSignals )
5883 return;
5884
5885 emit widgetValueHasChanged( this );
5886 } );
5887
5888 setWidgetContext( widgetContext() );
5889 return mComboBox;
5890 }
5891
setWidgetContext(const QgsProcessingParameterWidgetContext & context)5892 void QgsProcessingMapLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
5893 {
5894 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
5895 if ( mComboBox )
5896 {
5897 mComboBox->setWidgetContext( context );
5898
5899 if ( !( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional ) )
5900 {
5901 // non optional parameter -- if no default value set, default to active layer
5902 if ( !parameterDefinition()->defaultValueForGui().isValid() )
5903 mComboBox->setLayer( context.activeLayer() );
5904 }
5905 }
5906 }
5907
setWidgetValue(const QVariant & value,QgsProcessingContext & context)5908 void QgsProcessingMapLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
5909 {
5910 if ( mComboBox )
5911 mComboBox->setValue( value, context );
5912 }
5913
widgetValue() const5914 QVariant QgsProcessingMapLayerWidgetWrapper::widgetValue() const
5915 {
5916 return mComboBox ? mComboBox->value() : QVariant();
5917 }
5918
compatibleParameterTypes() const5919 QStringList QgsProcessingMapLayerWidgetWrapper::compatibleParameterTypes() const
5920 {
5921 return QStringList()
5922 << QgsProcessingParameterRasterLayer::typeName()
5923 << QgsProcessingParameterMeshLayer::typeName()
5924 << QgsProcessingParameterVectorLayer::typeName()
5925 << QgsProcessingParameterMapLayer::typeName()
5926 << QgsProcessingParameterPointCloudLayer::typeName()
5927 << QgsProcessingParameterAnnotationLayer::typeName()
5928 << QgsProcessingParameterString::typeName()
5929 << QgsProcessingParameterExpression::typeName();
5930 }
5931
compatibleOutputTypes() const5932 QStringList QgsProcessingMapLayerWidgetWrapper::compatibleOutputTypes() const
5933 {
5934 return QStringList()
5935 << QgsProcessingOutputString::typeName()
5936 << QgsProcessingOutputRasterLayer::typeName()
5937 << QgsProcessingOutputVectorLayer::typeName()
5938 << QgsProcessingOutputMapLayer::typeName()
5939 << QgsProcessingOutputFile::typeName();
5940 }
5941
modelerExpressionFormatString() const5942 QString QgsProcessingMapLayerWidgetWrapper::modelerExpressionFormatString() const
5943 {
5944 return tr( "path to a map layer" );
5945 }
5946
parameterType() const5947 QString QgsProcessingMapLayerWidgetWrapper::parameterType() const
5948 {
5949 return QgsProcessingParameterMapLayer::typeName();
5950 }
5951
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)5952 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMapLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
5953 {
5954 return new QgsProcessingMapLayerWidgetWrapper( parameter, type );
5955 }
5956
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)5957 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMapLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
5958 {
5959 return new QgsProcessingMapLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
5960 }
5961
5962
5963 //
5964 // QgsProcessingRasterLayerWidgetWrapper
5965 //
5966
QgsProcessingRasterLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)5967 QgsProcessingRasterLayerWidgetWrapper::QgsProcessingRasterLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
5968 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
5969 {
5970
5971 }
5972
compatibleParameterTypes() const5973 QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleParameterTypes() const
5974 {
5975 return QStringList()
5976 << QgsProcessingParameterRasterLayer::typeName()
5977 << QgsProcessingParameterMapLayer::typeName()
5978 << QgsProcessingParameterString::typeName()
5979 << QgsProcessingParameterExpression::typeName();
5980 }
5981
compatibleOutputTypes() const5982 QStringList QgsProcessingRasterLayerWidgetWrapper::compatibleOutputTypes() const
5983 {
5984 return QStringList()
5985 << QgsProcessingOutputString::typeName()
5986 << QgsProcessingOutputRasterLayer::typeName()
5987 << QgsProcessingOutputMapLayer::typeName()
5988 << QgsProcessingOutputFile::typeName()
5989 << QgsProcessingOutputFolder::typeName();
5990 }
5991
modelerExpressionFormatString() const5992 QString QgsProcessingRasterLayerWidgetWrapper::modelerExpressionFormatString() const
5993 {
5994 return tr( "path to a raster layer" );
5995 }
5996
parameterType() const5997 QString QgsProcessingRasterLayerWidgetWrapper::parameterType() const
5998 {
5999 return QgsProcessingParameterRasterLayer::typeName();
6000 }
6001
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)6002 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6003 {
6004 return new QgsProcessingRasterLayerWidgetWrapper( parameter, type );
6005 }
6006
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)6007 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingRasterLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6008 {
6009 Q_UNUSED( context );
6010 Q_UNUSED( widgetContext );
6011 Q_UNUSED( definition );
6012 Q_UNUSED( algorithm );
6013
6014 return nullptr;
6015 }
6016
6017
6018 //
6019 // QgsProcessingVectorLayerWidgetWrapper
6020 //
6021
QgsProcessingVectorLayerParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)6022 QgsProcessingVectorLayerParameterDefinitionWidget::QgsProcessingVectorLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6023 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6024 {
6025 QVBoxLayout *vlayout = new QVBoxLayout();
6026 vlayout->setContentsMargins( 0, 0, 0, 0 );
6027
6028 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6029 mGeometryTypeComboBox = new QgsCheckableComboBox();
6030 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
6031 mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
6032 mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
6033 mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
6034 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6035
6036 if ( const QgsProcessingParameterVectorLayer *vectorParam = dynamic_cast<const QgsProcessingParameterVectorLayer *>( definition ) )
6037 {
6038 for ( int i : vectorParam->dataTypes() )
6039 {
6040 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6041 }
6042 }
6043
6044 vlayout->addWidget( mGeometryTypeComboBox );
6045
6046 setLayout( vlayout );
6047 }
6048
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const6049 QgsProcessingParameterDefinition *QgsProcessingVectorLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6050 {
6051 QList< int > dataTypes;
6052 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6053 dataTypes << v.toInt();
6054
6055 auto param = std::make_unique< QgsProcessingParameterVectorLayer >( name, description, dataTypes );
6056 param->setFlags( flags );
6057 return param.release();
6058 }
6059
6060
QgsProcessingVectorLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)6061 QgsProcessingVectorLayerWidgetWrapper::QgsProcessingVectorLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6062 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6063 {
6064
6065 }
6066
compatibleParameterTypes() const6067 QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleParameterTypes() const
6068 {
6069 return QStringList()
6070 << QgsProcessingParameterVectorLayer::typeName()
6071 << QgsProcessingParameterMapLayer::typeName()
6072 << QgsProcessingParameterString::typeName()
6073 << QgsProcessingParameterExpression::typeName();
6074 }
6075
compatibleOutputTypes() const6076 QStringList QgsProcessingVectorLayerWidgetWrapper::compatibleOutputTypes() const
6077 {
6078 return QStringList()
6079 << QgsProcessingOutputString::typeName()
6080 << QgsProcessingOutputVectorLayer::typeName()
6081 << QgsProcessingOutputMapLayer::typeName()
6082 << QgsProcessingOutputFile::typeName()
6083 << QgsProcessingOutputFolder::typeName();
6084 }
6085
modelerExpressionFormatString() const6086 QString QgsProcessingVectorLayerWidgetWrapper::modelerExpressionFormatString() const
6087 {
6088 return tr( "path to a vector layer" );
6089 }
6090
compatibleDataTypes(const QgsProcessingParameterDefinition * parameter) const6091 QList<int> QgsProcessingVectorLayerWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6092 {
6093 if ( const QgsProcessingParameterVectorLayer *param = dynamic_cast< const QgsProcessingParameterVectorLayer *>( parameter ) )
6094 return param->dataTypes();
6095 else
6096 return QList< int >();
6097 }
6098
parameterType() const6099 QString QgsProcessingVectorLayerWidgetWrapper::parameterType() const
6100 {
6101 return QgsProcessingParameterVectorLayer::typeName();
6102 }
6103
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)6104 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6105 {
6106 return new QgsProcessingVectorLayerWidgetWrapper( parameter, type );
6107 }
6108
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)6109 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingVectorLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6110 {
6111 return new QgsProcessingVectorLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6112 }
6113
6114
6115
6116 //
6117 // QgsProcessingFeatureSourceLayerWidgetWrapper
6118 //
6119
QgsProcessingFeatureSourceParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)6120 QgsProcessingFeatureSourceParameterDefinitionWidget::QgsProcessingFeatureSourceParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6121 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6122 {
6123 QVBoxLayout *vlayout = new QVBoxLayout();
6124 vlayout->setContentsMargins( 0, 0, 0, 0 );
6125
6126 vlayout->addWidget( new QLabel( tr( "Geometry type" ) ) );
6127 mGeometryTypeComboBox = new QgsCheckableComboBox();
6128 mGeometryTypeComboBox->addItem( tr( "Geometry Not Required" ), QgsProcessing::TypeVector );
6129 mGeometryTypeComboBox->addItem( tr( "Point" ), QgsProcessing::TypeVectorPoint );
6130 mGeometryTypeComboBox->addItem( tr( "Line" ), QgsProcessing::TypeVectorLine );
6131 mGeometryTypeComboBox->addItem( tr( "Polygon" ), QgsProcessing::TypeVectorPolygon );
6132 mGeometryTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6133
6134 if ( const QgsProcessingParameterFeatureSource *sourceParam = dynamic_cast<const QgsProcessingParameterFeatureSource *>( definition ) )
6135 {
6136 for ( int i : sourceParam->dataTypes() )
6137 {
6138 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( i ), Qt::Checked );
6139 }
6140 }
6141 else
6142 {
6143 mGeometryTypeComboBox->setItemCheckState( mGeometryTypeComboBox->findData( QgsProcessing::TypeVectorAnyGeometry ), Qt::Checked );
6144 }
6145
6146 vlayout->addWidget( mGeometryTypeComboBox );
6147
6148 setLayout( vlayout );
6149 }
6150
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const6151 QgsProcessingParameterDefinition *QgsProcessingFeatureSourceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6152 {
6153 QList< int > dataTypes;
6154 for ( const QVariant &v : mGeometryTypeComboBox->checkedItemsData() )
6155 dataTypes << v.toInt();
6156
6157 auto param = std::make_unique< QgsProcessingParameterFeatureSource >( name, description, dataTypes );
6158 param->setFlags( flags );
6159 return param.release();
6160 }
6161
QgsProcessingFeatureSourceWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)6162 QgsProcessingFeatureSourceWidgetWrapper::QgsProcessingFeatureSourceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6163 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6164 {
6165
6166 }
6167
compatibleParameterTypes() const6168 QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleParameterTypes() const
6169 {
6170 return QStringList()
6171 << QgsProcessingParameterFeatureSource::typeName()
6172 << QgsProcessingParameterVectorLayer::typeName()
6173 << QgsProcessingParameterMapLayer::typeName()
6174 << QgsProcessingParameterString::typeName()
6175 << QgsProcessingParameterExpression::typeName();
6176 }
6177
compatibleOutputTypes() const6178 QStringList QgsProcessingFeatureSourceWidgetWrapper::compatibleOutputTypes() const
6179 {
6180 return QStringList()
6181 << QgsProcessingOutputString::typeName()
6182 << QgsProcessingOutputVectorLayer::typeName()
6183 << QgsProcessingOutputMapLayer::typeName()
6184 << QgsProcessingOutputFile::typeName()
6185 << QgsProcessingOutputFolder::typeName();
6186 }
6187
modelerExpressionFormatString() const6188 QString QgsProcessingFeatureSourceWidgetWrapper::modelerExpressionFormatString() const
6189 {
6190 return tr( "path to a vector layer" );
6191 }
6192
compatibleDataTypes(const QgsProcessingParameterDefinition * parameter) const6193 QList<int> QgsProcessingFeatureSourceWidgetWrapper::compatibleDataTypes( const QgsProcessingParameterDefinition *parameter ) const
6194 {
6195 if ( const QgsProcessingParameterFeatureSource *param = dynamic_cast< const QgsProcessingParameterFeatureSource *>( parameter ) )
6196 return param->dataTypes();
6197 else
6198 return QList< int >();
6199 }
6200
parameterType() const6201 QString QgsProcessingFeatureSourceWidgetWrapper::parameterType() const
6202 {
6203 return QgsProcessingParameterFeatureSource::typeName();
6204 }
6205
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)6206 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSourceWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6207 {
6208 return new QgsProcessingFeatureSourceWidgetWrapper( parameter, type );
6209 }
6210
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)6211 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFeatureSourceWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6212 {
6213 return new QgsProcessingFeatureSourceParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6214 }
6215
6216 //
6217 // QgsProcessingMeshLayerWidgetWrapper
6218 //
6219
QgsProcessingMeshLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)6220 QgsProcessingMeshLayerWidgetWrapper::QgsProcessingMeshLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6221 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
6222 {
6223
6224 }
6225
compatibleParameterTypes() const6226 QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleParameterTypes() const
6227 {
6228 return QStringList()
6229 << QgsProcessingParameterMeshLayer::typeName()
6230 << QgsProcessingParameterMapLayer::typeName()
6231 << QgsProcessingParameterString::typeName()
6232 << QgsProcessingParameterExpression::typeName();
6233 }
6234
compatibleOutputTypes() const6235 QStringList QgsProcessingMeshLayerWidgetWrapper::compatibleOutputTypes() const
6236 {
6237 return QStringList()
6238 << QgsProcessingOutputString::typeName()
6239 // TODO << QgsProcessingOutputMeshLayer::typeName()
6240 << QgsProcessingOutputMapLayer::typeName()
6241 << QgsProcessingOutputFile::typeName()
6242 << QgsProcessingOutputFolder::typeName();
6243 }
6244
modelerExpressionFormatString() const6245 QString QgsProcessingMeshLayerWidgetWrapper::modelerExpressionFormatString() const
6246 {
6247 return tr( "path to a mesh layer" );
6248 }
6249
parameterType() const6250 QString QgsProcessingMeshLayerWidgetWrapper::parameterType() const
6251 {
6252 return QgsProcessingParameterMeshLayer::typeName();
6253 }
6254
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)6255 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6256 {
6257 return new QgsProcessingMeshLayerWidgetWrapper( parameter, type );
6258 }
6259
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)6260 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6261 {
6262 Q_UNUSED( context );
6263 Q_UNUSED( widgetContext );
6264 Q_UNUSED( definition );
6265 Q_UNUSED( algorithm );
6266
6267 return nullptr;
6268 }
6269
6270
6271
6272 //
6273 // QgsProcessingRasterBandPanelWidget
6274 //
6275
QgsProcessingRasterBandPanelWidget(QWidget * parent,const QgsProcessingParameterBand * param)6276 QgsProcessingRasterBandPanelWidget::QgsProcessingRasterBandPanelWidget( QWidget *parent, const QgsProcessingParameterBand *param )
6277 : QWidget( parent )
6278 , mParam( param )
6279 {
6280 QHBoxLayout *hl = new QHBoxLayout();
6281 hl->setContentsMargins( 0, 0, 0, 0 );
6282
6283 mLineEdit = new QLineEdit();
6284 mLineEdit->setEnabled( false );
6285 hl->addWidget( mLineEdit, 1 );
6286
6287 mToolButton = new QToolButton();
6288 mToolButton->setText( QString( QChar( 0x2026 ) ) );
6289 hl->addWidget( mToolButton );
6290
6291 setLayout( hl );
6292
6293 if ( mParam )
6294 {
6295 mLineEdit->setText( tr( "%1 bands selected" ).arg( 0 ) );
6296 }
6297
6298 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingRasterBandPanelWidget::showDialog );
6299 }
6300
setBands(const QList<int> & bands)6301 void QgsProcessingRasterBandPanelWidget::setBands( const QList< int > &bands )
6302 {
6303 mBands = bands;
6304 }
6305
setBandNames(const QHash<int,QString> & names)6306 void QgsProcessingRasterBandPanelWidget::setBandNames( const QHash<int, QString> &names )
6307 {
6308 mBandNames = names;
6309 }
6310
setValue(const QVariant & value)6311 void QgsProcessingRasterBandPanelWidget::setValue( const QVariant &value )
6312 {
6313 if ( value.isValid() )
6314 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
6315 else
6316 mValue.clear();
6317
6318 updateSummaryText();
6319 emit changed();
6320 }
6321
showDialog()6322 void QgsProcessingRasterBandPanelWidget::showDialog()
6323 {
6324 QVariantList availableOptions;
6325 QStringList fieldNames;
6326 availableOptions.reserve( mBands.size() );
6327 for ( int band : std::as_const( mBands ) )
6328 {
6329 availableOptions << band;
6330 }
6331
6332 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
6333 if ( panel && panel->dockMode() )
6334 {
6335 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
6336 widget->setPanelTitle( mParam->description() );
6337
6338 widget->setValueFormatter( [this]( const QVariant & v ) -> QString
6339 {
6340 int band = v.toInt();
6341 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6342 } );
6343
6344 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
6345 {
6346 setValue( widget->selectedOptions() );
6347 } );
6348 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
6349 panel->openPanel( widget );
6350 }
6351 else
6352 {
6353 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
6354
6355 dlg.setValueFormatter( [this]( const QVariant & v ) -> QString
6356 {
6357 int band = v.toInt();
6358 return mBandNames.contains( band ) ? mBandNames.value( band ) : v.toString();
6359 } );
6360 if ( dlg.exec() )
6361 {
6362 setValue( dlg.selectedOptions() );
6363 }
6364 }
6365 }
6366
updateSummaryText()6367 void QgsProcessingRasterBandPanelWidget::updateSummaryText()
6368 {
6369 if ( mParam )
6370 mLineEdit->setText( tr( "%1 bands selected" ).arg( mValue.count() ) );
6371 }
6372
6373
6374
6375 //
6376 // QgsProcessingBandWidgetWrapper
6377 //
6378
QgsProcessingBandParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)6379 QgsProcessingBandParameterDefinitionWidget::QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6380 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6381 {
6382 QVBoxLayout *vlayout = new QVBoxLayout();
6383 vlayout->setContentsMargins( 0, 0, 0, 0 );
6384
6385 vlayout->addWidget( new QLabel( tr( "Default value" ) ) );
6386
6387 mDefaultLineEdit = new QLineEdit();
6388 mDefaultLineEdit->setToolTip( tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6389 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6390 {
6391 const QList< int > bands = QgsProcessingParameters::parameterAsInts( bandParam, bandParam->defaultValueForGui(), context );
6392 QStringList defVal;
6393 for ( int b : bands )
6394 {
6395 defVal << QString::number( b );
6396 }
6397
6398 mDefaultLineEdit->setText( defVal.join( ';' ) );
6399 }
6400 vlayout->addWidget( mDefaultLineEdit );
6401
6402 vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
6403 mParentLayerComboBox = new QComboBox();
6404
6405 QString initialParent;
6406 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6407 initialParent = bandParam->parentLayerParameterName();
6408
6409 if ( auto *lModel = widgetContext.model() )
6410 {
6411 // populate combo box with other model input choices
6412 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
6413 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
6414 {
6415 if ( const QgsProcessingParameterRasterLayer *definition = dynamic_cast< const QgsProcessingParameterRasterLayer * >( lModel->parameterDefinition( it.value().parameterName() ) ) )
6416 {
6417 mParentLayerComboBox-> addItem( definition->description(), definition->name() );
6418 if ( !initialParent.isEmpty() && initialParent == definition->name() )
6419 {
6420 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6421 }
6422 }
6423 }
6424 }
6425
6426 if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
6427 {
6428 // if no parent candidates found, we just add the existing one as a placeholder
6429 mParentLayerComboBox->addItem( initialParent, initialParent );
6430 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
6431 }
6432
6433 vlayout->addWidget( mParentLayerComboBox );
6434
6435 mAllowMultipleCheckBox = new QCheckBox( tr( "Allow multiple" ) );
6436 if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
6437 mAllowMultipleCheckBox->setChecked( bandParam->allowMultiple() );
6438
6439 vlayout->addWidget( mAllowMultipleCheckBox );
6440 setLayout( vlayout );
6441 }
6442
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const6443 QgsProcessingParameterDefinition *QgsProcessingBandParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6444 {
6445 auto param = std::make_unique< QgsProcessingParameterBand >( name, description, mDefaultLineEdit->text().split( ';' ), mParentLayerComboBox->currentData().toString(), false, mAllowMultipleCheckBox->isChecked() );
6446 param->setFlags( flags );
6447 return param.release();
6448 }
6449
QgsProcessingBandWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)6450 QgsProcessingBandWidgetWrapper::QgsProcessingBandWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
6451 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
6452 {
6453
6454 }
6455
createWidget()6456 QWidget *QgsProcessingBandWidgetWrapper::createWidget()
6457 {
6458 const QgsProcessingParameterBand *bandParam = dynamic_cast< const QgsProcessingParameterBand *>( parameterDefinition() );
6459 switch ( type() )
6460 {
6461 case QgsProcessingGui::Standard:
6462 case QgsProcessingGui::Batch:
6463 {
6464 if ( bandParam->allowMultiple() )
6465 {
6466 mPanel = new QgsProcessingRasterBandPanelWidget( nullptr, bandParam );
6467 mPanel->setToolTip( parameterDefinition()->toolTip() );
6468 connect( mPanel, &QgsProcessingRasterBandPanelWidget::changed, this, [ = ]
6469 {
6470 emit widgetValueHasChanged( this );
6471 } );
6472 return mPanel;
6473 }
6474 else
6475 {
6476 mComboBox = new QgsRasterBandComboBox();
6477 mComboBox->setShowNotSetOption( bandParam->flags() & QgsProcessingParameterDefinition::FlagOptional );
6478
6479 mComboBox->setToolTip( parameterDefinition()->toolTip() );
6480 connect( mComboBox, &QgsRasterBandComboBox::bandChanged, this, [ = ]( int )
6481 {
6482 emit widgetValueHasChanged( this );
6483 } );
6484 return mComboBox;
6485 }
6486 }
6487
6488 case QgsProcessingGui::Modeler:
6489 {
6490 mLineEdit = new QLineEdit();
6491 mLineEdit->setToolTip( QObject::tr( "Band number (separate bands with ; for multiple band parameters)" ) );
6492 connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]
6493 {
6494 emit widgetValueHasChanged( this );
6495 } );
6496 return mLineEdit;
6497 }
6498
6499 }
6500 return nullptr;
6501 }
6502
postInitialize(const QList<QgsAbstractProcessingParameterWidgetWrapper * > & wrappers)6503 void QgsProcessingBandWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
6504 {
6505 QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
6506 switch ( type() )
6507 {
6508 case QgsProcessingGui::Standard:
6509 case QgsProcessingGui::Batch:
6510 {
6511 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
6512 {
6513 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterBand * >( parameterDefinition() )->parentLayerParameterName() )
6514 {
6515 setParentLayerWrapperValue( wrapper );
6516 connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
6517 {
6518 setParentLayerWrapperValue( wrapper );
6519 } );
6520 break;
6521 }
6522 }
6523 break;
6524 }
6525
6526 case QgsProcessingGui::Modeler:
6527 break;
6528 }
6529 }
6530
setParentLayerWrapperValue(const QgsAbstractProcessingParameterWidgetWrapper * parentWrapper)6531 void QgsProcessingBandWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
6532 {
6533 // evaluate value to layer
6534 QgsProcessingContext *context = nullptr;
6535 std::unique_ptr< QgsProcessingContext > tmpContext;
6536 if ( mProcessingContextGenerator )
6537 context = mProcessingContextGenerator->processingContext();
6538
6539 if ( !context )
6540 {
6541 tmpContext = std::make_unique< QgsProcessingContext >();
6542 context = tmpContext.get();
6543 }
6544
6545 QVariant value = parentWrapper->parameterValue();
6546
6547 QgsRasterLayer *layer = QgsProcessingParameters::parameterAsRasterLayer( parentWrapper->parameterDefinition(), value, *context );
6548 if ( layer && layer->isValid() )
6549 {
6550 // need to grab ownership of layer if required - otherwise layer may be deleted when context
6551 // goes out of scope
6552 std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
6553 if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::RasterLayer )
6554 {
6555 mParentLayer.reset( qobject_cast< QgsRasterLayer * >( ownedLayer.release() ) );
6556 layer = mParentLayer.get();
6557 }
6558 else
6559 {
6560 // don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
6561 }
6562
6563 if ( mComboBox )
6564 mComboBox->setLayer( layer );
6565 else if ( mPanel )
6566 {
6567 QgsRasterDataProvider *provider = layer->dataProvider();
6568 if ( provider && layer->isValid() )
6569 {
6570 //fill available bands
6571 int nBands = provider->bandCount();
6572 QList< int > bands;
6573 QHash< int, QString > bandNames;
6574 for ( int i = 1; i <= nBands; ++i )
6575 {
6576 bandNames.insert( i, QgsRasterBandComboBox::displayBandName( provider, i ) );
6577 bands << i;
6578 }
6579 mPanel->setBands( bands );
6580 mPanel->setBandNames( bandNames );
6581 }
6582 }
6583 }
6584 else
6585 {
6586 if ( mComboBox )
6587 mComboBox->setLayer( nullptr );
6588 else if ( mPanel )
6589 mPanel->setBands( QList< int >() );
6590
6591 if ( value.isValid() && widgetContext().messageBar() )
6592 {
6593 widgetContext().messageBar()->clearWidgets();
6594 widgetContext().messageBar()->pushMessage( QString(), QObject::tr( "Could not load selected layer/table. Dependent bands could not be populated" ),
6595 Qgis::MessageLevel::Info );
6596 }
6597 }
6598
6599 if ( parameterDefinition()->defaultValueForGui().isValid() )
6600 setWidgetValue( parameterDefinition()->defaultValueForGui(), *context );
6601 }
6602
setWidgetValue(const QVariant & value,QgsProcessingContext & context)6603 void QgsProcessingBandWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
6604 {
6605 if ( mComboBox )
6606 {
6607 if ( !value.isValid() )
6608 mComboBox->setBand( -1 );
6609 else
6610 {
6611 const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
6612 mComboBox->setBand( v );
6613 }
6614 }
6615 else if ( mPanel )
6616 {
6617 QVariantList opts;
6618 if ( value.isValid() )
6619 {
6620 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6621 opts.reserve( v.size() );
6622 for ( int i : v )
6623 opts << i;
6624 }
6625 if ( mPanel )
6626 mPanel->setValue( value.isValid() ? opts : QVariant() );
6627 }
6628 else if ( mLineEdit )
6629 {
6630 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6631 if ( bandParam->allowMultiple() )
6632 {
6633 const QList< int > v = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
6634 QStringList opts;
6635 opts.reserve( v.size() );
6636 for ( int i : v )
6637 opts << QString::number( i );
6638 mLineEdit->setText( value.isValid() && !opts.empty() ? opts.join( ';' ) : QString() );
6639 }
6640 else
6641 {
6642 if ( value.isValid() )
6643 mLineEdit->setText( QString::number( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) ) );
6644 else
6645 mLineEdit->clear();
6646 }
6647 }
6648 }
6649
widgetValue() const6650 QVariant QgsProcessingBandWidgetWrapper::widgetValue() const
6651 {
6652 if ( mComboBox )
6653 return mComboBox->currentBand() == -1 ? QVariant() : mComboBox->currentBand();
6654 else if ( mPanel )
6655 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
6656 else if ( mLineEdit )
6657 {
6658 const QgsProcessingParameterBand *bandParam = static_cast< const QgsProcessingParameterBand * >( parameterDefinition() );
6659 if ( bandParam->allowMultiple() )
6660 {
6661 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
6662 const QStringList parts = mLineEdit->text().split( ';', QString::SkipEmptyParts );
6663 #else
6664 const QStringList parts = mLineEdit->text().split( ';', Qt::SkipEmptyParts );
6665 #endif
6666 QVariantList res;
6667 res.reserve( parts.count() );
6668 for ( const QString &s : parts )
6669 {
6670 bool ok = false;
6671 int band = s.toInt( &ok );
6672 if ( ok )
6673 res << band;
6674 }
6675 return res.isEmpty() ? QVariant() : res;
6676 }
6677 else
6678 {
6679 return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
6680 }
6681 }
6682 else
6683 return QVariant();
6684 }
6685
compatibleParameterTypes() const6686 QStringList QgsProcessingBandWidgetWrapper::compatibleParameterTypes() const
6687 {
6688 return QStringList()
6689 << QgsProcessingParameterBand::typeName()
6690 << QgsProcessingParameterNumber::typeName();
6691 }
6692
compatibleOutputTypes() const6693 QStringList QgsProcessingBandWidgetWrapper::compatibleOutputTypes() const
6694 {
6695 return QStringList()
6696 << QgsProcessingOutputNumber::typeName();
6697 }
6698
modelerExpressionFormatString() const6699 QString QgsProcessingBandWidgetWrapper::modelerExpressionFormatString() const
6700 {
6701 return tr( "selected band numbers as an array of numbers, or semicolon separated string of options (e.g. '1;3')" );
6702 }
6703
parameterType() const6704 QString QgsProcessingBandWidgetWrapper::parameterType() const
6705 {
6706 return QgsProcessingParameterBand::typeName();
6707 }
6708
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)6709 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBandWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
6710 {
6711 return new QgsProcessingBandWidgetWrapper( parameter, type );
6712 }
6713
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)6714 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBandWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
6715 {
6716 return new QgsProcessingBandParameterDefinitionWidget( context, widgetContext, definition, algorithm );
6717 }
6718
6719
6720
6721 //
6722 // QgsProcessingMultipleLayerPanelWidget
6723 //
6724
QgsProcessingMultipleLayerPanelWidget(QWidget * parent,const QgsProcessingParameterMultipleLayers * param)6725 QgsProcessingMultipleLayerPanelWidget::QgsProcessingMultipleLayerPanelWidget( QWidget *parent, const QgsProcessingParameterMultipleLayers *param )
6726 : QWidget( parent )
6727 , mParam( param )
6728 {
6729 QHBoxLayout *hl = new QHBoxLayout();
6730 hl->setContentsMargins( 0, 0, 0, 0 );
6731
6732 mLineEdit = new QLineEdit();
6733 mLineEdit->setEnabled( false );
6734 hl->addWidget( mLineEdit, 1 );
6735
6736 mToolButton = new QToolButton();
6737 mToolButton->setText( QString( QChar( 0x2026 ) ) );
6738 hl->addWidget( mToolButton );
6739
6740 setLayout( hl );
6741
6742 if ( mParam )
6743 {
6744 mLineEdit->setText( tr( "%1 inputs selected" ).arg( 0 ) );
6745 }
6746
6747 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMultipleLayerPanelWidget::showDialog );
6748 }
6749
setValue(const QVariant & value)6750 void QgsProcessingMultipleLayerPanelWidget::setValue( const QVariant &value )
6751 {
6752 if ( value.isValid() )
6753 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
6754 else
6755 mValue.clear();
6756
6757 updateSummaryText();
6758 emit changed();
6759 }
6760
setProject(QgsProject * project)6761 void QgsProcessingMultipleLayerPanelWidget::setProject( QgsProject *project )
6762 {
6763 mProject = project;
6764 if ( mProject )
6765 {
6766 connect( mProject, &QgsProject::layerRemoved, this, [&]( const QString & layerId )
6767 {
6768 if ( mValue.removeAll( layerId ) )
6769 {
6770 updateSummaryText();
6771 emit changed();
6772 }
6773 } );
6774 }
6775 }
6776
setModel(QgsProcessingModelAlgorithm * model,const QString & modelChildAlgorithmID)6777 void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorithm *model, const QString &modelChildAlgorithmID )
6778 {
6779 mModel = model;
6780 if ( !model )
6781 return;
6782
6783 switch ( mParam->layerType() )
6784 {
6785 case QgsProcessing::TypeFile:
6786 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFile::typeName(),
6787 QStringList() << QgsProcessingOutputFile::typeName() );
6788 break;
6789
6790 case QgsProcessing::TypeRaster:
6791 {
6792 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterRasterLayer::typeName()
6793 << QgsProcessingParameterMultipleLayers::typeName()
6794 << QgsProcessingParameterFile::typeName(),
6795 QStringList() << QgsProcessingOutputFile::typeName()
6796 << QgsProcessingOutputRasterLayer::typeName()
6797 << QgsProcessingOutputMapLayer::typeName()
6798 << QgsProcessingOutputMultipleLayers::typeName() );
6799 break;
6800 }
6801
6802 case QgsProcessing::TypeMesh:
6803 {
6804 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMeshLayer::typeName()
6805 << QgsProcessingParameterMultipleLayers::typeName()
6806 << QgsProcessingParameterFile::typeName(),
6807 QStringList() << QgsProcessingOutputFile::typeName()
6808 << QgsProcessingOutputMapLayer::typeName()
6809 << QgsProcessingOutputMultipleLayers::typeName() );
6810 break;
6811 }
6812
6813 case QgsProcessing::TypePlugin:
6814 {
6815 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
6816 << QgsProcessingParameterMultipleLayers::typeName()
6817 << QgsProcessingParameterFile::typeName(),
6818 QStringList() << QgsProcessingOutputFile::typeName()
6819 << QgsProcessingOutputMapLayer::typeName()
6820 << QgsProcessingOutputMultipleLayers::typeName() );
6821 break;
6822 }
6823
6824 case QgsProcessing::TypePointCloud:
6825 {
6826 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterPointCloudLayer::typeName()
6827 << QgsProcessingParameterMultipleLayers::typeName()
6828 << QgsProcessingParameterFile::typeName(),
6829 QStringList() << QgsProcessingOutputFile::typeName()
6830 << QgsProcessingOutputMapLayer::typeName()
6831 << QgsProcessingOutputMultipleLayers::typeName() );
6832 break;
6833 }
6834
6835 case QgsProcessing::TypeAnnotation:
6836 {
6837 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterAnnotationLayer::typeName()
6838 << QgsProcessingParameterMultipleLayers::typeName(),
6839 QStringList() << QgsProcessingOutputMapLayer::typeName()
6840 << QgsProcessingOutputMultipleLayers::typeName() );
6841 break;
6842 }
6843
6844 case QgsProcessing::TypeVector:
6845 {
6846 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6847 << QgsProcessingParameterVectorLayer::typeName()
6848 << QgsProcessingParameterFile::typeName()
6849 << QgsProcessingParameterMultipleLayers::typeName(),
6850 QStringList() << QgsProcessingOutputFile::typeName()
6851 << QgsProcessingOutputVectorLayer::typeName()
6852 << QgsProcessingOutputMapLayer::typeName()
6853 << QgsProcessingOutputMultipleLayers::typeName(),
6854 QList< int >() << QgsProcessing::TypeVector );
6855 break;
6856 }
6857
6858 case QgsProcessing::TypeVectorAnyGeometry:
6859 {
6860 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6861 << QgsProcessingParameterVectorLayer::typeName()
6862 << QgsProcessingParameterFile::typeName()
6863 << QgsProcessingParameterMultipleLayers::typeName(),
6864 QStringList() << QgsProcessingOutputFile::typeName()
6865 << QgsProcessingOutputVectorLayer::typeName()
6866 << QgsProcessingOutputMapLayer::typeName()
6867 << QgsProcessingOutputMultipleLayers::typeName() );
6868 break;
6869 }
6870
6871 case QgsProcessing::TypeVectorPoint:
6872 {
6873 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6874 << QgsProcessingParameterVectorLayer::typeName()
6875 << QgsProcessingParameterFile::typeName()
6876 << QgsProcessingParameterMultipleLayers::typeName(),
6877 QStringList() << QgsProcessingOutputFile::typeName()
6878 << QgsProcessingOutputVectorLayer::typeName()
6879 << QgsProcessingOutputMapLayer::typeName()
6880 << QgsProcessingOutputMultipleLayers::typeName(),
6881 QList< int >() << QgsProcessing::TypeVectorAnyGeometry << QgsProcessing::TypeVectorPoint );
6882 break;
6883 }
6884
6885 case QgsProcessing::TypeVectorLine:
6886 {
6887 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6888 << QgsProcessingParameterVectorLayer::typeName()
6889 << QgsProcessingParameterFile::typeName()
6890 << QgsProcessingParameterMultipleLayers::typeName(),
6891 QStringList() << QgsProcessingOutputFile::typeName()
6892 << QgsProcessingOutputVectorLayer::typeName()
6893 << QgsProcessingOutputMapLayer::typeName()
6894 << QgsProcessingOutputMultipleLayers::typeName(),
6895 QList< int >() << QgsProcessing::TypeVectorAnyGeometry << QgsProcessing::TypeVectorLine );
6896 break;
6897 }
6898
6899 case QgsProcessing::TypeVectorPolygon:
6900 {
6901 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6902 << QgsProcessingParameterVectorLayer::typeName()
6903 << QgsProcessingParameterFile::typeName()
6904 << QgsProcessingParameterMultipleLayers::typeName(),
6905 QStringList() << QgsProcessingOutputFile::typeName()
6906 << QgsProcessingOutputVectorLayer::typeName()
6907 << QgsProcessingOutputMultipleLayers::typeName()
6908 << QgsProcessingOutputMapLayer::typeName(),
6909 QList< int >() << QgsProcessing::TypeVectorAnyGeometry << QgsProcessing::TypeVectorPolygon );
6910 break;
6911 }
6912
6913 case QgsProcessing::TypeMapLayer:
6914 {
6915 mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
6916 << QgsProcessingParameterVectorLayer::typeName()
6917 << QgsProcessingParameterRasterLayer::typeName()
6918 << QgsProcessingParameterMeshLayer::typeName()
6919 << QgsProcessingParameterFile::typeName()
6920 << QgsProcessingParameterMultipleLayers::typeName(),
6921 QStringList() << QgsProcessingOutputFile::typeName()
6922 << QgsProcessingOutputMapLayer::typeName()
6923 << QgsProcessingOutputVectorLayer::typeName()
6924 << QgsProcessingOutputRasterLayer::typeName()
6925 // << QgsProcessingOutputMeshLayer::typeName()
6926 << QgsProcessingOutputMultipleLayers::typeName() );
6927 break;
6928 }
6929 }
6930 }
6931
showDialog()6932 void QgsProcessingMultipleLayerPanelWidget::showDialog()
6933 {
6934 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
6935 if ( panel && panel->dockMode() )
6936 {
6937 QgsProcessingMultipleInputPanelWidget *widget = new QgsProcessingMultipleInputPanelWidget( mParam, mValue, mModelSources, mModel );
6938 widget->setPanelTitle( mParam->description() );
6939 widget->setProject( mProject );
6940 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
6941 {
6942 setValue( widget->selectedOptions() );
6943 } );
6944 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
6945 panel->openPanel( widget );
6946 }
6947 else
6948 {
6949 QgsProcessingMultipleInputDialog dlg( mParam, mValue, mModelSources, mModel, this, Qt::WindowFlags() );
6950 dlg.setProject( mProject );
6951 if ( dlg.exec() )
6952 {
6953 setValue( dlg.selectedOptions() );
6954 }
6955 }
6956 }
6957
updateSummaryText()6958 void QgsProcessingMultipleLayerPanelWidget::updateSummaryText()
6959 {
6960 if ( mParam )
6961 mLineEdit->setText( tr( "%1 inputs selected" ).arg( mValue.count() ) );
6962 }
6963
6964 //
6965 // QgsProcessingMultipleLayerWidgetWrapper
6966 //
6967
QgsProcessingMultipleLayerParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm,QWidget * parent)6968 QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
6969 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
6970 {
6971 QVBoxLayout *vlayout = new QVBoxLayout();
6972 vlayout->setContentsMargins( 0, 0, 0, 0 );
6973
6974 vlayout->addWidget( new QLabel( tr( "Allowed layer type" ) ) );
6975 mLayerTypeComboBox = new QComboBox();
6976 mLayerTypeComboBox->addItem( tr( "Any Map Layer" ), QgsProcessing::TypeMapLayer );
6977 mLayerTypeComboBox->addItem( tr( "Vector (No Geometry Required)" ), QgsProcessing::TypeVector );
6978 mLayerTypeComboBox->addItem( tr( "Vector (Point)" ), QgsProcessing::TypeVectorPoint );
6979 mLayerTypeComboBox->addItem( tr( "Vector (Line)" ), QgsProcessing::TypeVectorLine );
6980 mLayerTypeComboBox->addItem( tr( "Vector (Polygon)" ), QgsProcessing::TypeVectorPolygon );
6981 mLayerTypeComboBox->addItem( tr( "Any Geometry Type" ), QgsProcessing::TypeVectorAnyGeometry );
6982 mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
6983 mLayerTypeComboBox->addItem( tr( "File" ), QgsProcessing::TypeFile );
6984 mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
6985 mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );
6986 mLayerTypeComboBox->addItem( tr( "Point Cloud" ), QgsProcessing::TypePointCloud );
6987 mLayerTypeComboBox->addItem( tr( "Annotation" ), QgsProcessing::TypeAnnotation );
6988 if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
6989 mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( layersParam->layerType() ) );
6990
6991 vlayout->addWidget( mLayerTypeComboBox );
6992 setLayout( vlayout );
6993 }
6994
createParameter(const QString & name,const QString & description,QgsProcessingParameterDefinition::Flags flags) const6995 QgsProcessingParameterDefinition *QgsProcessingMultipleLayerParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
6996 {
6997 auto param = std::make_unique< QgsProcessingParameterMultipleLayers >( name, description, static_cast< QgsProcessing::SourceType >( mLayerTypeComboBox->currentData().toInt() ) );
6998 param->setFlags( flags );
6999 return param.release();
7000 }
7001
QgsProcessingMultipleLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7002 QgsProcessingMultipleLayerWidgetWrapper::QgsProcessingMultipleLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7003 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7004 {
7005
7006 }
7007
createWidget()7008 QWidget *QgsProcessingMultipleLayerWidgetWrapper::createWidget()
7009 {
7010 const QgsProcessingParameterMultipleLayers *layerParam = dynamic_cast< const QgsProcessingParameterMultipleLayers *>( parameterDefinition() );
7011
7012 mPanel = new QgsProcessingMultipleLayerPanelWidget( nullptr, layerParam );
7013 mPanel->setToolTip( parameterDefinition()->toolTip() );
7014 mPanel->setProject( widgetContext().project() );
7015 if ( type() == QgsProcessingGui::Modeler )
7016 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7017 connect( mPanel, &QgsProcessingMultipleLayerPanelWidget::changed, this, [ = ]
7018 {
7019 emit widgetValueHasChanged( this );
7020 } );
7021 return mPanel;
7022 }
7023
setWidgetContext(const QgsProcessingParameterWidgetContext & context)7024 void QgsProcessingMultipleLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7025 {
7026 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
7027 if ( mPanel )
7028 {
7029 mPanel->setProject( context.project() );
7030 if ( type() == QgsProcessingGui::Modeler )
7031 mPanel->setModel( widgetContext().model(), widgetContext().modelChildAlgorithmId() );
7032 }
7033 }
7034
setWidgetValue(const QVariant & value,QgsProcessingContext & context)7035 void QgsProcessingMultipleLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7036 {
7037 if ( mPanel )
7038 {
7039 QVariantList opts;
7040 if ( value.isValid() )
7041 {
7042 const QList< QgsMapLayer * > v = QgsProcessingParameters::parameterAsLayerList( parameterDefinition(), value, context );
7043 opts.reserve( v.size() );
7044 for ( const QgsMapLayer *l : v )
7045 opts << l->source();
7046 }
7047
7048 for ( const QVariant &v : value.toList() )
7049 {
7050 if ( v.canConvert< QgsProcessingModelChildParameterSource >() )
7051 {
7052 const QgsProcessingModelChildParameterSource source = v.value< QgsProcessingModelChildParameterSource >();
7053 opts << QVariant::fromValue( source );
7054 }
7055 }
7056
7057 if ( mPanel )
7058 mPanel->setValue( value.isValid() ? opts : QVariant() );
7059 }
7060 }
7061
widgetValue() const7062 QVariant QgsProcessingMultipleLayerWidgetWrapper::widgetValue() const
7063 {
7064 if ( mPanel )
7065 return !mPanel->value().toList().isEmpty() ? mPanel->value() : QVariant();
7066 else
7067 return QVariant();
7068 }
7069
compatibleParameterTypes() const7070 QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleParameterTypes() const
7071 {
7072 return QStringList()
7073 << QgsProcessingParameterMultipleLayers::typeName()
7074 << QgsProcessingParameterMapLayer::typeName()
7075 << QgsProcessingParameterVectorLayer::typeName()
7076 << QgsProcessingParameterMeshLayer::typeName()
7077 << QgsProcessingParameterFeatureSource::typeName()
7078 << QgsProcessingParameterRasterLayer::typeName()
7079 << QgsProcessingParameterFile::typeName()
7080 << QgsProcessingParameterString::typeName();
7081 }
7082
compatibleOutputTypes() const7083 QStringList QgsProcessingMultipleLayerWidgetWrapper::compatibleOutputTypes() const
7084 {
7085 return QStringList()
7086 << QgsProcessingOutputMapLayer::typeName()
7087 << QgsProcessingOutputRasterLayer::typeName()
7088 << QgsProcessingOutputVectorLayer::typeName()
7089 << QgsProcessingOutputMultipleLayers::typeName()
7090 << QgsProcessingOutputFile::typeName()
7091 << QgsProcessingOutputString::typeName();
7092 }
7093
modelerExpressionFormatString() const7094 QString QgsProcessingMultipleLayerWidgetWrapper::modelerExpressionFormatString() const
7095 {
7096 return tr( "an array of layer paths, or semicolon separated string of layer paths" );
7097 }
7098
parameterType() const7099 QString QgsProcessingMultipleLayerWidgetWrapper::parameterType() const
7100 {
7101 return QgsProcessingParameterMultipleLayers::typeName();
7102 }
7103
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7104 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMultipleLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7105 {
7106 return new QgsProcessingMultipleLayerWidgetWrapper( parameter, type );
7107 }
7108
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)7109 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMultipleLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7110 {
7111 return new QgsProcessingMultipleLayerParameterDefinitionWidget( context, widgetContext, definition, algorithm );
7112 }
7113
7114
7115 //
7116 // QgsProcessingPointCloudLayerWidgetWrapper
7117 //
7118
QgsProcessingPointCloudLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7119 QgsProcessingPointCloudLayerWidgetWrapper::QgsProcessingPointCloudLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7120 : QgsProcessingMapLayerWidgetWrapper( parameter, type, parent )
7121 {
7122
7123 }
7124
compatibleParameterTypes() const7125 QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleParameterTypes() const
7126 {
7127 return QStringList()
7128 << QgsProcessingParameterPointCloudLayer::typeName()
7129 << QgsProcessingParameterMapLayer::typeName()
7130 << QgsProcessingParameterString::typeName()
7131 << QgsProcessingParameterExpression::typeName();
7132 }
7133
compatibleOutputTypes() const7134 QStringList QgsProcessingPointCloudLayerWidgetWrapper::compatibleOutputTypes() const
7135 {
7136 return QStringList()
7137 << QgsProcessingOutputString::typeName()
7138 // TODO << QgsProcessingOutputPointCloudLayer::typeName()
7139 << QgsProcessingOutputMapLayer::typeName()
7140 << QgsProcessingOutputFile::typeName()
7141 << QgsProcessingOutputFolder::typeName();
7142 }
7143
modelerExpressionFormatString() const7144 QString QgsProcessingPointCloudLayerWidgetWrapper::modelerExpressionFormatString() const
7145 {
7146 return tr( "path to a point cloud layer" );
7147 }
7148
parameterType() const7149 QString QgsProcessingPointCloudLayerWidgetWrapper::parameterType() const
7150 {
7151 return QgsProcessingParameterPointCloudLayer::typeName();
7152 }
7153
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7154 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingPointCloudLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7155 {
7156 return new QgsProcessingPointCloudLayerWidgetWrapper( parameter, type );
7157 }
7158
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)7159 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingPointCloudLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7160 {
7161 Q_UNUSED( context );
7162 Q_UNUSED( widgetContext );
7163 Q_UNUSED( definition );
7164 Q_UNUSED( algorithm );
7165
7166 return nullptr;
7167 }
7168
7169
7170 //
7171 // QgsProcessingAnnotationLayerWidgetWrapper
7172 //
7173
QgsProcessingAnnotationLayerWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7174 QgsProcessingAnnotationLayerWidgetWrapper::QgsProcessingAnnotationLayerWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7175 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7176 {
7177
7178 }
7179
compatibleParameterTypes() const7180 QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleParameterTypes() const
7181 {
7182 return QStringList()
7183 << QgsProcessingParameterAnnotationLayer::typeName()
7184 << QgsProcessingParameterMapLayer::typeName()
7185 << QgsProcessingParameterString::typeName()
7186 << QgsProcessingParameterExpression::typeName();
7187 }
7188
compatibleOutputTypes() const7189 QStringList QgsProcessingAnnotationLayerWidgetWrapper::compatibleOutputTypes() const
7190 {
7191 return QStringList()
7192 << QgsProcessingOutputString::typeName()
7193 << QgsProcessingOutputMapLayer::typeName();
7194 }
7195
modelerExpressionFormatString() const7196 QString QgsProcessingAnnotationLayerWidgetWrapper::modelerExpressionFormatString() const
7197 {
7198 return tr( "name of an annotation layer, or \"main\" for the main annotation layer" );
7199 }
7200
parameterType() const7201 QString QgsProcessingAnnotationLayerWidgetWrapper::parameterType() const
7202 {
7203 return QgsProcessingParameterAnnotationLayer::typeName();
7204 }
7205
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7206 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingAnnotationLayerWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7207 {
7208 return new QgsProcessingAnnotationLayerWidgetWrapper( parameter, type );
7209 }
7210
createParameterDefinitionWidget(QgsProcessingContext & context,const QgsProcessingParameterWidgetContext & widgetContext,const QgsProcessingParameterDefinition * definition,const QgsProcessingAlgorithm * algorithm)7211 QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingAnnotationLayerWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
7212 {
7213 Q_UNUSED( context );
7214 Q_UNUSED( widgetContext );
7215 Q_UNUSED( definition );
7216 Q_UNUSED( algorithm );
7217
7218 return nullptr;
7219 }
7220
setWidgetContext(const QgsProcessingParameterWidgetContext & context)7221 void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
7222 {
7223 QgsAbstractProcessingParameterWidgetWrapper::setWidgetContext( context );
7224 if ( mComboBox )
7225 {
7226 if ( mWidgetContext.project() )
7227 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7228 }
7229 }
7230
createWidget()7231 QWidget *QgsProcessingAnnotationLayerWidgetWrapper::createWidget()
7232 {
7233 mComboBox = new QgsMapLayerComboBox( );
7234 mComboBox->setFilters( QgsMapLayerProxyModel::AnnotationLayer );
7235
7236 switch ( type() )
7237 {
7238 case QgsProcessingGui::Standard:
7239 case QgsProcessingGui::Batch:
7240 break;
7241 case QgsProcessingGui::Modeler:
7242 mComboBox->setEditable( true );
7243 break;
7244 }
7245
7246 mComboBox->setToolTip( parameterDefinition()->toolTip() );
7247
7248 if ( mWidgetContext.project() )
7249 mComboBox->setAdditionalLayers( { mWidgetContext.project()->mainAnnotationLayer() } );
7250
7251 if ( parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
7252 mComboBox->setAllowEmptyLayer( true );
7253
7254 connect( mComboBox, &QgsMapLayerComboBox::layerChanged, this, [ = ]()
7255 {
7256 if ( mBlockSignals )
7257 return;
7258
7259 emit widgetValueHasChanged( this );
7260 } );
7261
7262 setWidgetContext( widgetContext() );
7263 return mComboBox;
7264 }
7265
setWidgetValue(const QVariant & value,QgsProcessingContext & context)7266 void QgsProcessingAnnotationLayerWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
7267 {
7268 if ( mComboBox )
7269 {
7270 if ( !value.isValid() && parameterDefinition()->flags() & QgsProcessingParameterDefinition::FlagOptional )
7271 {
7272 mComboBox->setLayer( nullptr );
7273 return;
7274 }
7275
7276 QVariant val = value;
7277 if ( val.canConvert<QgsProperty>() )
7278 {
7279 if ( val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
7280 {
7281 val = val.value< QgsProperty >().staticValue();
7282 }
7283 else
7284 {
7285 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), parameterDefinition()->defaultValueForGui().toString() );
7286 }
7287 }
7288
7289 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
7290 if ( !layer && val.type() == QVariant::String )
7291 {
7292 layer = QgsProcessingUtils::mapLayerFromString( val.toString(), context, false, QgsProcessingUtils::LayerHint::Annotation );
7293 }
7294
7295 if ( layer )
7296 {
7297 mComboBox->setLayer( layer );
7298 }
7299 }
7300 }
7301
widgetValue() const7302 QVariant QgsProcessingAnnotationLayerWidgetWrapper::widgetValue() const
7303 {
7304 return mComboBox && mComboBox->currentLayer() ?
7305 ( mWidgetContext.project() ? ( mComboBox->currentLayer() == mWidgetContext.project()->mainAnnotationLayer() ? QStringLiteral( "main" ) : mComboBox->currentLayer()->id() ) : mComboBox->currentLayer()->id() )
7306 : QVariant();
7307 }
7308
7309
7310
7311 //
7312 // QgsProcessingOutputWidgetWrapper
7313 //
7314
QgsProcessingOutputWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7315 QgsProcessingOutputWidgetWrapper::QgsProcessingOutputWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7316 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
7317 {
7318
7319 }
7320
createWidget()7321 QWidget *QgsProcessingOutputWidgetWrapper::createWidget()
7322 {
7323 const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( parameterDefinition() );
7324 switch ( type() )
7325 {
7326 case QgsProcessingGui::Standard:
7327 case QgsProcessingGui::Modeler:
7328 {
7329 mOutputWidget = new QgsProcessingLayerOutputDestinationWidget( destParam, false );
7330 if ( mProcessingContextGenerator )
7331 mOutputWidget->setContext( mProcessingContextGenerator->processingContext() );
7332 if ( mParametersGenerator )
7333 mOutputWidget->registerProcessingParametersGenerator( mParametersGenerator );
7334 mOutputWidget->setToolTip( parameterDefinition()->toolTip() );
7335
7336 connect( mOutputWidget, &QgsProcessingLayerOutputDestinationWidget::destinationChanged, this, [ = ]()
7337 {
7338 if ( mBlockSignals )
7339 return;
7340
7341 emit widgetValueHasChanged( this );
7342 } );
7343
7344 if ( type() == QgsProcessingGui::Standard
7345 && ( destParam->type() == QgsProcessingParameterRasterDestination::typeName() ||
7346 destParam->type() == QgsProcessingParameterFeatureSink::typeName() ||
7347 destParam->type() == QgsProcessingParameterVectorDestination::typeName() ) )
7348 mOutputWidget->addOpenAfterRunningOption();
7349
7350 return mOutputWidget;
7351 }
7352 case QgsProcessingGui::Batch:
7353 break;
7354 }
7355
7356 return nullptr;
7357 }
7358
7359
setWidgetValue(const QVariant & value,QgsProcessingContext &)7360 void QgsProcessingOutputWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
7361 {
7362 if ( mOutputWidget )
7363 mOutputWidget->setValue( value );
7364 }
7365
widgetValue() const7366 QVariant QgsProcessingOutputWidgetWrapper::widgetValue() const
7367 {
7368 if ( mOutputWidget )
7369 return mOutputWidget->value();
7370
7371 return QVariant();
7372 }
7373
customProperties() const7374 QVariantMap QgsProcessingOutputWidgetWrapper::customProperties() const
7375 {
7376 QVariantMap res;
7377 if ( mOutputWidget )
7378 res.insert( QStringLiteral( "OPEN_AFTER_RUNNING" ), mOutputWidget->openAfterRunning() );
7379 return res;
7380 }
7381
compatibleParameterTypes() const7382 QStringList QgsProcessingOutputWidgetWrapper::compatibleParameterTypes() const
7383 {
7384 return QStringList()
7385 << QgsProcessingParameterRasterLayer::typeName()
7386 << QgsProcessingParameterMeshLayer::typeName()
7387 << QgsProcessingParameterVectorLayer::typeName()
7388 << QgsProcessingParameterMapLayer::typeName()
7389 << QgsProcessingParameterString::typeName()
7390 << QgsProcessingParameterExpression::typeName();
7391 }
7392
compatibleOutputTypes() const7393 QStringList QgsProcessingOutputWidgetWrapper::compatibleOutputTypes() const
7394 {
7395 return QStringList()
7396 << QgsProcessingOutputString::typeName()
7397 << QgsProcessingOutputFolder::typeName()
7398 << QgsProcessingOutputFile::typeName();
7399 }
7400
7401 //
7402 // QgsProcessingFeatureSinkWidgetWrapper
7403 //
7404
QgsProcessingFeatureSinkWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7405 QgsProcessingFeatureSinkWidgetWrapper::QgsProcessingFeatureSinkWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7406 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7407 {
7408
7409 }
7410
parameterType() const7411 QString QgsProcessingFeatureSinkWidgetWrapper::parameterType() const
7412 {
7413 return QgsProcessingParameterFeatureSink::typeName();
7414 }
7415
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7416 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFeatureSinkWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7417 {
7418 return new QgsProcessingFeatureSinkWidgetWrapper( parameter, type );
7419 }
7420
modelerExpressionFormatString() const7421 QString QgsProcessingFeatureSinkWidgetWrapper::modelerExpressionFormatString() const
7422 {
7423 return tr( "path to layer destination" );
7424 }
7425
7426 //
7427 // QgsProcessingFeatureSinkWidgetWrapper
7428 //
7429
QgsProcessingVectorDestinationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7430 QgsProcessingVectorDestinationWidgetWrapper::QgsProcessingVectorDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7431 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7432 {
7433
7434 }
7435
parameterType() const7436 QString QgsProcessingVectorDestinationWidgetWrapper::parameterType() const
7437 {
7438 return QgsProcessingParameterVectorDestination::typeName();
7439 }
7440
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7441 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7442 {
7443 return new QgsProcessingVectorDestinationWidgetWrapper( parameter, type );
7444 }
7445
modelerExpressionFormatString() const7446 QString QgsProcessingVectorDestinationWidgetWrapper::modelerExpressionFormatString() const
7447 {
7448 return tr( "path to layer destination" );
7449 }
7450
7451 //
7452 // QgsProcessingFeatureSinkWidgetWrapper
7453 //
7454
QgsProcessingRasterDestinationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7455 QgsProcessingRasterDestinationWidgetWrapper::QgsProcessingRasterDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7456 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7457 {
7458
7459 }
7460
parameterType() const7461 QString QgsProcessingRasterDestinationWidgetWrapper::parameterType() const
7462 {
7463 return QgsProcessingParameterRasterDestination::typeName();
7464 }
7465
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7466 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingRasterDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7467 {
7468 return new QgsProcessingRasterDestinationWidgetWrapper( parameter, type );
7469 }
7470
modelerExpressionFormatString() const7471 QString QgsProcessingRasterDestinationWidgetWrapper::modelerExpressionFormatString() const
7472 {
7473 return tr( "path to layer destination" );
7474 }
7475
7476 //
7477 // QgsProcessingFileDestinationWidgetWrapper
7478 //
7479
QgsProcessingFileDestinationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7480 QgsProcessingFileDestinationWidgetWrapper::QgsProcessingFileDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7481 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7482 {
7483
7484 }
7485
parameterType() const7486 QString QgsProcessingFileDestinationWidgetWrapper::parameterType() const
7487 {
7488 return QgsProcessingParameterFileDestination::typeName();
7489 }
7490
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7491 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFileDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7492 {
7493 return new QgsProcessingFileDestinationWidgetWrapper( parameter, type );
7494 }
7495
modelerExpressionFormatString() const7496 QString QgsProcessingFileDestinationWidgetWrapper::modelerExpressionFormatString() const
7497 {
7498 return tr( "path to file destination" );
7499 }
7500
7501 //
7502 // QgsProcessingFolderDestinationWidgetWrapper
7503 //
7504
QgsProcessingFolderDestinationWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type,QWidget * parent)7505 QgsProcessingFolderDestinationWidgetWrapper::QgsProcessingFolderDestinationWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
7506 : QgsProcessingOutputWidgetWrapper( parameter, type, parent )
7507 {
7508
7509 }
7510
parameterType() const7511 QString QgsProcessingFolderDestinationWidgetWrapper::parameterType() const
7512 {
7513 return QgsProcessingParameterFolderDestination::typeName();
7514 }
7515
createWidgetWrapper(const QgsProcessingParameterDefinition * parameter,QgsProcessingGui::WidgetType type)7516 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFolderDestinationWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
7517 {
7518 return new QgsProcessingFolderDestinationWidgetWrapper( parameter, type );
7519 }
7520
modelerExpressionFormatString() const7521 QString QgsProcessingFolderDestinationWidgetWrapper::modelerExpressionFormatString() const
7522 {
7523 return tr( "path to folder destination" );
7524 }
7525
7526 ///@endcond PRIVATE
7527