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