31 #include <QToolButton> 
   32 #include <QVBoxLayout> 
   40   QHBoxLayout *hl = 
new QHBoxLayout();
 
   41   hl->setContentsMargins( 0, 0, 0, 0 );
 
   43   mLineEdit = 
new QLineEdit();
 
   44   mLineEdit->setEnabled( 
false );
 
   45   hl->addWidget( mLineEdit, 1 );
 
   47   mToolButton = 
new QToolButton();
 
   48   mToolButton->setText( QString( QChar( 0x2026 ) ) );
 
   49   hl->addWidget( mToolButton );
 
   53   mLineEdit->setText( tr( 
"%1 dataset groups selected" ).arg( 0 ) );
 
   55   mToolButton->setPopupMode( QToolButton::InstantPopup );
 
   56   QMenu *toolButtonMenu = 
new QMenu( 
this );
 
   57   mActionCurrentActiveDatasetGroups = toolButtonMenu->addAction( tr( 
"Current Active Dataset Group" ) );
 
   58   connect( mActionCurrentActiveDatasetGroups,
 
   59            &QAction::triggered, 
this, &QgsProcessingMeshDatasetGroupsWidget::selectCurrentActiveDatasetGroup );
 
   61   mActionAvailableDatasetGroups = toolButtonMenu->addAction( tr( 
"Select in Available Dataset Groups" ) );
 
   62   connect( mActionAvailableDatasetGroups, &QAction::triggered, 
this, &QgsProcessingMeshDatasetGroupsWidget::showDialog );
 
   64   mToolButton->setMenu( toolButtonMenu );
 
   67 void QgsProcessingMeshDatasetGroupsWidget::setMeshLayer( 
QgsMeshLayer *layer, 
bool layerFromProject )
 
   69   mActionCurrentActiveDatasetGroups->setEnabled( layer && layerFromProject );
 
   70   mActionAvailableDatasetGroups->setEnabled( layer );
 
   72   if ( mMeshLayer == layer )
 
   75   mDatasetGroupsNames.clear();
 
   77   if ( layerFromProject )
 
   85       for ( 
int i : datasetGroupsIndexes )
 
   88         if ( mParam->isDataTypeSupported( meta.
dataType() ) )
 
   90           mDatasetGroupsNames[i] = meta.
name();
 
  100 void QgsProcessingMeshDatasetGroupsWidget::setValue( 
const QVariant &value )
 
  102   if ( value.isValid() )
 
  103     mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
 
  111 QVariant QgsProcessingMeshDatasetGroupsWidget::value()
 const 
  116 void QgsProcessingMeshDatasetGroupsWidget::showDialog()
 
  118   QList<int> datasetGroupsIndexes;
 
  120   QVariantList availableOptions;
 
  123     datasetGroupsIndexes = mMeshLayer->datasetGroupsIndexes();
 
  124     for ( 
int i : std::as_const( datasetGroupsIndexes ) )
 
  127       if ( mParam->isDataTypeSupported( meta.
dataType() ) )
 
  129         availableOptions.append( i );
 
  130         options.append( meta.
name() );
 
  136     for ( 
int i : mDatasetGroupsNames.keys() )
 
  138       availableOptions.append( i );
 
  139       options.append( mDatasetGroupsNames.value( i ) );
 
  146     QgsProcessingMultipleSelectionPanelWidget *widget = 
new QgsProcessingMultipleSelectionPanelWidget( availableOptions, mValue );
 
  147     widget->setPanelTitle( tr( 
"Dataset Groups Available" ) );
 
  149     widget->setValueFormatter( [availableOptions, options]( 
const QVariant & v ) -> QString
 
  151       const int index = v.toInt();
 
  152       const int pos = availableOptions.indexOf( index );
 
  153       return ( pos >= 0 && pos < options.size() ) ? options.at( pos ) : QString();
 
  156     connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, 
this, [ = ]()
 
  158       setValue( widget->selectedOptions() );
 
  165     QgsProcessingMultipleSelectionDialog dlg( availableOptions, mValue, 
this, Qt::WindowFlags() );
 
  167     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() );
 
  180 void 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
 
  192          && mParam->isDataTypeSupported( mMeshLayer->datasetGroupMetadata( vectorDatasetGroup ).dataType() )
 
  193          && vectorDatasetGroup != scalarDatasetGroup )
 
  194       options.append( vectorDatasetGroup );
 
  204 QString QgsProcessingMeshDatasetGroupsWidgetWrapper::parameterType()
 const 
  211   return new QgsProcessingMeshDatasetGroupsWidgetWrapper( parameter, type );
 
  216   return new QgsProcessingMeshDatasetGroupsParameterDefinitionWidget( context, widgetContext, definition, 
algorithm );
 
  219 void QgsProcessingMeshDatasetGroupsWidgetWrapper::postInitialize( 
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
 
  231           setMeshLayerWrapperValue( wrapper );
 
  234             setMeshLayerWrapperValue( wrapper );
 
  253   if ( mProcessingContextGenerator )
 
  254     context = mProcessingContextGenerator->processingContext();
 
  256   bool layerFromProject;
 
  262     layerFromProject = 
false;
 
  271     mWidget->setMeshLayer( meshLayer, layerFromProject );
 
  274 QStringList QgsProcessingMeshDatasetGroupsWidgetWrapper::compatibleParameterTypes()
 const 
  281 QStringList QgsProcessingMeshDatasetGroupsWidgetWrapper::compatibleOutputTypes()
 const 
  287 QWidget *QgsProcessingMeshDatasetGroupsWidgetWrapper::createWidget() 
SIP_FACTORY 
  290   connect( mWidget, &QgsProcessingMeshDatasetGroupsWidget::changed, 
this, [ = ]
 
  292     emit widgetValueHasChanged( 
this );
 
  298 void QgsProcessingMeshDatasetGroupsWidgetWrapper::setWidgetValue( 
const QVariant &value, 
QgsProcessingContext &context )
 
  303   QList<int> datasetGroupIndexes;
 
  304   if ( value.type() == QVariant::List )
 
  312   QVariantList varList;
 
  313   for ( 
const int index : std::as_const( datasetGroupIndexes ) )
 
  314     varList.append( index );
 
  316   mWidget->setValue( varList );
 
  319 QVariant QgsProcessingMeshDatasetGroupsWidgetWrapper::widgetValue()
 const 
  322     return mWidget->value();
 
  327 void QgsProcessingMeshDatasetGroupsWidget::updateSummaryText()
 
  329   mLineEdit->setText( tr( 
"%n option(s) selected", 
nullptr, mValue.count() ) );
 
  340 QString QgsProcessingMeshDatasetTimeWidgetWrapper::parameterType()
 const 
  347   return new QgsProcessingMeshDatasetTimeWidgetWrapper( parameter, type );
 
  350 void QgsProcessingMeshDatasetTimeWidgetWrapper::postInitialize( 
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
 
  363           layerParameterWrapper = wrapper;
 
  366           datasetGroupsParameterWrapper = wrapper;
 
  368       setMeshLayerWrapperValue( layerParameterWrapper );
 
  369       setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
 
  372         setMeshLayerWrapperValue( layerParameterWrapper );
 
  373         setDatasetGroupIndexesWrapperValue( datasetGroupsParameterWrapper );
 
  386   return new QgsProcessingMeshDatasetTimeParameterDefinitionWidget( context, widgetContext, definition, 
algorithm );
 
  391   if ( !mWidget || !wrapper )
 
  396   if ( mProcessingContextGenerator )
 
  397     context = mProcessingContextGenerator->processingContext();
 
  399   bool layerFromProject;
 
  405     layerFromProject = 
false;
 
  413   mWidget->setMeshLayer( meshLayer, layerFromProject );
 
  418   if ( !mWidget || !wrapper )
 
  423   if ( !datasetGroupsVariant.isValid() || datasetGroupsVariant.type() != QVariant::List )
 
  424     mWidget->setDatasetGroupIndexes( QList<int>() );
 
  426   QVariantList datasetGroupsListVariant = datasetGroupsVariant.toList();
 
  428   QList<int> datasetGroupsIndexes;
 
  429   for ( 
const QVariant &variantIndex : datasetGroupsListVariant )
 
  430     datasetGroupsIndexes << variantIndex.toInt();
 
  432   mWidget->setDatasetGroupIndexes( datasetGroupsIndexes );
 
  436 QStringList QgsProcessingMeshDatasetTimeWidgetWrapper::compatibleParameterTypes()
 const 
  444 QStringList QgsProcessingMeshDatasetTimeWidgetWrapper::compatibleOutputTypes()
 const 
  450 QWidget *QgsProcessingMeshDatasetTimeWidgetWrapper::createWidget()
 
  459   connect( mWidget, &QgsProcessingMeshDatasetTimeWidget::changed, 
this, [ = ]
 
  461     emit widgetValueHasChanged( 
this );
 
  467 void QgsProcessingMeshDatasetTimeWidgetWrapper::setWidgetValue( 
const QVariant &value, 
QgsProcessingContext &context )
 
  471     mWidget->setValue( value );
 
  474 QVariant QgsProcessingMeshDatasetTimeWidgetWrapper::widgetValue()
 const 
  477     return mWidget->value();
 
  481 QgsProcessingMeshDatasetTimeWidget::QgsProcessingMeshDatasetTimeWidget( QWidget *parent,
 
  489   mValue.insert( QStringLiteral( 
"type" ), QStringLiteral( 
"static" ) );
 
  491   dateTimeEdit->setDisplayFormat( 
"yyyy-MM-dd HH:mm:ss" );
 
  495   connect( radioButtonCurrentCanvasTime, &QRadioButton::toggled, 
this, [
this]( 
bool isChecked ) {
if ( isChecked ) this->updateValue();} );
 
  496   connect( radioButtonDefinedDateTime, &QRadioButton::toggled, 
this, [
this]( 
bool isChecked ) {
if ( isChecked ) this->updateValue();} );
 
  497   connect( radioButtonDatasetGroupTimeStep, &QRadioButton::toggled, 
this, [
this]( 
bool isChecked ) {
if ( isChecked ) this->updateValue();} );
 
  498   connect( dateTimeEdit, &QgsDateTimeEdit::dateTimeChanged, 
this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
 
  499   connect( comboBoxDatasetTimeStep, qOverload<int>( &QComboBox::currentIndexChanged ),
 
  500            this, &QgsProcessingMeshDatasetTimeWidget::updateValue );
 
  505 void QgsProcessingMeshDatasetTimeWidget::setMeshLayer( 
QgsMeshLayer *layer, 
bool layerFromProject )
 
  507   if ( mMeshLayer == layer )
 
  510   mReferenceTime = QDateTime();
 
  512   if ( layerFromProject )
 
  519     mMeshLayer = 
nullptr;
 
  522     storeTimeStepsFromLayer( layer );
 
  525   if ( mReferenceTime.isValid() )
 
  526     whileBlocking( dateTimeEdit )->setDateTime( mReferenceTime );
 
  531 void QgsProcessingMeshDatasetTimeWidget::setDatasetGroupIndexes( 
const QList<int> datasetGroupIndexes )
 
  533   if ( datasetGroupIndexes == mDatasetGroupIndexes )
 
  535   mDatasetGroupIndexes = datasetGroupIndexes;
 
  540 void QgsProcessingMeshDatasetTimeWidget::setValue( 
const QVariant &value )
 
  542   if ( !value.isValid() || ( value.type() != QVariant::Map && !value.toDateTime().isValid() ) )
 
  546   if ( value.toDateTime().isValid() )
 
  548     QDateTime dateTime = value.toDateTime();
 
  549     dateTime.setTimeSpec( Qt::UTC );
 
  550     mValue.insert( QStringLiteral( 
"type" ), QStringLiteral( 
"defined-date-time" ) );
 
  551     mValue.insert( QStringLiteral( 
"value" ), dateTime );
 
  554     mValue = value.toMap();
 
  556   if ( !mValue.contains( QStringLiteral( 
"type" ) ) || !mValue.contains( QStringLiteral( 
"value" ) ) )
 
  559   QString type = mValue.value( QStringLiteral( 
"type" ) ).toString();
 
  562   if ( type == QLatin1String( 
"static" ) )
 
  566   else if ( type == QLatin1String( 
"dataset-time-step" ) )
 
  568     QVariantList dataset = mValue.value( QStringLiteral( 
"value" ) ).toList();
 
  569     whileBlocking( comboBoxDatasetTimeStep )->setCurrentIndex( comboBoxDatasetTimeStep->findData( dataset ) );
 
  570     whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( 
true );
 
  572   else if ( type == QLatin1String( 
"defined-date-time" ) )
 
  574     whileBlocking( dateTimeEdit )->setDateTime( mValue.value( QStringLiteral( 
"value" ) ).toDateTime() );
 
  575     whileBlocking( radioButtonDefinedDateTime )->setChecked( 
true );
 
  577   else if ( type == QLatin1String( 
"current-context-time" ) )
 
  579     whileBlocking( radioButtonCurrentCanvasTime )->setChecked( 
true );
 
  586 QVariant QgsProcessingMeshDatasetTimeWidget::value()
 const 
  591 void QgsProcessingMeshDatasetTimeWidget::updateWidget()
 
  593   bool isStatic = !hasTemporalDataset();
 
  594   setEnabled( !isStatic );
 
  596   if ( mCanvas != 
nullptr  && mCanvas->mapSettings().isTemporal() )
 
  598     whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( 
true && mReferenceTime.isValid() );
 
  599     labelCurrentCanvasTime->setText( mCanvas->mapSettings().temporalRange().begin().toString( 
"yyyy-MM-dd HH:mm:ss" ) );
 
  603     whileBlocking( radioButtonCurrentCanvasTime )->setEnabled( 
false );
 
  604     if ( radioButtonCurrentCanvasTime->isChecked() )
 
  605       whileBlocking( radioButtonDefinedDateTime )->setChecked( 
true );
 
  608   if ( ! mReferenceTime.isValid() )
 
  609     whileBlocking( radioButtonDatasetGroupTimeStep )->setChecked( 
true );
 
  611   whileBlocking( radioButtonDefinedDateTime )->setEnabled( mReferenceTime.isValid() );
 
  613   dateTimeEdit->setVisible( radioButtonDefinedDateTime->isChecked() && !isStatic );
 
  614   labelCurrentCanvasTime->setVisible( radioButtonCurrentCanvasTime->isChecked() && !isStatic );
 
  615   comboBoxDatasetTimeStep->setVisible( radioButtonDatasetGroupTimeStep->isChecked() && !isStatic );
 
  618 bool QgsProcessingMeshDatasetTimeWidget::hasTemporalDataset()
 const 
  620   for ( 
int index : mDatasetGroupIndexes )
 
  622     if ( mMeshLayer && mMeshLayer->datasetGroupMetadata( index ).isTemporal() )
 
  624     else if ( mDatasetTimeSteps.contains( index ) )
 
  632 void QgsProcessingMeshDatasetTimeWidget::populateTimeSteps()
 
  636     populateTimeStepsFromLayer();
 
  640   QMap<quint64, QgsMeshDatasetIndex> timeStep;
 
  641   for ( 
int groupIndex : mDatasetGroupIndexes )
 
  643     if ( !mDatasetTimeSteps.contains( groupIndex ) )
 
  645     const QList<qint64> relativeTimeSteps = mDatasetTimeSteps.value( groupIndex );
 
  646     for ( 
int index = 0; index < relativeTimeSteps.count(); ++index )
 
  649       if ( timeStep.contains( relativeTimeSteps.at( index ) ) )
 
  651       timeStep[relativeTimeSteps.at( index )] = datasetIndex;
 
  655   for ( qint64 key : timeStep.keys() )
 
  657     QString stringTime = QgsMeshLayerUtils::formatTime( key / 1000 / 3600, mReferenceTime, 
QgsMeshTimeSettings() );
 
  661     whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
 
  666 void QgsProcessingMeshDatasetTimeWidget::populateTimeStepsFromLayer()
 
  673   QMap<quint64, QgsMeshDatasetIndex> timeStep;
 
  674   for ( 
int groupIndex : std::as_const( mDatasetGroupIndexes ) )
 
  679     int datasetCount = mMeshLayer->datasetCount( groupIndex );
 
  681     for ( 
int index = 0; index < datasetCount; ++index )
 
  684       qint64 relativeTime = mMeshLayer->datasetRelativeTimeInMilliseconds( datasetIndex );
 
  685       if ( timeStep.contains( relativeTime ) )
 
  687       timeStep[relativeTime] = datasetIndex;
 
  691   for ( qint64 key : timeStep.keys() )
 
  693     QString stringTime = mMeshLayer->formatTime( key / 1000.0 / 3600.0 );
 
  697     whileBlocking( comboBoxDatasetTimeStep )->addItem( stringTime, data );
 
  701 void QgsProcessingMeshDatasetTimeWidget::storeTimeStepsFromLayer( 
QgsMeshLayer *layer )
 
  703   mDatasetTimeSteps.clear();
 
  707   for ( 
int groupIndex : datasetGroupsList )
 
  713     QList<qint64> relativeTimeSteps;
 
  714     relativeTimeSteps.reserve( datasetCount );
 
  715     for ( 
int index = 0; index < datasetCount; ++index )
 
  717     mDatasetTimeSteps[groupIndex] = relativeTimeSteps;
 
  721 void QgsProcessingMeshDatasetTimeWidget::buildValue()
 
  727     mValue[QStringLiteral( 
"type" )] = QStringLiteral( 
"static" );
 
  729   else if ( radioButtonDatasetGroupTimeStep->isChecked() )
 
  731     mValue[QStringLiteral( 
"type" )] = QStringLiteral( 
"dataset-time-step" );
 
  732     mValue[QStringLiteral( 
"value" )] = comboBoxDatasetTimeStep->currentData();
 
  734   else if ( radioButtonDefinedDateTime->isChecked() )
 
  736     mValue[QStringLiteral( 
"type" )] = QStringLiteral( 
"defined-date-time" );
 
  737     mValue[QStringLiteral( 
"value" )] = dateTimeEdit->dateTime();
 
  739   else if ( radioButtonCurrentCanvasTime->isChecked() && mCanvas )
 
  741     mValue[QStringLiteral( 
"type" )] = QStringLiteral( 
"current-context-time" );
 
  747 void QgsProcessingMeshDatasetTimeWidget::updateValue()
 
  754 QgsProcessingMeshDatasetGroupsParameterDefinitionWidget::QgsProcessingMeshDatasetGroupsParameterDefinitionWidget(
 
  762   QVBoxLayout *vlayout = 
new QVBoxLayout();
 
  763   vlayout->setContentsMargins( 0, 0, 0, 0 );
 
  765   vlayout->addWidget( 
new QLabel( tr( 
"Linked input" ) ) );
 
  767   mParentLayerComboBox = 
new QComboBox();
 
  768   vlayout->addWidget( mParentLayerComboBox );
 
  770   if ( QgsProcessingModelAlgorithm *model = widgetContext.
model() )
 
  772     const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
 
  773     for ( 
auto it = components.constBegin(); it != components.constEnd(); ++it )
 
  786   if ( currentIndex != -1 )
 
  787     mParentLayerComboBox->setCurrentIndex( currentIndex );
 
  792     mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  795   setLayout( vlayout );
 
  800   const QString &description,
 
  801   QgsProcessingParameterDefinition::Flags flags )
 const 
  803   QSet<int> supportedDataType;
 
  808   std::unique_ptr<QgsProcessingParameterMeshDatasetGroups> param =
 
  809     std::make_unique<QgsProcessingParameterMeshDatasetGroups>( name, description, mParentLayerComboBox->currentData().toString(), supportedDataType );
 
  810   param->setFlags( flags );
 
  811   return param.release();
 
  814 QgsProcessingMeshDatasetTimeParameterDefinitionWidget::QgsProcessingMeshDatasetTimeParameterDefinitionWidget(
 
  829   QVBoxLayout *vlayout = 
new QVBoxLayout();
 
  830   vlayout->setContentsMargins( 0, 0, 0, 0 );
 
  832   vlayout->addWidget( 
new QLabel( tr( 
"Linked input" ) ) );
 
  834   mParentDatasetComboBox = 
new QComboBox();
 
  835   vlayout->addWidget( mParentDatasetComboBox );
 
  837   QgsProcessingModelAlgorithm *model = widgetContext.
model();
 
  840     const QMap<QString, QgsProcessingModelParameter> components = model->parameterComponents();
 
  841     for ( 
auto it = components.constBegin(); it != components.constEnd(); ++it )
 
  854     if ( currentIndex != -1 )
 
  855       mParentDatasetComboBox->setCurrentIndex( currentIndex );
 
  860       mParentDatasetComboBox->setCurrentIndex( mParentDatasetComboBox->count() - 1 );
 
  870     connect( mParentDatasetComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), 
this, [
this, model]
 
  878   setLayout( vlayout );
 
  881 QgsProcessingParameterDefinition *QgsProcessingMeshDatasetTimeParameterDefinitionWidget::createParameter( 
const QString &name, 
const QString &description, QgsProcessingParameterDefinition::Flags flags )
 const 
  883   std::unique_ptr<QgsProcessingParameterMeshDatasetTime> param = std::make_unique<QgsProcessingParameterMeshDatasetTime>(
 
  884         name, description, mMeshLayerParameterName, mParentDatasetComboBox->currentData().toString() );
 
  886   param->setFlags( flags );
 
  887   return param.release();