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();