Skip to content

Commit

Permalink
Move processing algorithm configuration widget to gui library
Browse files Browse the repository at this point in the history
This way we can also use all the fancy widgets like a QgsExpressionLineEdit.
  • Loading branch information
m-kuhn committed Apr 9, 2018
1 parent 10db1c8 commit 3be4324
Show file tree
Hide file tree
Showing 20 changed files with 511 additions and 157 deletions.
6 changes: 0 additions & 6 deletions python/core/processing/qgsprocessingalgorithm.sip.in
Expand Up @@ -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,
Expand Down
Expand Up @@ -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 *
* *
Expand Down
23 changes: 23 additions & 0 deletions python/core/processing/qgsprocessingregistry.sip.in
Expand Up @@ -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:

Expand Down
1 change: 1 addition & 0 deletions python/gui/gui_auto.sip
Expand Up @@ -312,4 +312,5 @@
%Include layout/qgslayoutviewtoolzoom.sip
%Include locator/qgslocatorwidget.sip
%Include processing/qgsprocessingalgorithmdialogbase.sip
%Include processing/qgsprocessingconfigurationwidgets.sip
%Include qgsadvanceddigitizingcanvasitem.sip
61 changes: 61 additions & 0 deletions python/gui/processing/qgsprocessingconfigurationwidgets.sip.in
@@ -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 *
************************************************************************/
4 changes: 3 additions & 1 deletion python/plugins/processing/modeler/ModelerParametersDialog.py
Expand Up @@ -36,6 +36,7 @@
QHBoxLayout, QWidget)

from qgis.core import (Qgis,
QgsApplication,
QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterExtent,
Expand Down Expand Up @@ -118,7 +119,7 @@ def setupUi(self):
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)
Expand Down Expand Up @@ -330,6 +331,7 @@ def createAlgorithm(self):
output.setChildId(alg.childId())
output.setChildOutputName(dest.name())
outputs[name] = output

alg.setModelOutputs(outputs)

selectedOptions = self.dependenciesPanel.selectedoptions
Expand Down
1 change: 0 additions & 1 deletion src/analysis/CMakeLists.txt
Expand Up @@ -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
Expand Down
115 changes: 0 additions & 115 deletions src/analysis/processing/qgsalgorithmfilter.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -66,11 +60,6 @@ QgsFilterAlgorithm *QgsFilterAlgorithm::createInstance() const
return new QgsFilterAlgorithm();
}

QgsProcessingAlgorithmConfigurationWidget *QgsFilterAlgorithm::createModelerWidget() const
{
return new QgsFilterAlgorithmConfigurationWidget();
}

QgsFilterAlgorithm::~QgsFilterAlgorithm()
{
qDeleteAll( mOutputs );
Expand All @@ -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 ) );
Expand Down Expand Up @@ -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 );
}

0 comments on commit 3be4324

Please sign in to comment.