Skip to content

Commit

Permalink
QgsVectorFileWriter::writeAsVectorFormat(): return appropriate output…
Browse files Browse the repository at this point in the history
… layer name for GPX driver (github fixes #29819)
  • Loading branch information
rouault authored and nyalldawson committed May 27, 2019
1 parent 29806b4 commit 9167cb4
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/core/qgsvectorfilewriter.cpp
Expand Up @@ -428,7 +428,51 @@ void QgsVectorFileWriter::init( QString vectorFileName,
{
mLayer = OGR_DS_CreateLayer( mDS.get(), layerName.toUtf8().constData(), mOgrRef, wkbType, options );
if ( newLayer && mLayer )
{
*newLayer = OGR_L_GetName( mLayer );
if ( driverName == QLatin1String( "GPX" ) )
{
// See logic in GDAL ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp ICreateLayer()
switch ( QgsWkbTypes::flatType( geometryType ) )
{
case QgsWkbTypes::Point:
{
if ( !EQUAL( layerName.toUtf8().constData(), "track_points" ) &&
!EQUAL( layerName.toUtf8().constData(), "route_points" ) )
{
*newLayer = QStringLiteral( "waypoints" );
}
}
break;

case QgsWkbTypes::LineString:
{
const char *pszForceGPXTrack
= CSLFetchNameValue( options, "FORCE_GPX_TRACK" );
if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
*newLayer = QStringLiteral( "tracks" );
else
*newLayer = QStringLiteral( "routes" );

}
break;

case QgsWkbTypes::MultiLineString:
{
const char *pszForceGPXRoute
= CSLFetchNameValue( options, "FORCE_GPX_ROUTE" );
if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
*newLayer = QStringLiteral( "routes" );
else
*newLayer = QStringLiteral( "tracks" );
}
break;

default:
break;
}
}
}
}
else if ( driverName == QLatin1String( "DGN" ) )
{
Expand Down
126 changes: 126 additions & 0 deletions tests/src/core/testqgsvectorfilewriter.cpp
Expand Up @@ -62,6 +62,12 @@ class TestQgsVectorFileWriter: public QObject
public:
TestQgsVectorFileWriter();

void _testExportToGpx( const QString &geomTypeName,
const QString &wkt,
const QString &expectedLayerName,
const QString &inputLayerName = QStringLiteral( "test" ),
const QStringList &layerOptions = QStringList() );

private slots:
void initTestCase();// will be called before the first testfunction is executed.
void init() {} // will be called before each testfunction is executed.
Expand All @@ -84,6 +90,20 @@ class TestQgsVectorFileWriter: public QObject
void prepareWriteAsVectorFormat();
//! Test regression #21714 (Exported GeoPackages have wrong field definitions)
void testTextFieldLength();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxPoint();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxPointTrackPoints();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxPointRoutePoints();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxLineString();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxLineStringForceTrack();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxMultiLineString();
//! Test https://issues.qgis.org/issues/22005
void testExportToGpxMultiLineStringForceRoute();

private:
// a little util fn used by all tests
Expand Down Expand Up @@ -524,5 +544,111 @@ void TestQgsVectorFileWriter::testTextFieldLength()

}

void TestQgsVectorFileWriter::_testExportToGpx( const QString &geomTypeName,
const QString &wkt,
const QString &expectedLayerName,
const QString &inputLayerName,
const QStringList &layerOptions )
{
QTemporaryFile tmpFile( QDir::tempPath() + "/test_qgsvectorfilewriter_testExportToGpx" + geomTypeName + "_XXXXXX.gpx" );
tmpFile.open();
QString fileName( tmpFile.fileName( ) );
QString memLayerDef( geomTypeName );
if ( inputLayerName == QLatin1String( "track_points" ) )
{
memLayerDef += QStringLiteral( "?field=track_fid:int&field=track_seg_id:int" );
}
else if ( inputLayerName == QLatin1String( "route_points" ) )
{
memLayerDef += QStringLiteral( "?field=route_fid:int" );
}
QgsVectorLayer vl( memLayerDef, "test", "memory" );
QgsFeature f { vl.fields() };
if ( inputLayerName == QLatin1String( "track_points" ) )
{
f.setAttribute( 0, 1 );
f.setAttribute( 1, 1 );
}
else if ( inputLayerName == QLatin1String( "route_points" ) )
{
f.setAttribute( 0, 1 );
}
f.setGeometry( QgsGeometry::fromWkt( wkt ) );
QVERIFY( vl.startEditing() );
QVERIFY( vl.addFeature( f ) );
QgsVectorFileWriter::SaveVectorOptions options;
options.driverName = "GPX";
options.layerName = inputLayerName;
options.layerOptions = layerOptions;
QString outLayerName;
QgsVectorFileWriter::WriterError error( QgsVectorFileWriter::writeAsVectorFormat(
&vl,
fileName,
options,
nullptr, // newFilename
nullptr, // errorMessage
&outLayerName ) );
QCOMPARE( error, QgsVectorFileWriter::WriterError::NoError );
QCOMPARE( outLayerName, expectedLayerName );
QgsVectorLayer vl2( QStringLiteral( "%1|layername=%2" ).arg( fileName ).arg( outLayerName ), "src_test", "ogr" );
QVERIFY( vl2.isValid() );
QCOMPARE( vl2.featureCount(), 1L );
}

void TestQgsVectorFileWriter::testExportToGpxPoint()
{
_testExportToGpx( QStringLiteral( "Point" ),
QStringLiteral( "point(9 45)" ),
QStringLiteral( "waypoints" ) );
}

void TestQgsVectorFileWriter::testExportToGpxPointTrackPoints()
{
_testExportToGpx( QStringLiteral( "Point" ),
QStringLiteral( "point(9 45)" ),
QStringLiteral( "track_points" ),
QStringLiteral( "track_points" ) );
}

void TestQgsVectorFileWriter::testExportToGpxPointRoutePoints()
{
_testExportToGpx( QStringLiteral( "Point" ),
QStringLiteral( "point(9 45)" ),
QStringLiteral( "route_points" ),
QStringLiteral( "route_points" ) );
}

void TestQgsVectorFileWriter::testExportToGpxLineString()
{
_testExportToGpx( QStringLiteral( "LineString" ),
QStringLiteral( "linestring(9 45,10 46)" ),
QStringLiteral( "routes" ) );
}

void TestQgsVectorFileWriter::testExportToGpxLineStringForceTrack()
{
_testExportToGpx( QStringLiteral( "LineString" ),
QStringLiteral( "linestring(9 45,10 46)" ),
QStringLiteral( "tracks" ),
QStringLiteral( "test" ),
QStringList() << QStringLiteral( "FORCE_GPX_TRACK=YES" ) );
}

void TestQgsVectorFileWriter::testExportToGpxMultiLineString()
{
_testExportToGpx( QStringLiteral( "MultiLineString" ),
QStringLiteral( "multilinestring((9 45,10 46))" ),
QStringLiteral( "tracks" ) );
}

void TestQgsVectorFileWriter::testExportToGpxMultiLineStringForceRoute()
{
_testExportToGpx( QStringLiteral( "MultiLineString" ),
QStringLiteral( "multilinestring((9 45,10 46))" ),
QStringLiteral( "routes" ),
QStringLiteral( "test" ),
QStringList() << QStringLiteral( "FORCE_GPX_ROUTE=YES" ) );
}

QGSTEST_MAIN( TestQgsVectorFileWriter )
#include "testqgsvectorfilewriter.moc"

0 comments on commit 9167cb4

Please sign in to comment.