36#include "moc_qgsprocessingmeshdatasetwidget.cpp"
38using namespace Qt::StringLiterals;
46 QHBoxLayout *hl =
new QHBoxLayout();
47 hl->setContentsMargins( 0, 0, 0, 0 );
49 mLineEdit =
new QLineEdit();
50 mLineEdit->setEnabled(
false );
51 hl->addWidget( mLineEdit, 1 );
53 mToolButton =
new QToolButton();
54 mToolButton->setText( QString( QChar( 0x2026 ) ) );
55 hl->addWidget( mToolButton );
59 mLineEdit->setText( tr(
"%1 dataset groups selected" ).arg( 0 ) );
61 mToolButton->setPopupMode( QToolButton::InstantPopup );
62 QMenu *toolButtonMenu =
new QMenu(
this );
63 mActionCurrentActiveDatasetGroups = toolButtonMenu->addAction( tr(
"Current Active Dataset Group" ) );
64 connect( mActionCurrentActiveDatasetGroups, &QAction::triggered,
this, &QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup );
66 mActionAvailableDatasetGroups = toolButtonMenu->addAction( tr(
"Select in Available Dataset Groups" ) );
67 connect( mActionAvailableDatasetGroups, &QAction::triggered,
this, &QgsProcessingMeshDatasetGroupsWidget::showDialog );
69 mToolButton->setMenu( toolButtonMenu );
72void QgsProcessingMeshDatasetGroupsWidget::setMeshLayer(
QgsMeshLayer *layer,
bool layerFromProject )
74 mActionCurrentActiveDatasetGroups->setEnabled( layer && layerFromProject );
75 mActionAvailableDatasetGroups->setEnabled( layer );
77 if ( mMeshLayer == layer )
80 mDatasetGroupsNames.clear();
82 if ( layerFromProject )
90 for (
int i : datasetGroupsIndexes )
93 if ( mParam->isDataTypeSupported( meta.
dataType() ) )
95 mDatasetGroupsNames[i] = meta.
name();
105void QgsProcessingMeshDatasetGroupsWidget::setValue(
const QVariant &value )
107 if ( value.isValid() )
108 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
116QVariant QgsProcessingMeshDatasetGroupsWidget::value()
const
121void QgsProcessingMeshDatasetGroupsWidget::showDialog()
123 QList<int> datasetGroupsIndexes;
125 QVariantList availableOptions;
128 datasetGroupsIndexes = mMeshLayer->datasetGroupsIndexes();
129 for (
int i : std::as_const( datasetGroupsIndexes ) )
132 if ( mParam->isDataTypeSupported( meta.
dataType() ) )
134 availableOptions.append( i );
135 options.append( meta.
name() );
141 for (
auto it = mDatasetGroupsNames.constBegin(); it != mDatasetGroupsNames.constEnd(); it++ )
143 availableOptions.append( it.key() );
144 options.append( it.value() );
151 QgsProcessingMultipleSelectionPanelWidget *widget =
new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
152 widget->setPanelTitle( tr(
"Dataset Groups Available" ) );
154 widget->setValueFormatter( [availableOptions, options](
const QVariant &v ) -> QString {
155 const int index = v.toInt();
156 const int pos = availableOptions.indexOf( index );
157 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
160 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged,
this, [
this, widget]() { setValue( widget->selectedOptions() ); } );
166 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue,
this, Qt::WindowFlags() );
168 dlg.setValueFormatter( [datasetGroupsIndexes, options](
const QVariant &v ) -> QString {
169 const int index = v.toInt();
170 const int pos = datasetGroupsIndexes.indexOf( index );
171 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
175 setValue( dlg.selectedOptions() );
180void QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup()
182 QVariantList options;
183 if ( mMeshLayer && mParam )
185 int scalarDatasetGroup = mMeshLayer->rendererSettings().activeScalarDatasetGroup();
186 int vectorDatasetGroup = mMeshLayer->rendererSettings().activeVectorDatasetGroup();
188 if ( scalarDatasetGroup >= 0 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( scalarDatasetGroup ).dataType() ) )
189 options.append( scalarDatasetGroup );
191 if ( vectorDatasetGroup >= 0 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( vectorDatasetGroup ).dataType() ) && vectorDatasetGroup != scalarDatasetGroup )
192 options.append( vectorDatasetGroup );
202QString QgsProcessingMeshDatasetGroupsWidgetWrapper::parameterType()
const
209 return new QgsProcessingMeshDatasetGroupsWidgetWrapper( parameter, type );
216 return new QgsProcessingMeshDatasetGroupsParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
219void QgsProcessingMeshDatasetGroupsWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
231 setMeshLayerWrapperValue( wrapper );
250 if ( mProcessingContextGenerator )
251 context = mProcessingContextGenerator->processingContext();
253 bool layerFromProject;
259 layerFromProject =
false;
268 mWidget->setMeshLayer( meshLayer, layerFromProject );
271QWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidget()
SIP_FACTORY
274 connect( mWidget, &QgsProcessingMeshDatasetGroupsWidget::changed,
this, [
this] { emit widgetValueHasChanged(
this ); } );
279void QgsProcessingMeshDatasetGroupsWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext &context )
284 QList<int> datasetGroupIndexes;
285 if ( value.userType() == QMetaType::Type::QVariantList )
293 QVariantList varList;
294 for (
const int index : std::as_const( datasetGroupIndexes ) )
295 varList.append( index );
297 mWidget->setValue( varList );
300QVariant QgsProcessingMeshDatasetGroupsWidgetWrapper::widgetValue()
const
303 return mWidget->value();
308void QgsProcessingMeshDatasetGroupsWidget::updateSummaryText()
310 mLineEdit->setText( tr(
"%n option(s) selected",
nullptr, mValue.count() ) );
317QString QgsProcessingMeshDatasetTimeWidgetWrapper::parameterType()
const
324 return new QgsProcessingMeshDatasetTimeWidgetWrapper( parameter, type );
327void QgsProcessingMeshDatasetTimeWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
340 layerParameterWrapper = wrapper;
343 datasetGroupsParameterWrapper = wrapper;
345 setMeshLayerWrapperValue( layerParameterWrapper );
346 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
348 setMeshLayerWrapperValue( layerParameterWrapper );
349 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
364 return new QgsProcessingMeshDatasetTimeParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
369 if ( !mWidget || !wrapper )
374 if ( mProcessingContextGenerator )
375 context = mProcessingContextGenerator->processingContext();
377 bool layerFromProject;
383 layerFromProject =
false;
391 mWidget->setMeshLayer( meshLayer, layerFromProject );
396 if ( !mWidget || !wrapper )
401 if ( !datasetGroupsVariant.isValid() || datasetGroupsVariant.userType() != QMetaType::Type::QVariantList )
402 mWidget->setDatasetGroupIndexes( QList<int>() );
404 QVariantList datasetGroupsListVariant = datasetGroupsVariant.toList();
406 QList<int> datasetGroupsIndexes;
407 for (
const QVariant &variantIndex : datasetGroupsListVariant )
408 datasetGroupsIndexes << variantIndex.toInt();
410 mWidget->setDatasetGroupIndexes( datasetGroupsIndexes );
413QWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidget()
422 connect( mWidget, &QgsProcessingMeshDatasetTimeWidget::changed,
this, [
this] { emit widgetValueHasChanged(
this ); } );
427void QgsProcessingMeshDatasetTimeWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext &context )
431 mWidget->setValue( value );
434QVariant QgsProcessingMeshDatasetTimeWidgetWrapper::widgetValue()
const
437 return mWidget->value();
447 mValue.insert( u
"type"_s, u
"static"_s );
449 dateTimeEdit->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
453 connect( radioButtonCurrentCanvasTime, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
457 connect( radioButtonDefinedDateTime, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
461 connect( radioButtonDatasetGroupTimeStep, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
465 connect( dateTimeEdit, &QgsDateTimeEdit::dateTimeChanged,
this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
466 connect( comboBoxDatasetTimeStep, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
471void QgsProcessingMeshDatasetTimeWidget::setMeshLayer(
QgsMeshLayer *layer,
bool layerFromProject )
473 if ( mMeshLayer == layer )
476 mReferenceTime = QDateTime();
478 if ( layerFromProject )
485 mMeshLayer =
nullptr;
488 storeTimeStepsFromLayer( layer );
491 if ( mReferenceTime.isValid() )
492 whileBlocking( dateTimeEdit )->setDateTime( mReferenceTime );
497void QgsProcessingMeshDatasetTimeWidget::setDatasetGroupIndexes(
const QList<int> datasetGroupIndexes )
499 if ( datasetGroupIndexes == mDatasetGroupIndexes )
501 mDatasetGroupIndexes = datasetGroupIndexes;
506void QgsProcessingMeshDatasetTimeWidget::setValue(
const QVariant &value )
508 if ( !value.isValid() || ( value.userType() != QMetaType::Type::QVariantMap && !value.toDateTime().isValid() ) )
512 if ( value.toDateTime().isValid() )
514 QDateTime dateTime = value.toDateTime();
515 dateTime.setTimeSpec( Qt::UTC );
516 mValue.insert( u
"type"_s, u
"defined-date-time"_s );
517 mValue.insert( u
"value"_s, dateTime );
520 mValue = value.toMap();
522 if ( !mValue.contains( u
"type"_s ) || !mValue.contains( u
"value"_s ) )
525 QString type = mValue.value( u
"type"_s ).toString();
528 if ( type ==
"static"_L1 )
532 else if ( type ==
"dataset-time-step"_L1 )
534 QVariantList dataset = mValue.value( u
"value"_s ).toList();
535 whileBlocking( comboBoxDatasetTimeStep )->setCurrentIndex( comboBoxDatasetTimeStep->findData( dataset ) );
536 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked(
true );
538 else if ( type ==
"defined-date-time"_L1 )
540 whileBlocking( dateTimeEdit )->setDateTime( mValue.value( u
"value"_s ).toDateTime() );
541 whileBlocking( radioButtonDefinedDateTime )->setChecked(
true );
543 else if ( type ==
"current-context-time"_L1 )
545 whileBlocking( radioButtonCurrentCanvasTime )->setChecked(
true );
552QVariant QgsProcessingMeshDatasetTimeWidget::value()
const
557void QgsProcessingMeshDatasetTimeWidget::updateWidget()
559 bool isStatic = !hasTemporalDataset();
560 setEnabled( !isStatic );
562 if ( mCanvas && mCanvas->mapSettings().isTemporal() )
564 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled(
true && mReferenceTime.isValid() );
565 labelCurrentCanvasTime->setText( mCanvas->mapSettings().temporalRange().begin().toString(
"yyyy-MM-dd HH:mm:ss" ) );
569 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled(
false );
570 if ( radioButtonCurrentCanvasTime->isChecked() )
571 whileBlocking( radioButtonDefinedDateTime )->setChecked(
true );
574 if ( !mReferenceTime.isValid() )
575 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked(
true );
577 whileBlocking( radioButtonDefinedDateTime )->setEnabled( mReferenceTime.isValid() );
579 dateTimeEdit->setVisible( radioButtonDefinedDateTime->isChecked() && !isStatic );
580 labelCurrentCanvasTime->setVisible( radioButtonCurrentCanvasTime->isChecked() && !isStatic );
581 comboBoxDatasetTimeStep->setVisible( radioButtonDatasetGroupTimeStep->isChecked() && !isStatic );
584bool QgsProcessingMeshDatasetTimeWidget::hasTemporalDataset()
const
586 for (
int index : mDatasetGroupIndexes )
588 if ( mMeshLayer && mMeshLayer->datasetGroupMetadata( index ).isTemporal() )
590 else if ( mDatasetTimeSteps.contains( index ) )
598void QgsProcessingMeshDatasetTimeWidget::populateTimeSteps()
602 populateTimeStepsFromLayer();
606 QMap<quint64, QgsMeshDatasetIndex> timeStep;
607 for (
int groupIndex : mDatasetGroupIndexes )
609 if ( !mDatasetTimeSteps.contains( groupIndex ) )
611 const QList<qint64> relativeTimeSteps = mDatasetTimeSteps.value( groupIndex );
612 for (
int index = 0; index < relativeTimeSteps.count(); ++index )
615 if ( timeStep.contains( relativeTimeSteps.at( index ) ) )
617 timeStep[relativeTimeSteps.at( index )] = datasetIndex;
621 for (
auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
623 QString stringTime = QgsMeshLayerUtils::formatTime(
static_cast<double>( it.key() ) / 1000. / 3600., mReferenceTime,
QgsMeshTimeSettings() );
627 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
631void QgsProcessingMeshDatasetTimeWidget::populateTimeStepsFromLayer()
638 QMap<quint64, QgsMeshDatasetIndex> timeStep;
639 for (
int groupIndex : std::as_const( mDatasetGroupIndexes ) )
644 int datasetCount = mMeshLayer->datasetCount( groupIndex );
646 for (
int index = 0; index < datasetCount; ++index )
649 qint64 relativeTime = mMeshLayer->datasetRelativeTimeInMilliseconds( datasetIndex );
650 if ( timeStep.contains( relativeTime ) )
652 timeStep[relativeTime] = datasetIndex;
656 for (
auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
658 QString stringTime = mMeshLayer->formatTime(
static_cast<double>( it.key() ) / 1000.0 / 3600.0 );
662 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
666void QgsProcessingMeshDatasetTimeWidget::storeTimeStepsFromLayer(
QgsMeshLayer *layer )
668 mDatasetTimeSteps.clear();
672 for (
int groupIndex : datasetGroupsList )
678 QList<qint64> relativeTimeSteps;
679 relativeTimeSteps.reserve( datasetCount );
680 for (
int index = 0; index < datasetCount; ++index )
682 mDatasetTimeSteps[groupIndex] = relativeTimeSteps;
686void QgsProcessingMeshDatasetTimeWidget::buildValue()
692 mValue[u
"type"_s] = u
"static"_s;
694 else if ( radioButtonDatasetGroupTimeStep->isChecked() )
696 mValue[u
"type"_s] = u
"dataset-time-step"_s;
697 mValue[u
"value"_s] = comboBoxDatasetTimeStep->currentData();
699 else if ( radioButtonDefinedDateTime->isChecked() )
701 mValue[u
"type"_s] = u
"defined-date-time"_s;
702 mValue[u
"value"_s] = dateTimeEdit->dateTime();
704 else if ( radioButtonCurrentCanvasTime->isChecked() && mCanvas )
706 mValue[u
"type"_s] = u
"current-context-time"_s;
712void QgsProcessingMeshDatasetTimeWidget::updateValue()
719QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::QgsProcessingMeshDatasetGroupsParameterDefinitionWidget(
724 QVBoxLayout *vlayout =
new QVBoxLayout();
725 vlayout->setContentsMargins( 0, 0, 0, 0 );
727 vlayout->addWidget(
new QLabel( tr(
"Linked input" ) ) );
729 mParentLayerComboBox =
new QComboBox();
730 vlayout->addWidget( mParentLayerComboBox );
732 if ( QgsProcessingModelAlgorithm *model = widgetContext.
model() )
734 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
735 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
746 if ( datasetGroupDef )
749 if ( currentIndex != -1 )
750 mParentLayerComboBox->setCurrentIndex( currentIndex );
755 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
761 setLayout( vlayout );
766 QSet<int> supportedDataType;
771 auto param = std::make_unique<QgsProcessingParameterMeshDatasetGroups>( name, description, mParentLayerComboBox->currentData().toString(), supportedDataType );
773 return param.release();
776QgsProcessingMeshDatasetTimeParameterDefinitionWidget::QgsProcessingMeshDatasetTimeParameterDefinitionWidget(
787 QVBoxLayout *vlayout =
new QVBoxLayout();
788 vlayout->setContentsMargins( 0, 0, 0, 0 );
790 vlayout->addWidget(
new QLabel( tr(
"Linked input" ) ) );
792 mParentDatasetComboBox =
new QComboBox();
793 vlayout->addWidget( mParentDatasetComboBox );
795 QgsProcessingModelAlgorithm *model = widgetContext.
model();
798 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
799 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
811 if ( currentIndex != -1 )
812 mParentDatasetComboBox->setCurrentIndex( currentIndex );
817 mParentDatasetComboBox->setCurrentIndex( mParentDatasetComboBox->count() - 1 );
827 connect( mParentDatasetComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, [
this, model] {
836 setLayout( vlayout );
841 auto param = std::make_unique<QgsProcessingParameterMeshDatasetTime>( name, description, mMeshLayerParameterName, mParentDatasetComboBox->currentData().toString() );
844 return param.release();
ProcessingMode
Types of modes which Processing widgets can be created for.
@ Batch
Batch processing mode.
@ Standard
Standard (single-run) algorithm mode.
QFlags< ProcessingParameterFlag > ProcessingParameterFlags
Flags which dictate the behavior of Processing parameters.
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.
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.
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 ¶meters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a list of integer values.
static QgsMeshLayer * parameterAsMeshLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context)
Evaluates the parameter with matching definition and value to a mesh layer.
static int parameterAsInt(const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, 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.