24#include <QItemSelectionModel>
28#include <QStandardItemModel>
32#include "moc_qgsprocessingfieldmapwidgetwrapper.cpp"
34using namespace Qt::StringLiterals;
43QgsProcessingFieldMapPanelWidget::QgsProcessingFieldMapPanelWidget( QWidget *parent )
48 mModel = mFieldsView->model();
49 mFieldsView->setDestinationEditable(
true );
51 mLayerCombo->setAllowEmptyLayer(
true );
54 connect( mResetButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer );
55 connect( mAddButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::addField );
60 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
64 if ( !mBlockChangedSignal )
71void QgsProcessingFieldMapPanelWidget::setLayer(
QgsVectorLayer *layer )
73 if ( layer == mLayer )
77 mFieldsView->setSourceLayer( mLayer );
78 if ( mModel->rowCount() == 0 )
80 loadFieldsFromLayer();
84 if ( mSkipConfirmDialog )
89 QMessageBox dlg(
this );
90 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
91 dlg.setStandardButtons( QMessageBox::StandardButtons( QMessageBox::Yes | QMessageBox::No ) );
92 dlg.setDefaultButton( QMessageBox::No );
93 if ( dlg.exec() == QMessageBox::Yes )
95 loadFieldsFromLayer();
104QVariant QgsProcessingFieldMapPanelWidget::value()
const
106 const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
108 QVariantList results;
109 results.reserve( mapping.size() );
113 def.insert( u
"name"_s, field.field.name() );
114 def.insert( u
"type"_s,
static_cast<int>( field.field.type() ) );
115 def.insert( u
"type_name"_s, field.field.typeName() );
116 def.insert( u
"length"_s, field.field.length() );
117 def.insert( u
"precision"_s, field.field.precision() );
118 def.insert( u
"sub_type"_s,
static_cast<int>( field.field.subType() ) );
119 def.insert( u
"expression"_s, field.expression );
120 def.insert( u
"alias"_s, field.field.alias() );
121 def.insert( u
"comment"_s, field.field.comment() );
122 results.append( def );
127void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
129 if ( value.userType() != QMetaType::Type::QVariantList )
133 QMap<QString, QString> expressions;
136 const QVariantList fields = value.toList();
137 for (
const QVariant &field : fields )
139 const QVariantMap map = field.toMap();
141 f( map.value( u
"name"_s ).toString(),
142 static_cast<QMetaType::Type
>( map.value( u
"type"_s,
static_cast<int>( QMetaType::Type::UnknownType ) ).toInt() ),
143 map.value( u
"type_name"_s, QVariant::typeToName(
static_cast<QMetaType::Type
>( map.value( u
"type"_s,
static_cast<int>( QMetaType::Type::UnknownType ) ).toInt() ) ) ).toString(),
144 map.value( u
"length"_s, 0 ).toInt(),
145 map.value( u
"precision"_s, 0 ).toInt(),
148 f.setAlias( map.value( u
"alias"_s ).toString() );
149 f.setComment( map.value( u
"comment"_s ).toString() );
151 if ( map.contains( u
"constraints"_s ) )
163 f.setConstraints( fieldConstraints );
166 if ( !map.value( u
"expression"_s ).toString().isEmpty() )
168 expressions.insert( f.name(), map.value( u
"expression"_s ).toString() );
171 destinationFields.
append( f );
174 mBlockChangedSignal =
true;
175 if ( destinationFields.
size() > 0 )
176 mFieldsView->setDestinationFields( destinationFields, expressions );
177 mBlockChangedSignal =
false;
184 mFieldsView->registerExpressionContextGenerator( generator );
192void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
196 mFieldsView->setSourceFields( mLayer->fields() );
197 mFieldsView->setDestinationFields( mLayer->fields() );
201void QgsProcessingFieldMapPanelWidget::addField()
203 const int rowCount = mModel->rowCount();
204 mModel->appendField(
QgsField( u
"new_field"_s ) );
205 const QModelIndex index = mModel->index( rowCount, 0 );
206 mFieldsView->selectionModel()->select( index, QItemSelectionModel::SelectionFlags( QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows ) );
207 mFieldsView->scrollTo( index );
210void QgsProcessingFieldMapPanelWidget::loadLayerFields()
212 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerCombo->currentLayer() ) )
217 mFieldsView->setSourceFields( vl->fields() );
219 mFieldsView->setDestinationFields( vl->fields() );
227QgsProcessingFieldMapParameterDefinitionWidget::QgsProcessingFieldMapParameterDefinitionWidget(
232 QVBoxLayout *vlayout =
new QVBoxLayout();
233 vlayout->setContentsMargins( 0, 0, 0, 0 );
235 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
237 mParentLayerComboBox =
new QComboBox();
238 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
240 QString initialParent;
242 initialParent = mapParam->parentLayerParameterName();
244 if (
auto *lModel = widgetContext.
model() )
247 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
248 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
252 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
253 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
255 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
260 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
261 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
263 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
269 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
272 mParentLayerComboBox->addItem( initialParent, initialParent );
273 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
276 vlayout->addWidget( mParentLayerComboBox );
280 setLayout( vlayout );
285 auto param = std::make_unique<QgsProcessingParameterFieldMapping>( name, description, mParentLayerComboBox->currentData().toString() );
286 param->setFlags( flags );
287 return param.release();
298QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
305 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
308QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
310 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
311 mPanel->setToolTip( parameterDefinition()->toolTip() );
312 mPanel->registerExpressionContextGenerator(
this );
313 mPanel->setProcessingModeType( type() );
315 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [
this] { emit widgetValueHasChanged(
this ); } );
324 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
327void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
339 setParentLayerWrapperValue( wrapper );
352int QgsProcessingFieldMapWidgetWrapper::stretch()
const
361 std::unique_ptr<QgsProcessingContext> tmpContext;
362 if ( mProcessingContextGenerator )
363 context = mProcessingContextGenerator->processingContext();
367 tmpContext = std::make_unique<QgsProcessingContext>();
368 context = tmpContext.get();
375 mPanel->setLayer(
nullptr );
381 std::unique_ptr<QgsMapLayer> ownedLayer( context->
takeResultLayer( layer->
id() ) );
384 mParentLayer.reset( qobject_cast<QgsVectorLayer *>( ownedLayer.release() ) );
385 layer = mParentLayer.get();
393 mPanel->setLayer( layer );
396void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
399 mPanel->setValue( value );
402QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
404 return mPanel ? mPanel->value() : QVariant();
407QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
409 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
412const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
414 if ( mPanel && mPanel->layer() )
415 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.