22#include <QStandardItemModel> 
   24#include <QItemSelectionModel> 
   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 );
 
   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 |
 
   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.type() != QVariant::List )
 
  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(),
 
  136                static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"type" ), QVariant::Invalid ).toInt() ),
 
  137                map.value( QStringLiteral( 
"type_name" ), QVariant::typeToName( 
static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"type" ), QVariant::Invalid ).toInt() ) ) ).toString(),
 
  138                map.value( QStringLiteral( 
"length" ), 0 ).toInt(),
 
  139                map.value( QStringLiteral( 
"precision" ), 0 ).toInt(),
 
  141                static_cast< QVariant::Type 
>( map.value( QStringLiteral( 
"sub_type" ), QVariant::Invalid ).toInt() ) );
 
  142    f.setAlias( map.value( QStringLiteral( 
"alias" ) ).toString() );
 
  143    f.setComment( map.value( QStringLiteral( 
"comment" ) ).toString() );
 
  145    if ( map.contains( QStringLiteral( 
"constraints" ) ) )
 
  147      const QgsFieldConstraints::Constraints constraints = 
static_cast<QgsFieldConstraints::Constraints
>( map.value( QStringLiteral( 
"constraints" ), 0 ).toInt() );
 
  157      f.setConstraints( fieldConstraints );
 
  160    if ( !map.value( QStringLiteral( 
"expression" ) ).toString().isEmpty() )
 
  162      expressions.insert( f.name(), map.value( QStringLiteral( 
"expression" ) ).toString() );
 
  165    destinationFields.
append( f );
 
  168  mBlockChangedSignal = 
true;
 
  169  if ( destinationFields.
size() > 0 )
 
  170    mFieldsView->setDestinationFields( destinationFields, expressions );
 
  171  mBlockChangedSignal = 
false;
 
  178  mFieldsView->registerExpressionContextGenerator( generator );
 
  181void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
 
  185    mFieldsView->setSourceFields( mLayer->fields() );
 
  186    mFieldsView->setDestinationFields( mLayer->fields() );
 
  190void QgsProcessingFieldMapPanelWidget::addField()
 
  192  const int rowCount = mModel->rowCount();
 
  193  mModel->appendField( 
QgsField( QStringLiteral( 
"new_field" ) ) );
 
  194  const QModelIndex index = mModel->index( rowCount, 0 );
 
  195  mFieldsView->selectionModel()->select(
 
  197    QItemSelectionModel::SelectionFlags(
 
  198      QItemSelectionModel::Clear |
 
  199      QItemSelectionModel::Select |
 
  200      QItemSelectionModel::Current |
 
  201      QItemSelectionModel::Rows ) );
 
  202  mFieldsView->scrollTo( index );
 
  205void QgsProcessingFieldMapPanelWidget::loadLayerFields()
 
  207  if ( 
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
 
  209    mFieldsView->setSourceFields( vl->fields() );
 
  210    mFieldsView->setDestinationFields( vl->fields() );
 
  221  QVBoxLayout *vlayout = 
new QVBoxLayout();
 
  222  vlayout->setContentsMargins( 0, 0, 0, 0 );
 
  224  vlayout->addWidget( 
new QLabel( tr( 
"Parent layer" ) ) );
 
  226  mParentLayerComboBox = 
new QComboBox();
 
  227  mParentLayerComboBox->addItem( tr( 
"None" ), QVariant() );
 
  229  QString initialParent;
 
  231    initialParent = mapParam->parentLayerParameterName();
 
  233  if ( 
auto *lModel = widgetContext.
model() )
 
  236    const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
 
  237    for ( 
auto it = components.constBegin(); it != components.constEnd(); ++it )
 
  241        mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
 
  242        if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  244          mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  249        mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
 
  250        if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  252          mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  258  if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
 
  261    mParentLayerComboBox->addItem( initialParent, initialParent );
 
  262    mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  265  vlayout->addWidget( mParentLayerComboBox );
 
  266  setLayout( vlayout );
 
  269QgsProcessingParameterDefinition *QgsProcessingFieldMapParameterDefinitionWidget::createParameter( 
const QString &name, 
const QString &description, QgsProcessingParameterDefinition::Flags flags )
 const 
  271  auto param = std::make_unique< QgsProcessingParameterFieldMapping >( name, description, mParentLayerComboBox->currentData().toString() );
 
  272  param->setFlags( flags );
 
  273  return param.release();
 
  285QString QgsProcessingFieldMapWidgetWrapper::parameterType()
 const 
  292  return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
 
  295QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
 
  297  mPanel = 
new QgsProcessingFieldMapPanelWidget( 
nullptr );
 
  298  mPanel->setToolTip( parameterDefinition()->toolTip() );
 
  299  mPanel->registerExpressionContextGenerator( 
this );
 
  301  connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed, 
this, [ = ]
 
  303    emit widgetValueHasChanged( 
this );
 
  311  return new QgsProcessingFieldMapParameterDefinitionWidget( context, widgetContext, definition, 
algorithm );
 
  314void QgsProcessingFieldMapWidgetWrapper::postInitialize( 
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
 
  326          setParentLayerWrapperValue( wrapper );
 
  329            setParentLayerWrapperValue( wrapper );
 
  342int QgsProcessingFieldMapWidgetWrapper::stretch()
 const 
  351  std::unique_ptr< QgsProcessingContext > tmpContext;
 
  352  if ( mProcessingContextGenerator )
 
  353    context = mProcessingContextGenerator->processingContext();
 
  357    tmpContext = std::make_unique< QgsProcessingContext >();
 
  358    context = tmpContext.get();
 
  365      mPanel->setLayer( 
nullptr );
 
  371  std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
 
  372  if ( ownedLayer && ownedLayer->type() == Qgis::LayerType::Vector )
 
  374    mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
 
  375    layer = mParentLayer.get();
 
  383    mPanel->setLayer( layer );
 
  386void QgsProcessingFieldMapWidgetWrapper::setWidgetValue( 
const QVariant &value, 
QgsProcessingContext & )
 
  389    mPanel->setValue( value );
 
  392QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue()
 const 
  394  return mPanel ? mPanel->value() : QVariant();
 
  397QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes()
 const 
  403QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes()
 const 
  405  return QStringList();
 
  408QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString()
 const 
  410  return tr( 
"an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
 
  413const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer()
 const 
  415  if ( mPanel && mPanel->layer() )
 
  416    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.
 
QString typeName() const
Gets the field type.
 
QVariant::Type subType() const
If the field is a collection, gets its element's type.
 
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.