Skip to content

Commit 60ea095

Browse files
committed
Port calculation of iterating destination to c++
1 parent 40cae29 commit 60ea095

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

python/core/processing/qgsprocessingutils.sip

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ class QgsProcessingUtils
126126
:rtype: QgsRectangle
127127
%End
128128

129+
static QVariant generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context );
130+
%Docstring
131+
Converts an ``input`` parameter value for use in source iterating mode, where one individual sink
132+
is created per input feature.
133+
The ``id`` parameter represents the unique ID for this output, which is embedded into the resulting
134+
parameter value.
135+
:rtype: QVariant
136+
%End
137+
129138
};
130139

131140

src/core/processing/qgsprocessingutils.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgsvectorlayerexporter.h"
2424
#include "qgsvectorfilewriter.h"
2525
#include "qgsmemoryproviderutils.h"
26+
#include "qgsprocessingparameters.h"
2627

2728
QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
2829
{
@@ -365,6 +366,40 @@ QgsRectangle QgsProcessingUtils::combineLayerExtents( const QList<QgsMapLayer *>
365366
return extent;
366367
}
367368

369+
QVariant QgsProcessingUtils::generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context )
370+
{
371+
if ( !input.isValid() )
372+
return QStringLiteral( "memory:%1" ).arg( id.toString() );
373+
374+
if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
375+
{
376+
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( input );
377+
QVariant newSink = generateIteratingDestination( fromVar.sink, id, context );
378+
fromVar.sink = QgsProperty::fromValue( newSink );
379+
return fromVar;
380+
}
381+
else if ( input.canConvert<QgsProperty>() )
382+
{
383+
QString res = input.value< QgsProperty>().valueAsString( context.expressionContext() );
384+
return generateIteratingDestination( res, id, context );
385+
}
386+
else
387+
{
388+
QString res = input.toString();
389+
if ( res.startsWith( QStringLiteral( "memory:" ) ) )
390+
{
391+
return res + '_' + id.toString();
392+
}
393+
else
394+
{
395+
// assume a filename type output for now
396+
// TODO - uris?
397+
int lastIndex = res.lastIndexOf( '.' );
398+
return res.left( lastIndex ) + '_' + id.toString() + res.mid( lastIndex );
399+
}
400+
}
401+
}
402+
368403

369404
//
370405
// QgsProcessingFeatureSource

src/core/processing/qgsprocessingutils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ class CORE_EXPORT QgsProcessingUtils
161161
*/
162162
static QgsRectangle combineLayerExtents( const QList< QgsMapLayer *> layers, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
163163

164+
/**
165+
* Converts an \a input parameter value for use in source iterating mode, where one individual sink
166+
* is created per input feature.
167+
* The \a id parameter represents the unique ID for this output, which is embedded into the resulting
168+
* parameter value.
169+
*/
170+
static QVariant generateIteratingDestination( const QVariant &input, const QVariant &id, QgsProcessingContext &context );
171+
164172
private:
165173

166174
static bool canUseLayer( const QgsRasterLayer *layer );

tests/src/core/testqgsprocessing.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ class TestQgsProcessing: public QObject
290290
void processingFeatureSink();
291291
void algorithmScope();
292292
void validateInputCrs();
293+
void generateIteratingDestination();
293294

294295
private:
295296

@@ -2714,5 +2715,32 @@ void TestQgsProcessing::validateInputCrs()
27142715
alg.runValidateInputCrsChecks();
27152716
}
27162717

2718+
void TestQgsProcessing::generateIteratingDestination()
2719+
{
2720+
QgsProcessingContext context;
2721+
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 1, context ).toString(), QStringLiteral( "memory:x_1" ) );
2722+
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 2, context ).toString(), QStringLiteral( "memory:x_2" ) );
2723+
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 1, context ).toString(), QStringLiteral( "ape_1.shp" ) );
2724+
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 2, context ).toString(), QStringLiteral( "ape_2.shp" ) );
2725+
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "/home/bif.o/ape.shp", 2, context ).toString(), QStringLiteral( "/home/bif.o/ape_2.shp" ) );
2726+
2727+
QgsProject p;
2728+
QgsProcessingOutputLayerDefinition def;
2729+
def.sink = QgsProperty::fromValue( "ape.shp" );
2730+
def.destinationProject = &p;
2731+
QVariant res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
2732+
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
2733+
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
2734+
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
2735+
QCOMPARE( fromVar.destinationProject, &p );
2736+
2737+
def.sink = QgsProperty::fromExpression( "'ape' || '.shp'" );
2738+
res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
2739+
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
2740+
fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
2741+
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
2742+
QCOMPARE( fromVar.destinationProject, &p );
2743+
}
2744+
27172745
QGSTEST_MAIN( TestQgsProcessing )
27182746
#include "testqgsprocessing.moc"

0 commit comments

Comments
 (0)