QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgsdatetimeedit.h"
20#include "qgsmeshlayer.h"
21#include "qgsmeshlayerutils.h"
23#include "qgspanelwidget.h"
24#include "qgsmapcanvas.h"
27
28#include <QLineEdit>
29#include <QLabel>
30#include <QMenu>
31#include <QToolButton>
32#include <QVBoxLayout>
33
35
36QgsProcessingMeshDatasetGroupsWidget::QgsProcessingMeshDatasetGroupsWidget( QWidget *parent, const QgsProcessingParameterMeshDatasetGroups *param )
37 : QWidget( parent ),
38 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,
59 &QAction::triggered, this, &QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup );
60
61 mActionAvailableDatasetGroups = toolButtonMenu->addAction( tr( "Select in Available Dataset Groups" ) );
62 connect( mActionAvailableDatasetGroups, &QAction::triggered, this, &QgsProcessingMeshDatasetGroupsWidget::showDialog );
63
64 mToolButton->setMenu( toolButtonMenu );
65}
66
67void QgsProcessingMeshDatasetGroupsWidget::setMeshLayer( QgsMeshLayer *layer, bool layerFromProject )
68{
69 mActionCurrentActiveDatasetGroups->setEnabled( layer && layerFromProject );
70 mActionAvailableDatasetGroups->setEnabled( layer );
71
72 if ( mMeshLayer == layer )
73 return;
74
75 mDatasetGroupsNames.clear();
76
77 if ( layerFromProject )
78 mMeshLayer = layer;
79 else
80 {
81 mMeshLayer = nullptr;
82 if ( layer )
83 {
84 QList<int> datasetGroupsIndexes = layer->datasetGroupsIndexes();
85 for ( int i : datasetGroupsIndexes )
86 {
88 if ( mParam->isDataTypeSupported( meta.dataType() ) )
89 {
90 mDatasetGroupsNames[i] = meta.name();
91 }
92 }
93 }
94 }
95 mValue.clear();
96 updateSummaryText();
97 emit changed();
98}
99
100void QgsProcessingMeshDatasetGroupsWidget::setValue( const QVariant &value )
101{
102 if ( value.isValid() )
103 mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
104 else
105 mValue.clear();
106
107 updateSummaryText();
108 emit changed();
109}
110
111QVariant QgsProcessingMeshDatasetGroupsWidget::value() const
112{
113 return mValue;
114}
115
116void QgsProcessingMeshDatasetGroupsWidget::showDialog()
117{
118 QList<int> datasetGroupsIndexes;
119 QStringList options;
120 QVariantList availableOptions;
121 if ( mMeshLayer )
122 {
123 datasetGroupsIndexes = mMeshLayer->datasetGroupsIndexes();
124 for ( int i : std::as_const( datasetGroupsIndexes ) )
125 {
126 QgsMeshDatasetGroupMetadata meta = mMeshLayer->datasetGroupMetadata( i );
127 if ( mParam->isDataTypeSupported( meta.dataType() ) )
128 {
129 availableOptions.append( i );
130 options.append( meta.name() );
131 }
132 }
133 }
134 else
135 {
136 for ( auto it = mDatasetGroupsNames.constBegin(); it != mDatasetGroupsNames.constEnd(); it++ )
137 {
138 availableOptions.append( it.key() );
139 options.append( it.value() );
140 }
141 }
142
144 if ( panel && panel->dockMode() )
145 {
146 QgsProcessingMultipleSelectionPanelWidget *widget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
147 widget->setPanelTitle( tr( "Dataset Groups Available" ) );
148
149 widget->setValueFormatter( [availableOptions, options]( const QVariant & v ) -> QString
150 {
151 const int index = v.toInt();
152 const int pos = availableOptions.indexOf( index );
153 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
154 } );
155
156 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
157 {
158 setValue( widget->selectedOptions() );
159 } );
160 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
161 panel->openPanel( widget );
162 }
163 else
164 {
165 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, this, Qt::WindowFlags() );
166
167 dlg.setValueFormatter( [datasetGroupsIndexes, options]( const QVariant & v ) -> QString
168 {
169 const int index = v.toInt();
170 const int pos = datasetGroupsIndexes.indexOf( index );
171 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
172 } );
173 if ( dlg.exec() )
174 {
175 setValue( dlg.selectedOptions() );
176 }
177 }
178}
179
180void QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup()
181{
182 QVariantList options;
183 if ( mMeshLayer && mParam )
184 {
185 int scalarDatasetGroup = mMeshLayer->rendererSettings().activeScalarDatasetGroup();
186 int vectorDatasetGroup = mMeshLayer->rendererSettings().activeVectorDatasetGroup();
187
188 if ( scalarDatasetGroup >= 0 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( scalarDatasetGroup ).dataType() ) )
189 options.append( scalarDatasetGroup );
190
191 if ( vectorDatasetGroup >= 0
192 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( vectorDatasetGroup ).dataType() )
193 && vectorDatasetGroup != scalarDatasetGroup )
194 options.append( vectorDatasetGroup );
195 }
196
197 setValue( options );
198}
199
200QgsProcessingMeshDatasetGroupsWidgetWrapper::QgsProcessingMeshDatasetGroupsWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent ):
201 QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
202{}
203
204QString QgsProcessingMeshDatasetGroupsWidgetWrapper::parameterType() const
205{
207}
208
209QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
210{
211 return new QgsProcessingMeshDatasetGroupsWidgetWrapper( parameter, type );
212}
213
214QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
215{
216 return new QgsProcessingMeshDatasetGroupsParameterDefinitionWidget( context, widgetContext, definition, algorithm );
217}
218
219void QgsProcessingMeshDatasetGroupsWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
220{
222 switch ( type() )
223 {
226 {
227 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
228 {
229 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterMeshDatasetGroups * >( parameterDefinition() )->meshLayerParameterName() )
230 {
231 setMeshLayerWrapperValue( wrapper );
233 {
234 setMeshLayerWrapperValue( wrapper );
235 } );
236 break;
237 }
238 }
239 }
240 break;
242 break;
243 }
244}
245
246void QgsProcessingMeshDatasetGroupsWidgetWrapper::setMeshLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
247{
248 if ( ! mWidget )
249 return;
250
251 // evaluate value to layer
252 QgsProcessingContext *context = nullptr;
253 if ( mProcessingContextGenerator )
254 context = mProcessingContextGenerator->processingContext();
255
256 bool layerFromProject;
257 QgsMeshLayer *meshLayer;
258 if ( !context )
259 {
260 QgsProcessingContext dummyContext;
261 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), dummyContext );
262 layerFromProject = false;
263 }
264 else
265 {
266 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), *context );
267 layerFromProject = context->project() && context->project()->layerStore()->layers<QgsMeshLayer *>().contains( meshLayer );
268 }
269
270 if ( mWidget )
271 mWidget->setMeshLayer( meshLayer, layerFromProject );
272}
273
274QStringList QgsProcessingMeshDatasetGroupsWidgetWrapper::compatibleParameterTypes() const
275{
279}
280
281QStringList QgsProcessingMeshDatasetGroupsWidgetWrapper::compatibleOutputTypes() const
282{
283 return QStringList() << QgsProcessingOutputString::typeName()
285}
286
287QWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidget() SIP_FACTORY
288{
289 mWidget = new QgsProcessingMeshDatasetGroupsWidget( nullptr, static_cast<const QgsProcessingParameterMeshDatasetGroups *>( parameterDefinition() ) );
290 connect( mWidget, &QgsProcessingMeshDatasetGroupsWidget::changed, this, [ = ]
291 {
292 emit widgetValueHasChanged( this );
293 } );
294
295 return mWidget;
296}
297
298void QgsProcessingMeshDatasetGroupsWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
299{
300 if ( !mWidget )
301 return;
302
303 QList<int> datasetGroupIndexes;
304 if ( value.type() == QVariant::List )
305 {
306 //here we can't use QgsProcessingParameters::parameterAsInts() because this method return empry list when first value is 0...
307 datasetGroupIndexes = QgsProcessingParameters::parameterAsInts( parameterDefinition(), value, context );
308 }
309 else
310 datasetGroupIndexes.append( QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context ) );
311
312 QVariantList varList;
313 for ( const int index : std::as_const( datasetGroupIndexes ) )
314 varList.append( index );
315
316 mWidget->setValue( varList );
317}
318
319QVariant QgsProcessingMeshDatasetGroupsWidgetWrapper::widgetValue() const
320{
321 if ( mWidget )
322 return mWidget->value();
323 return QVariant();
324}
325
326
327void QgsProcessingMeshDatasetGroupsWidget::updateSummaryText()
328{
329 mLineEdit->setText( tr( "%n option(s) selected", nullptr, mValue.count() ) );
330}
331
332QgsProcessingMeshDatasetTimeWidgetWrapper::QgsProcessingMeshDatasetTimeWidgetWrapper( const QgsProcessingParameterDefinition *parameter,
334 QWidget *parent )
335 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
336{
337
338}
339
340QString QgsProcessingMeshDatasetTimeWidgetWrapper::parameterType() const
341{
343}
344
345QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
346{
347 return new QgsProcessingMeshDatasetTimeWidgetWrapper( parameter, type );
348}
349
350void QgsProcessingMeshDatasetTimeWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
351{
353 switch ( type() )
354 {
357 {
358 const QgsAbstractProcessingParameterWidgetWrapper *layerParameterWrapper = nullptr;
359 const QgsAbstractProcessingParameterWidgetWrapper *datasetGroupsParameterWrapper = nullptr;
360 for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
361 {
362 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterMeshDatasetTime * >( parameterDefinition() )->meshLayerParameterName() )
363 layerParameterWrapper = wrapper;
364
365 if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterMeshDatasetTime * >( parameterDefinition() )->datasetGroupParameterName() )
366 datasetGroupsParameterWrapper = wrapper;
367 }
368 setMeshLayerWrapperValue( layerParameterWrapper );
369 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
370 connect( datasetGroupsParameterWrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
371 {
372 setMeshLayerWrapperValue( layerParameterWrapper );
373 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
374 } );
375
376 break;
377 }
378
380 break;
381 }
382}
383
384QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
385{
386 return new QgsProcessingMeshDatasetTimeParameterDefinitionWidget( context, widgetContext, definition, algorithm );
387}
388
389void QgsProcessingMeshDatasetTimeWidgetWrapper::setMeshLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
390{
391 if ( !mWidget || !wrapper )
392 return;
393
394 // evaluate value to layer
395 QgsProcessingContext *context = nullptr;
396 if ( mProcessingContextGenerator )
397 context = mProcessingContextGenerator->processingContext();
398
399 bool layerFromProject;
400 QgsMeshLayer *meshLayer;
401 if ( !context )
402 {
403 QgsProcessingContext dummyContext;
404 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), dummyContext );
405 layerFromProject = false;
406 }
407 else
408 {
409 meshLayer = QgsProcessingParameters::parameterAsMeshLayer( wrapper->parameterDefinition(), wrapper->parameterValue(), *context );
410 layerFromProject = context->project() && context->project()->layerStore()->layers<QgsMeshLayer *>().contains( meshLayer );
411 }
412
413 mWidget->setMeshLayer( meshLayer, layerFromProject );
414}
415
416void QgsProcessingMeshDatasetTimeWidgetWrapper::setDatasetGroupIndexesWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *wrapper )
417{
418 if ( !mWidget || !wrapper )
419 return;
420
421 QVariant datasetGroupsVariant = wrapper->parameterValue();
422
423 if ( !datasetGroupsVariant.isValid() || datasetGroupsVariant.type() != QVariant::List )
424 mWidget->setDatasetGroupIndexes( QList<int>() );
425
426 QVariantList datasetGroupsListVariant = datasetGroupsVariant.toList();
427
428 QList<int> datasetGroupsIndexes;
429 for ( const QVariant &variantIndex : datasetGroupsListVariant )
430 datasetGroupsIndexes << variantIndex.toInt();
431
432 mWidget->setDatasetGroupIndexes( datasetGroupsIndexes );
433
434}
435
436QStringList QgsProcessingMeshDatasetTimeWidgetWrapper::compatibleParameterTypes() const
437{
438 return QStringList()
442}
443
444QStringList QgsProcessingMeshDatasetTimeWidgetWrapper::compatibleOutputTypes() const
445{
446 return QStringList()
448}
449
450QWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidget()
451{
452 mWidget = new QgsProcessingMeshDatasetTimeWidget( nullptr, static_cast<const QgsProcessingParameterMeshDatasetTime *>( parameterDefinition() ), widgetContext() );
453
454 QgsMapCanvas *canvas = widgetContext().mapCanvas();
455 if ( canvas )
456 {
457 connect( canvas, &QgsMapCanvas::temporalRangeChanged, mWidget, &QgsProcessingMeshDatasetTimeWidget::updateValue );
458 }
459 connect( mWidget, &QgsProcessingMeshDatasetTimeWidget::changed, this, [ = ]
460 {
461 emit widgetValueHasChanged( this );
462 } );
463
464 return mWidget;
465}
466
467void QgsProcessingMeshDatasetTimeWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
468{
469 Q_UNUSED( context );
470 if ( mWidget )
471 mWidget->setValue( value );
472}
473
474QVariant QgsProcessingMeshDatasetTimeWidgetWrapper::widgetValue() const
475{
476 if ( mWidget )
477 return mWidget->value();
478 return QVariant();
479}
480
481QgsProcessingMeshDatasetTimeWidget::QgsProcessingMeshDatasetTimeWidget( QWidget *parent,
484 QWidget( parent ),
485 mParam( param )
486{
487 setupUi( this );
488
489 mValue.insert( QStringLiteral( "type" ), QStringLiteral( "static" ) );
490
491 dateTimeEdit->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
492
493 mCanvas = context.mapCanvas();
494
495 connect( radioButtonCurrentCanvasTime, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue();} );
496 connect( radioButtonDefinedDateTime, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue();} );
497 connect( radioButtonDatasetGroupTimeStep, &QRadioButton::toggled, this, [this]( bool isChecked ) {if ( isChecked ) this->updateValue();} );
498 connect( dateTimeEdit, &QgsDateTimeEdit::dateTimeChanged, this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
499 connect( comboBoxDatasetTimeStep, qOverload<int>( &QComboBox::currentIndexChanged ),
500 this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
501
502 updateWidget();
503}
504
505void QgsProcessingMeshDatasetTimeWidget::setMeshLayer( QgsMeshLayer *layer, bool layerFromProject )
506{
507 if ( mMeshLayer == layer )
508 return;
509
510 mReferenceTime = QDateTime();
511
512 if ( layerFromProject )
513 {
514 mMeshLayer = layer;
515 mReferenceTime = static_cast<QgsMeshLayerTemporalProperties *>( layer->temporalProperties() )->referenceTime();
516 }
517 else
518 {
519 mMeshLayer = nullptr;
520 if ( layer )
521 mReferenceTime = layer->dataProvider()->temporalCapabilities()->referenceTime();
522 storeTimeStepsFromLayer( layer );
523 }
524
525 if ( mReferenceTime.isValid() )
526 whileBlocking( dateTimeEdit )->setDateTime( mReferenceTime );
527
528 updateValue();
529}
530
531void QgsProcessingMeshDatasetTimeWidget::setDatasetGroupIndexes( const QList<int> datasetGroupIndexes )
532{
533 if ( datasetGroupIndexes == mDatasetGroupIndexes )
534 return;
535 mDatasetGroupIndexes = datasetGroupIndexes;
536 populateTimeSteps();
537 updateValue();
538}
539
540void QgsProcessingMeshDatasetTimeWidget::setValue( const QVariant &value )
541{
542 if ( !value.isValid() || ( value.type() != QVariant::Map && !value.toDateTime().isValid() ) )
543 return;
544
545 mValue.clear();
546 if ( value.toDateTime().isValid() )
547 {
548 QDateTime dateTime = value.toDateTime();
549 dateTime.setTimeSpec( Qt::UTC );
550 mValue.insert( QStringLiteral( "type" ), QStringLiteral( "defined-date-time" ) );
551 mValue.insert( QStringLiteral( "value" ), dateTime );
552 }
553 else
554 mValue = value.toMap();
555
556 if ( !mValue.contains( QStringLiteral( "type" ) ) || !mValue.contains( QStringLiteral( "value" ) ) )
557 return;
558
559 QString type = mValue.value( QStringLiteral( "type" ) ).toString();
560
561 setEnabled( true );
562 if ( type == QLatin1String( "static" ) )
563 {
564 setEnabled( false );
565 }
566 else if ( type == QLatin1String( "dataset-time-step" ) )
567 {
568 QVariantList dataset = mValue.value( QStringLiteral( "value" ) ).toList();
569 whileBlocking( comboBoxDatasetTimeStep )->setCurrentIndex( comboBoxDatasetTimeStep->findData( dataset ) );
570 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( true );
571 }
572 else if ( type == QLatin1String( "defined-date-time" ) )
573 {
574 whileBlocking( dateTimeEdit )->setDateTime( mValue.value( QStringLiteral( "value" ) ).toDateTime() );
575 whileBlocking( radioButtonDefinedDateTime )->setChecked( true );
576 }
577 else if ( type == QLatin1String( "current-context-time" ) )
578 {
579 whileBlocking( radioButtonCurrentCanvasTime )->setChecked( true );
580 }
581
582 emit changed();
583 updateWidget();
584}
585
586QVariant QgsProcessingMeshDatasetTimeWidget::value() const
587{
588 return mValue;
589}
590
591void QgsProcessingMeshDatasetTimeWidget::updateWidget()
592{
593 bool isStatic = !hasTemporalDataset();
594 setEnabled( !isStatic );
595
596 if ( mCanvas != nullptr && mCanvas->mapSettings().isTemporal() )
597 {
598 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( true && mReferenceTime.isValid() );
599 labelCurrentCanvasTime->setText( mCanvas->mapSettings().temporalRange().begin().toString( "yyyy-MM-dd HH:mm:ss" ) );
600 }
601 else
602 {
603 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( false );
604 if ( radioButtonCurrentCanvasTime->isChecked() )
605 whileBlocking( radioButtonDefinedDateTime )->setChecked( true );
606 }
607
608 if ( ! mReferenceTime.isValid() )
609 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( true );
610
611 whileBlocking( radioButtonDefinedDateTime )->setEnabled( mReferenceTime.isValid() );
612
613 dateTimeEdit->setVisible( radioButtonDefinedDateTime->isChecked() && !isStatic );
614 labelCurrentCanvasTime->setVisible( radioButtonCurrentCanvasTime->isChecked() && !isStatic );
615 comboBoxDatasetTimeStep->setVisible( radioButtonDatasetGroupTimeStep->isChecked() && !isStatic );
616}
617
618bool QgsProcessingMeshDatasetTimeWidget::hasTemporalDataset() const
619{
620 for ( int index : mDatasetGroupIndexes )
621 {
622 if ( mMeshLayer && mMeshLayer->datasetGroupMetadata( index ).isTemporal() )
623 return true;
624 else if ( mDatasetTimeSteps.contains( index ) )
625 return true;
626 }
627
628 return false;
629}
630
631
632void QgsProcessingMeshDatasetTimeWidget::populateTimeSteps()
633{
634 if ( mMeshLayer )
635 {
636 populateTimeStepsFromLayer();
637 return;
638 }
639
640 QMap<quint64, QgsMeshDatasetIndex> timeStep;
641 for ( int groupIndex : mDatasetGroupIndexes )
642 {
643 if ( !mDatasetTimeSteps.contains( groupIndex ) )
644 continue;
645 const QList<qint64> relativeTimeSteps = mDatasetTimeSteps.value( groupIndex );
646 for ( int index = 0; index < relativeTimeSteps.count(); ++index )
647 {
648 QgsMeshDatasetIndex datasetIndex( groupIndex, index );
649 if ( timeStep.contains( relativeTimeSteps.at( index ) ) )
650 continue;
651 timeStep[relativeTimeSteps.at( index )] = datasetIndex;
652 }
653 }
654
655 for ( auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
656 {
657 QString stringTime = QgsMeshLayerUtils::formatTime( static_cast<double>( it.key() ) / 1000. / 3600., mReferenceTime, QgsMeshTimeSettings() );
658 QVariantList data;
659 const QgsMeshDatasetIndex &index = it.value();
660 data << index.group() << index.dataset();
661 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
662 }
663
664}
665
666void QgsProcessingMeshDatasetTimeWidget::populateTimeStepsFromLayer()
667{
668 whileBlocking( comboBoxDatasetTimeStep )->clear();
669
670 if ( !mMeshLayer )
671 return;
672
673 QMap<quint64, QgsMeshDatasetIndex> timeStep;
674 for ( int groupIndex : std::as_const( mDatasetGroupIndexes ) )
675 {
676 QgsMeshDatasetGroupMetadata meta = mMeshLayer->datasetGroupMetadata( groupIndex );
677 if ( !meta.isTemporal() )
678 continue;
679 int datasetCount = mMeshLayer->datasetCount( groupIndex );
680
681 for ( int index = 0; index < datasetCount; ++index )
682 {
683 QgsMeshDatasetIndex datasetIndex( groupIndex, index );
684 qint64 relativeTime = mMeshLayer->datasetRelativeTimeInMilliseconds( datasetIndex );
685 if ( timeStep.contains( relativeTime ) )
686 continue;
687 timeStep[relativeTime] = datasetIndex;
688 }
689 }
690
691 for ( auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
692 {
693 QString stringTime = mMeshLayer->formatTime( static_cast<double>( it.key() ) / 1000.0 / 3600.0 );
694 QVariantList data;
695 const QgsMeshDatasetIndex &index = it.value();
696 data << index.group() << index.dataset();
697 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
698 }
699}
700
701void QgsProcessingMeshDatasetTimeWidget::storeTimeStepsFromLayer( QgsMeshLayer *layer )
702{
703 mDatasetTimeSteps.clear();
704 if ( !layer )
705 return;
706 QList<int> datasetGroupsList = layer->datasetGroupsIndexes();
707 for ( int groupIndex : datasetGroupsList )
708 {
709 QgsMeshDatasetGroupMetadata meta = layer->datasetGroupMetadata( groupIndex );
710 if ( !meta.isTemporal() )
711 continue;
712 int datasetCount = layer->datasetCount( groupIndex );
713 QList<qint64> relativeTimeSteps;
714 relativeTimeSteps.reserve( datasetCount );
715 for ( int index = 0; index < datasetCount; ++index )
716 relativeTimeSteps.append( layer->datasetRelativeTimeInMilliseconds( QgsMeshDatasetIndex( groupIndex, index ) ) );
717 mDatasetTimeSteps[groupIndex] = relativeTimeSteps;
718 }
719}
720
721void QgsProcessingMeshDatasetTimeWidget::buildValue()
722{
723 mValue.clear();
724
725 if ( !isEnabled() )
726 {
727 mValue[QStringLiteral( "type" )] = QStringLiteral( "static" );
728 }
729 else if ( radioButtonDatasetGroupTimeStep->isChecked() )
730 {
731 mValue[QStringLiteral( "type" )] = QStringLiteral( "dataset-time-step" );
732 mValue[QStringLiteral( "value" )] = comboBoxDatasetTimeStep->currentData();
733 }
734 else if ( radioButtonDefinedDateTime->isChecked() )
735 {
736 mValue[QStringLiteral( "type" )] = QStringLiteral( "defined-date-time" );
737 mValue[QStringLiteral( "value" )] = dateTimeEdit->dateTime();
738 }
739 else if ( radioButtonCurrentCanvasTime->isChecked() && mCanvas )
740 {
741 mValue[QStringLiteral( "type" )] = QStringLiteral( "current-context-time" );
742 }
743
744 emit changed();
745}
746
747void QgsProcessingMeshDatasetTimeWidget::updateValue()
748{
749 updateWidget();
750 buildValue();
751}
752
753
754QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::QgsProcessingMeshDatasetGroupsParameterDefinitionWidget(
755 QgsProcessingContext &context,
756 const QgsProcessingParameterWidgetContext &widgetContext,
757 const QgsProcessingParameterDefinition *definition,
759 QWidget *parent )
760 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
761{
762 QVBoxLayout *vlayout = new QVBoxLayout();
763 vlayout->setContentsMargins( 0, 0, 0, 0 );
764
765 vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
766
767 mParentLayerComboBox = new QComboBox();
768 vlayout->addWidget( mParentLayerComboBox );
769
770 if ( QgsProcessingModelAlgorithm *model = widgetContext.model() )
771 {
772 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
773 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
774 {
775 const QgsProcessingParameterDefinition *def = model->parameterDefinition( it.value().parameterName() );
776 if ( def && def->type() == QgsProcessingParameterMeshLayer::typeName() )
777 {
778 mParentLayerComboBox->addItem( def->description(), def->name() );
779 }
780 }
781 }
782
783 const QgsProcessingParameterMeshDatasetGroups *datasetGroupDef =
784 static_cast< const QgsProcessingParameterMeshDatasetGroups *>( definition );
785 if ( datasetGroupDef )
786 {
787 int currentIndex = mParentLayerComboBox->findData( datasetGroupDef->meshLayerParameterName() );
788 if ( currentIndex != -1 )
789 mParentLayerComboBox->setCurrentIndex( currentIndex );
790 else if ( !datasetGroupDef->meshLayerParameterName().isEmpty() )
791 {
792 // if no layer parameter candidates found, we just add the existing one as a placeholder
793 mParentLayerComboBox->addItem( datasetGroupDef->meshLayerParameterName(), datasetGroupDef->meshLayerParameterName() );
794 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
795 }
796 }
797
798 setLayout( vlayout );
799}
800
801QgsProcessingParameterDefinition *QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::createParameter(
802 const QString &name,
803 const QString &description,
805{
806 QSet<int> supportedDataType;
807 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnEdges );
808 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnVertices );
809 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnFaces );
810 supportedDataType.insert( QgsMeshDatasetGroupMetadata::DataOnVolumes );
811 std::unique_ptr<QgsProcessingParameterMeshDatasetGroups> param =
812 std::make_unique<QgsProcessingParameterMeshDatasetGroups>( name, description, mParentLayerComboBox->currentData().toString(), supportedDataType );
813 param->setFlags( flags );
814 return param.release();
815}
816
817QgsProcessingMeshDatasetTimeParameterDefinitionWidget::QgsProcessingMeshDatasetTimeParameterDefinitionWidget(
818 QgsProcessingContext &context,
819 const QgsProcessingParameterWidgetContext &widgetContext,
820 const QgsProcessingParameterDefinition *definition,
822 QWidget *parent )
823 : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
824{
825 if ( definition )
826 {
827 const QgsProcessingParameterMeshDatasetTime *datasetTimeDef =
828 static_cast< const QgsProcessingParameterMeshDatasetTime *>( definition );
829 mMeshLayerParameterName = datasetTimeDef->meshLayerParameterName();
830 }
831
832 QVBoxLayout *vlayout = new QVBoxLayout();
833 vlayout->setContentsMargins( 0, 0, 0, 0 );
834
835 vlayout->addWidget( new QLabel( tr( "Linked input" ) ) );
836
837 mParentDatasetComboBox = new QComboBox();
838 vlayout->addWidget( mParentDatasetComboBox );
839
840 QgsProcessingModelAlgorithm *model = widgetContext.model();
841 if ( model )
842 {
843 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
844 for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
845 {
846 const QgsProcessingParameterDefinition *def = model->parameterDefinition( it.value().parameterName() );
848 mParentDatasetComboBox->addItem( def->description(), def->name() );
849 }
850 }
851
852 if ( definition )
853 {
854 const QgsProcessingParameterMeshDatasetTime *datasetTimeDef =
855 static_cast< const QgsProcessingParameterMeshDatasetTime *>( definition );
856 int currentIndex = mParentDatasetComboBox->findData( datasetTimeDef->datasetGroupParameterName() );
857 if ( currentIndex != -1 )
858 mParentDatasetComboBox->setCurrentIndex( currentIndex );
859 else if ( !datasetTimeDef->meshLayerParameterName().isEmpty() )
860 {
861 // if no layer parameter candidates found, we just add the existing one as a placeholder
862 mParentDatasetComboBox->addItem( datasetTimeDef->datasetGroupParameterName(), datasetTimeDef->datasetGroupParameterName() );
863 mParentDatasetComboBox->setCurrentIndex( mParentDatasetComboBox->count() - 1 );
864 }
865 }
866
867 if ( model )
868 {
869 const QgsProcessingParameterDefinition *currentDef = model->parameterDefinition( mParentDatasetComboBox->currentData().toString() );
870 if ( currentDef )
871 mMeshLayerParameterName = static_cast<const QgsProcessingParameterMeshDatasetGroups *>( currentDef )->meshLayerParameterName();
872
873 connect( mParentDatasetComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this, model]
874 {
875 const QgsProcessingParameterDefinition *currentDef = model->parameterDefinition( mParentDatasetComboBox->currentData().toString() );
876 if ( currentDef )
877 mMeshLayerParameterName = static_cast<const QgsProcessingParameterMeshDatasetGroups *>( currentDef )->meshLayerParameterName();
878 } );
879 }
880
881 setLayout( vlayout );
882}
883
884QgsProcessingParameterDefinition *QgsProcessingMeshDatasetTimeParameterDefinitionWidget::createParameter( const QString &name, const QString &description, Qgis::ProcessingParameterFlags flags ) const
885{
886 std::unique_ptr<QgsProcessingParameterMeshDatasetTime> param = std::make_unique<QgsProcessingParameterMeshDatasetTime>(
887 name, description, mMeshLayerParameterName, mParentDatasetComboBox->currentData().toString() );
888
889 param->setFlags( flags );
890 return param.release();
891}
892
QFlags< ProcessingParameterFlag > ProcessingParameterFlags
Flags which dictate the behavior of Processing parameters.
Definition: qgis.h:3066
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.
Definition: qgsmapcanvas.h:93
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.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
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.
QgsMeshDatasetIndex is 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.
Definition: qgsmeshlayer.h:101
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 a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void acceptPanel()
Accept the panel.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
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.
WidgetType
Types of dialogs which Processing widgets can be created for.
@ Modeler
Modeler dialog.
@ Standard
Standard algorithm dialog.
@ Batch
Batch processing dialog.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the parameter class.
Base class for the definition of processing parameters.
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.
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:5111
#define SIP_FACTORY
Definition: qgis_sip.h:76