Skip to content

Commit 6aa10c6

Browse files
committed
[processing] Cleanup some layer/writer related handling
Ensure that layers created by QgsProcessingUtils::createFeatureSink can always be retrieved using QgsProcessingUtils::mapLayerFromString
1 parent cb23ebe commit 6aa10c6

File tree

9 files changed

+33
-40
lines changed

9 files changed

+33
-40
lines changed

python/core/processing/qgsprocessingutils.sip

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ class QgsProcessingUtils
130130
const QgsFields &fields,
131131
QgsWkbTypes::Type geometryType,
132132
const QgsCoordinateReferenceSystem &crs,
133-
QgsProcessingContext &context,
134-
QgsVectorLayer **outputLayer /Out/ ) /PyName=createFeatureSink/;
133+
QgsProcessingContext &context ) /PyName=createFeatureSink/;
135134
%Docstring
136135
Creates a feature sink ready for adding features. The ``destination`` specifies a destination
137136
URI for the resultant layer. It may be updated in place to reflect the actual destination
@@ -142,7 +141,7 @@ class QgsProcessingUtils
142141
If the ``encoding`` is not specified, the default encoding from the ``context`` will be used.
143142

144143
If a layer is created for the feature sink, the layer will automatically be added to the ``context``'s
145-
temporary layer store, and the ``outputLayer`` argument updated to point at this newly created layer.
144+
temporary layer store.
146145

147146
.. note::
148147

python/plugins/processing/algs/qgis/VectorSplit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def processAlgorithm(self, context, feedback):
8686
for current, i in enumerate(uniqueValues):
8787
fName = u'{0}_{1}.shp'.format(baseName, str(i).strip())
8888

89-
writer, dest, _layer = QgsProcessingUtils.createFeatureSink(fName, None, fields, geomType, crs, context)
89+
writer, dest = QgsProcessingUtils.createFeatureSink(fName, None, fields, geomType, crs, context)
9090
for f in QgsProcessingUtils.getFeatures(layer, context):
9191
if f[fieldName] == i:
9292
writer.addFeature(f)

python/plugins/processing/algs/qgis/scripts/Number_of_unique_values_in_classes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
layer = QgsProcessingUtils.mapLayerFromString(input, context)
1111
fields = layer.fields()
1212
fields.append(QgsField('UNIQ_COUNT', QVariant.Int))
13-
writer, writer_dest, writer_layer = QgsProcessingUtils.createFeatureSink(N_unique_values, None, fields, layer.wkbType(), layer.crs(),
14-
context)
13+
writer, writer_dest = QgsProcessingUtils.createFeatureSink(N_unique_values, None, fields, layer.wkbType(), layer.crs(),
14+
context)
1515

1616
class_field_index = layer.fields().lookupField(class_field)
1717
value_field_index = layer.fields().lookupField(value_field)

python/plugins/processing/core/outputs.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,7 @@ def getVectorWriter(self, fields, geomType, crs, context):
385385
settings = QgsSettings()
386386
self.encoding = settings.value('/Processing/encoding', 'System', str)
387387

388-
w, w_dest, w_layer = QgsProcessingUtils.createFeatureSink(self.value, self.encoding, fields, geomType, crs, context)
389-
self.layer = w_layer
388+
w, w_dest = QgsProcessingUtils.createFeatureSink(self.value, self.encoding, fields, geomType, crs, context)
390389
self.value = w_dest
391390
return w
392391

python/plugins/processing/gui/Postprocessing.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,10 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
6161
continue
6262
if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
6363
try:
64-
if hasattr(out, "layer") and out.layer is not None:
65-
out.layer.setName(out.description)
66-
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(out.layer))
67-
# temporary hack to work around mutable outputs
68-
out.layer = None
64+
layer = QgsProcessingUtils.mapLayerFromString(out.value, context)
65+
if layer:
66+
layer.setName(out.description)
67+
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
6968
else:
7069
if ProcessingConfig.getSetting(
7170
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):

python/plugins/processing/tests/testdata/scripts/centroids.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
layer = QgsProcessingUtils.mapLayerFromString(INPUT_LAYER, context)
99
fields = layer.fields()
1010

11-
writer, writer_dest, writer_layer = QgsProcessingUtils.createFeatureSink(OUTPUT_LAYER, 'utf-8', fields, QgsWkbTypes.Point, layer.crs(),
11+
writer, writer_dest = QgsProcessingUtils.createFeatureSink(OUTPUT_LAYER, 'utf-8', fields, QgsWkbTypes.Point, layer.crs(),
1212
context)
1313

1414
features = QgsProcessingUtils.getFeatures(layer, context)

src/core/processing/qgsprocessingutils.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,10 @@ void parseDestinationString( QString &destination, QString &providerKey, QString
328328
}
329329
}
330330

331-
QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QgsVectorLayer *&outputLayer )
331+
QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context )
332332
{
333-
outputLayer = nullptr;
334-
QgsVectorLayer *layer = nullptr;
335-
336333
QString destEncoding = encoding;
334+
QgsVectorLayer *layer = nullptr;
337335
if ( destEncoding.isEmpty() )
338336
{
339337
// no destination encoding specified, use default
@@ -344,8 +342,6 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
344342
{
345343
// memory provider cannot be used with QgsVectorLayerImport - so create layer manually
346344
layer = QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs );
347-
if ( layer && layer->isValid() )
348-
destination = layer->id();
349345
}
350346
else
351347
{
@@ -376,6 +372,7 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
376372
return nullptr;
377373
}
378374

375+
// use destination string as layer name (eg "postgis:..." )
379376
layer = new QgsVectorLayer( uri, destination, providerKey );
380377
}
381378
}
@@ -389,19 +386,18 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
389386
return nullptr;
390387
}
391388

389+
// update destination to layer ID
390+
destination = layer->id();
391+
392392
context.temporaryLayerStore()->addMapLayer( layer );
393393

394-
outputLayer = layer;
395394
// this is a factory, so we need to return a proxy
396395
return new QgsProxyFeatureSink( layer->dataProvider() );
397396
}
398397

399-
void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QgsVectorLayer **outputLayer )
398+
void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context )
400399
{
401-
QgsVectorLayer *layer = nullptr;
402-
*sink = createFeatureSink( destination, encoding, fields, geometryType, crs, context, layer );
403-
if ( outputLayer )
404-
*outputLayer = layer;
400+
*sink = createFeatureSink( destination, encoding, fields, geometryType, crs, context );
405401
}
406402

407403

src/core/processing/qgsprocessingutils.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class CORE_EXPORT QgsProcessingUtils
141141
* If the \a encoding is not specified, the default encoding from the \a context will be used.
142142
*
143143
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
144-
* temporary layer store, and the \a outputLayer argument updated to point at this newly created layer.
144+
* temporary layer store.
145145
*
146146
* The caller takes responsibility for deleting the returned sink.
147147
*/
@@ -152,8 +152,7 @@ class CORE_EXPORT QgsProcessingUtils
152152
const QgsFields &fields,
153153
QgsWkbTypes::Type geometryType,
154154
const QgsCoordinateReferenceSystem &crs,
155-
QgsProcessingContext &context,
156-
QgsVectorLayer *&outputLayer ) SIP_FACTORY;
155+
QgsProcessingContext &context ) SIP_FACTORY;
157156
#endif
158157

159158
/**
@@ -166,7 +165,7 @@ class CORE_EXPORT QgsProcessingUtils
166165
* If the \a encoding is not specified, the default encoding from the \a context will be used.
167166
*
168167
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
169-
* temporary layer store, and the \a outputLayer argument updated to point at this newly created layer.
168+
* temporary layer store.
170169
*
171170
* \note this version of the createFeatureSink() function has an API designed around use from the
172171
* SIP bindings. c++ code should call the other createFeatureSink() version.
@@ -179,8 +178,7 @@ class CORE_EXPORT QgsProcessingUtils
179178
const QgsFields &fields,
180179
QgsWkbTypes::Type geometryType,
181180
const QgsCoordinateReferenceSystem &crs,
182-
QgsProcessingContext &context,
183-
QgsVectorLayer **outputLayer SIP_OUT ) SIP_PYNAME( createFeatureSink );
181+
QgsProcessingContext &context ) SIP_PYNAME( createFeatureSink );
184182

185183

186184
private:

tests/src/core/testqgsprocessing.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,9 @@ void TestQgsProcessing::createFeatureSink()
748748
QgsVectorLayer *layer = nullptr;
749749

750750
// should create a memory layer
751-
QgsFeatureSink *sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context, layer );
751+
QgsFeatureSink *sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context );
752752
QVERIFY( sink );
753+
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
753754
QVERIFY( layer );
754755
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
755756
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
@@ -765,8 +766,9 @@ void TestQgsProcessing::createFeatureSink()
765766

766767
// specific memory layer output
767768
destination = QStringLiteral( "memory:mylayer" );
768-
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context, layer );
769+
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context );
769770
QVERIFY( sink );
771+
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
770772
QVERIFY( layer );
771773
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
772774
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
@@ -784,8 +786,9 @@ void TestQgsProcessing::createFeatureSink()
784786
destination = QStringLiteral( "memory:mylayer" );
785787
QgsFields fields;
786788
fields.append( QgsField( QStringLiteral( "my_field" ), QVariant::String, QString(), 100 ) );
787-
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::PointZM, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
789+
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::PointZM, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
788790
QVERIFY( sink );
791+
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
789792
QVERIFY( layer );
790793
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
791794
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
@@ -807,16 +810,15 @@ void TestQgsProcessing::createFeatureSink()
807810
// non memory layer output
808811
destination = QDir::tempPath() + "/create_feature_sink.tab";
809812
QString prevDest = destination;
810-
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
813+
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
811814
QVERIFY( sink );
812815
f = QgsFeature( fields );
813816
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 0 1, 1 1, 1 0, 0 0 ))" ) ) );
814817
f.setAttributes( QgsAttributes() << "val" );
815818
QVERIFY( sink->addFeature( f ) );
816-
QVERIFY( !layer );
817819
QCOMPARE( destination, prevDest );
818820
delete sink;
819-
layer = new QgsVectorLayer( destination, "test_layer", "ogr" );
821+
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
820822
QVERIFY( layer->isValid() );
821823
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
822824
QCOMPARE( layer->fields().size(), 1 );
@@ -829,14 +831,14 @@ void TestQgsProcessing::createFeatureSink()
829831
// no extension, should default to shp
830832
destination = QDir::tempPath() + "/create_feature_sink2";
831833
prevDest = QDir::tempPath() + "/create_feature_sink2.shp";
832-
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Point25D, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
834+
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Point25D, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
833835
QVERIFY( sink );
834836
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PointZ(1 2 3)" ) ) );
835837
QVERIFY( sink->addFeature( f ) );
836838
QVERIFY( !layer );
837839
QCOMPARE( destination, prevDest );
838840
delete sink;
839-
layer = new QgsVectorLayer( destination, "test_layer", "ogr" );
841+
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
840842
QCOMPARE( layer->wkbType(), QgsWkbTypes::Point25D );
841843
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
842844
QCOMPARE( layer->fields().size(), 1 );

0 commit comments

Comments
 (0)