20 #include <QMessageBox> 
   21 #include <QPushButton> 
   22 #include <QStandardItemModel> 
   23 #include <QToolButton> 
   24 #include <QItemSelectionModel> 
   40 QgsProcessingFieldMapPanelWidget::QgsProcessingFieldMapPanelWidget( QWidget *parent )
 
   45   mModel = mFieldsView->model();
 
   46   mFieldsView->setDestinationEditable( 
true );
 
   48   mLayerCombo->setAllowEmptyLayer( 
true );
 
   51   connect( mResetButton, &QPushButton::clicked, 
this, &QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer );
 
   52   connect( mAddButton, &QPushButton::clicked, 
this, &QgsProcessingFieldMapPanelWidget::addField );
 
   56   connect( mLoadLayerFieldsButton, &QPushButton::clicked, 
this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
 
   60     if ( !mBlockChangedSignal )
 
   67 void QgsProcessingFieldMapPanelWidget::setLayer( 
QgsVectorLayer *layer )
 
   69   if ( layer == mLayer )
 
   73   mFieldsView->setSourceLayer( mLayer );
 
   74   if ( mModel->rowCount() == 0 )
 
   76     loadFieldsFromLayer();
 
   80   QMessageBox dlg( 
this );
 
   81   dlg.setText( tr( 
"Do you want to reset the field mapping?" ) );
 
   82   dlg.setStandardButtons(
 
   83     QMessageBox::StandardButtons( QMessageBox::Yes |
 
   85   dlg.setDefaultButton( QMessageBox::No );
 
   86   if ( dlg.exec() == QMessageBox::Yes )
 
   88     loadFieldsFromLayer();
 
   97 QVariant QgsProcessingFieldMapPanelWidget::value()
 const 
   99   const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
 
  101   QVariantList results;
 
  102   results.reserve( mapping.size() );
 
  106     def.insert( QStringLiteral( 
"name" ), 
field.field.
name() );
 
  107     def.insert( QStringLiteral( 
"type" ), 
static_cast< int >( 
field.field.
type() ) );
 
  108     def.insert( QStringLiteral( 
"type_name" ), 
field.field.
typeName() );
 
  109     def.insert( QStringLiteral( 
"length" ), 
field.field.
length() );
 
  110     def.insert( QStringLiteral( 
"precision" ), 
field.field.
precision() );
 
  111     def.insert( QStringLiteral( 
"sub_type" ), 
static_cast< int >( 
field.field.
subType() ) );
 
  112     def.insert( QStringLiteral( 
"expression" ), 
field.expression );
 
  113     results.append( def );
 
  118 void QgsProcessingFieldMapPanelWidget::setValue( 
const QVariant &value )
 
  120   if ( value.type() != QVariant::List )
 
  124   QMap<QString, QString> expressions;
 
  127   const QVariantList fields = value.toList();
 
  128   for ( 
const QVariant &
field : fields )
 
  130     const QVariantMap map = 
field.toMap();
 
  131     QgsField f( map.value( QStringLiteral( 
"name" ) ).toString(),
 
  132                 static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"type" ), QVariant::Invalid ).toInt() ),
 
  133                 map.value( QStringLiteral( 
"type_name" ), QVariant::typeToName( 
static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"type" ), QVariant::Invalid ).toInt() ) ) ).toString(),
 
  134                 map.value( QStringLiteral( 
"length" ), 0 ).toInt(),
 
  135                 map.value( QStringLiteral( 
"precision" ), 0 ).toInt(),
 
  137                 static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"sub_type" ), QVariant::Invalid ).toInt() ) );
 
  139     if ( map.contains( QStringLiteral( 
"constraints" ) ) )
 
  141       const QgsFieldConstraints::Constraints constraints = 
static_cast<QgsFieldConstraints::Constraints
>( map.value( QStringLiteral( 
"constraints" ), 0 ).toInt() );
 
  151       f.setConstraints( fieldConstraints );
 
  154     if ( !map.value( QStringLiteral( 
"expression" ) ).toString().isEmpty() )
 
  156       expressions.insert( f.name(), map.value( QStringLiteral( 
"expression" ) ).toString() );
 
  159     destinationFields.
append( f );
 
  162   mBlockChangedSignal = 
true;
 
  163   if ( destinationFields.
size() > 0 )
 
  164     mFieldsView->setDestinationFields( destinationFields, expressions );
 
  165   mBlockChangedSignal = 
false;
 
  172   mFieldsView->registerExpressionContextGenerator( generator );
 
  175 void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
 
  179     mFieldsView->setSourceFields( mLayer->fields() );
 
  180     mFieldsView->setDestinationFields( mLayer->fields() );
 
  184 void QgsProcessingFieldMapPanelWidget::addField()
 
  186   const int rowCount = mModel->rowCount();
 
  187   mModel->appendField( 
QgsField( QStringLiteral( 
"new_field" ) ) );
 
  188   const QModelIndex index = mModel->index( rowCount, 0 );
 
  189   mFieldsView->selectionModel()->select(
 
  191     QItemSelectionModel::SelectionFlags(
 
  192       QItemSelectionModel::Clear |
 
  193       QItemSelectionModel::Select |
 
  194       QItemSelectionModel::Current |
 
  195       QItemSelectionModel::Rows ) );
 
  196   mFieldsView->scrollTo( index );
 
  199 void QgsProcessingFieldMapPanelWidget::loadLayerFields()
 
  201   if ( 
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
 
  203     mFieldsView->setSourceFields( vl->fields() );
 
  204     mFieldsView->setDestinationFields( vl->fields() );
 
  215   QVBoxLayout *vlayout = 
new QVBoxLayout();
 
  216   vlayout->setContentsMargins( 0, 0, 0, 0 );
 
  218   vlayout->addWidget( 
new QLabel( tr( 
"Parent layer" ) ) );
 
  220   mParentLayerComboBox = 
new QComboBox();
 
  221   mParentLayerComboBox->addItem( tr( 
"None" ), QVariant() );
 
  223   QString initialParent;
 
  225     initialParent = mapParam->parentLayerParameterName();
 
  227   if ( 
auto *lModel = widgetContext.
model() )
 
  230     const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
 
  231     for ( 
auto it = components.constBegin(); it != components.constEnd(); ++it )
 
  235         mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
 
  236         if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  238           mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  243         mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
 
  244         if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  246           mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  252   if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
 
  255     mParentLayerComboBox->addItem( initialParent, initialParent );
 
  256     mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  259   vlayout->addWidget( mParentLayerComboBox );
 
  260   setLayout( vlayout );
 
  263 QgsProcessingParameterDefinition *QgsProcessingFieldMapParameterDefinitionWidget::createParameter( 
const QString &name, 
const QString &description, QgsProcessingParameterDefinition::Flags flags )
 const 
  265   auto param = std::make_unique< QgsProcessingParameterFieldMapping >( name, description, mParentLayerComboBox->currentData().toString() );
 
  266   param->setFlags( flags );
 
  267   return param.release();
 
  279 QString QgsProcessingFieldMapWidgetWrapper::parameterType()
 const 
  286   return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
 
  289 QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
 
  291   mPanel = 
new QgsProcessingFieldMapPanelWidget( 
nullptr );
 
  292   mPanel->setToolTip( parameterDefinition()->toolTip() );
 
  293   mPanel->registerExpressionContextGenerator( 
this );
 
  295   connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed, 
this, [ = ]
 
  297     emit widgetValueHasChanged( 
this );
 
  305   return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition, 
algorithm );
 
  308 void QgsProcessingFieldMapWidgetWrapper::postInitialize( 
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
 
  320           setParentLayerWrapperValue( wrapper );
 
  323             setParentLayerWrapperValue( wrapper );
 
  336 int QgsProcessingFieldMapWidgetWrapper::stretch()
 const 
  345   std::unique_ptr< QgsProcessingContext > tmpContext;
 
  346   if ( mProcessingContextGenerator )
 
  347     context = mProcessingContextGenerator->processingContext();
 
  351     tmpContext = std::make_unique< QgsProcessingContext >();
 
  352     context = tmpContext.get();
 
  359       mPanel->setLayer( 
nullptr );
 
  365   std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
 
  368     mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
 
  369     layer = mParentLayer.get();
 
  377     mPanel->setLayer( layer );
 
  380 void QgsProcessingFieldMapWidgetWrapper::setWidgetValue( 
const QVariant &value, 
QgsProcessingContext & )
 
  383     mPanel->setValue( value );
 
  386 QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
 const 
  388   return mPanel ? mPanel->value() : QVariant();
 
  391 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
 const 
  397 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
 const 
  399   return QStringList();
 
  402 QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
 const 
  404   return tr( 
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
 
  407 const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
 const 
  409   if ( mPanel && mPanel->layer() )
 
  410     return mPanel->layer();