Skip to content

Commit

Permalink
Port calculation of iterating destination to c++
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 12, 2017
1 parent 40cae29 commit 60ea095
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
9 changes: 9 additions & 0 deletions python/core/processing/qgsprocessingutils.sip
Expand Up @@ -126,6 +126,15 @@ class QgsProcessingUtils
:rtype: QgsRectangle
%End

static QVariant generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context );
%Docstring
Converts an ``input`` parameter value for use in source iterating mode, where one individual sink
is created per input feature.
The ``id`` parameter represents the unique ID for this output, which is embedded into the resulting
parameter value.
:rtype: QVariant
%End

};


Expand Down
35 changes: 35 additions & 0 deletions src/core/processing/qgsprocessingutils.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgsvectorlayerexporter.h"
#include "qgsvectorfilewriter.h"
#include "qgsmemoryproviderutils.h"
#include "qgsprocessingparameters.h"

QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
{
Expand Down Expand Up @@ -365,6 +366,40 @@ QgsRectangle QgsProcessingUtils::combineLayerExtents( const QList<QgsMapLayer *>
return extent;
}

QVariant QgsProcessingUtils::generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context )
{
if ( !input.isValid() )
return QStringLiteral( "memory:%1" ).arg( id.toString() );

if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
{
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( input );
QVariant newSink = generateIteratingDestination( fromVar.sink, id, context );
fromVar.sink = QgsProperty::fromValue( newSink );
return fromVar;
}
else if ( input.canConvert<QgsProperty>() )
{
QString res = input.value< QgsProperty>().valueAsString( context.expressionContext() );
return generateIteratingDestination( res, id, context );
}
else
{
QString res = input.toString();
if ( res.startsWith( QStringLiteral( "memory:" ) ) )
{
return res + '_' + id.toString();
}
else
{
// assume a filename type output for now
// TODO - uris?
int lastIndex = res.lastIndexOf( '.' );
return res.left( lastIndex ) + '_' + id.toString() + res.mid( lastIndex );
}
}
}


//
// QgsProcessingFeatureSource
Expand Down
8 changes: 8 additions & 0 deletions src/core/processing/qgsprocessingutils.h
Expand Up @@ -161,6 +161,14 @@ class CORE_EXPORT QgsProcessingUtils
*/
static QgsRectangle combineLayerExtents( const QList< QgsMapLayer *> layers, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );

/**
* Converts an \a input parameter value for use in source iterating mode, where one individual sink
* is created per input feature.
* The \a id parameter represents the unique ID for this output, which is embedded into the resulting
* parameter value.
*/
static QVariant generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context );

private:

static bool canUseLayer( const QgsRasterLayer *layer );
Expand Down
28 changes: 28 additions & 0 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -290,6 +290,7 @@ class TestQgsProcessing: public QObject
void processingFeatureSink();
void algorithmScope();
void validateInputCrs();
void generateIteratingDestination();

private:

Expand Down Expand Up @@ -2714,5 +2715,32 @@ void TestQgsProcessing::validateInputCrs()
alg.runValidateInputCrsChecks();
}

void TestQgsProcessing::generateIteratingDestination()
{
QgsProcessingContext context;
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 1, context ).toString(), QStringLiteral( "memory:x_1" ) );
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 2, context ).toString(), QStringLiteral( "memory:x_2" ) );
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 1, context ).toString(), QStringLiteral( "ape_1.shp" ) );
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 2, context ).toString(), QStringLiteral( "ape_2.shp" ) );
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "/home/bif.o/ape.shp", 2, context ).toString(), QStringLiteral( "/home/bif.o/ape_2.shp" ) );

QgsProject p;
QgsProcessingOutputLayerDefinition def;
def.sink = QgsProperty::fromValue( "ape.shp" );
def.destinationProject = &p;
QVariant res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
QCOMPARE( fromVar.destinationProject, &p );

def.sink = QgsProperty::fromExpression( "'ape' || '.shp'" );
res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
QCOMPARE( fromVar.destinationProject, &p );
}

QGSTEST_MAIN( TestQgsProcessing )
#include "testqgsprocessing.moc"

0 comments on commit 60ea095

Please sign in to comment.