Skip to content

Commit

Permalink
[processing] More fixes to convertToCompatibleFormat, lots of unit
Browse files Browse the repository at this point in the history
tests

Fixes #19938
  • Loading branch information
nyalldawson committed Sep 28, 2018
1 parent 737ab30 commit 308d713
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 2 deletions.
15 changes: 15 additions & 0 deletions python/plugins/processing/tests/GdalAlgorithmsTest.py
Expand Up @@ -194,6 +194,21 @@ def testGetOgrCompatibleSourceFromOgrLayer(self):
path, layer = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback, False)
self.assertEqual(path, source)

# geopackage with layer
source = os.path.join(testDataPath, 'custom', 'circular_strings.gpkg')
vl2 = QgsVectorLayer(source + '|layername=circular_strings')
self.assertTrue(vl2.isValid())
p.addMapLayer(vl2)
path, layer = alg.getOgrCompatibleSource('INPUT', {'INPUT': vl2.id()}, context, feedback, True)
self.assertEqual(path, source)
self.assertEqual(layer, 'circular_strings')
vl3 = QgsVectorLayer(source + '|layername=circular_strings_with_line')
self.assertTrue(vl3.isValid())
p.addMapLayer(vl3)
path, layer = alg.getOgrCompatibleSource('INPUT', {'INPUT': vl3.id()}, context, feedback, True)
self.assertEqual(path, source)
self.assertEqual(layer, 'circular_strings_with_line')

def testGetOgrCompatibleSourceFromFeatureSource(self):
# create a memory layer and add to project and context
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
Expand Down
Binary file not shown.
19 changes: 17 additions & 2 deletions src/core/processing/qgsprocessingutils.cpp
Expand Up @@ -629,8 +629,23 @@ QString QgsProcessingUtils::formatHelpMapAsHtml( const QVariantMap &map, const Q

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 )
bool requiresTranslation = false;

// if we are only looking for selected features then we have to export back to disk,
// as we need to subset only selected features, a concept which doesn't exist outside QGIS!
requiresTranslation = requiresTranslation || selectedFeaturesOnly;

// if the data provider is NOT ogr, then we HAVE to convert. Otherwise we run into
// issues with data providers like spatialite, delimited text where the format can be
// opened outside of QGIS, but with potentially very different behavior!
requiresTranslation = requiresTranslation || vl->dataProvider()->name() != QLatin1String( "ogr" );

// if the layer has a feature filter set, then we HAVE to convert. Feature filters are
// a purely QGIS concept.
requiresTranslation = requiresTranslation || !vl->subsetString().isEmpty();

// Check if layer is a disk based format and if so if the layer's path has a compatible filename suffix
if ( !requiresTranslation )
{
const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( vl->dataProvider()->name(), vl->source() );
if ( parts.contains( QLatin1String( "path" ) ) )
Expand Down
48 changes: 48 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -6758,6 +6758,54 @@ void TestQgsProcessing::convertCompatible()
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
QCOMPARE( t->featureCount(), static_cast< long >( ids.count() ) );

// using a feature filter -- this will require translation
layer->setSubsetString( "1 or 2" );
out = QgsProcessingUtils::convertToCompatibleFormat( layer, false, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
QVERIFY( out != layer->source() );
QVERIFY( out.endsWith( ".shp" ) );
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
QCOMPARE( t->featureCount(), layer->featureCount() );
layer->setSubsetString( QString() );

// non-OGR source -- must be translated, regardless of extension. (e.g. delimited text provider handles CSV very different to OGR!)
std::unique_ptr< QgsVectorLayer > memLayer = qgis::make_unique< QgsVectorLayer> ( "Point", "v1", "memory" );
for ( int i = 1; i < 6; ++i )
{
QgsFeature f( i );
f.setGeometry( QgsGeometry( new QgsPoint( 1, 2 ) ) );
memLayer->dataProvider()->addFeatures( QgsFeatureList() << f );
}
out = QgsProcessingUtils::convertToCompatibleFormat( memLayer.get(), false, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
QVERIFY( out != memLayer->source() );
QVERIFY( out.endsWith( ".shp" ) );
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
QCOMPARE( t->featureCount(), memLayer->featureCount() );

//delimited text -- must be translated, regardless of extension. (delimited text provider handles CSV very different to OGR!)
QString csvPath = "file://" + testDataDir + "delimitedtext/testpt.csv?type=csv&useHeader=No&detectTypes=yes&xyDms=yes&geomType=none&subsetIndex=no&watchFile=no";
std::unique_ptr< QgsVectorLayer > csvLayer = qgis::make_unique< QgsVectorLayer >( csvPath, "vl", "delimitedtext" );
QVERIFY( csvLayer->isValid() );
out = QgsProcessingUtils::convertToCompatibleFormat( csvLayer.get(), false, QStringLiteral( "test" ), QStringList() << "csv", QString( "csv" ), context, &feedback );
QVERIFY( out != csvLayer->source() );
QVERIFY( out.endsWith( ".csv" ) );
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
QCOMPARE( t->featureCount(), csvLayer->featureCount() );

// geopackage with layer
QString gpkgPath = testDataDir + "points_gpkg.gpkg|layername=points_gpkg";
std::unique_ptr< QgsVectorLayer > gpkgLayer = qgis::make_unique< QgsVectorLayer >( gpkgPath, "vl" );
QVERIFY( gpkgLayer->isValid() );
out = QgsProcessingUtils::convertToCompatibleFormat( gpkgLayer.get(), false, QStringLiteral( "test" ), QStringList() << "gpkg" << "shp", QString( "shp" ), context, &feedback );
// layer should be returned unchanged - underlying source is compatible
QCOMPARE( out, gpkgLayer->source() );
gpkgPath = testDataDir + "points_gpkg.gpkg|layername=points_small";
gpkgLayer = qgis::make_unique< QgsVectorLayer >( gpkgPath, "vl" );
QVERIFY( gpkgLayer->isValid() );
out = QgsProcessingUtils::convertToCompatibleFormat( gpkgLayer.get(), false, QStringLiteral( "test" ), QStringList() << "gpkg" << "shp", QString( "shp" ), context, &feedback );
QCOMPARE( out, gpkgLayer->source() );

// also test evaluating parameter to compatible format
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterFeatureSource( QStringLiteral( "source" ) ) );
Expand Down
Binary file modified tests/testdata/curved_polys.gpkg
Binary file not shown.

0 comments on commit 308d713

Please sign in to comment.