24#include <QItemSelectionModel>
28#include <QStandardItemModel>
31#include "moc_qgsprocessingaggregatewidgetwrapper.cpp"
41QgsProcessingAggregatePanelWidget::QgsProcessingAggregatePanelWidget( QWidget *parent )
46 mModel = mFieldsView->model();
48 mLayerCombo->setAllowEmptyLayer(
true );
51 connect( mResetButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::loadFieldsFromLayer );
52 connect( mAddButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::addField );
56 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::loadLayerFields );
59 if ( !mBlockChangedSignal )
66void QgsProcessingAggregatePanelWidget::setLayer(
QgsVectorLayer *layer )
68 if ( layer == mLayer )
72 mFieldsView->setSourceLayer( mLayer );
73 if ( mModel->rowCount() == 0 )
75 loadFieldsFromLayer();
79 if ( mSkipConfirmDialog )
84 QMessageBox dlg(
this );
85 dlg.setText( tr(
"Do you want to reset the field mapping?" ) );
86 dlg.setStandardButtons(
87 QMessageBox::StandardButtons( QMessageBox::Yes | QMessageBox::No )
89 dlg.setDefaultButton( QMessageBox::No );
90 if ( dlg.exec() == QMessageBox::Yes )
92 loadFieldsFromLayer();
101QVariant QgsProcessingAggregatePanelWidget::value()
const
103 const QList<QgsAggregateMappingModel::Aggregate> mapping = mFieldsView->mapping();
105 QVariantList results;
106 results.reserve( mapping.size() );
110 def.insert( QStringLiteral(
"name" ), aggregate.field.name() );
111 def.insert( QStringLiteral(
"type" ),
static_cast<int>( aggregate.field.type() ) );
112 def.insert( QStringLiteral(
"type_name" ), aggregate.field.typeName() );
113 def.insert( QStringLiteral(
"length" ), aggregate.field.length() );
114 def.insert( QStringLiteral(
"precision" ), aggregate.field.precision() );
115 def.insert( QStringLiteral(
"sub_type" ),
static_cast<int>( aggregate.field.subType() ) );
116 def.insert( QStringLiteral(
"input" ), aggregate.source );
117 def.insert( QStringLiteral(
"aggregate" ), aggregate.aggregate );
118 def.insert( QStringLiteral(
"delimiter" ), aggregate.delimiter );
119 results.append( def );
124void QgsProcessingAggregatePanelWidget::setValue(
const QVariant &value )
126 if ( value.userType() != QMetaType::Type::QVariantList )
129 QList<QgsAggregateMappingModel::Aggregate> aggregates;
131 const QVariantList fields = value.toList();
132 aggregates.reserve( fields.size() );
133 for (
const QVariant &field : fields )
135 const QVariantMap map = field.toMap();
136 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() ) );
141 aggregate.
source = map.value( QStringLiteral(
"input" ) ).toString();
142 aggregate.
aggregate = map.value( QStringLiteral(
"aggregate" ) ).toString();
143 aggregate.
delimiter = map.value( QStringLiteral(
"delimiter" ) ).toString();
145 aggregates.append( aggregate );
148 mBlockChangedSignal =
true;
150 if ( aggregates.size() > 0 )
151 mFieldsView->setMapping( aggregates );
153 mBlockChangedSignal =
false;
160 mFieldsView->registerExpressionContextGenerator( generator );
163void QgsProcessingAggregatePanelWidget::loadFieldsFromLayer()
167 mFieldsView->setSourceFields( mLayer->fields() );
171void QgsProcessingAggregatePanelWidget::addField()
173 const int rowCount = mModel->rowCount();
174 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
175 const QModelIndex index = mModel->index( rowCount, 0 );
176 mFieldsView->selectionModel()->select(
178 QItemSelectionModel::SelectionFlags(
179 QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows
182 mFieldsView->scrollTo( index );
185void QgsProcessingAggregatePanelWidget::loadLayerFields()
187 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerCombo->currentLayer() ) )
189 mFieldsView->setSourceFields( vl->fields() );
200 QVBoxLayout *vlayout =
new QVBoxLayout();
201 vlayout->setContentsMargins( 0, 0, 0, 0 );
203 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
205 mParentLayerComboBox =
new QComboBox();
206 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
208 QString initialParent;
210 initialParent = aggregateParam->parentLayerParameterName();
212 if (
auto *lModel = widgetContext.
model() )
215 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
216 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
220 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
221 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
223 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
228 mParentLayerComboBox->addItem( definition->
description(), definition->
name() );
229 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
231 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
237 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
240 mParentLayerComboBox->addItem( initialParent, initialParent );
241 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
244 vlayout->addWidget( mParentLayerComboBox );
245 setLayout( vlayout );
250 auto param = std::make_unique<QgsProcessingParameterAggregate>( name, description, mParentLayerComboBox->currentData().toString() );
251 param->setFlags( flags );
252 return param.release();
264QString QgsProcessingAggregateWidgetWrapper::parameterType()
const
271 return new QgsProcessingAggregateWidgetWrapper( parameter, type );
274QWidget *QgsProcessingAggregateWidgetWrapper::createWidget()
276 mPanel =
new QgsProcessingAggregatePanelWidget(
nullptr );
277 mPanel->setToolTip( parameterDefinition()->toolTip() );
278 mPanel->registerExpressionContextGenerator(
this );
280 connect( mPanel, &QgsProcessingAggregatePanelWidget::changed,
this, [
this] {
281 emit widgetValueHasChanged(
this );
289 return new QgsProcessingAggregateParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
292void QgsProcessingAggregateWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
302 if ( wrapper->parameterDefinition()->name() ==
static_cast<const QgsProcessingParameterAggregate *
>( parameterDefinition() )->parentLayerParameterName() )
304 setParentLayerWrapperValue( wrapper );
306 setParentLayerWrapperValue( wrapper );
319int QgsProcessingAggregateWidgetWrapper::stretch()
const
328 std::unique_ptr<QgsProcessingContext> tmpContext;
329 if ( mProcessingContextGenerator )
330 context = mProcessingContextGenerator->processingContext();
334 tmpContext = std::make_unique<QgsProcessingContext>();
335 context = tmpContext.get();
342 mPanel->setLayer(
nullptr );
348 std::unique_ptr<QgsMapLayer> ownedLayer( context->
takeResultLayer( layer->
id() ) );
351 mParentLayer.reset( qobject_cast<QgsVectorLayer *>( ownedLayer.release() ) );
352 layer = mParentLayer.get();
360 mPanel->setLayer( layer );
363void QgsProcessingAggregateWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
366 mPanel->setValue( value );
369QVariant QgsProcessingAggregateWidgetWrapper::widgetValue()
const
371 return mPanel ? mPanel->value() : QVariant();
374QString QgsProcessingAggregateWidgetWrapper::modelerExpressionFormatString()
const
376 return tr(
"an array of map items, each containing a 'name', 'type', 'aggregate' and 'input' value (and optional 'length' and 'precision' values)." );
379const QgsVectorLayer *QgsProcessingAggregateWidgetWrapper::linkedVectorLayer()
const
381 if ( mPanel && mPanel->layer() )
382 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).