17#include "moc_qgsprocessingfieldmapwidgetwrapper.cpp"
23#include <QStandardItemModel>
25#include <QItemSelectionModel>
41QgsProcessingFieldMapPanelWidget::QgsProcessingFieldMapPanelWidget( QWidget *parent )
46 mModel = mFieldsView->model();
47 mFieldsView->setDestinationEditable(
true );
49 mLayerCombo->setAllowEmptyLayer(
true );
52 connect( mResetButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer );
53 connect( mAddButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::addField );
58 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
62 if ( !mBlockChangedSignal )
69void QgsProcessingFieldMapPanelWidget::setLayer(
QgsVectorLayer *layer )
71 if ( layer == mLayer )
75 mFieldsView->setSourceLayer( mLayer );
76 if ( mModel->rowCount() == 0 )
78 loadFieldsFromLayer();
82 QMessageBox dlg(
this );
83 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
84 dlg.setStandardButtons(
85 QMessageBox::StandardButtons( QMessageBox::Yes | QMessageBox::No )
87 dlg.setDefaultButton( QMessageBox::No );
88 if ( dlg.exec() == QMessageBox::Yes )
90 loadFieldsFromLayer();
99QVariant QgsProcessingFieldMapPanelWidget::value()
const
101 const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
103 QVariantList results;
104 results.reserve( mapping.size() );
108 def.insert( QStringLiteral(
"name" ), field.field.name() );
109 def.insert( QStringLiteral(
"type" ),
static_cast<int>( field.field.type() ) );
110 def.insert( QStringLiteral(
"type_name" ), field.field.typeName() );
111 def.insert( QStringLiteral(
"length" ), field.field.length() );
112 def.insert( QStringLiteral(
"precision" ), field.field.precision() );
113 def.insert( QStringLiteral(
"sub_type" ),
static_cast<int>( field.field.subType() ) );
114 def.insert( QStringLiteral(
"expression" ), field.expression );
115 def.insert( QStringLiteral(
"alias" ), field.field.alias() );
116 def.insert( QStringLiteral(
"comment" ), field.field.comment() );
117 results.append( def );
122void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
124 if ( value.userType() != QMetaType::Type::QVariantList )
128 QMap<QString, QString> expressions;
131 const QVariantList fields = value.toList();
132 for (
const QVariant &field : fields )
134 const QVariantMap map = field.toMap();
135 QgsField f( map.value( QStringLiteral(
"name" ) ).toString(),
static_cast<QMetaType::Type
>( map.value( QStringLiteral(
"type" ),
static_cast<int>( QMetaType::Type::UnknownType ) ).toInt() ), map.value( QStringLiteral(
"type_name" ), QVariant::typeToName(
static_cast<QMetaType::Type
>( map.value( QStringLiteral(
"type" ),
static_cast<int>( QMetaType::Type::UnknownType ) ).toInt() ) ) ).toString(), map.value( QStringLiteral(
"length" ), 0 ).toInt(), map.value( QStringLiteral(
"precision" ), 0 ).toInt(), QString(),
static_cast<QMetaType::Type
>( map.value( QStringLiteral(
"sub_type" ),
QgsVariantUtils::createNullVariant( QMetaType::Type::UnknownType ) ).toInt() ) );
136 f.setAlias( map.value( QStringLiteral(
"alias" ) ).toString() );
137 f.setComment( map.value( QStringLiteral(
"comment" ) ).toString() );
139 if ( map.contains( QStringLiteral(
"constraints" ) ) )
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 );
175void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
179 mFieldsView->setSourceFields( mLayer->fields() );
180 mFieldsView->setDestinationFields( mLayer->fields() );
184void 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 | QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows
195 mFieldsView->scrollTo( index );
198void QgsProcessingFieldMapPanelWidget::loadLayerFields()
200 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerCombo->currentLayer() ) )
202 mFieldsView->setSourceFields( vl->fields() );
203 mFieldsView->setDestinationFields( vl->fields() );
214 QVBoxLayout *vlayout =
new QVBoxLayout();
215 vlayout->setContentsMargins( 0, 0, 0, 0 );
217 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
219 mParentLayerComboBox =
new QComboBox();
220 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
222 QString initialParent;
224 initialParent = mapParam->parentLayerParameterName();
226 if (
auto *lModel = widgetContext.
model() )
229 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
230 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
234 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
235 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
237 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
242 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
243 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
245 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
251 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
254 mParentLayerComboBox->addItem( initialParent, initialParent );
255 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
258 vlayout->addWidget( mParentLayerComboBox );
259 setLayout( vlayout );
264 auto param = std::make_unique<QgsProcessingParameterFieldMapping>( name, description, mParentLayerComboBox->currentData().toString() );
265 param->setFlags( flags );
266 return param.release();
278QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
285 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
288QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
290 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
291 mPanel->setToolTip( parameterDefinition()->toolTip() );
292 mPanel->registerExpressionContextGenerator(
this );
294 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [=] {
295 emit widgetValueHasChanged(
this );
303 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
306void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
318 setParentLayerWrapperValue( wrapper );
320 setParentLayerWrapperValue( wrapper );
333int QgsProcessingFieldMapWidgetWrapper::stretch()
const
342 std::unique_ptr<QgsProcessingContext> tmpContext;
343 if ( mProcessingContextGenerator )
344 context = mProcessingContextGenerator->processingContext();
348 tmpContext = std::make_unique<QgsProcessingContext>();
349 context = tmpContext.get();
356 mPanel->setLayer(
nullptr );
362 std::unique_ptr<QgsMapLayer> ownedLayer( context->
takeResultLayer( layer->
id() ) );
365 mParentLayer.reset( qobject_cast<QgsVectorLayer *>( ownedLayer.release() ) );
366 layer = mParentLayer.get();
374 mPanel->setLayer( layer );
377void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
380 mPanel->setValue( value );
383QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
385 return mPanel ? mPanel->value() : QVariant();
388QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
const
394QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
const
396 return QStringList();
399QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
401 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
404const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
406 if ( mPanel && mPanel->layer() )
407 return mPanel->layer();
QFlags< ProcessingParameterFlag > ProcessingParameterFlags
Flags which dictate the behavior of Processing parameters.
Abstract interface for generating an expression context.
Stores information about constraints which may be present on a field.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
@ ConstraintExpression
Field has an expression constraint set. See constraintExpression().
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
QFlags< Constraint > Constraints
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
int size() const
Returns number of items.
Abstract base class for processing algorithms.
Contains information about the context in which a processing algorithm is executed.
QgsMapLayer * takeResultLayer(const QString &id)
Takes the result map layer with matching id from the context and transfers ownership of it back to th...
WidgetType
Types of dialogs which Processing widgets can be created for.
@ Standard
Standard algorithm dialog.
@ Batch
Batch processing dialog.
Base class for the definition of processing parameters.
QString description() const
Returns the description for the parameter.
QString name() const
Returns the name of the parameter.
An input feature source (such as vector layers) parameter for processing algorithms.
A parameter for "field mapping" configurations, which consist of a definition of desired output field...
static QString typeName()
Returns the type name for the parameter class.
A vector layer (with or without geometry) parameter for processing algorithms.
Contains settings which reflect the context in which a Processing parameter widget is shown,...
QgsProcessingModelAlgorithm * model() const
Returns the model which the parameter widget is associated with.
static QgsVectorLayer * parameterAsVectorLayer(const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context)
Evaluates the parameter with matching definition to a vector layer.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Represents a vector layer which manages a vector based data sets.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
The Field struct holds information about a mapped field.