36#include "moc_qgsprocessingmeshdatasetwidget.cpp"
38using namespace Qt::StringLiterals;
43 : QWidget( parent ), mParam( param )
45 QHBoxLayout *hl =
new QHBoxLayout();
46 hl->setContentsMargins( 0, 0, 0, 0 );
48 mLineEdit =
new QLineEdit();
49 mLineEdit->setEnabled(
false );
50 hl->addWidget( mLineEdit, 1 );
52 mToolButton =
new QToolButton();
53 mToolButton->setText( QString( QChar( 0x2026 ) ) );
54 hl->addWidget( mToolButton );
58 mLineEdit->setText( tr(
"%1 dataset groups selected" ).arg( 0 ) );
60 mToolButton->setPopupMode( QToolButton::InstantPopup );
61 QMenu *toolButtonMenu =
new QMenu(
this );
62 mActionCurrentActiveDatasetGroups = toolButtonMenu->addAction( tr(
"Current Active Dataset Group" ) );
63 connect( mActionCurrentActiveDatasetGroups, &QAction::triggered,
this, &QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup );
65 mActionAvailableDatasetGroups = toolButtonMenu->addAction( tr(
"Select in Available Dataset Groups" ) );
66 connect( mActionAvailableDatasetGroups, &QAction::triggered,
this, &QgsProcessingMeshDatasetGroupsWidget::showDialog );
68 mToolButton->setMenu( toolButtonMenu );
71void QgsProcessingMeshDatasetGroupsWidget::setMeshLayer(
QgsMeshLayer *layer,
bool layerFromProject )
73 mActionCurrentActiveDatasetGroups->setEnabled( layer && layerFromProject );
74 mActionAvailableDatasetGroups->setEnabled( layer );
76 if ( mMeshLayer == layer )
79 mDatasetGroupsNames.clear();
81 if ( layerFromProject )
89 for (
int i : datasetGroupsIndexes )
92 if ( mParam->isDataTypeSupported( meta.
dataType() ) )
94 mDatasetGroupsNames[i] = meta.
name();
104void QgsProcessingMeshDatasetGroupsWidget::setValue(
const QVariant &value )
106 if ( value.isValid() )
107 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
115QVariant QgsProcessingMeshDatasetGroupsWidget::value()
const
120void QgsProcessingMeshDatasetGroupsWidget::showDialog()
122 QList<int> datasetGroupsIndexes;
124 QVariantList availableOptions;
127 datasetGroupsIndexes = mMeshLayer->datasetGroupsIndexes();
128 for (
int i : std::as_const( datasetGroupsIndexes ) )
131 if ( mParam->isDataTypeSupported( meta.
dataType() ) )
133 availableOptions.append( i );
134 options.append( meta.
name() );
140 for (
auto it = mDatasetGroupsNames.constBegin(); it != mDatasetGroupsNames.constEnd(); it++ )
142 availableOptions.append( it.key() );
143 options.append( it.value() );
150 QgsProcessingMultipleSelectionPanelWidget *widget =
new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
151 widget->setPanelTitle( tr(
"Dataset Groups Available" ) );
153 widget->setValueFormatter( [availableOptions, options](
const QVariant &v ) -> QString {
154 const int index = v.toInt();
155 const int pos = availableOptions.indexOf( index );
156 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
159 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged,
this, [
this, widget]() {
160 setValue( widget->selectedOptions() );
167 QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue,
this, Qt::WindowFlags() );
169 dlg.setValueFormatter( [datasetGroupsIndexes, options](
const QVariant &v ) -> QString {
170 const int index = v.toInt();
171 const int pos = datasetGroupsIndexes.indexOf( index );
172 return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
176 setValue( dlg.selectedOptions() );
181void QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup()
183 QVariantList options;
184 if ( mMeshLayer && mParam )
186 int scalarDatasetGroup = mMeshLayer->rendererSettings().activeScalarDatasetGroup();
187 int vectorDatasetGroup = mMeshLayer->rendererSettings().activeVectorDatasetGroup();
189 if ( scalarDatasetGroup >= 0 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( scalarDatasetGroup ).dataType() ) )
190 options.append( scalarDatasetGroup );
192 if ( vectorDatasetGroup >= 0
193 && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( vectorDatasetGroup ).dataType() )
194 && vectorDatasetGroup != scalarDatasetGroup )
195 options.append( vectorDatasetGroup );
205QString QgsProcessingMeshDatasetGroupsWidgetWrapper::parameterType()
const
212 return new QgsProcessingMeshDatasetGroupsWidgetWrapper( parameter, type );
217 return new QgsProcessingMeshDatasetGroupsParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
220void QgsProcessingMeshDatasetGroupsWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
232 setMeshLayerWrapperValue( wrapper );
234 setMeshLayerWrapperValue( wrapper );
253 if ( mProcessingContextGenerator )
254 context = mProcessingContextGenerator->processingContext();
256 bool layerFromProject;
262 layerFromProject =
false;
271 mWidget->setMeshLayer( meshLayer, layerFromProject );
274QWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidget()
SIP_FACTORY
277 connect( mWidget, &QgsProcessingMeshDatasetGroupsWidget::changed,
this, [
this] {
278 emit widgetValueHasChanged(
this );
284void QgsProcessingMeshDatasetGroupsWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext &context )
289 QList<int> datasetGroupIndexes;
290 if ( value.userType() == QMetaType::Type::QVariantList )
298 QVariantList varList;
299 for (
const int index : std::as_const( datasetGroupIndexes ) )
300 varList.append( index );
302 mWidget->setValue( varList );
305QVariant QgsProcessingMeshDatasetGroupsWidgetWrapper::widgetValue()
const
308 return mWidget->value();
313void QgsProcessingMeshDatasetGroupsWidget::updateSummaryText()
315 mLineEdit->setText( tr(
"%n option(s) selected",
nullptr, mValue.count() ) );
323QString QgsProcessingMeshDatasetTimeWidgetWrapper::parameterType()
const
330 return new QgsProcessingMeshDatasetTimeWidgetWrapper( parameter, type );
333void QgsProcessingMeshDatasetTimeWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
346 layerParameterWrapper = wrapper;
349 datasetGroupsParameterWrapper = wrapper;
351 setMeshLayerWrapperValue( layerParameterWrapper );
352 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
354 setMeshLayerWrapperValue( layerParameterWrapper );
355 setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
368 return new QgsProcessingMeshDatasetTimeParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
373 if ( !mWidget || !wrapper )
378 if ( mProcessingContextGenerator )
379 context = mProcessingContextGenerator->processingContext();
381 bool layerFromProject;
387 layerFromProject =
false;
395 mWidget->setMeshLayer( meshLayer, layerFromProject );
400 if ( !mWidget || !wrapper )
405 if ( !datasetGroupsVariant.isValid() || datasetGroupsVariant.userType() != QMetaType::Type::QVariantList )
406 mWidget->setDatasetGroupIndexes( QList<int>() );
408 QVariantList datasetGroupsListVariant = datasetGroupsVariant.toList();
410 QList<int> datasetGroupsIndexes;
411 for (
const QVariant &variantIndex : datasetGroupsListVariant )
412 datasetGroupsIndexes << variantIndex.toInt();
414 mWidget->setDatasetGroupIndexes( datasetGroupsIndexes );
417QWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidget()
426 connect( mWidget, &QgsProcessingMeshDatasetTimeWidget::changed,
this, [
this] {
427 emit widgetValueHasChanged(
this );
433void QgsProcessingMeshDatasetTimeWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext &context )
437 mWidget->setValue( value );
440QVariant QgsProcessingMeshDatasetTimeWidgetWrapper::widgetValue()
const
443 return mWidget->value();
448 : QWidget( parent ), mParam( param )
452 mValue.insert( u
"type"_s, u
"static"_s );
454 dateTimeEdit->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
458 connect( radioButtonCurrentCanvasTime, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
if ( isChecked ) this->updateValue(); } );
459 connect( radioButtonDefinedDateTime, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
if ( isChecked ) this->updateValue(); } );
460 connect( radioButtonDatasetGroupTimeStep, &QRadioButton::toggled,
this, [
this](
bool isChecked ) {
if ( isChecked ) this->updateValue(); } );
461 connect( dateTimeEdit, &QgsDateTimeEdit::dateTimeChanged,
this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
462 connect( comboBoxDatasetTimeStep, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
467void QgsProcessingMeshDatasetTimeWidget::setMeshLayer(
QgsMeshLayer *layer,
bool layerFromProject )
469 if ( mMeshLayer == layer )
472 mReferenceTime = QDateTime();
474 if ( layerFromProject )
481 mMeshLayer =
nullptr;
484 storeTimeStepsFromLayer( layer );
487 if ( mReferenceTime.isValid() )
488 whileBlocking( dateTimeEdit )->setDateTime( mReferenceTime );
493void QgsProcessingMeshDatasetTimeWidget::setDatasetGroupIndexes(
const QList<int> datasetGroupIndexes )
495 if ( datasetGroupIndexes == mDatasetGroupIndexes )
497 mDatasetGroupIndexes = datasetGroupIndexes;
502void QgsProcessingMeshDatasetTimeWidget::setValue(
const QVariant &value )
504 if ( !value.isValid() || ( value.userType() != QMetaType::Type::QVariantMap && !value.toDateTime().isValid() ) )
508 if ( value.toDateTime().isValid() )
510 QDateTime dateTime = value.toDateTime();
511 dateTime.setTimeSpec( Qt::UTC );
512 mValue.insert( u
"type"_s, u
"defined-date-time"_s );
513 mValue.insert( u
"value"_s, dateTime );
516 mValue = value.toMap();
518 if ( !mValue.contains( u
"type"_s ) || !mValue.contains( u
"value"_s ) )
521 QString type = mValue.value( u
"type"_s ).toString();
524 if ( type ==
"static"_L1 )
528 else if ( type ==
"dataset-time-step"_L1 )
530 QVariantList dataset = mValue.value( u
"value"_s ).toList();
531 whileBlocking( comboBoxDatasetTimeStep )->setCurrentIndex( comboBoxDatasetTimeStep->findData( dataset ) );
532 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked(
true );
534 else if ( type ==
"defined-date-time"_L1 )
536 whileBlocking( dateTimeEdit )->setDateTime( mValue.value( u
"value"_s ).toDateTime() );
537 whileBlocking( radioButtonDefinedDateTime )->setChecked(
true );
539 else if ( type ==
"current-context-time"_L1 )
541 whileBlocking( radioButtonCurrentCanvasTime )->setChecked(
true );
548QVariant QgsProcessingMeshDatasetTimeWidget::value()
const
553void QgsProcessingMeshDatasetTimeWidget::updateWidget()
555 bool isStatic = !hasTemporalDataset();
556 setEnabled( !isStatic );
558 if ( mCanvas && mCanvas->mapSettings().isTemporal() )
560 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled(
true && mReferenceTime.isValid() );
561 labelCurrentCanvasTime->setText( mCanvas->mapSettings().temporalRange().begin().toString(
"yyyy-MM-dd HH:mm:ss" ) );
565 whileBlocking( radioButtonCurrentCanvasTime )->setEnabled(
false );
566 if ( radioButtonCurrentCanvasTime->isChecked() )
567 whileBlocking( radioButtonDefinedDateTime )->setChecked(
true );
570 if ( !mReferenceTime.isValid() )
571 whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked(
true );
573 whileBlocking( radioButtonDefinedDateTime )->setEnabled( mReferenceTime.isValid() );
575 dateTimeEdit->setVisible( radioButtonDefinedDateTime->isChecked() && !isStatic );
576 labelCurrentCanvasTime->setVisible( radioButtonCurrentCanvasTime->isChecked() && !isStatic );
577 comboBoxDatasetTimeStep->setVisible( radioButtonDatasetGroupTimeStep->isChecked() && !isStatic );
580bool QgsProcessingMeshDatasetTimeWidget::hasTemporalDataset()
const
582 for (
int index : mDatasetGroupIndexes )
584 if ( mMeshLayer && mMeshLayer->datasetGroupMetadata( index ).isTemporal() )
586 else if ( mDatasetTimeSteps.contains( index ) )
594void QgsProcessingMeshDatasetTimeWidget::populateTimeSteps()
598 populateTimeStepsFromLayer();
602 QMap<quint64, QgsMeshDatasetIndex> timeStep;
603 for (
int groupIndex : mDatasetGroupIndexes )
605 if ( !mDatasetTimeSteps.contains( groupIndex ) )
607 const QList<qint64> relativeTimeSteps = mDatasetTimeSteps.value( groupIndex );
608 for (
int index = 0; index < relativeTimeSteps.count(); ++index )
611 if ( timeStep.contains( relativeTimeSteps.at( index ) ) )
613 timeStep[relativeTimeSteps.at( index )] = datasetIndex;
617 for (
auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
619 QString stringTime = QgsMeshLayerUtils::formatTime(
static_cast<double>( it.key() ) / 1000. / 3600., mReferenceTime,
QgsMeshTimeSettings() );
623 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
627void QgsProcessingMeshDatasetTimeWidget::populateTimeStepsFromLayer()
634 QMap<quint64, QgsMeshDatasetIndex> timeStep;
635 for (
int groupIndex : std::as_const( mDatasetGroupIndexes ) )
640 int datasetCount = mMeshLayer->datasetCount( groupIndex );
642 for (
int index = 0; index < datasetCount; ++index )
645 qint64 relativeTime = mMeshLayer->datasetRelativeTimeInMilliseconds( datasetIndex );
646 if ( timeStep.contains( relativeTime ) )
648 timeStep[relativeTime] = datasetIndex;
652 for (
auto it = timeStep.constBegin(); it != timeStep.constEnd(); it++ )
654 QString stringTime = mMeshLayer->formatTime(
static_cast<double>( it.key() ) / 1000.0 / 3600.0 );
658 whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
662void QgsProcessingMeshDatasetTimeWidget::storeTimeStepsFromLayer(
QgsMeshLayer *layer )
664 mDatasetTimeSteps.clear();
668 for (
int groupIndex : datasetGroupsList )
674 QList<qint64> relativeTimeSteps;
675 relativeTimeSteps.reserve( datasetCount );
676 for (
int index = 0; index < datasetCount; ++index )
678 mDatasetTimeSteps[groupIndex] = relativeTimeSteps;
682void QgsProcessingMeshDatasetTimeWidget::buildValue()
688 mValue[u
"type"_s] = u
"static"_s;
690 else if ( radioButtonDatasetGroupTimeStep->isChecked() )
692 mValue[u
"type"_s] = u
"dataset-time-step"_s;
693 mValue[u
"value"_s] = comboBoxDatasetTimeStep->currentData();
695 else if ( radioButtonDefinedDateTime->isChecked() )
697 mValue[u
"type"_s] = u
"defined-date-time"_s;
698 mValue[u
"value"_s] = dateTimeEdit->dateTime();
700 else if ( radioButtonCurrentCanvasTime->isChecked() && mCanvas )
702 mValue[u
"type"_s] = u
"current-context-time"_s;
708void QgsProcessingMeshDatasetTimeWidget::updateValue()
715QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::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 );
759 setLayout( vlayout );
764 const QString &description,
768 QSet<int> supportedDataType;
773 auto param = std::make_unique<QgsProcessingParameterMeshDatasetGroups>( name, description, mParentLayerComboBox->currentData().toString(), supportedDataType );
775 return param.release();
778QgsProcessingMeshDatasetTimeParameterDefinitionWidget::QgsProcessingMeshDatasetTimeParameterDefinitionWidget(
793 QVBoxLayout *vlayout =
new QVBoxLayout();
794 vlayout->setContentsMargins( 0, 0, 0, 0 );
796 vlayout->addWidget(
new QLabel( tr(
"Linked input" ) ) );
798 mParentDatasetComboBox =
new QComboBox();
799 vlayout->addWidget( mParentDatasetComboBox );
801 QgsProcessingModelAlgorithm *model = widgetContext.
model();
804 const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
805 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
817 if ( currentIndex != -1 )
818 mParentDatasetComboBox->setCurrentIndex( currentIndex );
823 mParentDatasetComboBox->setCurrentIndex( mParentDatasetComboBox->count() - 1 );
833 connect( mParentDatasetComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, [
this, model] {
840 setLayout( vlayout );
845 auto param = std::make_unique<QgsProcessingParameterMeshDatasetTime>(
846 name, description, mMeshLayerParameterName, mParentDatasetComboBox->currentData().toString()
850 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.