mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
Add method to evaluate parameters to compatible vector layers
of a specified type
This commit is contained in:
parent
f8e37aa7cb
commit
9e184feaed
@ -472,6 +472,22 @@ class QgsProcessingParameters
|
||||
:rtype: QgsProcessingFeatureSource
|
||||
%End
|
||||
|
||||
static QString parameterAsCompatibleSourceLayerPath( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat = QString( "shp" ), QgsProcessingFeedback *feedback = 0 );
|
||||
%Docstring
|
||||
Evaluates the parameter with matching ``definition`` to a source vector layer file path of compatible format.
|
||||
|
||||
If the parameter is evaluated to an existing layer, and that layer is not of the format listed in the
|
||||
``compatibleFormats`` argument, then the layer will first be exported to a compatible format
|
||||
in a temporary location. The function will then return the path to that temporary file.
|
||||
|
||||
``compatibleFormats`` should consist entirely of lowercase file extensions, e.g. 'shp'.
|
||||
|
||||
The ``preferredFormat`` argument is used to specify to desired file extension to use when a temporary
|
||||
layer export is required. This defaults to shapefiles, because shapefiles are the future (don't believe the geopackage hype!).
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
static QgsMapLayer *parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context );
|
||||
%Docstring
|
||||
Evaluates the parameter with matching ``definition`` to a map layer.
|
||||
|
@ -158,6 +158,27 @@ class QgsProcessingUtils
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
static QString convertToCompatibleFormat( const QgsVectorLayer *layer,
|
||||
bool selectedFeaturesOnly,
|
||||
const QString &baseName,
|
||||
const QStringList &compatibleFormats,
|
||||
const QString &preferredFormat,
|
||||
QgsProcessingContext &context,
|
||||
QgsProcessingFeedback *feedback );
|
||||
%Docstring
|
||||
Converts a source vector ``layer`` to a file path to a vector layer of compatible format.
|
||||
|
||||
If the specified ``layer`` is not of the format listed in the
|
||||
``compatibleFormats`` argument, then the layer will first be exported to a compatible format
|
||||
in a temporary location using ``baseName``. The function will then return the path to that temporary file.
|
||||
|
||||
``compatibleFormats`` should consist entirely of lowercase file extensions, e.g. 'shp'.
|
||||
|
||||
The ``preferredFormat`` argument is used to specify to desired file extension to use when a temporary
|
||||
layer export is required. This defaults to shapefiles.
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
class QgsProcessingFeatureSource : QgsFeatureSource
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsvectorlayerfeatureiterator.h"
|
||||
#include "qgsprocessingoutputs.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsvectorfilewriter.h"
|
||||
|
||||
bool QgsProcessingParameters::isDynamic( const QVariantMap ¶meters, const QString &name )
|
||||
{
|
||||
@ -327,6 +328,49 @@ QgsProcessingFeatureSource *QgsProcessingParameters::parameterAsSource( const Qg
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
if ( !definition )
|
||||
return QString();
|
||||
|
||||
QVariant val = parameters.value( definition->name() );
|
||||
|
||||
bool selectedFeaturesOnly = false;
|
||||
if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
|
||||
{
|
||||
// input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
|
||||
QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
|
||||
selectedFeaturesOnly = fromVar.selectedFeaturesOnly;
|
||||
val = fromVar.source;
|
||||
}
|
||||
|
||||
QString layerRef;
|
||||
if ( val.canConvert<QgsProperty>() )
|
||||
{
|
||||
layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
|
||||
}
|
||||
else if ( !val.isValid() || val.toString().isEmpty() )
|
||||
{
|
||||
// fall back to default
|
||||
layerRef = definition->defaultValue().toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
layerRef = val.toString();
|
||||
}
|
||||
|
||||
if ( layerRef.isEmpty() )
|
||||
return QString();
|
||||
|
||||
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context ) );
|
||||
if ( !vl )
|
||||
return QString();
|
||||
|
||||
return QgsProcessingUtils::convertToCompatibleFormat( vl, selectedFeaturesOnly, definition->name(),
|
||||
compatibleFormats, preferredFormat, context, feedback );
|
||||
}
|
||||
|
||||
|
||||
QgsMapLayer *QgsProcessingParameters::parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
|
||||
{
|
||||
if ( !definition )
|
||||
|
@ -32,6 +32,7 @@ class QgsFeatureSink;
|
||||
class QgsFeatureSource;
|
||||
class QgsProcessingFeatureSource;
|
||||
class QgsProcessingOutputDefinition;
|
||||
class QgsProcessingFeedback;
|
||||
|
||||
/**
|
||||
* \class QgsProcessingFeatureSourceDefinition
|
||||
@ -508,6 +509,21 @@ class CORE_EXPORT QgsProcessingParameters
|
||||
*/
|
||||
static QgsProcessingFeatureSource *parameterAsSource( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Evaluates the parameter with matching \a definition to a source vector layer file path of compatible format.
|
||||
*
|
||||
* If the parameter is evaluated to an existing layer, and that layer is not of the format listed in the
|
||||
* \a compatibleFormats argument, then the layer will first be exported to a compatible format
|
||||
* in a temporary location. The function will then return the path to that temporary file.
|
||||
*
|
||||
* \a compatibleFormats should consist entirely of lowercase file extensions, e.g. 'shp'.
|
||||
*
|
||||
* The \a preferredFormat argument is used to specify to desired file extension to use when a temporary
|
||||
* layer export is required. This defaults to shapefiles, because shapefiles are the future (don't believe the geopackage hype!).
|
||||
*/
|
||||
static QString parameterAsCompatibleSourceLayerPath( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat = QString( "shp" ), QgsProcessingFeedback *feedback = nullptr );
|
||||
|
||||
/**
|
||||
* Evaluates the parameter with matching \a definition to a map layer.
|
||||
*
|
||||
|
@ -461,6 +461,42 @@ QString QgsProcessingUtils::formatHelpMapAsHtml( const QVariantMap &map, const Q
|
||||
return s;
|
||||
}
|
||||
|
||||
QString QgsProcessingUtils::convertToCompatibleFormat( const QgsVectorLayer *vl, bool selectedFeaturesOnly, const QString &baseName, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
bool requiresTranslation = selectedFeaturesOnly;
|
||||
if ( !selectedFeaturesOnly )
|
||||
{
|
||||
QFileInfo fi( vl->source() );
|
||||
requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
|
||||
}
|
||||
|
||||
if ( requiresTranslation )
|
||||
{
|
||||
QString temp = QgsProcessingUtils::generateTempFilename( baseName + '.' + preferredFormat );
|
||||
|
||||
QgsVectorFileWriter writer( temp, context.defaultEncoding(),
|
||||
vl->fields(), vl->wkbType(), vl->crs(), QgsVectorFileWriter::driverForExtension( preferredFormat ) );
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it;
|
||||
if ( selectedFeaturesOnly )
|
||||
it = vl->getSelectedFeatures();
|
||||
else
|
||||
it = vl->getFeatures();
|
||||
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
if ( feedback->isCanceled() )
|
||||
return QString();
|
||||
writer.addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vl->source();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsProcessingFeatureSource
|
||||
|
@ -28,6 +28,7 @@
|
||||
class QgsProject;
|
||||
class QgsProcessingContext;
|
||||
class QgsMapLayerStore;
|
||||
class QgsProcessingFeedback;
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
@ -189,6 +190,26 @@ class CORE_EXPORT QgsProcessingUtils
|
||||
*/
|
||||
static QString formatHelpMapAsHtml( const QVariantMap &map, const QgsProcessingAlgorithm *algorithm );
|
||||
|
||||
/**
|
||||
* Converts a source vector \a layer to a file path to a vector layer of compatible format.
|
||||
*
|
||||
* If the specified \a layer is not of the format listed in the
|
||||
* \a compatibleFormats argument, then the layer will first be exported to a compatible format
|
||||
* in a temporary location using \a baseName. The function will then return the path to that temporary file.
|
||||
*
|
||||
* \a compatibleFormats should consist entirely of lowercase file extensions, e.g. 'shp'.
|
||||
*
|
||||
* The \a preferredFormat argument is used to specify to desired file extension to use when a temporary
|
||||
* layer export is required. This defaults to shapefiles.
|
||||
*/
|
||||
static QString convertToCompatibleFormat( const QgsVectorLayer *layer,
|
||||
bool selectedFeaturesOnly,
|
||||
const QString &baseName,
|
||||
const QStringList &compatibleFormats,
|
||||
const QString &preferredFormat,
|
||||
QgsProcessingContext &context,
|
||||
QgsProcessingFeedback *feedback );
|
||||
|
||||
private:
|
||||
|
||||
static bool canUseLayer( const QgsRasterLayer *layer );
|
||||
|
@ -333,6 +333,7 @@ class TestQgsProcessing: public QObject
|
||||
void modelExecution();
|
||||
void modelAcceptableValues();
|
||||
void tempUtils();
|
||||
void convertCompatible();
|
||||
|
||||
private:
|
||||
|
||||
@ -5039,5 +5040,80 @@ void TestQgsProcessing::tempUtils()
|
||||
QVERIFY( tempFile2.startsWith( tempFolder ) );
|
||||
}
|
||||
|
||||
void TestQgsProcessing::convertCompatible()
|
||||
{
|
||||
// start with a compatible shapefile
|
||||
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
||||
QString vector = testDataDir + "points.shp";
|
||||
QgsVectorLayer *layer = new QgsVectorLayer( vector, "vl" );
|
||||
QgsProject p;
|
||||
p.addMapLayer( layer );
|
||||
|
||||
QgsProcessingContext context;
|
||||
context.setProject( &p );
|
||||
QgsProcessingFeedback feedback;
|
||||
QString out = QgsProcessingUtils::convertToCompatibleFormat( layer, false, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
|
||||
// layer should be returned unchanged - underlying source is compatible
|
||||
QCOMPARE( out, layer->source() );
|
||||
|
||||
// don't include shp as compatible type
|
||||
out = QgsProcessingUtils::convertToCompatibleFormat( layer, false, QStringLiteral( "test" ), QStringList() << "tab", QString( "tab" ), context, &feedback );
|
||||
QVERIFY( out != layer->source() );
|
||||
QVERIFY( out.endsWith( ".tab" ) );
|
||||
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
||||
|
||||
// make sure all features are copied
|
||||
QgsVectorLayer *t = new QgsVectorLayer( out, "vl2" );
|
||||
QCOMPARE( layer->featureCount(), t->featureCount() );
|
||||
QCOMPARE( layer->crs(), t->crs() );
|
||||
|
||||
// use a selection - this will require translation
|
||||
QgsFeatureIds ids;
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = layer->getFeatures();
|
||||
it.nextFeature( f );
|
||||
ids.insert( f.id() );
|
||||
it.nextFeature( f );
|
||||
ids.insert( f.id() );
|
||||
|
||||
layer->selectByIds( ids );
|
||||
out = QgsProcessingUtils::convertToCompatibleFormat( layer, true, QStringLiteral( "test" ), QStringList() << "tab", QString( "tab" ), context, &feedback );
|
||||
QVERIFY( out != layer->source() );
|
||||
QVERIFY( out.endsWith( ".tab" ) );
|
||||
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
||||
delete t;
|
||||
t = new QgsVectorLayer( out, "vl2" );
|
||||
QCOMPARE( t->featureCount(), static_cast< long >( ids.count() ) );
|
||||
|
||||
// using a selection but existing format - will still require translation
|
||||
out = QgsProcessingUtils::convertToCompatibleFormat( layer, true, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
|
||||
QVERIFY( out != layer->source() );
|
||||
QVERIFY( out.endsWith( ".shp" ) );
|
||||
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
||||
delete t;
|
||||
t = new QgsVectorLayer( out, "vl2" );
|
||||
QCOMPARE( t->featureCount(), static_cast< long >( ids.count() ) );
|
||||
|
||||
|
||||
// also test evaluating parameter to compatible format
|
||||
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterFeatureSource( QStringLiteral( "source" ) ) );
|
||||
QVariantMap params;
|
||||
params.insert( QStringLiteral( "source" ), QgsProcessingFeatureSourceDefinition( layer->id(), false ) );
|
||||
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
||||
QCOMPARE( out, layer->source() );
|
||||
|
||||
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "tab", QString( "tab" ), &feedback );
|
||||
QVERIFY( out != layer->source() );
|
||||
QVERIFY( out.endsWith( ".tab" ) );
|
||||
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
||||
|
||||
// selected only, will force export
|
||||
params.insert( QStringLiteral( "source" ), QgsProcessingFeatureSourceDefinition( layer->id(), true ) );
|
||||
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
||||
QVERIFY( out != layer->source() );
|
||||
QVERIFY( out.endsWith( ".shp" ) );
|
||||
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsProcessing )
|
||||
#include "testqgsprocessing.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user