Add raster layer output parameters

This commit is contained in:
Nyall Dawson 2017-06-06 14:38:24 +10:00
parent e6a71ab5fc
commit a27c22d9b1
13 changed files with 251 additions and 13 deletions

View File

@ -368,6 +368,12 @@ class QgsProcessingAlgorithm
:rtype: QgsRasterLayer
%End
QString parameterAsRasterOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a raster output layer destination.
:rtype: str
%End
QgsVectorLayer *parameterAsVectorLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a vector layer.

View File

@ -30,6 +30,8 @@ class QgsProcessingOutputDefinition
%ConvertToSubClassCode
if ( sipCpp->type() == "outputVector" )
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == "outputRaster" )
sipType = sipType_QgsProcessingOutputRasterLayer;
%End
public:
@ -118,6 +120,26 @@ class QgsProcessingOutputVectorLayer : QgsProcessingOutputDefinition
};
class QgsProcessingOutputRasterLayer : QgsProcessingOutputDefinition
{
%Docstring
A raster layer output for processing algorithms.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsprocessingoutputs.h"
%End
public:
QgsProcessingOutputRasterLayer( const QString &name, const QString &description = QString() );
%Docstring
Constructor for QgsProcessingOutputRasterLayer.
%End
virtual QString type() const;
};

View File

@ -171,6 +171,8 @@ class QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSource;
else if ( sipCpp->type() == "sink" )
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
%End
public:
@ -419,6 +421,12 @@ class QgsProcessingParameters
:rtype: QgsRasterLayer
%End
static QString parameterAsRasterOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a raster output layer destination.
:rtype: str
%End
static QgsVectorLayer *parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a vector layer.
@ -1221,6 +1229,31 @@ class QgsProcessingParameterFeatureSink : QgsProcessingParameterDefinition
};
class QgsProcessingParameterRasterOutput : QgsProcessingParameterDefinition
{
%Docstring
A raster layer output parameter.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:
QgsProcessingParameterRasterOutput( const QString &name, const QString &description = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterRasterOutput.
%End
virtual QString type() const;
virtual bool isDestination() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;
};
/************************************************************************

View File

@ -34,9 +34,11 @@ from qgis.core import (QgsProject,
QgsProcessingUtils,
QgsMessageLog,
QgsProcessingParameterDefinition,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputLayerDefinition,
QgsProcessingParameterFeatureSink,
QgsProcessingParameterRasterOutput,
QgsProcessingAlgorithm)
from qgis.gui import QgsMessageBar
from qgis.utils import iface
@ -56,8 +58,6 @@ from processing.core.parameters import ParameterExtent
from processing.core.parameters import ParameterMultipleInput
from processing.core.GeoAlgorithm import executeAlgorithm
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputVector
from processing.core.outputs import OutputTable
from processing.tools import dataobjects
@ -113,7 +113,7 @@ class AlgorithmDialog(AlgorithmDialogBase):
else:
dest_project = None
if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \
isinstance(param, (OutputRaster, QgsProcessingParameterFeatureSink, OutputTable)):
isinstance(param, (QgsProcessingParameterRasterOutput, QgsProcessingParameterFeatureSink, OutputTable)):
if self.mainWidget.checkBoxes[param.name()].isChecked():
dest_project = QgsProject.instance()

View File

@ -56,10 +56,10 @@ def getFileFilter(param):
for i in range(len(exts)):
exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterMultipleLayers').format(exts[i].upper(), exts[i].lower())
return ';;'.join(exts)
elif param.type() == 'raster':
elif param.type() in ('raster', 'rasterOut'):
exts = dataobjects.getSupportedOutputRasterLayerExtensions()
for i in range(len(exts)):
exts[i] = tr('{0} files (*.{1})', 'ParameterRaster').format(exts[i].upper(), exts[i].lower())
exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterRasterOutput').format(exts[i].upper(), exts[i].lower())
return ';;'.join(exts)
elif param.type() == 'table':
exts = ['csv', 'dbf']

View File

@ -36,6 +36,8 @@ from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterFeatureSource,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer,
QgsProcessingParameterRasterOutput,
QgsProcessingParameterFeatureSink)
from qgis.PyQt import uic
from qgis.PyQt.QtCore import QCoreApplication
@ -46,9 +48,7 @@ from qgis.PyQt.QtGui import QIcon
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
from processing.gui.wrappers import WidgetWrapperFactory
from processing.core.parameters import ParameterVector, ParameterExtent, ParameterPoint
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputTable
from processing.core.outputs import OutputVector
pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType(
@ -157,7 +157,7 @@ class ParametersPanel(BASE, WIDGET):
widget = DestinationSelectionPanel(output, self.alg)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
if isinstance(output, (OutputRaster, QgsProcessingParameterFeatureSink, OutputTable)):
if isinstance(output, (QgsProcessingParameterRasterOutput, QgsProcessingParameterFeatureSink, OutputTable)):
check = QCheckBox()
check.setText(self.tr('Open output file after running algorithm'))
check.setChecked(True)

View File

@ -247,6 +247,11 @@ QgsRasterLayer *QgsProcessingAlgorithm::parameterAsRasterLayer( const QVariantMa
return QgsProcessingParameters::parameterAsRasterLayer( parameterDefinition( name ), parameters, context );
}
QString QgsProcessingAlgorithm::parameterAsRasterOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
{
return QgsProcessingParameters::parameterAsRasterOutputLayer( parameterDefinition( name ), parameters, context );
}
QgsVectorLayer *QgsProcessingAlgorithm::parameterAsVectorLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
{
return QgsProcessingParameters::parameterAsVectorLayer( parameterDefinition( name ), parameters, context );

View File

@ -354,6 +354,11 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
QgsRasterLayer *parameterAsRasterLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
/**
* Evaluates the parameter with matching \a name to a raster output layer destination.
*/
QString parameterAsRasterOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
/**
* Evaluates the parameter with matching \a name to a vector layer.
*

View File

@ -38,3 +38,7 @@ void QgsProcessingOutputVectorLayer::setDataType( QgsProcessingParameterDefiniti
{
mDataType = type;
}
QgsProcessingOutputRasterLayer::QgsProcessingOutputRasterLayer( const QString &name, const QString &description )
: QgsProcessingOutputDefinition( name, description )
{}

View File

@ -45,6 +45,8 @@ class CORE_EXPORT QgsProcessingOutputDefinition
SIP_CONVERT_TO_SUBCLASS_CODE
if ( sipCpp->type() == "outputVector" )
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == "outputRaster" )
sipType = sipType_QgsProcessingOutputRasterLayer;
SIP_END
#endif
@ -137,6 +139,24 @@ class CORE_EXPORT QgsProcessingOutputVectorLayer : public QgsProcessingOutputDef
QgsProcessingParameterDefinition::LayerType mDataType = QgsProcessingParameterDefinition::TypeVectorAny;
};
/**
* \class QgsProcessingOutputRasterLayer
* \ingroup core
* A raster layer output for processing algorithms.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingOutputRasterLayer : public QgsProcessingOutputDefinition
{
public:
/**
* Constructor for QgsProcessingOutputRasterLayer.
*/
QgsProcessingOutputRasterLayer( const QString &name, const QString &description = QString() );
QString type() const override { return QStringLiteral( "outputRaster" ); }
};
#endif // QGSPROCESSINGOUTPUTS_H

View File

@ -338,6 +338,46 @@ QgsRasterLayer *QgsProcessingParameters::parameterAsRasterLayer( const QgsProces
return qobject_cast< QgsRasterLayer *>( parameterAsLayer( definition, parameters, context ) );
}
QString QgsProcessingParameters::parameterAsRasterOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
QVariant val;
if ( definition )
{
val = parameters.value( definition->name() );
}
QgsProject *destinationProject = nullptr;
QVariantMap createOptions;
if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
{
// input is a QgsProcessingOutputLayerDefinition - get extra properties from it
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
destinationProject = fromVar.destinationProject;
createOptions = fromVar.createOptions;
val = fromVar.sink;
}
QString dest;
if ( val.canConvert<QgsProperty>() )
{
dest = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
}
else if ( !val.isValid() || val.toString().isEmpty() )
{
// fall back to default
dest = definition->defaultValue().toString();
}
else
{
dest = val.toString();
}
if ( destinationProject )
context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( definition ? definition->description() : QString(), destinationProject ) );
return dest;
}
QgsVectorLayer *QgsProcessingParameters::parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
return qobject_cast< QgsVectorLayer *>( parameterAsLayer( definition, parameters, context ) );
@ -681,6 +721,11 @@ bool QgsProcessingParameterMapLayer::checkValueIsAcceptable( const QVariant &inp
return true;
}
if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
{
return true;
}
if ( input.type() != QVariant::String || input.toString().isEmpty() )
return mFlags & FlagOptional;
@ -713,11 +758,6 @@ bool QgsProcessingParameterExtent::checkValueIsAcceptable( const QVariant &input
return true;
}
if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
{
return true;
}
if ( input.type() != QVariant::String || input.toString().isEmpty() )
return mFlags & FlagOptional;
@ -1442,3 +1482,34 @@ void QgsProcessingParameterFeatureSink::setDataType( QgsProcessingParameterDefin
{
mDataType = type;
}
QgsProcessingParameterRasterOutput::QgsProcessingParameterRasterOutput( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
{}
bool QgsProcessingParameterRasterOutput::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
{
QVariant var = input;
if ( !var.isValid() )
return mFlags & FlagOptional;
if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
{
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
var = fromVar.sink;
}
if ( var.canConvert<QgsProperty>() )
{
return true;
}
if ( var.type() != QVariant::String )
return false;
if ( var.toString().isEmpty() )
return mFlags & FlagOptional;
return true;
}

View File

@ -206,6 +206,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSource;
else if ( sipCpp->type() == "sink" )
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
SIP_END
#endif
@ -445,6 +447,11 @@ class CORE_EXPORT QgsProcessingParameters
*/
static QgsRasterLayer *parameterAsRasterLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition to a raster output layer destination.
*/
static QString parameterAsRasterOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition to a vector layer.
*
@ -1219,6 +1226,28 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingParame
QgsProcessingParameterDefinition::LayerType mDataType = QgsProcessingParameterDefinition::TypeVectorAny;
};
/**
* \class QgsProcessingParameterRasterOutput
* \ingroup core
* A raster layer output parameter.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingParameterRasterOutput : public QgsProcessingParameterDefinition
{
public:
/**
* Constructor for QgsProcessingParameterRasterOutput.
*/
QgsProcessingParameterRasterOutput( const QString &name, const QString &description = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
QString type() const override { return QStringLiteral( "rasterOut" ); }
bool isDestination() const override { return true; }
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
};
#endif // QGSPROCESSINGPARAMETERS_H

View File

@ -216,6 +216,7 @@ class TestQgsProcessing: public QObject
void parameterField();
void parameterFeatureSource();
void parameterFeatureSink();
void parameterRasterOut();
void checkParamValues();
void combineLayerExtent();
void processingFeatureSource();
@ -2357,6 +2358,48 @@ void TestQgsProcessing::parameterFeatureSink()
}
void TestQgsProcessing::parameterRasterOut()
{
// setup a context
QgsProject p;
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
QgsProcessingContext context;
context.setProject( &p );
// not optional!
std::unique_ptr< QgsProcessingParameterRasterOutput > def( new QgsProcessingParameterRasterOutput( "non_optional", QString(), QString(), false ) );
QVERIFY( !def->checkValueIsAcceptable( false ) );
QVERIFY( !def->checkValueIsAcceptable( true ) );
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
QVERIFY( !def->checkValueIsAcceptable( "" ) );
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
// should be OK with or without context - it's an output layer!
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif", &context ) );
QVariantMap params;
params.insert( "non_optional", "test.tif" );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );
// optional
def.reset( new QgsProcessingParameterRasterOutput( "optional", QString(), QString( "default.tif" ), true ) );
QVERIFY( !def->checkValueIsAcceptable( false ) );
QVERIFY( !def->checkValueIsAcceptable( true ) );
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
QVERIFY( def->checkValueIsAcceptable( "" ) );
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
params.insert( "optional", QVariant() );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context ), QStringLiteral( "default.tif" ) );
}
void TestQgsProcessing::checkParamValues()
{
DummyAlgorithm a( "asd" );