Move processing algorithm configuration widget to gui library

This way we can also use all the fancy widgets like a QgsExpressionLineEdit.
This commit is contained in:
Matthias Kuhn 2018-04-06 15:53:33 +02:00
parent 10db1c8f0e
commit 3be4324d60
20 changed files with 511 additions and 157 deletions

View File

@ -349,12 +349,6 @@ If an algorithm subclass implements a custom parameters widget, a copy of this w
should be constructed and returned by this method.
The base class implementation returns None, which indicates that an autogenerated
parameters widget should be used.
%End
virtual QgsProcessingAlgorithmConfigurationWidget *createModelerWidget() const /Factory/;
%Docstring
If an algorithm subclass implements a configuration widget for the algorithm itself,
a new instance of this widget should be returned by this method.
%End
QgsExpressionContext createExpressionContext( const QVariantMap &parameters,

View File

@ -9,19 +9,68 @@
class QgsProcessingAlgorithmConfigurationWidget : QWidget
{
%Docstring
A configuration widget for processing algorithms allows to provide additional
configuration options directly on algorithm level, in addition to parameters.
.. versionadded:: 3.2
%End
%TypeHeaderCode
#include "qgsprocessingalgorithmconfigurationwidget.h"
%End
public:
QgsProcessingAlgorithmConfigurationWidget( QWidget *parent = 0 );
%Docstring
Creates a new QgsProcessingAlgorithmConfigurationWidget
%End
virtual ~QgsProcessingAlgorithmConfigurationWidget();
virtual QVariantMap configuration() const = 0;
%Docstring
Read the current configuration from this widget.
%End
virtual void setConfiguration( const QVariantMap &configuration ) = 0;
%Docstring
Set the configuration which this widget should represent.
%End
};
class QgsProcessingAlgorithmConfigurationWidgetFactory
{
%Docstring
Interface base class for factories for algorithm configuration widgets.
.. versionadded:: 3.2
%End
%TypeHeaderCode
#include "qgsprocessingalgorithmconfigurationwidget.h"
%End
public:
virtual ~QgsProcessingAlgorithmConfigurationWidgetFactory();
virtual QgsProcessingAlgorithmConfigurationWidget *create( QgsProcessingAlgorithm *algorithm ) const = 0 /Factory/;
%Docstring
Create a new configuration widget for ``algorithm``.
%End
virtual bool canCreateFor( QgsProcessingAlgorithm *algorithm ) const = 0;
%Docstring
Check if this factory can create widgets for ``algorithm``.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -143,6 +143,29 @@ Return a list with all known parameter types.
.. versionadded:: 3.2
%End
void addAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory /Transfer/ );
%Docstring
Add a new configuration widget factory for customized algorithm configuration
widgets. Ownership is taken.
.. versionadded:: 3.2
%End
void removeAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory );
%Docstring
Remove a configuration widget factory for customized algorithm configuration
widgets.
.. versionadded:: 3.2
%End
QgsProcessingAlgorithmConfigurationWidget *algorithmConfigurationWidget( QgsProcessingAlgorithm *algorithm ) const;
%Docstring
algorithmConfigurationWidget
@param algorithm
@return
%End
signals:

View File

@ -312,4 +312,5 @@
%Include layout/qgslayoutviewtoolzoom.sip
%Include locator/qgslocatorwidget.sip
%Include processing/qgsprocessingalgorithmdialogbase.sip
%Include processing/qgsprocessingconfigurationwidgets.sip
%Include qgsadvanceddigitizingcanvasitem.sip

View File

@ -0,0 +1,61 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingconfigurationwidgets.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsProcessingConfigurationWidgets
{
%Docstring
This class is responsible for the management of processing widgets which
QGIS internally.
Standalone applications that require to show configuration widgets for processing
algorithms will need to execute the following code to have the configuration
interfaces available.
.. code-block:: python
# At startup time
QgsApplicationProcessingConfigurationWidgets.initialize()
# At exit time
QgsApplicationProcessingConfigurationWidgets.cleanup()
%End
%TypeHeaderCode
#include "qgsprocessingconfigurationwidgets.h"
%End
public:
static void initialize();
%Docstring
Initialize native configuration widgets.
%End
static void cleanup();
%Docstring
Cleanup native configuration widgets.
%End
private:
QgsProcessingConfigurationWidgets();
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingconfigurationwidgets.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -36,6 +36,7 @@ from qgis.PyQt.QtWidgets import (QDialog, QDialogButtonBox, QLabel, QLineEdit,
QHBoxLayout, QWidget)
from qgis.core import (Qgis,
QgsApplication,
QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterExtent,
@ -118,7 +119,7 @@ class ModelerParametersDialog(QDialog):
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
self.verticalLayout.addWidget(line)
self.algorithmItem = self._alg.createModelerWidget()
self.algorithmItem = QgsApplication.instance().processingRegistry().algorithmConfigurationWidget(self._alg)
if self.configuration:
self.algorithmItem.setConfiguration(self.configuration)
self.verticalLayout.addWidget(self.algorithmItem)
@ -330,6 +331,7 @@ class ModelerParametersDialog(QDialog):
output.setChildId(alg.childId())
output.setChildOutputName(dest.name())
outputs[name] = output
alg.setModelOutputs(outputs)
selectedOptions = self.dependenciesPanel.selectedoptions

View File

@ -140,7 +140,6 @@ SET(QGIS_ANALYSIS_MOC_HDRS
network/qgsvectorlayerdirector.h
processing/qgsalgorithmfiledownloader.h
processing/qgsalgorithmfilter.h
vector/geometry_checker/qgsfeaturepool.h
vector/geometry_checker/qgsgeometrychecker.h

View File

@ -18,12 +18,6 @@
#include "qgsalgorithmfilter.h"
#include "qgsapplication.h"
#include <QLabel>
#include <QGridLayout>
#include <QTableWidget>
#include <QHeaderView>
#include <QToolButton>
///@cond PRIVATE
QString QgsFilterAlgorithm::name() const
@ -66,11 +60,6 @@ QgsFilterAlgorithm *QgsFilterAlgorithm::createInstance() const
return new QgsFilterAlgorithm();
}
QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithm::createModelerWidget() const
{
return new QgsFilterAlgorithmConfigurationWidget();
}
QgsFilterAlgorithm::~QgsFilterAlgorithm()
{
qDeleteAll( mOutputs );
@ -93,60 +82,6 @@ void QgsFilterAlgorithm::initAlgorithm( const QVariantMap &configuration )
}
QgsFilterAlgorithmConfigurationWidget::QgsFilterAlgorithmConfigurationWidget( QWidget *parent )
: QgsProcessingAlgorithmConfigurationWidget( parent )
{
setContentsMargins( 0, 0, 0, 0 );
mOutputExpressionWidget = new QTableWidget();
mOutputExpressionWidget->setColumnCount( 2 );
mOutputExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Output Name" ) ) );
mOutputExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Filter Expression" ) ) );
mOutputExpressionWidget->horizontalHeader()->setStretchLastSection( true );
QGridLayout *layout = new QGridLayout();
setLayout( layout );
layout->addWidget( new QLabel( tr( "Outputs and filters" ) ), 0, 0, 1, 2 );
layout->addWidget( mOutputExpressionWidget, 1, 0, 4, 1 );
QToolButton *addOutputButton = new QToolButton();
addOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
addOutputButton->setText( tr( "Add Output" ) );
QToolButton *removeOutputButton = new QToolButton();
removeOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
removeOutputButton->setToolTip( tr( "Remove Selected Outputs" ) );
layout->addWidget( addOutputButton, 2, 1, 1, 1 );
layout->addWidget( removeOutputButton, 3, 1, 1, 1 );
connect( addOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::addOutput );
connect( removeOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs );
connect( mOutputExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, [removeOutputButton, this]
{
removeOutputButton->setEnabled( !mOutputExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
} );
}
QVariantMap QgsFilterAlgorithmConfigurationWidget::configuration() const
{
QVariantList outputs;
for ( int i = 0; i < mOutputExpressionWidget->rowCount(); ++i )
{
QVariantMap output;
output.insert( QStringLiteral( "name" ), mOutputExpressionWidget->item( i, 0 )->text() );
output.insert( QStringLiteral( "expression" ), mOutputExpressionWidget->item( i, 1 )->text() );
outputs.append( output );
}
QVariantMap map;
map.insert( "outputs", outputs );
return map;
}
QVariantMap QgsFilterAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
@ -195,53 +130,3 @@ QVariantMap QgsFilterAlgorithm::processAlgorithm( const QVariantMap &parameters,
return outputs;
}
void QgsFilterAlgorithmConfigurationWidget::setConfiguration( const QVariantMap &configuration )
{
mOutputExpressionWidget->setRowCount( 0 );
int currentRow = 0;
const QVariantList outputs = configuration.value( "outputs" ).toList();
for ( const QVariant &outputvar : outputs )
{
const QVariantMap output = outputvar.toMap();
mOutputExpressionWidget->insertRow( currentRow );
mOutputExpressionWidget->setItem( currentRow, 0, new QTableWidgetItem( output.value( "name" ).toString() ) );
mOutputExpressionWidget->setItem( currentRow, 1, new QTableWidgetItem( output.value( "expression" ).toString() ) );
currentRow++;
}
if ( outputs.isEmpty() )
addOutput();
}
void QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs()
{
QItemSelection selection( mOutputExpressionWidget->selectionModel()->selection() );
QList<int> rows;
const QModelIndexList indexes = selection.indexes();
for ( const QModelIndex &index : indexes )
{
rows.append( index.row() );
}
qSort( rows );
int prev = -1;
for ( int i = rows.count() - 1; i >= 0; i -= 1 )
{
int current = rows[i];
if ( current != prev )
{
mOutputExpressionWidget->removeRow( current );
prev = current;
}
}
}
void QgsFilterAlgorithmConfigurationWidget::addOutput()
{
mOutputExpressionWidget->setRowCount( mOutputExpressionWidget->rowCount() + 1 );
}

View File

@ -22,38 +22,18 @@
#include "qgis.h"
#include "qgsprocessingalgorithm.h"
#include "qgsprocessingalgorithmconfigurationwidget.h"
class QgsProcessingModelAlgorithm;
class QTableWidget;
///@cond PRIVATE
class QgsFilterAlgorithmConfigurationWidget : public QgsProcessingAlgorithmConfigurationWidget
{
Q_OBJECT
public:
QgsFilterAlgorithmConfigurationWidget( QWidget *parent = nullptr );
QVariantMap configuration() const override;
void setConfiguration( const QVariantMap &configuration ) override;
private slots:
void removeSelectedOutputs();
void addOutput();
private:
QTableWidget *mOutputExpressionWidget;
};
/**
* Feature filter algorithm for modeler.
* Accepts a list of expressions and names and creates outputs where
* matching features are sent to.
*
* \since QGIS 3.2
*/
class QgsFilterAlgorithm : public QgsProcessingAlgorithm
{
@ -70,7 +50,6 @@ class QgsFilterAlgorithm : public QgsProcessingAlgorithm
virtual Flags flags() const override;
QString shortHelpString() const override;
QgsFilterAlgorithm *createInstance() const override SIP_FACTORY;
QgsProcessingAlgorithmConfigurationWidget *createModelerWidget() const override SIP_FACTORY;
protected:

View File

@ -608,6 +608,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/gui/attributetable
${CMAKE_SOURCE_DIR}/src/gui/auth
${CMAKE_SOURCE_DIR}/src/gui/ogr
${CMAKE_SOURCE_DIR}/src/gui/processing
${CMAKE_SOURCE_DIR}/src/gui/raster
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets/core

View File

@ -246,6 +246,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsruntimeprofiler.h"
#include "qgshandlebadlayers.h"
#include "qgsprintlayout.h"
#include "qgsprocessingconfigurationwidgets.h"
#include "qgsprocessingregistry.h"
#include "qgsproject.h"
#include "qgsprojectlayergroupdialog.h"
@ -1457,6 +1458,7 @@ QgisApp::~QgisApp()
// cancel request for FileOpen events
QgsApplication::setFileOpenEventReceiver( nullptr );
QgsProcessingConfigurationWidgets::cleanup();
unregisterCustomLayoutDropHandler( mLayoutQptDropHandler );
@ -10495,6 +10497,7 @@ void QgisApp::initNativeProcessing()
#ifdef HAVE_3D
QgsApplication::processingRegistry()->addProvider( new Qgs3DAlgorithms( QgsApplication::processingRegistry() ) );
#endif
QgsProcessingConfigurationWidgets::initialize();
}
void QgisApp::initLayouts()

View File

@ -64,6 +64,7 @@ const QgsProcessingAlgorithm *QgsProcessingModelChildAlgorithm::algorithm() cons
void QgsProcessingModelChildAlgorithm::setModelOutputs( const QMap<QString, QgsProcessingModelOutput> &modelOutputs )
{
mModelOutputs = modelOutputs;
QMap<QString, QgsProcessingModelOutput>::iterator outputIt = mModelOutputs.begin();
for ( ; outputIt != mModelOutputs.end(); ++outputIt )
{

View File

@ -131,11 +131,6 @@ QWidget *QgsProcessingAlgorithm::createCustomParametersWidget( QWidget * ) const
return nullptr;
}
QgsProcessingAlgorithmConfigurationWidget *QgsProcessingAlgorithm::createModelerWidget() const
{
return nullptr;
}
QgsExpressionContext QgsProcessingAlgorithm::createExpressionContext( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeatureSource *source ) const
{

View File

@ -356,12 +356,6 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
virtual QWidget *createCustomParametersWidget( QWidget *parent = nullptr ) const SIP_FACTORY;
/**
* If an algorithm subclass implements a configuration widget for the algorithm itself,
* a new instance of this widget should be returned by this method.
*/
virtual QgsProcessingAlgorithmConfigurationWidget *createModelerWidget() const SIP_FACTORY;
/**
* Creates an expression context relating to the algorithm. This can be called by algorithms
* to create a new expression context ready for evaluating expressions within the algorithm.

View File

@ -24,6 +24,10 @@
#include <QVariantMap>
#include "qgis_core.h"
#include "qgis_sip.h"
class QgsProcessingAlgorithm;
class QgsProcessingAlgorithmConfigurationWidget;
/**
* A configuration widget for processing algorithms allows to provide additional
@ -37,6 +41,7 @@ class CORE_EXPORT QgsProcessingAlgorithmConfigurationWidget : public QWidget
Q_OBJECT
public:
/**
* Creates a new QgsProcessingAlgorithmConfigurationWidget
*/
@ -54,4 +59,28 @@ class CORE_EXPORT QgsProcessingAlgorithmConfigurationWidget : public QWidget
virtual void setConfiguration( const QVariantMap &configuration ) = 0;
};
/**
* Interface base class for factories for algorithm configuration widgets.
*
* \since QGIS 3.2
* \ingroup core
*/
class CORE_EXPORT QgsProcessingAlgorithmConfigurationWidgetFactory
{
public:
virtual ~QgsProcessingAlgorithmConfigurationWidgetFactory() = default;
/**
* Create a new configuration widget for \a algorithm.
*/
virtual QgsProcessingAlgorithmConfigurationWidget *create( QgsProcessingAlgorithm *algorithm ) const = 0 SIP_FACTORY;
/**
* Check if this factory can create widgets for \a algorithm.
*/
virtual bool canCreateFor( QgsProcessingAlgorithm *algorithm ) const = 0;
};
#endif // QGSPROCESSINGALGORITHMCONFIGURATIONWIDGET_H

View File

@ -18,6 +18,7 @@
#include "qgsprocessingregistry.h"
#include "qgsvectorfilewriter.h"
#include "qgsprocessingparametertypeimpl.h"
#include "qgsprocessingalgorithmconfigurationwidget.h"
QgsProcessingRegistry::QgsProcessingRegistry( QObject *parent SIP_TRANSFERTHIS )
: QObject( parent )
@ -189,3 +190,27 @@ QList<QgsProcessingParameterType *> QgsProcessingRegistry::parameterTypes() cons
return mParameterTypes.values();
}
void QgsProcessingRegistry::addAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory )
{
mAlgorithmConfigurationWidgetFactories.append( factory );
}
void QgsProcessingRegistry::removeAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory )
{
mAlgorithmConfigurationWidgetFactories.removeAll( factory );
delete factory;
}
QgsProcessingAlgorithmConfigurationWidget *QgsProcessingRegistry::algorithmConfigurationWidget( QgsProcessingAlgorithm *algorithm ) const
{
for ( const auto *factory : mAlgorithmConfigurationWidgetFactories )
{
if ( factory->canCreateFor( algorithm ) )
{
return factory->create( algorithm );
}
}
return nullptr;
}

View File

@ -24,6 +24,7 @@
#include <QMap>
class QgsProcessingParameterType;
class QgsProcessingAlgorithmConfigurationWidgetFactory;
/**
* \class QgsProcessingRegistry
@ -168,6 +169,29 @@ class CORE_EXPORT QgsProcessingRegistry : public QObject
*/
QList<QgsProcessingParameterType *> parameterTypes() const;
/**
* Add a new configuration widget factory for customized algorithm configuration
* widgets. Ownership is taken.
*
* \since QGIS 3.2
*/
void addAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory SIP_TRANSFER );
/**
* Remove a configuration widget factory for customized algorithm configuration
* widgets.
*
* \since QGIS 3.2
*/
void removeAlgorithmConfigurationWidgetFactory( QgsProcessingAlgorithmConfigurationWidgetFactory *factory );
/**
* @brief algorithmConfigurationWidget
* @param algorithm
* @return
*/
QgsProcessingAlgorithmConfigurationWidget *algorithmConfigurationWidget( QgsProcessingAlgorithm *algorithm ) const;
signals:
@ -200,6 +224,8 @@ class CORE_EXPORT QgsProcessingRegistry : public QObject
//! Hash of available parameter types by id. This object owns the pointers.
QMap<QString, QgsProcessingParameterType *> mParameterTypes;
QList <QgsProcessingAlgorithmConfigurationWidgetFactory *> mAlgorithmConfigurationWidgetFactories;
#ifdef SIP_RUN
QgsProcessingRegistry( const QgsProcessingRegistry &other );
#endif

View File

@ -193,6 +193,7 @@ SET(QGIS_GUI_SRCS
ogr/qgsvectorlayersaveasdialog.cpp
processing/qgsprocessingalgorithmdialogbase.cpp
processing/qgsprocessingconfigurationwidgets.cpp
qgisinterface.cpp
qgsactionmenu.cpp
@ -710,6 +711,7 @@ SET(QGIS_GUI_MOC_HDRS
locator/qgslocatorwidget.h
processing/qgsprocessingalgorithmdialogbase.h
processing/qgsprocessingconfigurationwidgets.h
)
SET_PROPERTY(GLOBAL PROPERTY QGIS_GUI_MOC_HDRS ${QGIS_GUI_MOC_HDRS})
@ -881,6 +883,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/layout
${CMAKE_SOURCE_DIR}/src/core/locator
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/processing
${CMAKE_SOURCE_DIR}/src/core/providers/memory
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/scalebar

View File

@ -0,0 +1,187 @@
/***************************************************************************
qgsprocessingconfigurationwidgets.cpp
---------------------
begin : April 2018
copyright : (C) 2018 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprocessingconfigurationwidgets.h"
#include "qgsprocessingalgorithm.h"
#include "qgsexpressionlineedit.h"
#include "qgsapplication.h"
#include "qgsprocessingregistry.h"
#include <QTableWidget>
#include <QGridLayout>
#include <QToolButton>
#include <QLabel>
#include <QCheckBox>
#include <QHeaderView>
QList<QgsProcessingAlgorithmConfigurationWidgetFactory *> QgsProcessingConfigurationWidgets::sProcessingAlgorithmConfigurationWidgetFactories;
QgsProcessingConfigurationWidgets::QgsProcessingConfigurationWidgets()
{
}
void QgsProcessingConfigurationWidgets::initialize()
{
if ( !sProcessingAlgorithmConfigurationWidgetFactories.isEmpty() )
{
QgsDebugMsg( "QgsProcessingConfigurationWidgets::initialize() called more than once. Exiting now." );
return;
}
QgsProcessingAlgorithmConfigurationWidgetFactory *factory = new QgsFilterAlgorithmConfigurationWidgetFactory();
sProcessingAlgorithmConfigurationWidgetFactories.append( factory );
QgsApplication::instance()->processingRegistry()->addAlgorithmConfigurationWidgetFactory( factory );
}
void QgsProcessingConfigurationWidgets::cleanup()
{
for ( QgsProcessingAlgorithmConfigurationWidgetFactory *factory : qgis::as_const( sProcessingAlgorithmConfigurationWidgetFactories ) )
QgsApplication::instance()->processingRegistry()->removeAlgorithmConfigurationWidgetFactory( factory );
sProcessingAlgorithmConfigurationWidgetFactories.clear();
}
QgsFilterAlgorithmConfigurationWidget::QgsFilterAlgorithmConfigurationWidget( QWidget *parent )
: QgsProcessingAlgorithmConfigurationWidget( parent )
{
setContentsMargins( 0, 0, 0, 0 );
mOutputExpressionWidget = new QTableWidget();
mOutputExpressionWidget->setColumnCount( 3 );
mOutputExpressionWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Output Name" ) ) );
mOutputExpressionWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Filter Expression" ) ) );
mOutputExpressionWidget->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Final Output" ) ) );
mOutputExpressionWidget->horizontalHeader()->setResizeMode( 1, QHeaderView::Stretch );
QGridLayout *layout = new QGridLayout();
setLayout( layout );
layout->addWidget( new QLabel( tr( "Outputs and filters" ) ), 0, 0, 1, 2 );
layout->addWidget( mOutputExpressionWidget, 1, 0, 4, 1 );
QToolButton *addOutputButton = new QToolButton();
addOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLayer.svg" ) ) );
addOutputButton->setText( tr( "Add Output" ) );
QToolButton *removeOutputButton = new QToolButton();
removeOutputButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
removeOutputButton->setToolTip( tr( "Remove Selected Outputs" ) );
layout->addWidget( addOutputButton, 2, 1, 1, 1 );
layout->addWidget( removeOutputButton, 3, 1, 1, 1 );
connect( addOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::addOutput );
connect( removeOutputButton, &QToolButton::clicked, this, &QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs );
connect( mOutputExpressionWidget->selectionModel(), &QItemSelectionModel::selectionChanged, [removeOutputButton, this]
{
removeOutputButton->setEnabled( !mOutputExpressionWidget->selectionModel()->selectedIndexes().isEmpty() );
} );
}
QVariantMap QgsFilterAlgorithmConfigurationWidget::configuration() const
{
QVariantList outputs;
for ( int i = 0; i < mOutputExpressionWidget->rowCount(); ++i )
{
QVariantMap output;
output.insert( QStringLiteral( "name" ), mOutputExpressionWidget->item( i, 0 )->text() );
output.insert( QStringLiteral( "expression" ), qobject_cast<QgsExpressionLineEdit *>( mOutputExpressionWidget->cellWidget( i, 1 ) )->expression() );
output.insert( QStringLiteral( "isModelOutput" ), qobject_cast<QCheckBox *>( mOutputExpressionWidget->cellWidget( i, 2 ) )->isChecked() );
outputs.append( output );
}
QVariantMap map;
map.insert( "outputs", outputs );
return map;
}
void QgsFilterAlgorithmConfigurationWidget::setConfiguration( const QVariantMap &configuration )
{
mOutputExpressionWidget->setRowCount( 0 );
int currentRow = 0;
const QVariantList outputs = configuration.value( "outputs" ).toList();
for ( const QVariant &outputvar : outputs )
{
const QVariantMap output = outputvar.toMap();
mOutputExpressionWidget->insertRow( currentRow );
mOutputExpressionWidget->setItem( currentRow, 0, new QTableWidgetItem( output.value( "name" ).toString() ) );
QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
expressionBuilder->setExpression( output.value( "expression" ).toString() );
mOutputExpressionWidget->setCellWidget( currentRow, 1, expressionBuilder );
QCheckBox *isModelOutput = new QCheckBox();
isModelOutput->setChecked( output.value( "isModelOutput" ).toBool() );
mOutputExpressionWidget->setCellWidget( currentRow, 2, isModelOutput );
currentRow++;
}
if ( outputs.isEmpty() )
addOutput();
}
void QgsFilterAlgorithmConfigurationWidget::removeSelectedOutputs()
{
QItemSelection selection( mOutputExpressionWidget->selectionModel()->selection() );
QList<int> rows;
const QModelIndexList indexes = selection.indexes();
for ( const QModelIndex &index : indexes )
{
rows.append( index.row() );
}
qSort( rows );
int prev = -1;
for ( int i = rows.count() - 1; i >= 0; i -= 1 )
{
int current = rows[i];
if ( current != prev )
{
mOutputExpressionWidget->removeRow( current );
prev = current;
}
}
}
void QgsFilterAlgorithmConfigurationWidget::addOutput()
{
int rowIndex = mOutputExpressionWidget->rowCount() + 1;
mOutputExpressionWidget->setRowCount( rowIndex );
QgsExpressionLineEdit *expressionBuilder = new QgsExpressionLineEdit();
mOutputExpressionWidget->setCellWidget( rowIndex, 1, expressionBuilder );
mOutputExpressionWidget->setCellWidget( rowIndex, 2, new QCheckBox() );
}
QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithmConfigurationWidgetFactory::create( QgsProcessingAlgorithm *algorithm ) const
{
if ( algorithm->name() == QStringLiteral( "filter" ) )
return new QgsFilterAlgorithmConfigurationWidget();
else
return nullptr;
}
bool QgsFilterAlgorithmConfigurationWidgetFactory::canCreateFor( QgsProcessingAlgorithm *algorithm ) const
{
if ( algorithm->name() == QStringLiteral( "filter" ) )
return true;
else
return false;
}

View File

@ -0,0 +1,97 @@
/***************************************************************************
qgsprocessingconfigurationwidgets.h
---------------------
begin : April 2018
copyright : (C) 2018 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROCESSINGCONFIGURATIONWIDGETS_H
#define QGSPROCESSINGCONFIGURATIONWIDGETS_H
#include "qgsprocessingalgorithmconfigurationwidget.h"
#include "qgis_gui.h"
#include "qgis_sip.h"
class QTableWidget;
/**
* This class is responsible for the management of processing widgets which
* QGIS internally.
*
* Standalone applications that require to show configuration widgets for processing
* algorithms will need to execute the following code to have the configuration
* interfaces available.
*
* \code{.py}
* # At startup time
* QgsApplicationProcessingConfigurationWidgets.initialize()
*
* # At exit time
* QgsApplicationProcessingConfigurationWidgets.cleanup()
* \endcode
*/
class GUI_EXPORT QgsProcessingConfigurationWidgets
{
public:
/**
* Initialize native configuration widgets.
*/
static void initialize();
/**
* Cleanup native configuration widgets.
*/
static void cleanup();
private:
QgsProcessingConfigurationWidgets() SIP_FORCE;
static QList<QgsProcessingAlgorithmConfigurationWidgetFactory *> sProcessingAlgorithmConfigurationWidgetFactories;
};
///@cond PRIVATE
#ifndef SIP_RUN
class QgsFilterAlgorithmConfigurationWidget : public QgsProcessingAlgorithmConfigurationWidget
{
Q_OBJECT
public:
QgsFilterAlgorithmConfigurationWidget( QWidget *parent = nullptr );
QVariantMap configuration() const override;
void setConfiguration( const QVariantMap &configuration ) override;
private slots:
void removeSelectedOutputs();
void addOutput();
private:
QTableWidget *mOutputExpressionWidget;
};
class QgsFilterAlgorithmConfigurationWidgetFactory : public QgsProcessingAlgorithmConfigurationWidgetFactory
{
public:
virtual QgsProcessingAlgorithmConfigurationWidget *create( QgsProcessingAlgorithm *algorithm ) const override;
virtual bool canCreateFor( QgsProcessingAlgorithm *algorithm ) const override;
};
#endif
///@endcond
#endif // QGSPROCESSINGCONFIGURATIONWIDGETS_H