20 #include <QMessageBox>
21 #include <QPushButton>
22 #include <QStandardItemModel>
23 #include <QToolButton>
24 #include <QItemSelectionModel>
43 QgsProcessingAggregatePanelWidget::QgsProcessingAggregatePanelWidget( QWidget *parent )
48 mModel = mFieldsView->model();
50 mLayerCombo->setAllowEmptyLayer(
true );
53 connect( mResetButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::loadFieldsFromLayer );
54 connect( mAddButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::addField );
58 connect( mLoadLayerFieldsButton, &QPushButton::clicked,
this, &QgsProcessingAggregatePanelWidget::loadLayerFields );
62 if ( !mBlockChangedSignal )
69 void QgsProcessingAggregatePanelWidget::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();
99 QVariant QgsProcessingAggregatePanelWidget::value()
const
101 const QList<QgsAggregateMappingModel::Aggregate> mapping = mFieldsView->mapping();
103 QVariantList results;
104 results.reserve( mapping.size() );
108 def.insert( QStringLiteral(
"name" ), aggregate.field.name() );
109 def.insert( QStringLiteral(
"type" ),
static_cast< int >( aggregate.field.type() ) );
110 def.insert( QStringLiteral(
"type_name" ), aggregate.field.typeName() );
111 def.insert( QStringLiteral(
"length" ), aggregate.field.length() );
112 def.insert( QStringLiteral(
"precision" ), aggregate.field.precision() );
113 def.insert( QStringLiteral(
"sub_type" ),
static_cast< int >( aggregate.field.subType() ) );
114 def.insert( QStringLiteral(
"input" ), aggregate.source );
115 def.insert( QStringLiteral(
"aggregate" ), aggregate.aggregate );
116 def.insert( QStringLiteral(
"delimiter" ), aggregate.delimiter );
117 results.append( def );
122 void QgsProcessingAggregatePanelWidget::setValue(
const QVariant &value )
124 if ( value.type() != QVariant::List )
127 QList< QgsAggregateMappingModel::Aggregate > aggregates;
129 const QVariantList fields = value.toList();
130 aggregates.reserve( fields.size() );
131 for (
const QVariant &
field : fields )
133 const QVariantMap map =
field.toMap();
134 const QgsField f( map.value( QStringLiteral(
"name" ) ).toString(),
135 static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ),
136 map.value( QStringLiteral(
"type_name" ), QVariant::typeToName(
static_cast< QVariant::Type
>( map.value( QStringLiteral(
"type" ), QVariant::Invalid ).toInt() ) ) ).toString(),
137 map.value( QStringLiteral(
"length" ), 0 ).toInt(),
138 map.value( QStringLiteral(
"precision" ), 0 ).toInt(),
140 static_cast< QVariant::Type
>( map.value( QStringLiteral(
"sub_type" ), QVariant::Invalid ).toInt() ) );
145 aggregate.
source = map.value( QStringLiteral(
"input" ) ).toString();
146 aggregate.
aggregate = map.value( QStringLiteral(
"aggregate" ) ).toString();
147 aggregate.
delimiter = map.value( QStringLiteral(
"delimiter" ) ).toString();
149 aggregates.append( aggregate );
152 mBlockChangedSignal =
true;
154 if ( aggregates.size() > 0 )
155 mFieldsView->setMapping( aggregates );
157 mBlockChangedSignal =
false;
164 mFieldsView->registerExpressionContextGenerator( generator );
167 void QgsProcessingAggregatePanelWidget::loadFieldsFromLayer()
171 mFieldsView->setSourceFields( mLayer->fields() );
175 void QgsProcessingAggregatePanelWidget::addField()
177 const int rowCount = mModel->rowCount();
178 mModel->appendField(
QgsField( QStringLiteral(
"new_field" ) ) );
179 const QModelIndex index = mModel->index( rowCount, 0 );
180 mFieldsView->selectionModel()->select(
182 QItemSelectionModel::SelectionFlags(
183 QItemSelectionModel::Clear |
184 QItemSelectionModel::Select |
185 QItemSelectionModel::Current |
186 QItemSelectionModel::Rows ) );
187 mFieldsView->scrollTo( index );
190 void QgsProcessingAggregatePanelWidget::loadLayerFields()
192 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
194 mFieldsView->setSourceFields( vl->fields() );
205 QVBoxLayout *vlayout =
new QVBoxLayout();
206 vlayout->setContentsMargins( 0, 0, 0, 0 );
208 vlayout->addWidget(
new QLabel( tr(
"Parent layer" ) ) );
210 mParentLayerComboBox =
new QComboBox();
211 mParentLayerComboBox->addItem( tr(
"None" ), QVariant() );
213 QString initialParent;
215 initialParent = aggregateParam->parentLayerParameterName();
217 if (
auto *lModel = widgetContext.
model() )
220 const QMap<QString, QgsProcessingModelParameter> components = lModel->parameterComponents();
221 for (
auto it = components.constBegin(); it != components.constEnd(); ++it )
225 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
226 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
228 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
233 mParentLayerComboBox-> addItem( definition->
description(), definition->
name() );
234 if ( !initialParent.isEmpty() && initialParent == definition->
name() )
236 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
242 if ( mParentLayerComboBox->count() == 1 && !initialParent.isEmpty() )
245 mParentLayerComboBox->addItem( initialParent, initialParent );
246 mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
249 vlayout->addWidget( mParentLayerComboBox );
250 setLayout( vlayout );
253 QgsProcessingParameterDefinition *QgsProcessingAggregateParameterDefinitionWidget::createParameter(
const QString &name,
const QString &description, QgsProcessingParameterDefinition::Flags flags )
const
255 auto param = std::make_unique< QgsProcessingParameterAggregate >( name, description, mParentLayerComboBox->currentData().toString() );
256 param->setFlags( flags );
257 return param.release();
269 QString QgsProcessingAggregateWidgetWrapper::parameterType()
const
276 return new QgsProcessingAggregateWidgetWrapper( parameter, type );
279 QWidget *QgsProcessingAggregateWidgetWrapper::createWidget()
281 mPanel =
new QgsProcessingAggregatePanelWidget(
nullptr );
282 mPanel->setToolTip( parameterDefinition()->toolTip() );
283 mPanel->registerExpressionContextGenerator(
this );
285 connect( mPanel, &QgsProcessingAggregatePanelWidget::changed,
this, [ = ]
287 emit widgetValueHasChanged(
this );
295 return new QgsProcessingAggregateParameterDefinitionWidget( context, widgetContext, definition,
algorithm );
298 void QgsProcessingAggregateWidgetWrapper::postInitialize(
const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
308 if ( wrapper->parameterDefinition()->name() ==
static_cast< const QgsProcessingParameterAggregate *
>( parameterDefinition() )->parentLayerParameterName() )
310 setParentLayerWrapperValue( wrapper );
313 setParentLayerWrapperValue( wrapper );
326 int QgsProcessingAggregateWidgetWrapper::stretch()
const
335 std::unique_ptr< QgsProcessingContext > tmpContext;
336 if ( mProcessingContextGenerator )
337 context = mProcessingContextGenerator->processingContext();
341 tmpContext = std::make_unique< QgsProcessingContext >();
342 context = tmpContext.get();
349 mPanel->setLayer(
nullptr );
355 std::unique_ptr< QgsMapLayer > ownedLayer( context->
takeResultLayer( layer->
id() ) );
358 mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
359 layer = mParentLayer.get();
367 mPanel->setLayer( layer );
370 void QgsProcessingAggregateWidgetWrapper::setWidgetValue(
const QVariant &value,
QgsProcessingContext & )
373 mPanel->setValue( value );
376 QVariant QgsProcessingAggregateWidgetWrapper::widgetValue()
const
378 return mPanel ? mPanel->value() : QVariant();
381 QStringList QgsProcessingAggregateWidgetWrapper::compatibleParameterTypes()
const
387 QStringList QgsProcessingAggregateWidgetWrapper::compatibleOutputTypes()
const
389 return QStringList();
392 QString QgsProcessingAggregateWidgetWrapper::modelerExpressionFormatString()
const
394 return tr(
"an array of map items, each containing a 'name', 'type', 'aggregate' and 'input' value (and optional 'length' and 'precision' values)." );
397 const QgsVectorLayer *QgsProcessingAggregateWidgetWrapper::linkedVectorLayer()
const
399 if ( mPanel && mPanel->layer() )
400 return mPanel->layer();