QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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 {
68 removeOutputButton->setEnabled( !mOutputExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
69 } );
70}
71
72QVariantMap QgsFilterAlgorithmConfigurationWidget::configuration() const
73{
74 QVariantList outputs;
75
76 for ( int i = 0; i < mOutputExpressionWidget->rowCount(); ++i )
77 {
78 QVariantMap output;
79 output.insert( QStringLiteral( "name" ), mOutputExpressionWidget->item( i, 0 )->text() );
80 output.insert( QStringLiteral( "expression" ), qobject_cast<QgsExpressionLineEdit *>( mOutputExpressionWidget->cellWidget( i, 1 ) )->expression() );
81 output.insert( QStringLiteral( "isModelOutput" ), qobject_cast<QCheckBox *>( mOutputExpressionWidget->cellWidget( i, 2 ) )->isChecked() );
82 outputs.append( output );
83 }
84
85 QVariantMap map;
86 map.insert( "outputs", outputs );
87
88 return map;
89}
90
91
92void QgsFilterAlgorithmConfigurationWidget::setConfiguration( const QVariantMap &configuration )
93{
94 mOutputExpressionWidget->setRowCount( 0 );
95 int currentRow = 0;
96 const QVariantList outputs = configuration.value( "outputs" ).toList();
97
98 for ( const QVariant &outputvar : outputs )
99 {
100 const QVariantMap output = outputvar.toMap();
101 mOutputExpressionWidget->insertRow( currentRow );
102 mOutputExpressionWidget->setItem( currentRow, 0, new QTableWidgetItem( output.value( "name" ).toString() ) );
103 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
104 expressionBuilder->registerExpressionContextGenerator( this );
105 expressionBuilder->setExpression( output.value( "expression" ).toString() );
106 mOutputExpressionWidget->setCellWidget( currentRow, 1, expressionBuilder );
107 QCheckBox *isModelOutput = new QCheckBox();
108 isModelOutput->setChecked( output.value( "isModelOutput" ).toBool() );
109 mOutputExpressionWidget->setCellWidget( currentRow, 2, isModelOutput );
110
111 currentRow++;
112 }
113
114 if ( outputs.isEmpty() )
115 addOutput();
116}
117
118void QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs()
119{
120 const QItemSelection selection( mOutputExpressionWidget->selectionModel()->selection() );
121
122 QList<int> rows;
123 const QModelIndexList indexes = selection.indexes();
124 for ( const QModelIndex &index : indexes )
125 {
126 rows.append( index.row() );
127 }
128
129 std::sort( rows.begin(), rows.end() );
130
131 int prev = -1;
132 for ( int i = rows.count() - 1; i >= 0; i -= 1 )
133 {
134 const int current = rows[i];
135 if ( current != prev )
136 {
137 mOutputExpressionWidget->removeRow( current );
138 prev = current;
139 }
140 }
141}
142
143void QgsFilterAlgorithmConfigurationWidget::addOutput()
144{
145 const int rowIndex = mOutputExpressionWidget->rowCount();
146 mOutputExpressionWidget->setRowCount( rowIndex + 1 );
147 QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
148 expressionBuilder->registerExpressionContextGenerator( this );
149 mOutputExpressionWidget->setItem( rowIndex, 0, new QTableWidgetItem( QString() ) );
150 mOutputExpressionWidget->setCellWidget( rowIndex, 1, expressionBuilder );
151 mOutputExpressionWidget->setCellWidget( rowIndex, 2, new QCheckBox() );
152}
153
154QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithmConfigurationWidgetFactory::create( const QgsProcessingAlgorithm *algorithm ) const
155{
156 if ( algorithm->name() == QLatin1String( "filter" ) )
157 return new QgsFilterAlgorithmConfigurationWidget();
158 else
159 return nullptr;
160}
161
162bool QgsFilterAlgorithmConfigurationWidgetFactory::canCreateFor( const QgsProcessingAlgorithm *algorithm ) const
163{
164 return algorithm->name() == QLatin1String( "filter" );
165}
166
167
168//
169// QgsConditionalBranchAlgorithmConfigurationWidget
170//
171
172QgsConditionalBranchAlgorithmConfigurationWidget::QgsConditionalBranchAlgorithmConfigurationWidget( QWidget *parent )
174{
175 setContentsMargins( 0, 0, 0, 0 );
176
177 mConditionExpressionWidget = new QTableWidget();
178 mConditionExpressionWidget->setColumnCount( 2 );
179 mConditionExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Branch Name" ) ) );
180 mConditionExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Condition" ) ) );
181 mConditionExpressionWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
182 QGridLayout *layout = new QGridLayout();
183 setLayout( layout );
184
185 layout->addWidget( new QLabel( tr( "Conditions" ) ), 0, 0, 1, 2 );
186 layout->addWidget( mConditionExpressionWidget, 1, 0, 4, 1 );
187 QToolButton *addConditionButton = new QToolButton();
188 addConditionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
189 addConditionButton->setText( tr( "Add Condition" ) );
190
191 QToolButton *removeConditionButton = new QToolButton();
192 removeConditionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
193 removeConditionButton->setToolTip( tr( "Remove Selected Conditions" ) );
194
195 layout->addWidget( addConditionButton, 2, 1, 1, 1 );
196 layout->addWidget( removeConditionButton, 3, 1, 1, 1 );
197
198 connect( addConditionButton, &QToolButton::clicked, this, &QgsConditionalBranchAlgorithmConfigurationWidget::addCondition );
199 connect( removeConditionButton, &QToolButton::clicked, this, &QgsConditionalBranchAlgorithmConfigurationWidget::removeSelectedConditions );
200
201 connect( mConditionExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, [removeConditionButton, this]
202 {
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.
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