QGIS API Documentation 3.43.0-Master (2366440f66a)
qgsprocessingmeshdatasetwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingmeshdatasetgroupswidget.h
3 ---------------------
4 Date : October 2020
5 Copyright : (C) 2020 by Vincent Cloarec
6 Email : vcloarec at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "moc_qgsprocessingmeshdatasetwidget.cpp"
18#include "qgsdatetimeedit.h"
21#include "qgsmeshlayer.h"
22#include "qgsmeshlayerutils.h"
24#include "qgspanelwidget.h"
25#include "qgsmapcanvas.h"
28
29#include <QLineEdit>
30#include <QLabel>
31#include <QMenu>
32#include <QToolButton>
33#include <QVBoxLayout>
34
36
37QgsProcessingMeshDatasetGroupsWidget::QgsProcessingMeshDatasetGroupsWidget( QWidget *parent, const QgsProcessingParameterMeshDatasetGroups *param )
38 : QWidget( parent ), mParam( param )
39{
40 QHBoxLayout *hl = new QHBoxLayout();
41 hl->setContentsMargins( 0, 0, 0, 0 );
42
43 mLineEdit = new QLineEdit();
44 mLineEdit->setEnabled( false );
45 hl->addWidget( mLineEdit, 1 );
46
47 mToolButton = new QToolButton();
48 mToolButton->setText( QString( QChar( 0x2026 ) ) );
49 hl->addWidget( mToolButton );
50
51 setLayout( hl );
52
53 mLineEdit->setText( tr( "%1 dataset groups selected" ).arg( 0 ) );
54
55 mToolButton->setPopupMode( QToolButton::InstantPopup );
56 QMenu *toolButtonMenu = new QMenu( this );
57 mActionCurrentActiveDatasetGroups = toolButtonMenu->addAction( tr( "Current Active Dataset Group" ) );
58 connect( mActionCurrentActiveDatasetGroups, &QAction::triggered, this, &QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup );
59
60 mActionAvailableDatasetGroups = toolButtonMenu->addAction( tr( "Select in Available Dataset Groups" ) );
61 connect( mActionAvailableDatasetGroups, &QAction::triggered, this, &QgsProcessingMeshDatasetGroupsWidget::showDialog );
62
63 mToolButton->setMenu( toolButtonMenu );
64}
65
66void QgsProcessingMeshDatasetGroupsWidget::setMeshLayer( QgsMeshLayer *layer, bool layerFromProject )
67{
68 mActionCurrentActiveDatasetGroups->setEnabled( layer && layerFromProject );
69 mActionAvailableDatasetGroups->setEnabled( layer );
70
71 if ( mMeshLayer == layer )
72 return;
73
74 mDatasetGroupsNames.clear();
75
76 if ( layerFromProject )
77 mMeshLayer = layer;
78 else
79 {
80 mMeshLayer = nullptr;
81 if ( layer )
82 {
83 QList<int> datasetGroupsIndexes = layer->datasetGroupsIndexes();
84 for ( int i : datasetGroupsIndexes )
85 {
87 if ( mParam->isDataTypeSupported( meta.dataType() ) )
88 {
89 mDatasetGroupsNames[i] = meta.name();
90 }
91 }
92 }
93 }
94 mValue.clear();
95 updateSummaryText();
96 emit changed();
97}
98
99void QgsProcessingMeshDatasetGroupsWidget::setValue( const QVariant &value )
100{
101 if ( value.isValid() )
102 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
103 else
104 mValue.clear();
105
106 updateSummaryText();
107 emit changed();
108}
109
110QVariant QgsProcessingMeshDatasetGroupsWidget::value() const
111{
112 return mValue;
113}
114
115void QgsProcessingMeshDatasetGroupsWidget::showDialog()
116{
117 QList<int> datasetGroupsIndexes;
118 QStringList options;
119 QVariantList availableOptions;
120 if ( mMeshLayer )
121 {
122 datasetGroupsIndexes = mMeshLayer->datasetGroupsIndexes();
123 for ( int i : std::as_const( datasetGroupsIndexes ) )
124 {
125 QgsMeshDatasetGroupMetadata meta = mMeshLayer->datasetGroupMetadata( i );
126 if ( mParam->isDataTypeSupported( meta.dataType() ) )
127 {
128 availableOptions.append( i );
129 options.append( meta.name() );
130 }
131 }
132 }
133 else
134 {
135 for ( auto it = mDatasetGroupsNames.constBegin(); it != mDatasetGroupsNames.constEnd(); it++ )
136 {
137 availableOptions.append( it.key() );
138 options.append( it.value() );
139 }
140 }
141
143 if ( panel && panel->dockMode() )
144 {
145 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
146 widget->setPanelTitle( tr( "Dataset Groups Available" ) );
147
148 widget->setValueFormatter( [availableOptions, options]( const QVariant &v ) -> QString {
149 const int index = v.toInt();
150 const int pos = availableOptions.indexOf( index );
151 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
152 } );
153
154 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [=]() {
155 setValue( widget->selectedOptions() );
156 } );
157 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
158 panel->openPanel( widget );
159 }
160 else
161 {
162 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
163
164 dlg.setValueFormatter( [datasetGroupsIndexes, options]( const QVariant &v ) -> QString {
165 const int index = v.toInt();
166 const int pos = datasetGroupsIndexes.indexOf( index );
167 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
168 } );
169 if ( dlg.exec() )
170 {
171 setValue( dlg.selectedOptions() );
172 }
173 }
174}
175
176void QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup()
177{
178 QVariantList options;
179 if ( mMeshLayer && mParam )
180 {
181 int scalarDatasetGroup = mMeshLayer->rendererSettings().activeScalarDatasetGroup();
182 int vectorDatasetGroup = mMeshLayer->rendererSettings().activeVectorDatasetGroup();
183
184 if ( scalarDatasetGroup >= 0 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( scalarDatasetGroup ).dataType() ) )
185 options.append( scalarDatasetGroup );
186
187 if ( vectorDatasetGroup >= 0
188 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( vectorDatasetGroup ).dataType() )
189 && vectorDatasetGroup != scalarDatasetGroup )
190 options.append( vectorDatasetGroup );
191 }
192
193 setValue( options );
194}
195
196QgsProcessingMeshDatasetGroupsWidgetWrapper::QgsProcessingMeshDatasetGroupsWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type, QWidget *parent )
197 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
198{}
199
200QString QgsProcessingMeshDatasetGroupsWidgetWrapper::parameterType() const
201{
203}
204
205QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type )
206{
207 return new QgsProcessingMeshDatasetGroupsWidgetWrapper( parameter, type );
208}
209
210QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
211{
212 return new QgsProcessingMeshDatasetGroupsParameterDefinitionWidget( context, widgetContext, definition, algorithm );
213}
214
215void QgsProcessingMeshDatasetGroupsWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
216{
218 switch ( type() )
219 {
222 {
223 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
224 {
225 if ( wrapper->parameterDefinition()->name() == static_cast<const QgsProcessingParameterMeshDatasetGroups *>( parameterDefinition() )->meshLayerParameterName() )
226 {
227 setMeshLayerWrapperValue( wrapper );
229 setMeshLayerWrapperValue( wrapper );
230 } );
231 break;
232 }
233 }
234 }
235 break;
237 break;
238 }
239}
240
241void QgsProcessingMeshDatasetGroupsWidgetWrapper::setMeshLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
242{
243 if ( !mWidget )
244 return;
245
246 // evaluate value to layer
247 QgsProcessingContext *context = nullptr;
248 if ( mProcessingContextGenerator )
249 context = mProcessingContextGenerator->processingContext();
250
251 bool layerFromProject;
252 QgsMeshLayer *meshLayer;
253 if ( !context )
254 {
255 QgsProcessingContext dummyContext;
256 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), dummyContext );
257 layerFromProject = false;
258 }
259 else
260 {
261 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), *context );
262 layerFromProject = context->project() && context->project()->layerStore()->layers<QgsMeshLayer *>().contains( meshLayer );
263 }
264
265 if ( mWidget )
266 mWidget->setMeshLayer( meshLayer, layerFromProject );
267}
268
269QWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidget() SIP_FACTORY
270{
271 mWidget = new QgsProcessingMeshDatasetGroupsWidget( nullptr, static_cast<const QgsProcessingParameterMeshDatasetGroups *>( parameterDefinition() ) );
272 connect( mWidget, &QgsProcessingMeshDatasetGroupsWidget::changed, this, [=] {
273 emit widgetValueHasChanged( this );
274 } );
275
276 return mWidget;
277}
278
279void QgsProcessingMeshDatasetGroupsWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
280{
281 if ( !mWidget )
282 return;
283
284 QList<int> datasetGroupIndexes;
285 if ( value.userType() == QMetaType::Type::QVariantList )
286 {
287 //here we can't use QgsProcessingParameters::parameterAsInts() because this method return empry list when first value is 0...
288 datasetGroupIndexes = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
289 }
290 else
291 datasetGroupIndexes.append( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) );
292
293 QVariantList varList;
294 for ( const int index : std::as_const( datasetGroupIndexes ) )
295 varList.append( index );
296
297 mWidget->setValue( varList );
298}
299
300QVariant QgsProcessingMeshDatasetGroupsWidgetWrapper::widgetValue() const
301{
302 if ( mWidget )
303 return mWidget->value();
304 return QVariant();
305}
306
307
308void QgsProcessingMeshDatasetGroupsWidget::updateSummaryText()
309{
310 mLineEdit->setText( tr( "%n option(s) selected", nullptr, mValue.count() ) );
311}
312
313QgsProcessingMeshDatasetTimeWidgetWrapper::QgsProcessingMeshDatasetTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type, QWidget *parent )
314 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
315{
316}
317
318QString QgsProcessingMeshDatasetTimeWidgetWrapper::parameterType() const
319{
321}
322
323QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type )
324{
325 return new QgsProcessingMeshDatasetTimeWidgetWrapper( parameter, type );
326}
327
328void QgsProcessingMeshDatasetTimeWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
329{
331 switch ( type() )
332 {
335 {
336 const QgsAbstractProcessingParameterWidgetWrapper *layerParameterWrapper = nullptr;
337 const QgsAbstractProcessingParameterWidgetWrapper *datasetGroupsParameterWrapper = nullptr;
338 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
339 {
340 if ( wrapper->parameterDefinition()->name() == static_cast<const QgsProcessingParameterMeshDatasetTime *>( parameterDefinition() )->meshLayerParameterName() )
341 layerParameterWrapper = wrapper;
342
343 if ( wrapper->parameterDefinition()->name() == static_cast<const QgsProcessingParameterMeshDatasetTime *>( parameterDefinition() )->datasetGroupParameterName() )
344 datasetGroupsParameterWrapper = wrapper;
345 }
346 setMeshLayerWrapperValue( layerParameterWrapper );
347 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
348 connect( datasetGroupsParameterWrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [=] {
349 setMeshLayerWrapperValue( layerParameterWrapper );
350 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
351 } );
352
353 break;
354 }
355
357 break;
358 }
359}
360
361QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
362{
363 return new QgsProcessingMeshDatasetTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
364}
365
366void QgsProcessingMeshDatasetTimeWidgetWrapper::setMeshLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
367{
368 if ( !mWidget || !wrapper )
369 return;
370
371 // evaluate value to layer
372 QgsProcessingContext *context = nullptr;
373 if ( mProcessingContextGenerator )
374 context = mProcessingContextGenerator->processingContext();
375
376 bool layerFromProject;
377 QgsMeshLayer *meshLayer;
378 if ( !context )
379 {
380 QgsProcessingContext dummyContext;
381 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), dummyContext );
382 layerFromProject = false;
383 }
384 else
385 {
386 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), *context );
387 layerFromProject = context->project() && context->project()->layerStore()->layers<QgsMeshLayer *>().contains( meshLayer );
388 }
389
390 mWidget->setMeshLayer( meshLayer, layerFromProject );
391}
392
393void QgsProcessingMeshDatasetTimeWidgetWrapper::setDatasetGroupIndexesWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
394{
395 if ( !mWidget || !wrapper )
396 return;
397
398 QVariant datasetGroupsVariant = wrapper->parameterValue();
399
400 if ( !datasetGroupsVariant.isValid() || datasetGroupsVariant.userType() != QMetaType::Type::QVariantList )
401 mWidget->setDatasetGroupIndexes( QList<int>() );
402
403 QVariantList datasetGroupsListVariant = datasetGroupsVariant.toList();
404
405 QList<int> datasetGroupsIndexes;
406 for ( const QVariant &variantIndex : datasetGroupsListVariant )
407 datasetGroupsIndexes << variantIndex.toInt();
408
409 mWidget->setDatasetGroupIndexes( datasetGroupsIndexes );
410}
411
412QWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidget()
413{
414 mWidget = new QgsProcessingMeshDatasetTimeWidget( nullptr, static_cast<const QgsProcessingParameterMeshDatasetTime *>( parameterDefinition() ), widgetContext() );
415
416 QgsMapCanvas *canvas = widgetContext().mapCanvas();
417 if ( canvas )
418 {
419 connect( canvas, &QgsMapCanvas::temporalRangeChanged, mWidget, &QgsProcessingMeshDatasetTimeWidget::updateValue );
420 }
421 connect( mWidget, &QgsProcessingMeshDatasetTimeWidget::changed, this, [=] {
422 emit widgetValueHasChanged( this );
423 } );
424
425 return mWidget;
426}
427
428void QgsProcessingMeshDatasetTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
429{
430 Q_UNUSED( context );
431 if ( mWidget )
432 mWidget->setValue( value );
433}
434
435QVariant QgsProcessingMeshDatasetTimeWidgetWrapper::widgetValue() const
436{
437 if ( mWidget )
438 return mWidget->value();
439 return QVariant();
440}
441
442QgsProcessingMeshDatasetTimeWidget::QgsProcessingMeshDatasetTimeWidget( QWidget *parent, const QgsProcessingParameterMeshDatasetTime *param, const QgsProcessingParameterWidgetContext &context )
443 : QWidget( parent ), mParam( param )
444{
445 setupUi( this );
446
447 mValue.insert( QStringLiteral( "type" ), QStringLiteral( "static" ) );
448
449 dateTimeEdit->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
450
451 mCanvas = context.mapCanvas();
452
453 connect( radioButtonCurrentCanvasTime, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue(); } );
454 connect( radioButtonDefinedDateTime, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue(); } );
455 connect( radioButtonDatasetGroupTimeStep, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue(); } );
456 connect( dateTimeEdit, &QgsDateTimeEdit::dateTimeChanged, this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
457 connect( comboBoxDatasetTimeStep, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
458
459 updateWidget();
460}
461
462void QgsProcessingMeshDatasetTimeWidget::setMeshLayer( QgsMeshLayer *layer, bool layerFromProject )
463{
464 if ( mMeshLayer == layer )
465 return;
466
467 mReferenceTime = QDateTime();
468
469 if ( layerFromProject )
470 {
471 mMeshLayer = layer;
472 mReferenceTime = static_cast<QgsMeshLayerTemporalProperties *>( layer->temporalProperties() )->referenceTime();
473 }
474 else
475 {
476 mMeshLayer = nullptr;
477 if ( layer )
478 mReferenceTime = layer->dataProvider()->temporalCapabilities()->referenceTime();
479 storeTimeStepsFromLayer( layer );
480 }
481
482 if ( mReferenceTime.isValid() )
483 whileBlocking( dateTimeEdit )->setDateTime( mReferenceTime );
484
485 updateValue();
486}
487
488void QgsProcessingMeshDatasetTimeWidget::setDatasetGroupIndexes( const QList<int> datasetGroupIndexes )
489{
490 if ( datasetGroupIndexes == mDatasetGroupIndexes )
491 return;
492 mDatasetGroupIndexes = datasetGroupIndexes;
493 populateTimeSteps();
494 updateValue();
495}
496
497void QgsProcessingMeshDatasetTimeWidget::setValue( const QVariant &value )
498{
499 if ( !value.isValid() || ( value.userType() != QMetaType::Type::QVariantMap && !value.toDateTime().isValid() ) )
500 return;
501
502 mValue.clear();
503 if ( value.toDateTime().isValid() )
504 {
505 QDateTime dateTime = value.toDateTime();
506 dateTime.setTimeSpec( Qt::UTC );
507 mValue.insert( QStringLiteral( "type" ), QStringLiteral( "defined-date-time" ) );
508 mValue.insert( QStringLiteral( "value" ), dateTime );
509 }
510 else
511 mValue = value.toMap();
512
513 if ( !mValue.contains( QStringLiteral( "type" ) ) || !mValue.contains( QStringLiteral( "value" ) ) )
514 return;
515
516 QString type = mValue.value( QStringLiteral( "type" ) ).toString();
517
518 setEnabled( true );
519 if ( type == QLatin1String( "static" ) )
520 {
521 setEnabled( false );
522 }
523 else if ( type == QLatin1String( "dataset-time-step" ) )
524 {
525 QVariantList dataset = mValue.value( QStringLiteral( "value" ) ).toList();
526 whileBlocking( comboBoxDatasetTimeStep )->setCurrentIndex( comboBoxDatasetTimeStep->findData( dataset ) );
527 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( true );
528 }
529 else if ( type == QLatin1String( "defined-date-time" ) )
530 {
531 whileBlocking( dateTimeEdit )->setDateTime( mValue.value( QStringLiteral( "value" ) ).toDateTime() );
532 whileBlocking( radioButtonDefinedDateTime )->setChecked( true );
533 }
534 else if ( type == QLatin1String( "current-context-time" ) )
535 {
536 whileBlocking( radioButtonCurrentCanvasTime )->setChecked( true );
537 }
538
539 emit changed();
540 updateWidget();
541}
542
543QVariant QgsProcessingMeshDatasetTimeWidget::value() const
544{
545 return mValue;
546}
547
548void QgsProcessingMeshDatasetTimeWidget::updateWidget()
549{
550 bool isStatic = !hasTemporalDataset();
551 setEnabled( !isStatic );
552
553 if ( mCanvas && mCanvas->mapSettings().isTemporal() )
554 {
555 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( true && mReferenceTime.isValid() );
556 labelCurrentCanvasTime->setText( mCanvas->mapSettings().temporalRange().begin().toString( "yyyy-MM-dd HH:mm:ss" ) );
557 }
558 else
559 {
560 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( false );
561 if ( radioButtonCurrentCanvasTime->isChecked() )
562 whileBlocking( radioButtonDefinedDateTime )->setChecked( true );
563 }
564
565 if ( !mReferenceTime.isValid() )
566 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( true );
567
568 whileBlocking( radioButtonDefinedDateTime )->setEnabled( mReferenceTime.isValid() );
569
570 dateTimeEdit->setVisible( radioButtonDefinedDateTime->isChecked() && !isStatic );
571 labelCurrentCanvasTime->setVisible( radioButtonCurrentCanvasTime->isChecked() && !isStatic );
572 comboBoxDatasetTimeStep->setVisible( radioButtonDatasetGroupTimeStep->isChecked() && !isStatic );
573}
574
575bool QgsProcessingMeshDatasetTimeWidget::hasTemporalDataset() const
576{
577 for ( int index : mDatasetGroupIndexes )
578 {
579 if ( mMeshLayer && mMeshLayer->datasetGroupMetadata( index ).isTemporal() )
580 return true;
581 else if ( mDatasetTimeSteps.contains( index ) )
582 return true;
583 }
584
585 return false;
586}
587
588
589void QgsProcessingMeshDatasetTimeWidget::populateTimeSteps()
590{
591 if ( mMeshLayer )
592 {
593 populateTimeStepsFromLayer();
594 return;
595 }
596
597 QMap<quint64, QgsMeshDatasetIndex> timeStep;
598 for ( int groupIndex : mDatasetGroupIndexes )
599 {
600 if ( !mDatasetTimeSteps.contains( groupIndex ) )
601 continue;
602 const QList<qint64> relativeTimeSteps = mDatasetTimeSteps.value( groupIndex );
603 for ( int index = 0; index < relativeTimeSteps.count(); ++index )
604 {
605 QgsMeshDatasetIndex datasetIndex( groupIndex, index );
606 if ( timeStep.contains( relativeTimeSteps.at( index ) ) )
607 continue;
608 timeStep[relativeTimeSteps.at( index )] = datasetIndex;
609 }
610 }
611
612 for ( auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
613 {
614 QString stringTime = QgsMeshLayerUtils::formatTime( static_cast<double>( it.key() ) / 1000. / 3600., mReferenceTime, QgsMeshTimeSettings() );
615 QVariantList data;
616 const QgsMeshDatasetIndex &index = it.value();
617 data << index.group() << index.dataset();
618 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
619 }
620}
621
622void QgsProcessingMeshDatasetTimeWidget::populateTimeStepsFromLayer()
623{
624 whileBlocking( comboBoxDatasetTimeStep )->clear();
625
626 if ( !mMeshLayer )
627 return;
628
629 QMap<quint64, QgsMeshDatasetIndex> timeStep;
630 for ( int groupIndex : std::as_const( mDatasetGroupIndexes ) )
631 {
632 QgsMeshDatasetGroupMetadata meta = mMeshLayer->datasetGroupMetadata( groupIndex );
633 if ( !meta.isTemporal() )
634 continue;
635 int datasetCount = mMeshLayer->datasetCount( groupIndex );
636
637 for ( int index = 0; index < datasetCount; ++index )
638 {
639 QgsMeshDatasetIndex datasetIndex( groupIndex, index );
640 qint64 relativeTime = mMeshLayer->datasetRelativeTimeInMilliseconds( datasetIndex );
641 if ( timeStep.contains( relativeTime ) )
642 continue;
643 timeStep[relativeTime] = datasetIndex;
644 }
645 }
646
647 for ( auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
648 {
649 QString stringTime = mMeshLayer->formatTime( static_cast<double>( it.key() ) / 1000.0 / 3600.0 );
650 QVariantList data;
651 const QgsMeshDatasetIndex &index = it.value();
652 data << index.group() << index.dataset();
653 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
654 }
655}
656
657void QgsProcessingMeshDatasetTimeWidget::storeTimeStepsFromLayer( QgsMeshLayer *layer )
658{
659 mDatasetTimeSteps.clear();
660 if ( !layer )
661 return;
662 QList<int> datasetGroupsList = layer->datasetGroupsIndexes();
663 for ( int groupIndex : datasetGroupsList )
664 {
665 QgsMeshDatasetGroupMetadata meta = layer->datasetGroupMetadata( groupIndex );
666 if ( !meta.isTemporal() )
667 continue;
668 int datasetCount = layer->datasetCount( groupIndex );
669 QList<qint64> relativeTimeSteps;
670 relativeTimeSteps.reserve( datasetCount );
671 for ( int index = 0; index < datasetCount; ++index )
672 relativeTimeSteps.append( layer->datasetRelativeTimeInMilliseconds( QgsMeshDatasetIndex( groupIndex, index ) ) );
673 mDatasetTimeSteps[groupIndex] = relativeTimeSteps;
674 }
675}
676
677void QgsProcessingMeshDatasetTimeWidget::buildValue()
678{
679 mValue.clear();
680
681 if ( !isEnabled() )
682 {
683 mValue[QStringLiteral( "type" )] = QStringLiteral( "static" );
684 }
685 else if ( radioButtonDatasetGroupTimeStep->isChecked() )
686 {
687 mValue[QStringLiteral( "type" )] = QStringLiteral( "dataset-time-step" );
688 mValue[QStringLiteral( "value" )] = comboBoxDatasetTimeStep->currentData();
689 }
690 else if ( radioButtonDefinedDateTime->isChecked() )
691 {
692 mValue[QStringLiteral( "type" )] = QStringLiteral( "defined-date-time" );
693 mValue[QStringLiteral( "value" )] = dateTimeEdit->dateTime();
694 }
695 else if ( radioButtonCurrentCanvasTime->isChecked() && mCanvas )
696 {
697 mValue[QStringLiteral( "type" )] = QStringLiteral( "current-context-time" );
698 }
699
700 emit changed();
701}
702
703void QgsProcessingMeshDatasetTimeWidget::updateValue()
704{
705 updateWidget();
706 buildValue();
707}
708
709
710QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::QgsProcessingMeshDatasetGroupsParameterDefinitionWidget(
711 QgsProcessingContext &context,
712 const QgsProcessingParameterWidgetContext &widgetContext,
713 const QgsProcessingParameterDefinition *definition,
715 QWidget *parent
716)
717 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
718{
719 QVBoxLayout *vlayout = new QVBoxLayout();
720 vlayout->setContentsMargins( 0, 0, 0, 0 );
721
722 vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
723
724 mParentLayerComboBox = new QComboBox();
725 vlayout->addWidget( mParentLayerComboBox );
726
727 if ( QgsProcessingModelAlgorithm *model = widgetContext.model() )
728 {
729 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
730 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
731 {
732 const QgsProcessingParameterDefinition *def = model->parameterDefinition( it.value().parameterName() );
733 if ( def && def->type() == QgsProcessingParameterMeshLayer::typeName() )
734 {
735 mParentLayerComboBox->addItem( def->description(), def->name() );
736 }
737 }
738 }
739
740 const QgsProcessingParameterMeshDatasetGroups *datasetGroupDef = static_cast<const QgsProcessingParameterMeshDatasetGroups *>( definition );
741 if ( datasetGroupDef )
742 {
743 int currentIndex = mParentLayerComboBox->findData( datasetGroupDef->meshLayerParameterName() );
744 if ( currentIndex != -1 )
745 mParentLayerComboBox->setCurrentIndex( currentIndex );
746 else if ( !datasetGroupDef->meshLayerParameterName().isEmpty() )
747 {
748 // if no layer parameter candidates found, we just add the existing one as a placeholder
749 mParentLayerComboBox->addItem( datasetGroupDef->meshLayerParameterName(), datasetGroupDef->meshLayerParameterName() );
750 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
751 }
752 }
753
754 setLayout( vlayout );
755}
756
757QgsProcessingParameterDefinition *QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::createParameter(
758 const QString &name,
759 const QString &description,
761) const
762{
763 QSet<int> supportedDataType;
764 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnEdges );
765 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnVertices );
766 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnFaces );
767 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnVolumes );
768 auto param = std::make_unique<QgsProcessingParameterMeshDatasetGroups>( name, description, mParentLayerComboBox->currentData().toString(), supportedDataType );
769 param->setFlags( flags );
770 return param.release();
771}
772
773QgsProcessingMeshDatasetTimeParameterDefinitionWidget::QgsProcessingMeshDatasetTimeParameterDefinitionWidget(
774 QgsProcessingContext &context,
775 const QgsProcessingParameterWidgetContext &widgetContext,
776 const QgsProcessingParameterDefinition *definition,
778 QWidget *parent
779)
780 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
781{
782 if ( definition )
783 {
784 const QgsProcessingParameterMeshDatasetTime *datasetTimeDef = static_cast<const QgsProcessingParameterMeshDatasetTime *>( definition );
785 mMeshLayerParameterName = datasetTimeDef->meshLayerParameterName();
786 }
787
788 QVBoxLayout *vlayout = new QVBoxLayout();
789 vlayout->setContentsMargins( 0, 0, 0, 0 );
790
791 vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
792
793 mParentDatasetComboBox = new QComboBox();
794 vlayout->addWidget( mParentDatasetComboBox );
795
796 QgsProcessingModelAlgorithm *model = widgetContext.model();
797 if ( model )
798 {
799 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
800 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
801 {
802 const QgsProcessingParameterDefinition *def = model->parameterDefinition( it.value().parameterName() );
804 mParentDatasetComboBox->addItem( def->description(), def->name() );
805 }
806 }
807
808 if ( definition )
809 {
810 const QgsProcessingParameterMeshDatasetTime *datasetTimeDef = static_cast<const QgsProcessingParameterMeshDatasetTime *>( definition );
811 int currentIndex = mParentDatasetComboBox->findData( datasetTimeDef->datasetGroupParameterName() );
812 if ( currentIndex != -1 )
813 mParentDatasetComboBox->setCurrentIndex( currentIndex );
814 else if ( !datasetTimeDef->meshLayerParameterName().isEmpty() )
815 {
816 // if no layer parameter candidates found, we just add the existing one as a placeholder
817 mParentDatasetComboBox->addItem( datasetTimeDef->datasetGroupParameterName(), datasetTimeDef->datasetGroupParameterName() );
818 mParentDatasetComboBox->setCurrentIndex( mParentDatasetComboBox->count() - 1 );
819 }
820 }
821
822 if ( model )
823 {
824 const QgsProcessingParameterDefinition *currentDef = model->parameterDefinition( mParentDatasetComboBox->currentData().toString() );
825 if ( currentDef )
826 mMeshLayerParameterName = static_cast<const QgsProcessingParameterMeshDatasetGroups *>( currentDef )->meshLayerParameterName();
827
828 connect( mParentDatasetComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this, model] {
829 const QgsProcessingParameterDefinition *currentDef = model->parameterDefinition( mParentDatasetComboBox->currentData().toString() );
830 if ( currentDef )
831 mMeshLayerParameterName = static_cast<const QgsProcessingParameterMeshDatasetGroups *>( currentDef )->meshLayerParameterName();
832 } );
833 }
834
835 setLayout( vlayout );
836}
837
838QgsProcessingParameterDefinition *QgsProcessingMeshDatasetTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
839{
840 auto param = std::make_unique<QgsProcessingParameterMeshDatasetTime>(
841 name, description, mMeshLayerParameterName, mParentDatasetComboBox->currentData().toString()
842 );
843
844 param->setFlags( flags );
845 return param.release();
846}
847
ProcessingMode
Types of modes which Processing widgets can be created for.
Definition qgis.h:3537
@ Batch
Batch processing mode.
@ Modeler
Modeler mode.
@ Standard
Standard (single-run) algorithm mode.
QFlags< ProcessingParameterFlag > ProcessingParameterFlags
Flags which dictate the behavior of Processing parameters.
Definition qgis.h:3643
A widget wrapper for Processing parameter value widgets.
QVariant parameterValue() const
Returns the current value of the parameter.
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
virtual void postInitialize(const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers)
Called after all wrappers have been created within a particular dialog or context,...
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
Map canvas is a class for displaying all GIS data types on a canvas.
void temporalRangeChanged()
Emitted when the map canvas temporal range changes.
QVector< T > layers() const
Returns a list of registered map layers with a specified layer type.
QDateTime referenceTime() const
Returns the reference time.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
A collection of dataset group metadata such as whether the data is vector or scalar,...
bool isTemporal() const
Returns whether the dataset group is temporal (contains time-related dataset)
QString name() const
Returns name of the dataset group.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
An index that identifies the dataset group (e.g.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group()
Implementation of map layer temporal properties for mesh layers.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
QList< int > datasetGroupsIndexes() const
Returns the list of indexes of dataset groups handled by the layer.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
qint64 datasetRelativeTimeInMilliseconds(const QgsMeshDatasetIndex &index)
Returns the relative time (in milliseconds) of the dataset from the reference time of its group.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
Represents a mesh time settings for mesh datasets.
Base class for any widget that can be shown as an inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void acceptPanel()
Accept the panel.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
Abstract base class for widgets which allow users to specify the properties of a Processing parameter...
Abstract base class for processing algorithms.
Contains information about the context in which a processing algorithm is executed.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Base class for the definition of processing parameters.
void setFlags(Qgis::ProcessingParameterFlags flags)
Sets the flags associated with the parameter.
QString description() const
Returns the description for the parameter.
virtual QString type() const =0
Unique parameter type name.
QString name() const
Returns the name of the parameter.
A parameter for processing algorithms that need a list of mesh dataset groups.
static QString typeName()
Returns the type name for the parameter class.
QString meshLayerParameterName() const
Returns the name of the mesh layer parameter.
A parameter for processing algorithms that need a list of mesh dataset index from time parameter.
QString datasetGroupParameterName() const
Returns the name of the dataset groups parameter.
QString meshLayerParameterName() const
Returns the name of the mesh layer parameter.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
Contains settings which reflect the context in which a Processing parameter widget is shown.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsProcessingModelAlgorithm * model() const
Returns the model which the parameter widget is associated with.
static QList< int > parameterAsInts(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of integer values.
static QgsMeshLayer * parameterAsMeshLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context)
Evaluates the parameter with matching definition and value to a mesh layer.
static int parameterAsInt(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a static integer value.
QgsMapLayerStore * layerStore()
Returns a pointer to the project's internal layer store.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6206
#define SIP_FACTORY
Definition qgis_sip.h:76