QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
qgsprocessingconfigurationwidgets.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingconfigurationwidgets.cpp
3 ---------------------
4 begin : April 2018
5 copyright : (C) 2018 by Matthias Kuhn
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
20#include "moc_qgsprocessingconfigurationwidgets.cpp"
23#include "qgsapplication.h"
24#include "qgsgui.h"
26
27#include <QTableWidget>
28#include <QGridLayout>
29#include <QToolButton>
30#include <QLabel>
31#include <QCheckBox>
32#include <QHeaderView>
33
35
36QgsFilterAlgorithmConfigurationWidget::QgsFilterAlgorithmConfigurationWidget( QWidget *parent )
38{
39 setContentsMargins( 0, 0, 0, 0 );
40
41 mOutputExpressionWidget = new QTableWidget();
42 mOutputExpressionWidget->setColumnCount( 3 );
43 mOutputExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Output Name" ) ) );
44 mOutputExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Filter Expression" ) ) );
45 mOutputExpressionWidget->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Final Output" ) ) );
46 mOutputExpressionWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
47 QGridLayout *layout = new QGridLayout();
48 setLayout( layout );
49
50 layout->addWidget( new QLabel( tr( "Outputs and filters" ) ), 0, 0, 1, 2 );
51 layout->addWidget( mOutputExpressionWidget, 1, 0, 4, 1 );
52 QToolButton *addOutputButton = new QToolButton();
53 addOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
54 addOutputButton->setText( tr( "Add Output" ) );
55
56 QToolButton *removeOutputButton = new QToolButton();
57 removeOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
58 removeOutputButton->setToolTip( tr( "Remove Selected Outputs" ) );
59
60 layout->addWidget( addOutputButton, 2, 1, 1, 1 );
61 layout->addWidget( removeOutputButton, 3, 1, 1, 1 );
62
63 connect( addOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::addOutput );
64 connect( removeOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs );
65
66 connect( mOutputExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, [removeOutputButton, this] {
67 removeOutputButton->setEnabled( !mOutputExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
68 } );
69}
70
71QVariantMap QgsFilterAlgorithmConfigurationWidget::configuration() const
72{
73 QVariantList outputs;
74
75 for ( int i = 0; i < mOutputExpressionWidget->rowCount(); ++i )
76 {
77 QVariantMap output;
78 output.insert( QStringLiteral( "name" ), mOutputExpressionWidget->item( i, 0 )->text() );
79 output.insert( QStringLiteral( "expression" ), qobject_cast<QgsExpressionLineEdit *>( mOutputExpressionWidget->cellWidget( i, 1 ) )->expression() );
80 output.insert( QStringLiteral( "isModelOutput" ), qobject_cast<QCheckBox *>( mOutputExpressionWidget->cellWidget( i, 2 ) )->isChecked() );
81 outputs.append( output );
82 }
83
84 QVariantMap map;
85 map.insert( "outputs", outputs );
86
87 return map;
88}
89
90
91void QgsFilterAlgorithmConfigurationWidget::setConfiguration( const QVariantMap &configuration )
92{
93 mOutputExpressionWidget->setRowCount( 0 );
94 int currentRow = 0;
95 const QVariantList outputs = configuration.value( "outputs" ).toList();
96
97 for ( const QVariant &outputvar : outputs )
98 {
99 const QVariantMap output = outputvar.toMap();
100 mOutputExpressionWidget->insertRow( currentRow );
101 mOutputExpressionWidget->setItem( currentRow, 0, new QTableWidgetItem( output.value( "name" ).toString() ) );
102 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
103 expressionBuilder->registerExpressionContextGenerator( this );
104 expressionBuilder->setExpression( output.value( "expression" ).toString() );
105 mOutputExpressionWidget->setCellWidget( currentRow, 1, expressionBuilder );
106 QCheckBox *isModelOutput = new QCheckBox();
107 isModelOutput->setChecked( output.value( "isModelOutput" ).toBool() );
108 mOutputExpressionWidget->setCellWidget( currentRow, 2, isModelOutput );
109
110 currentRow++;
111 }
112
113 if ( outputs.isEmpty() )
114 addOutput();
115}
116
117void QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs()
118{
119 const QItemSelection selection( mOutputExpressionWidget->selectionModel()->selection() );
120
121 QList<int> rows;
122 const QModelIndexList indexes = selection.indexes();
123 for ( const QModelIndex &index : indexes )
124 {
125 rows.append( index.row() );
126 }
127
128 std::sort( rows.begin(), rows.end() );
129
130 int prev = -1;
131 for ( int i = rows.count() - 1; i >= 0; i -= 1 )
132 {
133 const int current = rows[i];
134 if ( current != prev )
135 {
136 mOutputExpressionWidget->removeRow( current );
137 prev = current;
138 }
139 }
140}
141
142void QgsFilterAlgorithmConfigurationWidget::addOutput()
143{
144 const int rowIndex = mOutputExpressionWidget->rowCount();
145 mOutputExpressionWidget->setRowCount( rowIndex + 1 );
146 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
147 expressionBuilder->registerExpressionContextGenerator( this );
148 mOutputExpressionWidget->setItem( rowIndex, 0, new QTableWidgetItem( QString() ) );
149 mOutputExpressionWidget->setCellWidget( rowIndex, 1, expressionBuilder );
150 mOutputExpressionWidget->setCellWidget( rowIndex, 2, new QCheckBox() );
151}
152
153QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithmConfigurationWidgetFactory::create( const QgsProcessingAlgorithm *algorithm ) const
154{
155 if ( algorithm->name() == QLatin1String( "filter" ) )
156 return new QgsFilterAlgorithmConfigurationWidget();
157 else
158 return nullptr;
159}
160
161bool QgsFilterAlgorithmConfigurationWidgetFactory::canCreateFor( const QgsProcessingAlgorithm *algorithm ) const
162{
163 return algorithm->name() == QLatin1String( "filter" );
164}
165
166
167//
168// QgsConditionalBranchAlgorithmConfigurationWidget
169//
170
171QgsConditionalBranchAlgorithmConfigurationWidget::QgsConditionalBranchAlgorithmConfigurationWidget( QWidget *parent )
173{
174 setContentsMargins( 0, 0, 0, 0 );
175
176 mConditionExpressionWidget = new QTableWidget();
177 mConditionExpressionWidget->setColumnCount( 2 );
178 mConditionExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Branch Name" ) ) );
179 mConditionExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Condition" ) ) );
180 mConditionExpressionWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
181 QGridLayout *layout = new QGridLayout();
182 setLayout( layout );
183
184 layout->addWidget( new QLabel( tr( "Conditions" ) ), 0, 0, 1, 2 );
185 layout->addWidget( mConditionExpressionWidget, 1, 0, 4, 1 );
186 QToolButton *addConditionButton = new QToolButton();
187 addConditionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
188 addConditionButton->setText( tr( "Add Condition" ) );
189
190 QToolButton *removeConditionButton = new QToolButton();
191 removeConditionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
192 removeConditionButton->setToolTip( tr( "Remove Selected Conditions" ) );
193
194 layout->addWidget( addConditionButton, 2, 1, 1, 1 );
195 layout->addWidget( removeConditionButton, 3, 1, 1, 1 );
196
197 connect( addConditionButton, &QToolButton::clicked, this, &QgsConditionalBranchAlgorithmConfigurationWidget::addCondition );
198 connect( removeConditionButton, &QToolButton::clicked, this, &QgsConditionalBranchAlgorithmConfigurationWidget::removeSelectedConditions );
199
200 connect( mConditionExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, [removeConditionButton, this] {
201 removeConditionButton->setEnabled( !mConditionExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
202 } );
203}
204
205QVariantMap QgsConditionalBranchAlgorithmConfigurationWidget::configuration() const
206{
207 QVariantList outputs;
208
209 for ( int i = 0; i < mConditionExpressionWidget->rowCount(); ++i )
210 {
211 QVariantMap output;
212 output.insert( QStringLiteral( "name" ), mConditionExpressionWidget->item( i, 0 )->text() );
213 output.insert( QStringLiteral( "expression" ), qobject_cast<QgsExpressionLineEdit *>( mConditionExpressionWidget->cellWidget( i, 1 ) )->expression() );
214 outputs.append( output );
215 }
216
217 QVariantMap map;
218 map.insert( "conditions", outputs );
219
220 return map;
221}
222
223
224void QgsConditionalBranchAlgorithmConfigurationWidget::setConfiguration( const QVariantMap &configuration )
225{
226 mConditionExpressionWidget->setRowCount( 0 );
227 int currentRow = 0;
228 const QVariantList conditions = configuration.value( "conditions" ).toList();
229
230 for ( const QVariant &conditionvar : conditions )
231 {
232 const QVariantMap output = conditionvar.toMap();
233 mConditionExpressionWidget->insertRow( currentRow );
234 mConditionExpressionWidget->setItem( currentRow, 0, new QTableWidgetItem( output.value( "name" ).toString() ) );
235 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
236 expressionBuilder->registerExpressionContextGenerator( this );
237 expressionBuilder->setExpression( output.value( "expression" ).toString() );
238 mConditionExpressionWidget->setCellWidget( currentRow, 1, expressionBuilder );
239 currentRow++;
240 }
241
242 if ( conditions.isEmpty() )
243 addCondition();
244}
245
246void QgsConditionalBranchAlgorithmConfigurationWidget::removeSelectedConditions()
247{
248 const QItemSelection selection( mConditionExpressionWidget->selectionModel()->selection() );
249
250 QList<int> rows;
251 const QModelIndexList indexes = selection.indexes();
252 for ( const QModelIndex &index : indexes )
253 {
254 rows.append( index.row() );
255 }
256
257 std::sort( rows.begin(), rows.end() );
258
259 int prev = -1;
260 for ( int i = rows.count() - 1; i >= 0; i -= 1 )
261 {
262 const int current = rows[i];
263 if ( current != prev )
264 {
265 mConditionExpressionWidget->removeRow( current );
266 prev = current;
267 }
268 }
269}
270
271void QgsConditionalBranchAlgorithmConfigurationWidget::addCondition()
272{
273 const int rowIndex = mConditionExpressionWidget->rowCount();
274 mConditionExpressionWidget->setRowCount( rowIndex + 1 );
275 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
276 expressionBuilder->registerExpressionContextGenerator( this );
277 mConditionExpressionWidget->setItem( rowIndex, 0, new QTableWidgetItem( QString() ) );
278 mConditionExpressionWidget->setCellWidget( rowIndex, 1, expressionBuilder );
279}
280
281QgsConditionalBranchAlgorithmConfigurationWidget *QgsConditionalBranchAlgorithmConfigurationWidgetFactory::create( const QgsProcessingAlgorithm *algorithm ) const
282{
283 if ( algorithm->name() == QLatin1String( "condition" ) )
284 return new QgsConditionalBranchAlgorithmConfigurationWidget();
285 else
286 return nullptr;
287}
288
289bool QgsConditionalBranchAlgorithmConfigurationWidgetFactory::canCreateFor( const QgsProcessingAlgorithm *algorithm ) const
290{
291 return algorithm->name() == QLatin1String( "condition" );
292}
293
294
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
void registerExpressionContextGenerator(const QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
A configuration widget for processing algorithms allows providing additional configuration options di...
Abstract base class for processing algorithms.
virtual QString name() const =0
Returns the algorithm name, used for identifying the algorithm.
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