mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Restore ability to save outputs directly to Spatialite/PostGIS providers
This commit is contained in:
parent
5e92c0dbf4
commit
607fed8c48
@ -1206,6 +1206,13 @@ class QgsProcessingParameterFeatureSink : QgsProcessingParameterDefinition
|
||||
:rtype: QgsProcessingParameterDefinition.LayerType
|
||||
%End
|
||||
|
||||
bool hasGeometry() const;
|
||||
%Docstring
|
||||
Returns true if sink is likely to include geometries. In cases were presence of geometry
|
||||
cannot be reliably determined in advance, this method will default to returning true.
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setDataType( QgsProcessingParameterDefinition::LayerType type );
|
||||
%Docstring
|
||||
Sets the layer ``type`` for the sinks associated with the parameter.
|
||||
|
@ -37,7 +37,7 @@ from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog
|
||||
from qgis.core import (QgsDataSourceUri,
|
||||
QgsCredentials,
|
||||
QgsSettings,
|
||||
QgsProcessingOutputVectorLayer,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingFeatureSinkDefinition)
|
||||
from processing.core.ProcessingConfig import ProcessingConfig
|
||||
from processing.core.outputs import OutputVector
|
||||
@ -67,7 +67,7 @@ class DestinationSelectionPanel(BASE, WIDGET):
|
||||
self.encoding = settings.value('/Processing/encoding', 'System')
|
||||
|
||||
if hasattr(self.leText, 'setPlaceholderText'):
|
||||
if isinstance(self.parameter, QgsProcessingOutputVectorLayer) \
|
||||
if isinstance(self.parameter, QgsProcessingParameterFeatureSink) \
|
||||
and alg.provider().supportsNonFileBasedOutput():
|
||||
# use memory layers for temporary files if supported
|
||||
self.leText.setPlaceholderText(self.SAVE_TO_TEMP_LAYER)
|
||||
@ -82,7 +82,7 @@ class DestinationSelectionPanel(BASE, WIDGET):
|
||||
else:
|
||||
popupMenu = QMenu()
|
||||
|
||||
if isinstance(self.parameter, QgsProcessingOutputVectorLayer) \
|
||||
if isinstance(self.parameter, QgsProcessingParameterFeatureSink) \
|
||||
and self.alg.provider().supportsNonFileBasedOutput():
|
||||
# use memory layers for temporary layers if supported
|
||||
actionSaveToTemp = QAction(
|
||||
@ -103,7 +103,7 @@ class DestinationSelectionPanel(BASE, WIDGET):
|
||||
actionShowExpressionsBuilder.triggered.connect(self.showExpressionsBuilder)
|
||||
popupMenu.addAction(actionShowExpressionsBuilder)
|
||||
|
||||
if isinstance(self.parameter, QgsProcessingOutputVectorLayer) \
|
||||
if isinstance(self.parameter, QgsProcessingParameterFeatureSink) \
|
||||
and self.alg.provider().supportsNonFileBasedOutput():
|
||||
actionSaveToSpatialite = QAction(
|
||||
self.tr('Save to Spatialite table...'), self.btnSelect)
|
||||
@ -145,7 +145,7 @@ class DestinationSelectionPanel(BASE, WIDGET):
|
||||
uri = QgsDataSourceUri()
|
||||
uri.setConnection(host, str(port), dbname, user, password)
|
||||
uri.setDataSource(dlg.schema, dlg.table,
|
||||
"the_geom" if self.parameter.hasGeometry() else None)
|
||||
"the_geom" if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.parameter.hasGeometry() else None)
|
||||
|
||||
connInfo = uri.connectionInfo()
|
||||
(success, user, passwd) = QgsCredentials.instance().get(connInfo, None, None)
|
||||
@ -185,7 +185,7 @@ class DestinationSelectionPanel(BASE, WIDGET):
|
||||
uri = QgsDataSourceUri()
|
||||
uri.setDatabase(fileName)
|
||||
uri.setDataSource('', self.parameter.name().lower(),
|
||||
'the_geom' if self.parameter.hasGeometry() else None)
|
||||
'the_geom' if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.parameter.hasGeometry() else None)
|
||||
self.leText.setText("spatialite:" + uri.uri())
|
||||
|
||||
def selectFile(self):
|
||||
|
@ -59,7 +59,7 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
|
||||
feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion())))
|
||||
try:
|
||||
layer = QgsProcessingUtils.mapLayerFromString(l, context)
|
||||
if layer:
|
||||
if layer is not None:
|
||||
layer.setName(details.name)
|
||||
details.project.addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
|
||||
else:
|
||||
|
@ -84,6 +84,8 @@ QVariantMap QgsCentroidAlgorithm::processAlgorithm( const QVariantMap ¶meter
|
||||
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT_LAYER" ), context, source->fields(), QgsWkbTypes::Point, source->sourceCrs(), dest ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
@ -157,6 +159,8 @@ QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap ¶meters,
|
||||
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT_LAYER" ), context, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs(), dest ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
// fixed parameters
|
||||
//bool dissolve = QgsProcessingParameters::parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
|
||||
|
@ -1348,6 +1348,25 @@ QgsProcessingParameterDefinition::LayerType QgsProcessingParameterFeatureSink::d
|
||||
return mDataType;
|
||||
}
|
||||
|
||||
bool QgsProcessingParameterFeatureSink::hasGeometry() const
|
||||
{
|
||||
switch ( mDataType )
|
||||
{
|
||||
case TypeAny:
|
||||
case TypeVectorAny:
|
||||
case TypeVectorPoint:
|
||||
case TypeVectorLine:
|
||||
case TypeVectorPolygon:
|
||||
case TypeTable:
|
||||
return true;
|
||||
|
||||
case TypeRaster:
|
||||
case TypeFile:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsProcessingParameterFeatureSink::setDataType( QgsProcessingParameterDefinition::LayerType type )
|
||||
{
|
||||
mDataType = type;
|
||||
|
@ -1202,6 +1202,12 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingParame
|
||||
*/
|
||||
QgsProcessingParameterDefinition::LayerType dataType() const;
|
||||
|
||||
/**
|
||||
* Returns true if sink is likely to include geometries. In cases were presence of geometry
|
||||
* cannot be reliably determined in advance, this method will default to returning true.
|
||||
*/
|
||||
bool hasGeometry() const;
|
||||
|
||||
/**
|
||||
* Sets the layer \a type for the sinks associated with the parameter.
|
||||
* \see dataType()
|
||||
|
@ -265,7 +265,6 @@ void parseDestinationString( QString &destination, QString &providerKey, QString
|
||||
QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &createOptions )
|
||||
{
|
||||
QVariantMap options = createOptions;
|
||||
QgsVectorLayer *layer = nullptr;
|
||||
if ( !options.contains( QStringLiteral( "fileEncoding" ) ) )
|
||||
{
|
||||
// no destination encoding specified, use default
|
||||
@ -275,7 +274,23 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, Qgs
|
||||
if ( destination.isEmpty() || destination.startsWith( QStringLiteral( "memory:" ) ) )
|
||||
{
|
||||
// memory provider cannot be used with QgsVectorLayerImport - so create layer manually
|
||||
layer = QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs );
|
||||
std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer( destination, fields, geometryType, crs ) );
|
||||
if ( !layer )
|
||||
return nullptr;
|
||||
|
||||
if ( !layer->isValid() )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// update destination to layer ID
|
||||
destination = layer->id();
|
||||
|
||||
// this is a factory, so we need to return a proxy
|
||||
std::unique_ptr< QgsProxyFeatureSink > sink( new QgsProxyFeatureSink( layer->dataProvider() ) );
|
||||
context.temporaryLayerStore()->addMapLayer( layer.release() );
|
||||
|
||||
return sink.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -297,33 +312,19 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, Qgs
|
||||
else
|
||||
{
|
||||
//create empty layer
|
||||
{
|
||||
QgsVectorLayerExporter import( uri, providerKey, fields, geometryType, crs, false, &options );
|
||||
if ( import.errorCode() )
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr< QgsVectorLayerExporter > exporter( new QgsVectorLayerExporter( uri, providerKey, fields, geometryType, crs, false, &options ) );
|
||||
if ( exporter->errorCode() )
|
||||
return nullptr;
|
||||
|
||||
// use destination string as layer name (eg "postgis:..." )
|
||||
layer = new QgsVectorLayer( uri, destination, providerKey );
|
||||
std::unique_ptr< QgsVectorLayer > layer( new QgsVectorLayer( uri, destination, providerKey ) );
|
||||
// update destination to layer ID
|
||||
destination = layer->id();
|
||||
context.temporaryLayerStore()->addMapLayer( layer.release() );
|
||||
return exporter.release();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !layer )
|
||||
return nullptr;
|
||||
|
||||
if ( !layer->isValid() )
|
||||
{
|
||||
delete layer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// update destination to layer ID
|
||||
destination = layer->id();
|
||||
|
||||
context.temporaryLayerStore()->addMapLayer( layer );
|
||||
|
||||
// this is a factory, so we need to return a proxy
|
||||
return new QgsProxyFeatureSink( layer->dataProvider() );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString &destination, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, const QVariantMap &options )
|
||||
|
@ -2286,6 +2286,17 @@ void TestQgsProcessing::parameterFeatureSink()
|
||||
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
||||
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
||||
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSinkDefinition( "layer1231123" ) ) );
|
||||
|
||||
// test hasGeometry
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeAny ).hasGeometry() );
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeVectorAny ).hasGeometry() );
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeVectorPoint ).hasGeometry() );
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeVectorLine ).hasGeometry() );
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeVectorPolygon ).hasGeometry() );
|
||||
QVERIFY( !QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeRaster ).hasGeometry() );
|
||||
QVERIFY( !QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeFile ).hasGeometry() );
|
||||
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessingParameterDefinition::TypeTable ).hasGeometry() );
|
||||
|
||||
}
|
||||
|
||||
void TestQgsProcessing::checkParamValues()
|
||||
|
Loading…
x
Reference in New Issue
Block a user