mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
[processing] Cleanup some layer/writer related handling
Ensure that layers created by QgsProcessingUtils::createFeatureSink can always be retrieved using QgsProcessingUtils::mapLayerFromString
This commit is contained in:
parent
cb23ebed65
commit
6aa10c6817
@ -130,8 +130,7 @@ class QgsProcessingUtils
|
|||||||
const QgsFields &fields,
|
const QgsFields &fields,
|
||||||
QgsWkbTypes::Type geometryType,
|
QgsWkbTypes::Type geometryType,
|
||||||
const QgsCoordinateReferenceSystem &crs,
|
const QgsCoordinateReferenceSystem &crs,
|
||||||
QgsProcessingContext &context,
|
QgsProcessingContext &context ) /PyName=createFeatureSink/;
|
||||||
QgsVectorLayer **outputLayer /Out/ ) /PyName=createFeatureSink/;
|
|
||||||
%Docstring
|
%Docstring
|
||||||
Creates a feature sink ready for adding features. The ``destination`` specifies a destination
|
Creates a feature sink ready for adding features. The ``destination`` specifies a destination
|
||||||
URI for the resultant layer. It may be updated in place to reflect the actual destination
|
URI for the resultant layer. It may be updated in place to reflect the actual destination
|
||||||
@ -142,7 +141,7 @@ class QgsProcessingUtils
|
|||||||
If the ``encoding`` is not specified, the default encoding from the ``context`` will be used.
|
If the ``encoding`` is not specified, the default encoding from the ``context`` will be used.
|
||||||
|
|
||||||
If a layer is created for the feature sink, the layer will automatically be added to the ``context``'s
|
If a layer is created for the feature sink, the layer will automatically be added to the ``context``'s
|
||||||
temporary layer store, and the ``outputLayer`` argument updated to point at this newly created layer.
|
temporary layer store.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ class VectorSplit(GeoAlgorithm):
|
|||||||
for current, i in enumerate(uniqueValues):
|
for current, i in enumerate(uniqueValues):
|
||||||
fName = u'{0}_{1}.shp'.format(baseName, str(i).strip())
|
fName = u'{0}_{1}.shp'.format(baseName, str(i).strip())
|
||||||
|
|
||||||
writer, dest, _layer = QgsProcessingUtils.createFeatureSink(fName, None, fields, geomType, crs, context)
|
writer, dest = QgsProcessingUtils.createFeatureSink(fName, None, fields, geomType, crs, context)
|
||||||
for f in QgsProcessingUtils.getFeatures(layer, context):
|
for f in QgsProcessingUtils.getFeatures(layer, context):
|
||||||
if f[fieldName] == i:
|
if f[fieldName] == i:
|
||||||
writer.addFeature(f)
|
writer.addFeature(f)
|
||||||
|
@ -10,8 +10,8 @@ from qgis.core import QgsFeature, QgsField, QgsProcessingUtils
|
|||||||
layer = QgsProcessingUtils.mapLayerFromString(input, context)
|
layer = QgsProcessingUtils.mapLayerFromString(input, context)
|
||||||
fields = layer.fields()
|
fields = layer.fields()
|
||||||
fields.append(QgsField('UNIQ_COUNT', QVariant.Int))
|
fields.append(QgsField('UNIQ_COUNT', QVariant.Int))
|
||||||
writer, writer_dest, writer_layer = QgsProcessingUtils.createFeatureSink(N_unique_values, None, fields, layer.wkbType(), layer.crs(),
|
writer, writer_dest = QgsProcessingUtils.createFeatureSink(N_unique_values, None, fields, layer.wkbType(), layer.crs(),
|
||||||
context)
|
context)
|
||||||
|
|
||||||
class_field_index = layer.fields().lookupField(class_field)
|
class_field_index = layer.fields().lookupField(class_field)
|
||||||
value_field_index = layer.fields().lookupField(value_field)
|
value_field_index = layer.fields().lookupField(value_field)
|
||||||
|
@ -385,8 +385,7 @@ class OutputVector(Output):
|
|||||||
settings = QgsSettings()
|
settings = QgsSettings()
|
||||||
self.encoding = settings.value('/Processing/encoding', 'System', str)
|
self.encoding = settings.value('/Processing/encoding', 'System', str)
|
||||||
|
|
||||||
w, w_dest, w_layer = QgsProcessingUtils.createFeatureSink(self.value, self.encoding, fields, geomType, crs, context)
|
w, w_dest = QgsProcessingUtils.createFeatureSink(self.value, self.encoding, fields, geomType, crs, context)
|
||||||
self.layer = w_layer
|
|
||||||
self.value = w_dest
|
self.value = w_dest
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
@ -61,11 +61,10 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
|
|||||||
continue
|
continue
|
||||||
if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
|
if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
|
||||||
try:
|
try:
|
||||||
if hasattr(out, "layer") and out.layer is not None:
|
layer = QgsProcessingUtils.mapLayerFromString(out.value, context)
|
||||||
out.layer.setName(out.description)
|
if layer:
|
||||||
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(out.layer))
|
layer.setName(out.description)
|
||||||
# temporary hack to work around mutable outputs
|
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
|
||||||
out.layer = None
|
|
||||||
else:
|
else:
|
||||||
if ProcessingConfig.getSetting(
|
if ProcessingConfig.getSetting(
|
||||||
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
|
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
|
||||||
|
@ -8,7 +8,7 @@ from qgis.core import QgsWkbTypes, QgsProcessingUtils
|
|||||||
layer = QgsProcessingUtils.mapLayerFromString(INPUT_LAYER, context)
|
layer = QgsProcessingUtils.mapLayerFromString(INPUT_LAYER, context)
|
||||||
fields = layer.fields()
|
fields = layer.fields()
|
||||||
|
|
||||||
writer, writer_dest, writer_layer = QgsProcessingUtils.createFeatureSink(OUTPUT_LAYER, 'utf-8', fields, QgsWkbTypes.Point, layer.crs(),
|
writer, writer_dest = QgsProcessingUtils.createFeatureSink(OUTPUT_LAYER, 'utf-8', fields, QgsWkbTypes.Point, layer.crs(),
|
||||||
context)
|
context)
|
||||||
|
|
||||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||||
|
@ -328,12 +328,10 @@ void parseDestinationString( QString &destination, QString &providerKey, QString
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QgsVectorLayer *&outputLayer )
|
QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context )
|
||||||
{
|
{
|
||||||
outputLayer = nullptr;
|
|
||||||
QgsVectorLayer *layer = nullptr;
|
|
||||||
|
|
||||||
QString destEncoding = encoding;
|
QString destEncoding = encoding;
|
||||||
|
QgsVectorLayer *layer = nullptr;
|
||||||
if ( destEncoding.isEmpty() )
|
if ( destEncoding.isEmpty() )
|
||||||
{
|
{
|
||||||
// no destination encoding specified, use default
|
// no destination encoding specified, use default
|
||||||
@ -344,8 +342,6 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
|
|||||||
{
|
{
|
||||||
// memory provider cannot be used with QgsVectorLayerImport - so create layer manually
|
// memory provider cannot be used with QgsVectorLayerImport - so create layer manually
|
||||||
layer = QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs );
|
layer = QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs );
|
||||||
if ( layer && layer->isValid() )
|
|
||||||
destination = layer->id();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -376,6 +372,7 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use destination string as layer name (eg "postgis:..." )
|
||||||
layer = new QgsVectorLayer( uri, destination, providerKey );
|
layer = new QgsVectorLayer( uri, destination, providerKey );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,19 +386,18 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, con
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update destination to layer ID
|
||||||
|
destination = layer->id();
|
||||||
|
|
||||||
context.temporaryLayerStore()->addMapLayer( layer );
|
context.temporaryLayerStore()->addMapLayer( layer );
|
||||||
|
|
||||||
outputLayer = layer;
|
|
||||||
// this is a factory, so we need to return a proxy
|
// this is a factory, so we need to return a proxy
|
||||||
return new QgsProxyFeatureSink( layer->dataProvider() );
|
return new QgsProxyFeatureSink( layer->dataProvider() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QgsVectorLayer **outputLayer )
|
void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context )
|
||||||
{
|
{
|
||||||
QgsVectorLayer *layer = nullptr;
|
*sink = createFeatureSink( destination, encoding, fields, geometryType, crs, context );
|
||||||
*sink = createFeatureSink( destination, encoding, fields, geometryType, crs, context, layer );
|
|
||||||
if ( outputLayer )
|
|
||||||
*outputLayer = layer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ class CORE_EXPORT QgsProcessingUtils
|
|||||||
* If the \a encoding is not specified, the default encoding from the \a context will be used.
|
* If the \a encoding is not specified, the default encoding from the \a context will be used.
|
||||||
*
|
*
|
||||||
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
|
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
|
||||||
* temporary layer store, and the \a outputLayer argument updated to point at this newly created layer.
|
* temporary layer store.
|
||||||
*
|
*
|
||||||
* The caller takes responsibility for deleting the returned sink.
|
* The caller takes responsibility for deleting the returned sink.
|
||||||
*/
|
*/
|
||||||
@ -152,8 +152,7 @@ class CORE_EXPORT QgsProcessingUtils
|
|||||||
const QgsFields &fields,
|
const QgsFields &fields,
|
||||||
QgsWkbTypes::Type geometryType,
|
QgsWkbTypes::Type geometryType,
|
||||||
const QgsCoordinateReferenceSystem &crs,
|
const QgsCoordinateReferenceSystem &crs,
|
||||||
QgsProcessingContext &context,
|
QgsProcessingContext &context ) SIP_FACTORY;
|
||||||
QgsVectorLayer *&outputLayer ) SIP_FACTORY;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,7 +165,7 @@ class CORE_EXPORT QgsProcessingUtils
|
|||||||
* If the \a encoding is not specified, the default encoding from the \a context will be used.
|
* If the \a encoding is not specified, the default encoding from the \a context will be used.
|
||||||
*
|
*
|
||||||
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
|
* If a layer is created for the feature sink, the layer will automatically be added to the \a context's
|
||||||
* temporary layer store, and the \a outputLayer argument updated to point at this newly created layer.
|
* temporary layer store.
|
||||||
*
|
*
|
||||||
* \note this version of the createFeatureSink() function has an API designed around use from the
|
* \note this version of the createFeatureSink() function has an API designed around use from the
|
||||||
* SIP bindings. c++ code should call the other createFeatureSink() version.
|
* SIP bindings. c++ code should call the other createFeatureSink() version.
|
||||||
@ -179,8 +178,7 @@ class CORE_EXPORT QgsProcessingUtils
|
|||||||
const QgsFields &fields,
|
const QgsFields &fields,
|
||||||
QgsWkbTypes::Type geometryType,
|
QgsWkbTypes::Type geometryType,
|
||||||
const QgsCoordinateReferenceSystem &crs,
|
const QgsCoordinateReferenceSystem &crs,
|
||||||
QgsProcessingContext &context,
|
QgsProcessingContext &context ) SIP_PYNAME( createFeatureSink );
|
||||||
QgsVectorLayer **outputLayer SIP_OUT ) SIP_PYNAME( createFeatureSink );
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -748,8 +748,9 @@ void TestQgsProcessing::createFeatureSink()
|
|||||||
QgsVectorLayer *layer = nullptr;
|
QgsVectorLayer *layer = nullptr;
|
||||||
|
|
||||||
// should create a memory layer
|
// should create a memory layer
|
||||||
QgsFeatureSink *sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context, layer );
|
QgsFeatureSink *sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context );
|
||||||
QVERIFY( sink );
|
QVERIFY( sink );
|
||||||
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
||||||
QVERIFY( layer );
|
QVERIFY( layer );
|
||||||
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
||||||
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
||||||
@ -765,8 +766,9 @@ void TestQgsProcessing::createFeatureSink()
|
|||||||
|
|
||||||
// specific memory layer output
|
// specific memory layer output
|
||||||
destination = QStringLiteral( "memory:mylayer" );
|
destination = QStringLiteral( "memory:mylayer" );
|
||||||
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context, layer );
|
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem(), context );
|
||||||
QVERIFY( sink );
|
QVERIFY( sink );
|
||||||
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
||||||
QVERIFY( layer );
|
QVERIFY( layer );
|
||||||
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
||||||
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
||||||
@ -784,8 +786,9 @@ void TestQgsProcessing::createFeatureSink()
|
|||||||
destination = QStringLiteral( "memory:mylayer" );
|
destination = QStringLiteral( "memory:mylayer" );
|
||||||
QgsFields fields;
|
QgsFields fields;
|
||||||
fields.append( QgsField( QStringLiteral( "my_field" ), QVariant::String, QString(), 100 ) );
|
fields.append( QgsField( QStringLiteral( "my_field" ), QVariant::String, QString(), 100 ) );
|
||||||
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::PointZM, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
|
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::PointZM, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
|
||||||
QVERIFY( sink );
|
QVERIFY( sink );
|
||||||
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
||||||
QVERIFY( layer );
|
QVERIFY( layer );
|
||||||
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink )->destinationSink(), layer->dataProvider() );
|
||||||
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
||||||
@ -807,16 +810,15 @@ void TestQgsProcessing::createFeatureSink()
|
|||||||
// non memory layer output
|
// non memory layer output
|
||||||
destination = QDir::tempPath() + "/create_feature_sink.tab";
|
destination = QDir::tempPath() + "/create_feature_sink.tab";
|
||||||
QString prevDest = destination;
|
QString prevDest = destination;
|
||||||
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
|
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
|
||||||
QVERIFY( sink );
|
QVERIFY( sink );
|
||||||
f = QgsFeature( fields );
|
f = QgsFeature( fields );
|
||||||
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 0 1, 1 1, 1 0, 0 0 ))" ) ) );
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 0 1, 1 1, 1 0, 0 0 ))" ) ) );
|
||||||
f.setAttributes( QgsAttributes() << "val" );
|
f.setAttributes( QgsAttributes() << "val" );
|
||||||
QVERIFY( sink->addFeature( f ) );
|
QVERIFY( sink->addFeature( f ) );
|
||||||
QVERIFY( !layer );
|
|
||||||
QCOMPARE( destination, prevDest );
|
QCOMPARE( destination, prevDest );
|
||||||
delete sink;
|
delete sink;
|
||||||
layer = new QgsVectorLayer( destination, "test_layer", "ogr" );
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
||||||
QVERIFY( layer->isValid() );
|
QVERIFY( layer->isValid() );
|
||||||
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
||||||
QCOMPARE( layer->fields().size(), 1 );
|
QCOMPARE( layer->fields().size(), 1 );
|
||||||
@ -829,14 +831,14 @@ void TestQgsProcessing::createFeatureSink()
|
|||||||
// no extension, should default to shp
|
// no extension, should default to shp
|
||||||
destination = QDir::tempPath() + "/create_feature_sink2";
|
destination = QDir::tempPath() + "/create_feature_sink2";
|
||||||
prevDest = QDir::tempPath() + "/create_feature_sink2.shp";
|
prevDest = QDir::tempPath() + "/create_feature_sink2.shp";
|
||||||
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Point25D, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context, layer );
|
sink = QgsProcessingUtils::createFeatureSink( destination, QString(), fields, QgsWkbTypes::Point25D, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ), context );
|
||||||
QVERIFY( sink );
|
QVERIFY( sink );
|
||||||
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PointZ(1 2 3)" ) ) );
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PointZ(1 2 3)" ) ) );
|
||||||
QVERIFY( sink->addFeature( f ) );
|
QVERIFY( sink->addFeature( f ) );
|
||||||
QVERIFY( !layer );
|
QVERIFY( !layer );
|
||||||
QCOMPARE( destination, prevDest );
|
QCOMPARE( destination, prevDest );
|
||||||
delete sink;
|
delete sink;
|
||||||
layer = new QgsVectorLayer( destination, "test_layer", "ogr" );
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
||||||
QCOMPARE( layer->wkbType(), QgsWkbTypes::Point25D );
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::Point25D );
|
||||||
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
||||||
QCOMPARE( layer->fields().size(), 1 );
|
QCOMPARE( layer->fields().size(), 1 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user