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