24#include <QItemSelectionModel>
28#include <QStandardItemModel>
31#include "moc_qgsprocessingfieldmapwidgetwrapper.cpp"
40QgsProcessingFieldMapPanelWidget::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 );
57 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
61 if ( !mBlockChangedSignal )
68void QgsProcessingFieldMapPanelWidget::setLayer(
QgsVectorLayer *layer )
70 if ( layer == mLayer )
74 mFieldsView->setSourceLayer( mLayer );
75 if ( mModel->rowCount() == 0 )
77 loadFieldsFromLayer();
81 if ( mSkipConfirmDialog )
86 QMessageBox dlg(
this );
87 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
88 dlg.setStandardButtons(
89 QMessageBox::StandardButtons( QMessageBox::Yes | QMessageBox::No )
91 dlg.setDefaultButton( QMessageBox::No );
92 if ( dlg.exec() == QMessageBox::Yes )
94 loadFieldsFromLayer();
103QVariant QgsProcessingFieldMapPanelWidget::value()
const
105 const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
107 QVariantList results;
108 results.reserve( mapping.size() );
112 def.insert( QStringLiteral(
"name" ), field.field.name() );
113 def.insert( QStringLiteral(
"type" ),
static_cast<int>( field.field.type() ) );
114 def.insert( QStringLiteral(
"type_name" ), field.field.typeName() );
115 def.insert( QStringLiteral(
"length" ), field.field.length() );
116 def.insert( QStringLiteral(
"precision" ), field.field.precision() );
117 def.insert( QStringLiteral(
"sub_type" ),
static_cast<int>( field.field.subType() ) );
118 def.insert( QStringLiteral(
"expression" ), field.expression );
119 def.insert( QStringLiteral(
"alias" ), field.field.alias() );
120 def.insert( QStringLiteral(
"comment" ), field.field.comment() );
121 results.append( def );
126void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
128 if ( value.userType() != QMetaType::Type::QVariantList )
132 QMap<QString, QString> expressions;
135 const QVariantList fields = value.toList();
136 for (
const QVariant &field : fields )
138 const QVariantMap map = field.toMap();
139 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() ) );
140 f.setAlias( map.value( QStringLiteral(
"alias" ) ).toString() );
141 f.setComment( map.value( QStringLiteral(
"comment" ) ).toString() );
143 if ( map.contains( QStringLiteral(
"constraints" ) ) )
155 f.setConstraints( fieldConstraints );
158 if ( !map.value( QStringLiteral(
"expression" ) ).toString().isEmpty() )
160 expressions.insert( f.name(), map.value( QStringLiteral(
"expression" ) ).toString() );
163 destinationFields.
append( f );
166 mBlockChangedSignal =
true;
167 if ( destinationFields.
size() > 0 )
168 mFieldsView->setDestinationFields( destinationFields, expressions );
169 mBlockChangedSignal =
false;
176 mFieldsView->registerExpressionContextGenerator( generator );
179void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
183 mFieldsView->setSourceFields( mLayer->fields() );
184 mFieldsView->setDestinationFields( mLayer->fields() );
188void QgsProcessingFieldMapPanelWidget::addField()
190 const int rowCount = mModel->rowCount();
191 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
192 const QModelIndex index = mModel->index( rowCount, 0 );
193 mFieldsView->selectionModel()->select(
195 QItemSelectionModel::SelectionFlags(
196 QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows
199 mFieldsView->scrollTo( index );
202void QgsProcessingFieldMapPanelWidget::loadLayerFields()
204 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerCombo->currentLayer() ) )
206 mFieldsView->setDestinationFields( vl->fields() );
217 QVBoxLayout *vlayout =
new QVBoxLayout();
218 vlayout->setContentsMargins( 0, 0, 0, 0 );
220 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
222 mParentLayerComboBox =
new QComboBox();
223 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
225 QString initialParent;
227 initialParent = mapParam->parentLayerParameterName();
229 if (
auto *lModel = widgetContext.
model() )
232 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
233 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
237 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
238 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
240 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
245 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
246 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
248 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
254 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
257 mParentLayerComboBox->addItem( initialParent, initialParent );
258 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
261 vlayout->addWidget( mParentLayerComboBox );
262 setLayout( vlayout );
267 auto param = std::make_unique<QgsProcessingParameterFieldMapping>( name, description, mParentLayerComboBox->currentData().toString() );
268 param->setFlags( flags );
269 return param.release();
281QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
288 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
291QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
293 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
294 mPanel->setToolTip( parameterDefinition()->toolTip() );
295 mPanel->registerExpressionContextGenerator(
this );
297 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [
this] {
298 emit widgetValueHasChanged(
this );
306 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
309void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
321 setParentLayerWrapperValue( wrapper );
323 setParentLayerWrapperValue( wrapper );
336int 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 );
380void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
383 mPanel->setValue( value );
386QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
388 return mPanel ? mPanel->value() : QVariant();
391QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
393 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
396const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
398 if ( mPanel && mPanel->layer() )
399 return mPanel->layer();
ProcessingMode
Types of modes which Processing widgets can be created for.
@ Batch
Batch processing mode.
@ Standard
Standard (single-run) algorithm mode.
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...
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 dataset.
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.