20 #include <QMessageBox>
21 #include <QPushButton>
22 #include <QStandardItemModel>
23 #include <QToolButton>
24 #include <QItemSelectionModel>
29 #include "qgsprocessingmodelalgorithm.h"
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(
"length" ),
field.field.
length() );
109 def.insert( QStringLiteral(
"precision" ),
field.field.
precision() );
110 def.insert( QStringLiteral(
"expression" ),
field.expression );
111 results.append( def );
116 void QgsProcessingFieldMapPanelWidget::setValue(
const QVariant &value )
118 if ( value.type() != QVariant::List )
122 QMap<QString, QString> expressions;
125 const QVariantList fields = value.toList();
126 for (
const QVariant &
field : fields )
128 const QVariantMap map =
field.toMap();
129 QgsField f( map.value( QStringLiteral(
"name" ) ).toString(),
130 static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ),
131 QVariant::typeToName(
static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ) ),
132 map.value( QStringLiteral(
"length" ), 0 ).toInt(),
133 map.value( QStringLiteral(
"precision" ), 0 ).toInt() );
135 if ( map.contains( QStringLiteral(
"constraints" ) ) )
137 const QgsFieldConstraints::Constraints constraints =
static_cast<QgsFieldConstraints::Constraints
>( map.value( QStringLiteral(
"constraints" ), 0 ).toInt() );
147 f.setConstraints( fieldConstraints );
150 if ( !map.value( QStringLiteral(
"expression" ) ).toString().isEmpty() )
152 expressions.insert( f.name(), map.value( QStringLiteral(
"expression" ) ).toString() );
155 destinationFields.
append( f );
158 mBlockChangedSignal =
true;
159 if ( destinationFields.
size() > 0 )
160 mFieldsView->setDestinationFields( destinationFields, expressions );
161 mBlockChangedSignal =
false;
168 mFieldsView->registerExpressionContextGenerator( generator );
171 void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
175 mFieldsView->setSourceFields( mLayer->fields() );
176 mFieldsView->setDestinationFields( mLayer->fields() );
180 void QgsProcessingFieldMapPanelWidget::addField()
182 const int rowCount = mModel->rowCount();
183 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
184 QModelIndex index = mModel->index( rowCount, 0 );
185 mFieldsView->selectionModel()->select(
187 QItemSelectionModel::SelectionFlags(
188 QItemSelectionModel::Clear |
189 QItemSelectionModel::Select |
190 QItemSelectionModel::Current |
191 QItemSelectionModel::Rows ) );
192 mFieldsView->scrollTo( index );
195 void QgsProcessingFieldMapPanelWidget::loadLayerFields()
197 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
199 mFieldsView->setSourceFields( vl->fields() );
200 mFieldsView->setDestinationFields( vl->fields() );
211 QVBoxLayout *vlayout =
new QVBoxLayout();
212 vlayout->setContentsMargins( 0, 0, 0, 0 );
214 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
216 mParentLayerComboBox =
new QComboBox();
217 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
219 QString initialParent;
221 initialParent = mapParam->parentLayerParameterName();
223 if (
auto *lModel = widgetContext.
model() )
226 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
227 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
231 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
232 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
234 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
239 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
240 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
242 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
248 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
251 mParentLayerComboBox->addItem( initialParent, initialParent );
252 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
255 vlayout->addWidget( mParentLayerComboBox );
256 setLayout( vlayout );
259 QgsProcessingParameterDefinition *QgsProcessingFieldMapParameterDefinitionWidget::createParameter(
const QString &name,
const QString &description, QgsProcessingParameterDefinition::Flags flags )
const
261 auto param = std::make_unique< QgsProcessingParameterFieldMapping >( name, description, mParentLayerComboBox->currentData().toString() );
262 param->setFlags( flags );
263 return param.release();
275 QString QgsProcessingFieldMapWidgetWrapper::parameterType()
const
282 return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
285 QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
287 mPanel =
new QgsProcessingFieldMapPanelWidget(
nullptr );
288 mPanel->setToolTip( parameterDefinition()->toolTip() );
289 mPanel->registerExpressionContextGenerator(
this );
291 connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed,
this, [ = ]
293 emit widgetValueHasChanged(
this );
301 return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
304 void QgsProcessingFieldMapWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
316 setParentLayerWrapperValue( wrapper );
319 setParentLayerWrapperValue( wrapper );
332 int QgsProcessingFieldMapWidgetWrapper::stretch()
const
341 std::unique_ptr< QgsProcessingContext > tmpContext;
342 if ( mProcessingContextGenerator )
343 context = mProcessingContextGenerator->processingContext();
347 tmpContext = std::make_unique< QgsProcessingContext >();
348 context = tmpContext.get();
355 mPanel->setLayer(
nullptr );
361 std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
364 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
365 layer = mParentLayer.get();
373 mPanel->setLayer( layer );
376 void QgsProcessingFieldMapWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
379 mPanel->setValue( value );
382 QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
const
384 return mPanel ? mPanel->value() : QVariant();
387 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
const
393 QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
const
395 return QStringList();
398 QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
const
400 return tr(
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
403 const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
const
405 if ( mPanel && mPanel->layer() )
406 return mPanel->layer();
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.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
int size() const
Returns number of items.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
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.
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.