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