Skip to content

Commit dc341d2

Browse files
committed
Add flags to QgsVectorFileWriter methods which return lists of drivers
Initially only flag available is whether to sort drivers by recommended order. The recommended order puts GPKG first and SHP second, then leaves the rest alphabetical. This fixes a few instances in the QGIS gui where these recommended formats are not listed first.
1 parent eb6f64e commit dc341d2

File tree

7 files changed

+195
-65
lines changed

7 files changed

+195
-65
lines changed

python/core/qgsvectorfilewriter.sip

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ Some formats require a compulsory encoding, typically UTF-8. If no compulsory en
145145
SymbolLayerSymbology
146146
};
147147

148+
149+
enum VectorFormatOption
150+
{
151+
SortRecommended,
152+
};
153+
typedef QFlags<QgsVectorFileWriter::VectorFormatOption> VectorFormatOptions;
154+
155+
148156
class FieldValueConverter
149157
{
150158
%Docstring
@@ -460,27 +468,41 @@ Create a new vector file writer
460468

461469

462470

463-
static QMap< QString, QString> supportedFiltersAndFormats();
471+
static QList< QPair< QString, QString > > supportedFiltersAndFormats( VectorFormatOptions options = SortRecommended );
464472
%Docstring
465-
Returns a map with format filter string as key and OGR format key as value.
473+
Returns a list or pairs, with format filter string as first element and OGR format key as second element.
474+
475+
The ``options`` argument can be used to control the sorting and filtering of
476+
returned formats.
477+
466478
.. seealso:: supportedOutputVectorLayerExtensions()
467-
:rtype: QMap< str, QString>
479+
:rtype: list of QPair< str, QString >
468480
%End
469481

470-
static QStringList supportedFormatExtensions();
482+
static QStringList supportedFormatExtensions( VectorFormatOptions options = SortRecommended );
471483
%Docstring
472484
Returns a list of file extensions for supported formats.
485+
486+
The ``options`` argument can be used to control the sorting and filtering of
487+
returned formats.
488+
473489
.. versionadded:: 3.0
474490
.. seealso:: supportedFiltersAndFormats()
475491
:rtype: list of str
476492
%End
477493

478-
static QMap< QString, QString> ogrDriverList();
494+
static QList< QPair< QString, QString > > ogrDriverList( VectorFormatOptions options = SortRecommended );
479495
%Docstring
480496
Returns driver list that can be used for dialogs. It contains all OGR drivers
481-
+ some additional internal QGIS driver names to distinguish between more
482-
supported formats of the same OGR driver
483-
:rtype: QMap< str, QString>
497+
plus some additional internal QGIS driver names to distinguish between more
498+
supported formats of the same OGR driver.
499+
500+
The returned list consists of pairs of driver long name (e.g. user-friendly
501+
display name for the format) to internal driver short name.
502+
503+
The ``options`` argument can be used to control the sorting and filtering of
504+
returned drivers.
505+
:rtype: list of QPair< str, QString >
484506
%End
485507

486508
static QString driverForExtension( const QString &extension );
@@ -492,9 +514,12 @@ Create a new vector file writer
492514
:rtype: str
493515
%End
494516

495-
static QString fileFilterString();
517+
static QString fileFilterString( VectorFormatOptions options = SortRecommended );
496518
%Docstring
497-
Returns filter string that can be used for dialogs
519+
Returns filter string that can be used for dialogs.
520+
521+
The ``options`` argument can be used to control the sorting and filtering of
522+
returned drivers.
498523
:rtype: str
499524
%End
500525

@@ -639,6 +664,8 @@ Close opened shapefile for writing
639664

640665
QFlags<QgsVectorFileWriter::EditionCapability> operator|(QgsVectorFileWriter::EditionCapability f1, QFlags<QgsVectorFileWriter::EditionCapability> f2);
641666

667+
QFlags<QgsVectorFileWriter::VectorFormatOption> operator|(QgsVectorFileWriter::VectorFormatOption f1, QFlags<QgsVectorFileWriter::VectorFormatOption> f2);
668+
642669

643670

644671
/************************************************************************

python/plugins/processing/algs/gdal/GdalUtils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ def getVectorDriverFromFileName(filename):
174174
return 'ESRI Shapefile'
175175

176176
formats = QgsVectorFileWriter.supportedFiltersAndFormats()
177-
for k, v in list(formats.items()):
178-
if ext in k:
179-
return v
177+
for format in formats:
178+
if ext in format[0]:
179+
return format[1]
180180
return 'ESRI Shapefile'
181181

182182
@staticmethod

src/core/qgsvectorfilewriter.cpp

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,13 +2681,16 @@ void QgsVectorFileWriter::setSymbologyScale( double d )
26812681
mRenderContext.setRendererScale( mSymbologyScale );
26822682
}
26832683

2684-
QMap< QString, QString> QgsVectorFileWriter::supportedFiltersAndFormats()
2684+
QList< QPair< QString, QString > > QgsVectorFileWriter::supportedFiltersAndFormats( const VectorFormatOptions options )
26852685
{
2686-
QMap<QString, QString> resultMap;
2686+
QList< QPair< QString, QString > > resultMap;
26872687

26882688
QgsApplication::registerOgrDrivers();
26892689
int const drvCount = OGRGetDriverCount();
26902690

2691+
QPair< QString, QString > shapeFormat;
2692+
QPair< QString, QString > gpkgFormat;
2693+
26912694
for ( int i = 0; i < drvCount; ++i )
26922695
{
26932696
OGRSFDriverH drv = OGRGetDriver( i );
@@ -2700,51 +2703,68 @@ QMap< QString, QString> QgsVectorFileWriter::supportedFiltersAndFormats()
27002703
if ( filterString.isEmpty() )
27012704
continue;
27022705

2703-
resultMap.insert( filterString, drvName );
2706+
if ( options & SortRecommended )
2707+
{
2708+
if ( drvName == QStringLiteral( "ESRI Shapefile" ) )
2709+
{
2710+
shapeFormat = qMakePair( filterString, drvName );
2711+
continue;
2712+
}
2713+
else if ( drvName == QStringLiteral( "GPKG" ) )
2714+
{
2715+
gpkgFormat = qMakePair( filterString, drvName );
2716+
continue;
2717+
}
2718+
}
2719+
resultMap << qMakePair( filterString, drvName );
27042720
}
27052721
}
27062722
}
27072723

2724+
std::sort( resultMap.begin(), resultMap.end(), []( const QPair< QString, QString > &a, const QPair< QString, QString > &b ) -> bool
2725+
{
2726+
return a.second < b.second;
2727+
} );
2728+
2729+
if ( options & SortRecommended )
2730+
{
2731+
if ( !shapeFormat.first.isEmpty() )
2732+
{
2733+
resultMap.insert( 0, shapeFormat );
2734+
}
2735+
if ( !gpkgFormat.first.isEmpty() )
2736+
{
2737+
resultMap.insert( 0, gpkgFormat );
2738+
}
2739+
}
2740+
27082741
return resultMap;
27092742
}
27102743

2711-
QStringList QgsVectorFileWriter::supportedFormatExtensions()
2744+
QStringList QgsVectorFileWriter::supportedFormatExtensions( const VectorFormatOptions options )
27122745
{
2713-
QgsStringMap formats = supportedFiltersAndFormats();
2746+
const auto formats = supportedFiltersAndFormats( options );
27142747
QStringList extensions;
27152748

27162749
QRegularExpression rx( QStringLiteral( "\\*\\.([a-zA-Z0-9]*)" ) );
27172750

2718-
QgsStringMap::const_iterator formatIt = formats.constBegin();
2751+
auto formatIt = formats.constBegin();
27192752
for ( ; formatIt != formats.constEnd(); ++formatIt )
27202753
{
2721-
QString ext = formatIt.key();
2754+
QString ext = formatIt->first;
27222755
QRegularExpressionMatch match = rx.match( ext );
27232756
if ( !match.hasMatch() )
27242757
continue;
27252758

27262759
QString matched = match.captured( 1 );
2727-
2728-
// special handling for the two main contenders for glory
2729-
if ( matched.compare( QStringLiteral( "gpkg" ), Qt::CaseInsensitive ) == 0 )
2730-
continue;
2731-
if ( matched.compare( QStringLiteral( "shp" ), Qt::CaseInsensitive ) == 0 )
2732-
continue;
2733-
27342760
extensions << matched;
27352761
}
2736-
2737-
std::sort( extensions.begin(), extensions.end() );
2738-
2739-
// Make https://twitter.com/shapefiIe a sad little fellow
2740-
extensions.insert( 0, QStringLiteral( "gpkg" ) );
2741-
extensions.insert( 1, QStringLiteral( "shp" ) );
27422762
return extensions;
27432763
}
27442764

2745-
QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
2765+
QList< QPair< QString, QString> > QgsVectorFileWriter::ogrDriverList( const VectorFormatOptions options )
27462766
{
2747-
QMap<QString, QString> resultMap;
2767+
QList< QPair< QString, QString> > resultMap;
27482768

27492769
QgsApplication::registerOgrDrivers();
27502770
int const drvCount = OGRGetDriverCount();
@@ -2756,6 +2776,10 @@ QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
27562776
if ( drv )
27572777
{
27582778
QString drvName = OGR_Dr_GetName( drv );
2779+
if ( drvName == QLatin1String( "ESRI Shapefile" ) )
2780+
{
2781+
writableDrivers << QStringLiteral( "DBF file" );
2782+
}
27592783
if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
27602784
{
27612785
// Add separate format for Mapinfo MIF (MITAB is OGR default)
@@ -2786,24 +2810,35 @@ QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
27862810
}
27872811
CPLFree( options[0] );
27882812
}
2789-
else if ( drvName == QLatin1String( "ESRI Shapefile" ) )
2790-
{
2791-
writableDrivers << QStringLiteral( "DBF file" );
2792-
}
27932813
writableDrivers << drvName;
27942814
}
27952815
}
27962816
}
2817+
std::sort( writableDrivers.begin(), writableDrivers.end() );
2818+
if ( options & SortRecommended )
2819+
{
2820+
// recommended order sorting, so we shift certain formats to the top
2821+
if ( writableDrivers.contains( QStringLiteral( "ESRI Shapefile" ) ) )
2822+
{
2823+
writableDrivers.removeAll( QStringLiteral( "ESRI Shapefile" ) );
2824+
writableDrivers.insert( 0, QStringLiteral( "ESRI Shapefile" ) );
2825+
}
2826+
if ( writableDrivers.contains( QStringLiteral( "GPKG" ) ) )
2827+
{
2828+
// Make https://twitter.com/shapefiIe a sad little fellow
2829+
writableDrivers.removeAll( QStringLiteral( "GPKG" ) );
2830+
writableDrivers.insert( 0, QStringLiteral( "GPKG" ) );
2831+
}
2832+
}
27972833

2798-
Q_FOREACH ( const QString &drvName, writableDrivers )
2834+
for ( const QString &drvName : qgis::as_const( writableDrivers ) )
27992835
{
28002836
MetaData metadata;
28012837
if ( driverMetadata( drvName, metadata ) && !metadata.trLongName.isEmpty() )
28022838
{
2803-
resultMap.insert( metadata.trLongName, drvName );
2839+
resultMap << qMakePair( metadata.trLongName, drvName );
28042840
}
28052841
}
2806-
28072842
return resultMap;
28082843
}
28092844

@@ -2841,17 +2876,16 @@ QString QgsVectorFileWriter::driverForExtension( const QString &extension )
28412876
return QString();
28422877
}
28432878

2844-
QString QgsVectorFileWriter::fileFilterString()
2879+
QString QgsVectorFileWriter::fileFilterString( const VectorFormatOptions options )
28452880
{
28462881
QString filterString;
2847-
QMap< QString, QString> driverFormatMap = supportedFiltersAndFormats();
2848-
QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
2849-
for ( ; it != driverFormatMap.constEnd(); ++it )
2882+
const auto driverFormatMap = supportedFiltersAndFormats( options );
2883+
for ( auto it = driverFormatMap.constBegin(); it != driverFormatMap.constEnd(); ++it )
28502884
{
28512885
if ( !filterString.isEmpty() )
28522886
filterString += QLatin1String( ";;" );
28532887

2854-
filterString += it.key();
2888+
filterString += it->first;
28552889
}
28562890
return filterString;
28572891
}

src/core/qgsvectorfilewriter.h

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
186186
SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels)
187187
};
188188

189+
190+
/**
191+
* Options for sorting and filtering vector formats.
192+
* \since QGIS 3.0
193+
*/
194+
enum VectorFormatOption
195+
{
196+
SortRecommended = 1 << 1, //!< Use recommended sort order, with extremely commonly used formats listed first
197+
};
198+
Q_DECLARE_FLAGS( VectorFormatOptions, VectorFormatOption )
199+
189200
/**
190201
* \ingroup core
191202
* Interface to convert raw field values to their user-friendly value.
@@ -496,24 +507,38 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
496507
QgsVectorFileWriter &operator=( const QgsVectorFileWriter &rh ) = delete;
497508

498509
/**
499-
* Returns a map with format filter string as key and OGR format key as value.
510+
* Returns a list or pairs, with format filter string as first element and OGR format key as second element.
511+
*
512+
* The \a options argument can be used to control the sorting and filtering of
513+
* returned formats.
514+
*
500515
* \see supportedOutputVectorLayerExtensions()
501516
*/
502-
static QMap< QString, QString> supportedFiltersAndFormats();
517+
static QList< QPair< QString, QString > > supportedFiltersAndFormats( VectorFormatOptions options = SortRecommended );
503518

504519
/**
505520
* Returns a list of file extensions for supported formats.
521+
*
522+
* The \a options argument can be used to control the sorting and filtering of
523+
* returned formats.
524+
*
506525
* \since QGIS 3.0
507526
* \see supportedFiltersAndFormats()
508527
*/
509-
static QStringList supportedFormatExtensions();
528+
static QStringList supportedFormatExtensions( VectorFormatOptions options = SortRecommended );
510529

511530
/**
512531
* Returns driver list that can be used for dialogs. It contains all OGR drivers
513-
* + some additional internal QGIS driver names to distinguish between more
514-
* supported formats of the same OGR driver
532+
* plus some additional internal QGIS driver names to distinguish between more
533+
* supported formats of the same OGR driver.
534+
*
535+
* The returned list consists of pairs of driver long name (e.g. user-friendly
536+
* display name for the format) to internal driver short name.
537+
*
538+
* The \a options argument can be used to control the sorting and filtering of
539+
* returned drivers.
515540
*/
516-
static QMap< QString, QString> ogrDriverList();
541+
static QList< QPair< QString, QString > > ogrDriverList( VectorFormatOptions options = SortRecommended );
517542

518543
/**
519544
* Returns the OGR driver name for a specified file \a extension. E.g. the
@@ -523,8 +548,13 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
523548
*/
524549
static QString driverForExtension( const QString &extension );
525550

526-
//! Returns filter string that can be used for dialogs
527-
static QString fileFilterString();
551+
/**
552+
* Returns filter string that can be used for dialogs.
553+
*
554+
* The \a options argument can be used to control the sorting and filtering of
555+
* returned drivers.
556+
*/
557+
static QString fileFilterString( VectorFormatOptions options = SortRecommended );
528558

529559
//! Creates a filter for an OGR driver key
530560
static QString filterForDriver( const QString &driverName );
@@ -701,6 +731,7 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
701731
};
702732

703733
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsVectorFileWriter::EditionCapabilities )
734+
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsVectorFileWriter::VectorFormatOptions )
704735

705736
// clazy:excludeall=qstring-allocations
706737

src/gui/ogr/qgsvectorlayersaveasdialog.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ void QgsVectorLayerSaveAsDialog::setup()
8787
QgsSettings settings;
8888
restoreGeometry( settings.value( QStringLiteral( "Windows/VectorLayerSaveAs/geometry" ) ).toByteArray() );
8989

90-
QMap<QString, QString> map = QgsVectorFileWriter::ogrDriverList();
90+
const QList< QPair< QString, QString > > map = QgsVectorFileWriter::ogrDriverList();
9191
mFormatComboBox->blockSignals( true );
92-
for ( QMap< QString, QString>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
92+
for ( auto it = map.constBegin(); it != map.constEnd(); ++it )
9393
{
94-
mFormatComboBox->addItem( it.key(), it.value() );
94+
mFormatComboBox->addItem( it->first, it->second );
9595
}
9696

9797
QString format = settings.value( QStringLiteral( "UI/lastVectorFormat" ), "GPKG" ).toString();

0 commit comments

Comments
 (0)