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