QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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
6  email : [email protected]
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 "qgsprocessingalgorithm.h"
21 #include "qgsexpressionlineedit.h"
22 #include "qgsapplication.h"
23 #include "qgsgui.h"
25 
26 #include <QTableWidget>
27 #include <QGridLayout>
28 #include <QToolButton>
29 #include <QLabel>
30 #include <QCheckBox>
31 #include <QHeaderView>
32 
34 
35 QgsFilterAlgorithmConfigurationWidget::QgsFilterAlgorithmConfigurationWidget( QWidget *parent )
37 {
38  setContentsMargins( 0, 0, 0, 0 );
39 
40  mOutputExpressionWidget = new QTableWidget();
41  mOutputExpressionWidget->setColumnCount( 3 );
42  mOutputExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Output Name" ) ) );
43  mOutputExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Filter Expression" ) ) );
44  mOutputExpressionWidget->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Final Output" ) ) );
45  mOutputExpressionWidget->horizontalHeader()->setResizeMode( 1, QHeaderView::Stretch );
46  QGridLayout *layout = new QGridLayout();
47  setLayout( layout );
48 
49  layout->addWidget( new QLabel( tr( "Outputs and filters" ) ), 0, 0, 1, 2 );
50  layout->addWidget( mOutputExpressionWidget, 1, 0, 4, 1 );
51  QToolButton *addOutputButton = new QToolButton();
52  addOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
53  addOutputButton->setText( tr( "Add Output" ) );
54 
55  QToolButton *removeOutputButton = new QToolButton();
56  removeOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
57  removeOutputButton->setToolTip( tr( "Remove Selected Outputs" ) );
58 
59  layout->addWidget( addOutputButton, 2, 1, 1, 1 );
60  layout->addWidget( removeOutputButton, 3, 1, 1, 1 );
61 
62  connect( addOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::addOutput );
63  connect( removeOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs );
64 
65  connect( mOutputExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, [removeOutputButton, this]
66  {
67  removeOutputButton->setEnabled( !mOutputExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
68  } );
69 }
70 
71 QVariantMap 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 
91 void 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->setExpression( output.value( "expression" ).toString() );
104  mOutputExpressionWidget->setCellWidget( currentRow, 1, expressionBuilder );
105  QCheckBox *isModelOutput = new QCheckBox();
106  isModelOutput->setChecked( output.value( "isModelOutput" ).toBool() );
107  mOutputExpressionWidget->setCellWidget( currentRow, 2, isModelOutput );
108 
109  currentRow++;
110  }
111 
112  if ( outputs.isEmpty() )
113  addOutput();
114 }
115 
116 void QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs()
117 {
118  QItemSelection selection( mOutputExpressionWidget->selectionModel()->selection() );
119 
120  QList<int> rows;
121  const QModelIndexList indexes = selection.indexes();
122  for ( const QModelIndex &index : indexes )
123  {
124  rows.append( index.row() );
125  }
126 
127  std::sort( rows.begin(), rows.end() );
128 
129  int prev = -1;
130  for ( int i = rows.count() - 1; i >= 0; i -= 1 )
131  {
132  int current = rows[i];
133  if ( current != prev )
134  {
135  mOutputExpressionWidget->removeRow( current );
136  prev = current;
137  }
138  }
139 }
140 
141 void QgsFilterAlgorithmConfigurationWidget::addOutput()
142 {
143  int rowIndex = mOutputExpressionWidget->rowCount();
144  mOutputExpressionWidget->setRowCount( rowIndex + 1 );
145  QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
146  mOutputExpressionWidget->setItem( rowIndex, 0, new QTableWidgetItem( QString() ) );
147  mOutputExpressionWidget->setCellWidget( rowIndex, 1, expressionBuilder );
148  mOutputExpressionWidget->setCellWidget( rowIndex, 2, new QCheckBox() );
149 }
150 
151 QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithmConfigurationWidgetFactory::create( const QgsProcessingAlgorithm *algorithm ) const
152 {
153  if ( algorithm->name() == QStringLiteral( "filter" ) )
154  return new QgsFilterAlgorithmConfigurationWidget();
155  else
156  return nullptr;
157 }
158 
159 bool QgsFilterAlgorithmConfigurationWidgetFactory::canCreateFor( const QgsProcessingAlgorithm *algorithm ) const
160 {
161  return algorithm->name() == QStringLiteral( "filter" );
162 }
163 
virtual QString name() const =0
Returns the algorithm name, used for identifying the algorithm.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Abstract base class for processing algorithms.
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...
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
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