Skip to content

Commit

Permalink
Add file based and HTML outputs to c++ API
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 6, 2017
1 parent 74ffdb1 commit 1f0a3d9
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 0 deletions.
6 changes: 6 additions & 0 deletions python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -374,6 +374,12 @@ class QgsProcessingAlgorithm
:rtype: str
%End

QString parameterAsFileOutput( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a file based output 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.
Expand Down
21 changes: 21 additions & 0 deletions python/core/processing/qgsprocessingoutputs.sip
Expand Up @@ -32,6 +32,8 @@ class QgsProcessingOutputDefinition
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == "outputRaster" )
sipType = sipType_QgsProcessingOutputRasterLayer;
else if ( sipCpp->type() == "outputHtml" )
sipType = sipType_QgsProcessingOutputHtml;
%End
public:

Expand Down Expand Up @@ -140,6 +142,25 @@ class QgsProcessingOutputRasterLayer : QgsProcessingOutputDefinition
virtual QString type() const;
};

class QgsProcessingOutputHtml : QgsProcessingOutputDefinition
{
%Docstring
A HTML file output for processing algorithms.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingoutputs.h"
%End
public:

QgsProcessingOutputHtml( const QString &name, const QString &description = QString() );
%Docstring
Constructor for QgsProcessingOutputHtml.
%End

virtual QString type() const;
};



Expand Down
48 changes: 48 additions & 0 deletions python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -173,6 +173,8 @@ class QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
else if ( sipCpp->type() == "fileOut" )
sipType = sipType_QgsProcessingParameterFileOutput;
%End
public:

Expand Down Expand Up @@ -427,6 +429,12 @@ class QgsProcessingParameters
:rtype: str
%End

static QString parameterAsFileOutput( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a file based output 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.
Expand Down Expand Up @@ -1254,6 +1262,46 @@ class QgsProcessingParameterRasterOutput : QgsProcessingParameterDefinition

};

class QgsProcessingParameterFileOutput : QgsProcessingParameterDefinition
{
%Docstring
A generic file based output parameter.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterFileOutput( const QString &name, const QString &description = QString(),
const QString &fileFilter = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterFileOutput.
%End

virtual QString type() const;
virtual bool isDestination() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;


QString fileFilter() const;
%Docstring
Returns the file filter string for files compatible with this output.
.. seealso:: setFileFilter()
:rtype: str
%End

void setFileFilter( const QString &filter );
%Docstring
Sets the file ``filter`` string for files compatible with this output.
.. seealso:: fileFilter()
%End

};



/************************************************************************
Expand Down
5 changes: 5 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -359,6 +359,11 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
QString parameterAsRasterOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;

/**
* Evaluates the parameter with matching \a name to a file based output destination.
*/
QString parameterAsFileOutput( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;

/**
* Evaluates the parameter with matching \a name to a vector layer.
*
Expand Down
6 changes: 6 additions & 0 deletions src/core/processing/qgsprocessingoutputs.cpp
Expand Up @@ -42,3 +42,9 @@ void QgsProcessingOutputVectorLayer::setDataType( QgsProcessingParameterDefiniti
QgsProcessingOutputRasterLayer::QgsProcessingOutputRasterLayer( const QString &name, const QString &description )
: QgsProcessingOutputDefinition( name, description )
{}

QgsProcessingOutputHtml::QgsProcessingOutputHtml( const QString &name, const QString &description )
: QgsProcessingOutputDefinition( name, description )
{

}
19 changes: 19 additions & 0 deletions src/core/processing/qgsprocessingoutputs.h
Expand Up @@ -47,6 +47,8 @@ class CORE_EXPORT QgsProcessingOutputDefinition
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == "outputRaster" )
sipType = sipType_QgsProcessingOutputRasterLayer;
else if ( sipCpp->type() == "outputHtml" )
sipType = sipType_QgsProcessingOutputHtml;
SIP_END
#endif

Expand Down Expand Up @@ -157,6 +159,23 @@ class CORE_EXPORT QgsProcessingOutputRasterLayer : public QgsProcessingOutputDef
QString type() const override { return QStringLiteral( "outputRaster" ); }
};

/**
* \class QgsProcessingOutputHtml
* \ingroup core
* A HTML file output for processing algorithms.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingOutputHtml : public QgsProcessingOutputDefinition
{
public:

/**
* Constructor for QgsProcessingOutputHtml.
*/
QgsProcessingOutputHtml( const QString &name, const QString &description = QString() );

QString type() const override { return QStringLiteral( "outputHtml" ); }
};

#endif // QGSPROCESSINGOUTPUTS_H

Expand Down
78 changes: 78 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -378,6 +378,39 @@ QString QgsProcessingParameters::parameterAsRasterOutputLayer( const QgsProcessi
return dest;
}

QString QgsProcessingParameters::parameterAsFileOutput( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
QVariant val;
if ( definition )
{
val = parameters.value( definition->name() );
}

if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
{
// input is a QgsProcessingOutputLayerDefinition - get extra properties from it
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
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();
}

return dest;
}

QgsVectorLayer *QgsProcessingParameters::parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
return qobject_cast< QgsVectorLayer *>( parameterAsLayer( definition, parameters, context ) );
Expand Down Expand Up @@ -1513,3 +1546,48 @@ bool QgsProcessingParameterRasterOutput::checkValueIsAcceptable( const QVariant
return true;
}


QgsProcessingParameterFileOutput::QgsProcessingParameterFileOutput( const QString &name, const QString &description, const QString &fileFilter, const QVariant &defaultValue, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mFileFilter( fileFilter.isEmpty() ? QObject::tr( "All files (*.*)" ) : fileFilter )
{

}

bool QgsProcessingParameterFileOutput::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;

// possible enhancement - check that value is compatible with file filter?

return true;
}

QString QgsProcessingParameterFileOutput::fileFilter() const
{
return mFileFilter;
}

void QgsProcessingParameterFileOutput::setFileFilter( const QString &fileFilter )
{
mFileFilter = fileFilter;
}
46 changes: 46 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -208,6 +208,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
else if ( sipCpp->type() == "fileOut" )
sipType = sipType_QgsProcessingParameterFileOutput;
SIP_END
#endif

Expand Down Expand Up @@ -452,6 +454,11 @@ class CORE_EXPORT QgsProcessingParameters
*/
static QString parameterAsRasterOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a definition to a file based output destination.
*/
static QString parameterAsFileOutput( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a definition to a vector layer.
*
Expand Down Expand Up @@ -1248,6 +1255,45 @@ class CORE_EXPORT QgsProcessingParameterRasterOutput : public QgsProcessingParam
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
};

/**
* \class QgsProcessingParameterFileOutput
* \ingroup core
* A generic file based output parameter.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingParameterFileOutput : public QgsProcessingParameterDefinition
{
public:

/**
* Constructor for QgsProcessingParameterFileOutput.
*/
QgsProcessingParameterFileOutput( const QString &name, const QString &description = QString(),
const QString &fileFilter = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );

QString type() const override { return QStringLiteral( "fileOut" ); }
bool isDestination() const override { return true; }
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;

/**
* Returns the file filter string for files compatible with this output.
* \see setFileFilter()
*/
QString fileFilter() const;

/**
* Sets the file \a filter string for files compatible with this output.
* \see fileFilter()
*/
void setFileFilter( const QString &filter );

private:

QString mFileFilter;
};

#endif // QGSPROCESSINGPARAMETERS_H


50 changes: 50 additions & 0 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -217,6 +217,7 @@ class TestQgsProcessing: public QObject
void parameterFeatureSource();
void parameterFeatureSink();
void parameterRasterOut();
void parameterFileOut();
void checkParamValues();
void combineLayerExtent();
void processingFeatureSource();
Expand Down Expand Up @@ -2383,6 +2384,8 @@ void TestQgsProcessing::parameterRasterOut()
QVariantMap params;
params.insert( "non_optional", "test.tif" );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );
params.insert( "non_optional", QgsProcessingOutputLayerDefinition( "test.tif" ) );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );

// optional
def.reset( new QgsProcessingParameterRasterOutput( "optional", QString(), QString( "default.tif" ), true ) );
Expand All @@ -2400,6 +2403,53 @@ void TestQgsProcessing::parameterRasterOut()

}

void TestQgsProcessing::parameterFileOut()
{
// setup a context
QgsProject p;
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
QgsProcessingContext context;
context.setProject( &p );

// not optional!
std::unique_ptr< QgsProcessingParameterFileOutput > def( new QgsProcessingParameterFileOutput( "non_optional", QString(), QStringLiteral( "BMP files (*.bmp)" ), QString(), false ) );
QCOMPARE( def->fileFilter(), QStringLiteral( "BMP files (*.bmp)" ) );
def->setFileFilter( QStringLiteral( "PCX files (*.pcx)" ) );
QCOMPARE( def->fileFilter(), QStringLiteral( "PCX files (*.pcx)" ) );

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 file!
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.txt" ) );
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.txt", &context ) );

QVariantMap params;
params.insert( "non_optional", "test.txt" );
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "test.txt" ) );
params.insert( "non_optional", QgsProcessingOutputLayerDefinition( "test.txt" ) );
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "test.txt" ) );

// optional
def.reset( new QgsProcessingParameterFileOutput( "optional", QString(), QString(), QString( "default.txt" ), 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.txt" ) );
QVERIFY( def->checkValueIsAcceptable( "" ) );
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );

params.insert( "optional", QVariant() );
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "default.txt" ) );
}

void TestQgsProcessing::checkParamValues()
{
DummyAlgorithm a( "asd" );
Expand Down

0 comments on commit 1f0a3d9

Please sign in to comment.