20 #include <QMessageBox>
21 #include <QPushButton>
22 #include <QStandardItemModel>
23 #include <QToolButton>
28 #include "qgsprocessingmodelalgorithm.h"
39 QgsProcessingFieldMapPanelWidget::QgsProcessingFieldMapPanelWidget( QWidget *parent )
44 mModel = mFieldsView->model();
45 mFieldsView->setDestinationEditable(
true );
47 mLayerCombo->setAllowEmptyLayer(
true );
50 connect( mResetButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer );
51 connect( mAddButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::addField );
55 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
59 if ( !mBlockChangedSignal )
66 void QgsProcessingFieldMapPanelWidget::setLayer(
QgsVectorLayer *layer )
68 if ( layer == mLayer )
72 mFieldsView->setSourceLayer( mLayer );
73 if ( mModel->rowCount() == 0 )
75 loadFieldsFromLayer();
79 QMessageBox dlg(
this );
80 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
81 dlg.setStandardButtons(
82 QMessageBox::StandardButtons( QMessageBox::Yes |
84 dlg.setDefaultButton( QMessageBox::No );
85 if ( dlg.exec() == QMessageBox::Yes )
87 loadFieldsFromLayer();
96 QVariant QgsProcessingFieldMapPanelWidget::value()
const
98 const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
100 QVariantList results;
101 results.reserve( mapping.size() );
105 def.insert( QStringLiteral(
"name" ),
field.field.
name() );
106 def.insert( QStringLiteral(
"type" ),
static_cast< int >(
field.field.
type() ) );
107 def.insert( QStringLiteral(
"length" ),
field.field.
length() );
108 def.insert( QStringLiteral(
"precision" ),
field.field.
precision() );
109 def.insert( QStringLiteral(
"expression" ),
field.expression );
110 results.append( def );
115 void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
117 if ( value.type() != QVariant::List )
121 QMap<QString, QString> expressions;
124 const QVariantList fields = value.toList();
125 for (
const QVariant &
field : fields )
127 const QVariantMap map =
field.toMap();
128 QgsField f( map.value( QStringLiteral(
"name" ) ).toString(),
129 static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ),
130 QVariant::typeToName(
static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ) ),
131 map.value( QStringLiteral(
"length" ), 0 ).toInt(),
132 map.value( QStringLiteral(
"precision" ), 0 ).toInt() );
136 if ( mLayer && layerFieldIdx >= 0 && ! map.contains( QStringLiteral(
"constraints" ) ) )
138 f.setConstraints( layerFields.
at( layerFieldIdx ).
constraints() );
142 const QgsFieldConstraints::Constraints constraints =
static_cast<QgsFieldConstraints::Constraints
>( map.value( QStringLiteral(
"constraints" ), 0 ).toInt() );
152 f.setConstraints( fieldConstraints );
155 if ( !map.value( QStringLiteral(
"expression" ) ).toString().isEmpty() )
157 expressions.insert( f.name(), map.value( QStringLiteral(
"expression" ) ).toString() );
160 destinationFields.
append( f );
163 mBlockChangedSignal =
true;
164 if ( destinationFields.
size() > 0 )
165 mFieldsView->setDestinationFields( destinationFields, expressions );
166 mBlockChangedSignal =
false;
173 mFieldsView->registerExpressionContextGenerator( generator );
176 void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
180 mFieldsView->setSourceFields( mLayer->fields() );
181 mFieldsView->setDestinationFields( mLayer->fields() );
185 void QgsProcessingFieldMapPanelWidget::addField()
187 const int rowCount = mModel->rowCount();
188 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
189 QModelIndex index = mModel->index( rowCount, 0 );
190 mFieldsView->selectionModel()->select(
192 QItemSelectionModel::SelectionFlags(
193 QItemSelectionModel::Clear |
194 QItemSelectionModel::Select |
195 QItemSelectionModel::Current |
196 QItemSelectionModel::Rows ) );
197 mFieldsView->scrollTo( index );
200 void QgsProcessingFieldMapPanelWidget::loadLayerFields()
202 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
204 mFieldsView->setSourceFields( vl->fields() );
205 mFieldsView->setDestinationFields( vl->fields() );
216 QVBoxLayout *vlayout =
new QVBoxLayout();
217 vlayout->setContentsMargins( 0, 0, 0, 0 );
219 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
221 mParentLayerComboBox =
new QComboBox();
222 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
224 QString initialParent;
226 initialParent = mapParam->parentLayerParameterName();
228 if (
auto *lModel = widgetContext.
model() )
231 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
232 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
236 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
237 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
239 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
244 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
245 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
247 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
253 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
256 mParentLayerComboBox->addItem( initialParent, initialParent );
257 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
260 vlayout->addWidget( mParentLayerComboBox );
261 setLayout( vlayout );
264 QgsProcessingParameterDefinition *QgsProcessingFieldMapParameterDefinitionWidget::createParameter(
const QString &name,
const QString &description, QgsProcessingParameterDefinition::Flags flags )
const
266 auto param = qgis::make_unique< QgsProcessingParameterFieldMapping >( name, description, mParentLayerComboBox->currentData().toString() );
267 param->setFlags( flags );
268 return param.release();
280 QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
287 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
290 QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
292 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
293 mPanel->setToolTip( parameterDefinition()->toolTip() );
294 mPanel->registerExpressionContextGenerator(
this );
296 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [ = ]
298 emit widgetValueHasChanged(
this );
306 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
309 void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
321 setParentLayerWrapperValue( wrapper );
324 setParentLayerWrapperValue( wrapper );
337 int QgsProcessingFieldMapWidgetWrapper::stretch()
const
346 std::unique_ptr< QgsProcessingContext > tmpContext;
347 if ( mProcessingContextGenerator )
348 context = mProcessingContextGenerator->processingContext();
352 tmpContext = qgis::make_unique< QgsProcessingContext >();
353 context = tmpContext.get();
360 mPanel->setLayer(
nullptr );
366 std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
369 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
370 layer = mParentLayer.get();
378 mPanel->setLayer( layer );
381 void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
384 mPanel->setValue( value );
387 QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
389 return mPanel ? mPanel->value() : QVariant();
392 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
const
398 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
const
400 return QStringList();
403 QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
405 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
408 const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
410 if ( mPanel && mPanel->layer() )
411 return mPanel->layer();