17#include "moc_qgsprocessingaggregatewidgetwrapper.cpp" 
   23#include <QStandardItemModel> 
   25#include <QItemSelectionModel> 
   42QgsProcessingAggregatePanelWidget::QgsProcessingAggregatePanelWidget( QWidget *parent )
 
   47  mModel = mFieldsView->model();
 
   49  mLayerCombo->setAllowEmptyLayer( 
true );
 
   52  connect( mResetButton, &QPushButton::clicked, 
this, &QgsProcessingAggregatePanelWidget::loadFieldsFromLayer );
 
   53  connect( mAddButton, &QPushButton::clicked, 
this, &QgsProcessingAggregatePanelWidget::addField );
 
   57  connect( mLoadLayerFieldsButton, &QPushButton::clicked, 
this, &QgsProcessingAggregatePanelWidget::loadLayerFields );
 
   60    if ( !mBlockChangedSignal )
 
   67void QgsProcessingAggregatePanelWidget::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 | QMessageBox::No )
 
   85  dlg.setDefaultButton( QMessageBox::No );
 
   86  if ( dlg.exec() == QMessageBox::Yes )
 
   88    loadFieldsFromLayer();
 
   97QVariant QgsProcessingAggregatePanelWidget::value()
 const 
   99  const QList<QgsAggregateMappingModel::Aggregate> mapping = mFieldsView->mapping();
 
  101  QVariantList results;
 
  102  results.reserve( mapping.size() );
 
  106    def.insert( QStringLiteral( 
"name" ), aggregate.field.name() );
 
  107    def.insert( QStringLiteral( 
"type" ), 
static_cast<int>( aggregate.field.type() ) );
 
  108    def.insert( QStringLiteral( 
"type_name" ), aggregate.field.typeName() );
 
  109    def.insert( QStringLiteral( 
"length" ), aggregate.field.length() );
 
  110    def.insert( QStringLiteral( 
"precision" ), aggregate.field.precision() );
 
  111    def.insert( QStringLiteral( 
"sub_type" ), 
static_cast<int>( aggregate.field.subType() ) );
 
  112    def.insert( QStringLiteral( 
"input" ), aggregate.source );
 
  113    def.insert( QStringLiteral( 
"aggregate" ), aggregate.aggregate );
 
  114    def.insert( QStringLiteral( 
"delimiter" ), aggregate.delimiter );
 
  115    results.append( def );
 
  120void QgsProcessingAggregatePanelWidget::setValue( 
const QVariant &value )
 
  122  if ( value.userType() != QMetaType::Type::QVariantList )
 
  125  QList<QgsAggregateMappingModel::Aggregate> aggregates;
 
  127  const QVariantList fields = value.toList();
 
  128  aggregates.reserve( fields.size() );
 
  129  for ( 
const QVariant &field : fields )
 
  131    const QVariantMap map = field.toMap();
 
  132    const 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() ) );
 
  137    aggregate.
source = map.value( QStringLiteral( 
"input" ) ).toString();
 
  138    aggregate.
aggregate = map.value( QStringLiteral( 
"aggregate" ) ).toString();
 
  139    aggregate.
delimiter = map.value( QStringLiteral( 
"delimiter" ) ).toString();
 
  141    aggregates.append( aggregate );
 
  144  mBlockChangedSignal = 
true;
 
  146  if ( aggregates.size() > 0 )
 
  147    mFieldsView->setMapping( aggregates );
 
  149  mBlockChangedSignal = 
false;
 
  156  mFieldsView->registerExpressionContextGenerator( generator );
 
  159void QgsProcessingAggregatePanelWidget::loadFieldsFromLayer()
 
  163    mFieldsView->setSourceFields( mLayer->fields() );
 
  167void QgsProcessingAggregatePanelWidget::addField()
 
  169  const int rowCount = mModel->rowCount();
 
  170  mModel->appendField( 
QgsField( QStringLiteral( 
"new_field" ) ) );
 
  171  const QModelIndex index = mModel->index( rowCount, 0 );
 
  172  mFieldsView->selectionModel()->select(
 
  174    QItemSelectionModel::SelectionFlags(
 
  175      QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows
 
  178  mFieldsView->scrollTo( index );
 
  181void QgsProcessingAggregatePanelWidget::loadLayerFields()
 
  183  if ( 
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerCombo->currentLayer() ) )
 
  185    mFieldsView->setSourceFields( vl->fields() );
 
  196  QVBoxLayout *vlayout = 
new QVBoxLayout();
 
  197  vlayout->setContentsMargins( 0, 0, 0, 0 );
 
  199  vlayout->addWidget( 
new QLabel( tr( 
"Parent layer" ) ) );
 
  201  mParentLayerComboBox = 
new QComboBox();
 
  202  mParentLayerComboBox->addItem( tr( 
"None" ), QVariant() );
 
  204  QString initialParent;
 
  206    initialParent = aggregateParam->parentLayerParameterName();
 
  208  if ( 
auto *lModel = widgetContext.
model() )
 
  211    const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
 
  212    for ( 
auto it = components.constBegin(); it != components.constEnd(); ++it )
 
  216        mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
 
  217        if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  219          mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  224        mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
 
  225        if ( !initialParent.isEmpty() && initialParent == definition->
name() )
 
  227          mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  233  if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
 
  236    mParentLayerComboBox->addItem( initialParent, initialParent );
 
  237    mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
 
  240  vlayout->addWidget( mParentLayerComboBox );
 
  241  setLayout( vlayout );
 
  246  auto param = std::make_unique<QgsProcessingParameterAggregate>( name, description, mParentLayerComboBox->currentData().toString() );
 
  247  param->setFlags( flags );
 
  248  return param.release();
 
  260QString QgsProcessingAggregateWidgetWrapper::parameterType()
 const 
  267  return new QgsProcessingAggregateWidgetWrapper( parameter, type );
 
  270QWidget *QgsProcessingAggregateWidgetWrapper::createWidget()
 
  272  mPanel = 
new QgsProcessingAggregatePanelWidget( 
nullptr );
 
  273  mPanel->setToolTip( parameterDefinition()->toolTip() );
 
  274  mPanel->registerExpressionContextGenerator( 
this );
 
  276  connect( mPanel, &QgsProcessingAggregatePanelWidget::changed, 
this, [
this] {
 
  277    emit widgetValueHasChanged( 
this );
 
  285  return new QgsProcessingAggregateParameterDefinitionWidget( context, widgetContext, definition, 
algorithm );
 
  288void QgsProcessingAggregateWidgetWrapper::postInitialize( 
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
 
  298        if ( wrapper->parameterDefinition()->name() == 
static_cast<const QgsProcessingParameterAggregate *
>( parameterDefinition() )->parentLayerParameterName() )
 
  300          setParentLayerWrapperValue( wrapper );
 
  302            setParentLayerWrapperValue( wrapper );
 
  315int QgsProcessingAggregateWidgetWrapper::stretch()
 const 
  324  std::unique_ptr<QgsProcessingContext> tmpContext;
 
  325  if ( mProcessingContextGenerator )
 
  326    context = mProcessingContextGenerator->processingContext();
 
  330    tmpContext = std::make_unique<QgsProcessingContext>();
 
  331    context = tmpContext.get();
 
  338      mPanel->setLayer( 
nullptr );
 
  344  std::unique_ptr<QgsMapLayer> ownedLayer( context->
takeResultLayer( layer->
id() ) );
 
  347    mParentLayer.reset( qobject_cast<QgsVectorLayer *>( ownedLayer.release() ) );
 
  348    layer = mParentLayer.get();
 
  356    mPanel->setLayer( layer );
 
  359void QgsProcessingAggregateWidgetWrapper::setWidgetValue( 
const QVariant &value, 
QgsProcessingContext & )
 
  362    mPanel->setValue( value );
 
  365QVariant QgsProcessingAggregateWidgetWrapper::widgetValue()
 const 
  367  return mPanel ? mPanel->value() : QVariant();
 
  370QString QgsProcessingAggregateWidgetWrapper::modelerExpressionFormatString()
 const 
  372  return tr( 
"an array of map items, each containing a 'name', 'type', 'aggregate' and 'input' value (and optional 'length' and 'precision' values)." );
 
  375const QgsVectorLayer *QgsProcessingAggregateWidgetWrapper::linkedVectorLayer()
 const 
  377  if ( mPanel && mPanel->layer() )
 
  378    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.
 
Encapsulate a field in an attribute table or data source.
 
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...
 
A parameter for "aggregate" configurations, which consist of a definition of desired output fields,...
 
static QString typeName()
Returns the type name for the parameter class.
 
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 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 Aggregate struct holds information about an aggregate column.
 
QString source
The source expression used as the input for the aggregate calculation.
 
QString delimiter
Delimiter string.
 
QString aggregate
Aggregate name.
 
QgsField field
The field in its current status (it might have been renamed)