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 if ( mModel->rowCount() == 0 )
74 loadFieldsFromLayer();
78 QMessageBox dlg(
this );
79 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
80 dlg.setStandardButtons(
81 QMessageBox::StandardButtons( QMessageBox::Yes |
83 dlg.setDefaultButton( QMessageBox::No );
84 if ( dlg.exec() == QMessageBox::Yes )
86 loadFieldsFromLayer();
95 QVariant QgsProcessingFieldMapPanelWidget::value()
const
97 const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
100 results.reserve( mapping.size() );
104 def.insert( QStringLiteral(
"name" ), field.field.name() );
105 def.insert( QStringLiteral(
"type" ),
static_cast< int >( field.field.type() ) );
106 def.insert( QStringLiteral(
"length" ), field.field.length() );
107 def.insert( QStringLiteral(
"precision" ), field.field.precision() );
108 def.insert( QStringLiteral(
"expression" ), field.expression );
109 results.append( def );
114 void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
116 if ( value.type() != QVariant::List )
120 QMap<QString, QString> expressions;
122 const QVariantList fields = value.
toList();
123 for (
const QVariant &field : fields )
125 const QVariantMap map = field.toMap();
126 QgsField f( map.value( QStringLiteral(
"name" ) ).toString(),
127 static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ),
128 QVariant::typeToName(
static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ) ),
129 map.value( QStringLiteral(
"length" ), 0 ).toInt(),
130 map.value( QStringLiteral(
"precision" ), 0 ).toInt() );
132 if ( !map.value( QStringLiteral(
"expression" ) ).toString().isEmpty() )
134 expressions.insert( f.name(), map.value( QStringLiteral(
"expression" ) ).toString() );
137 destinationFields.
append( f );
140 mBlockChangedSignal =
true;
141 if ( destinationFields.
size() > 0 )
142 mFieldsView->setDestinationFields( destinationFields, expressions );
143 mBlockChangedSignal =
false;
150 mFieldsView->registerExpressionContextGenerator( generator );
153 void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
157 mFieldsView->setSourceFields( mLayer->fields() );
158 mFieldsView->setDestinationFields( mLayer->fields() );
162 void QgsProcessingFieldMapPanelWidget::addField()
164 const int rowCount = mModel->rowCount();
165 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
166 QModelIndex index = mModel->index( rowCount, 0 );
167 mFieldsView->selectionModel()->select(
169 QItemSelectionModel::SelectionFlags(
170 QItemSelectionModel::Clear |
171 QItemSelectionModel::Select |
172 QItemSelectionModel::Current |
173 QItemSelectionModel::Rows ) );
174 mFieldsView->scrollTo( index );
177 void QgsProcessingFieldMapPanelWidget::loadLayerFields()
179 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
181 mFieldsView->setSourceFields( vl->fields() );
182 mFieldsView->setDestinationFields( vl->fields() );
193 QVBoxLayout *vlayout =
new QVBoxLayout();
194 vlayout->setMargin( 0 );
195 vlayout->setContentsMargins( 0, 0, 0, 0 );
197 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
199 mParentLayerComboBox =
new QComboBox();
200 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
202 QString initialParent;
204 initialParent = mapParam->parentLayerParameterName();
206 if ( widgetContext.
model() )
209 const QMap<QString, QgsProcessingModelParameter> components = widgetContext.
model()->parameterComponents();
210 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
214 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
215 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
217 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
222 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
223 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
225 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
231 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
234 mParentLayerComboBox->addItem( initialParent, initialParent );
235 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
238 vlayout->addWidget( mParentLayerComboBox );
239 setLayout( vlayout );
242 QgsProcessingParameterDefinition *QgsProcessingFieldMapParameterDefinitionWidget::createParameter(
const QString &name,
const QString &description, QgsProcessingParameterDefinition::Flags flags )
const
244 auto param = qgis::make_unique< QgsProcessingParameterFieldMapping >( name, description, mParentLayerComboBox->currentData().toString() );
245 param->setFlags( flags );
246 return param.release();
258 QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
265 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
268 QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
270 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
271 mPanel->setToolTip( parameterDefinition()->toolTip() );
272 mPanel->registerExpressionContextGenerator(
this );
274 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [ = ]
276 emit widgetValueHasChanged(
this );
284 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
287 void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
299 setParentLayerWrapperValue( wrapper );
302 setParentLayerWrapperValue( wrapper );
315 int QgsProcessingFieldMapWidgetWrapper::stretch()
const
324 std::unique_ptr< QgsProcessingContext > tmpContext;
325 if ( mProcessingContextGenerator )
326 context = mProcessingContextGenerator->processingContext();
330 tmpContext = qgis::make_unique< QgsProcessingContext >();
331 context = tmpContext.get();
338 mPanel->setLayer(
nullptr );
344 std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
347 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
348 layer = mParentLayer.get();
356 mPanel->setLayer( layer );
359 void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
362 mPanel->setValue( value );
365 QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
367 return mPanel ? mPanel->value() : QVariant();
370 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
const
376 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
const
378 return QStringList();
381 QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
383 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
386 const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
388 if ( mPanel && mPanel->layer() )
389 return mPanel->layer();