Skip to content

Commit 0ba03e5

Browse files
committedNov 10, 2017
[GDAL/OGR providers] Improve list of extensions, remove duplicates, support netCDF vector (fixes #17000)
- Read GDAL 2.0 GDAL_DMD_EXTENSIONS metadata item to retrieve a list of extensions - Remove 'duplicated' drivers from list (such as KML/LIBKML, DGN/DGNv8) - Support netCDF as a vector format (in addition to raster) - For OGR formats, dynamically build list for unknown drivers ('static' list kept for now)
1 parent 2ca4ee5 commit 0ba03e5

File tree

4 files changed

+110
-119
lines changed

4 files changed

+110
-119
lines changed
 

‎src/providers/gdal/qgsgdaldataitems.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,10 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
256256
// return item without testing if:
257257
// scanExtSetting
258258
// or zipfile and scan zip == "Basic scan"
259-
if ( scanExtSetting ||
260-
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) )
259+
// netCDF files can be both raster or vector, so fallback to opening
260+
if ( ( scanExtSetting ||
261+
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) ) &&
262+
suffix != QLatin1String( "nc" ) )
261263
{
262264
// Skip this layer if it's handled by ogr:
263265
if ( ogrSupportedDbLayersExtensions.contains( suffix ) )

‎src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 46 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,14 +1922,6 @@ void buildSupportedRasterFileFilterAndExtensions( QString &fileFiltersString, QS
19221922

19231923
GDALDriverH myGdalDriver; // current driver
19241924

1925-
char **myGdalDriverMetadata; // driver metadata strings
1926-
1927-
QString myGdalDriverLongName( QLatin1String( "" ) ); // long name for the given driver
1928-
QString myGdalDriverExtension( QLatin1String( "" ) ); // file name extension for given driver
1929-
QString myGdalDriverDescription; // QString wrapper of GDAL driver description
1930-
1931-
QStringList metadataTokens; // essentially the metadata string delimited by '='
1932-
19331925
QStringList catchallFilter; // for Any file(*.*), but also for those
19341926
// drivers with no specific file filter
19351927

@@ -1943,10 +1935,6 @@ void buildSupportedRasterFileFilterAndExtensions( QString &fileFiltersString, QS
19431935
// theoreticaly we can open those files because there exists a
19441936
// driver for them, the user will have to use the "All Files" to
19451937
// open datasets with no explicitly defined file name extension.
1946-
// Note that file name extension strings are of the form
1947-
// "DMD_EXTENSION=.*". We'll also store the long name of the
1948-
// driver, which will be found in DMD_LONGNAME, which will have the
1949-
// same form.
19501938

19511939
fileFiltersString.clear();
19521940

@@ -1965,100 +1953,75 @@ void buildSupportedRasterFileFilterAndExtensions( QString &fileFiltersString, QS
19651953
}
19661954

19671955
// in GDAL 2.0 vector and mixed drivers are returned by GDALGetDriver, so filter out non-raster drivers
1968-
// TODO also make sure drivers are not loaded unnecessarily (as GDALAllRegister() and OGRRegisterAll load all drivers)
19691956
if ( QString( GDALGetMetadataItem( myGdalDriver, GDAL_DCAP_RASTER, nullptr ) ) != QLatin1String( "YES" ) )
19701957
continue;
19711958

19721959
// now we need to see if the driver is for something currently
19731960
// supported; if not, we give it a miss for the next driver
19741961

1975-
myGdalDriverDescription = GDALGetDescription( myGdalDriver );
1976-
// QgsDebugMsg(QString("got driver string %1").arg(myGdalDriverDescription));
1977-
1978-
myGdalDriverExtension.clear();
1979-
myGdalDriverLongName.clear();
1962+
QString myGdalDriverDescription = GDALGetDescription( myGdalDriver );
1963+
if ( myGdalDriverDescription == QLatin1String( "BIGGIF" ) )
1964+
{
1965+
// BIGGIF is a technical driver. The plain GIF driver will do
1966+
continue;
1967+
}
19801968

1981-
myGdalDriverMetadata = GDALGetMetadata( myGdalDriver, nullptr );
1969+
// QgsDebugMsg(QString("got driver string %1").arg(myGdalDriverDescription));
19821970

1983-
// presumably we know we've run out of metadta if either the
1984-
// address is 0, or the first character is null
1985-
while ( myGdalDriverMetadata && myGdalDriverMetadata[0] )
1971+
QString myGdalDriverExtensions = GDALGetMetadataItem( myGdalDriver, GDAL_DMD_EXTENSIONS, "" );
1972+
QString myGdalDriverLongName = GDALGetMetadataItem( myGdalDriver, GDAL_DMD_LONGNAME, "" );
1973+
// remove any superfluous (.*) strings at the end as
1974+
// they'll confuse QFileDialog::getOpenFileNames()
1975+
myGdalDriverLongName.remove( QRegExp( "\\(.*\\)$" ) );
1976+
1977+
// if we have both the file name extension and the long name,
1978+
// then we've all the information we need for the current
1979+
// driver; therefore emit a file filter string and move to
1980+
// the next driver
1981+
if ( !( myGdalDriverExtensions.isEmpty() || myGdalDriverLongName.isEmpty() ) )
19861982
{
1987-
metadataTokens = QString( *myGdalDriverMetadata ).split( '=', QString::SkipEmptyParts );
1988-
// QgsDebugMsg(QString("\t%1").arg(*myGdalDriverMetadata));
1989-
1990-
// XXX add check for malformed metadataTokens
1983+
const QStringList splitExtensions = myGdalDriverExtensions.split( ' ', QString::SkipEmptyParts );
19911984

1992-
// Note that it's oddly possible for there to be a
1993-
// DMD_EXTENSION with no corresponding defined extension
1994-
// string; so we check that there're more than two tokens.
1985+
// XXX add check for SDTS; in that case we want (*CATD.DDF)
1986+
QString glob;
19951987

1996-
if ( metadataTokens.count() > 1 )
1988+
for ( const QString &ext : splitExtensions )
19971989
{
1998-
if ( "DMD_EXTENSION" == metadataTokens[0] )
1999-
{
2000-
myGdalDriverExtension = metadataTokens[1];
2001-
2002-
}
2003-
else if ( "DMD_LONGNAME" == metadataTokens[0] )
2004-
{
2005-
myGdalDriverLongName = metadataTokens[1];
2006-
2007-
// remove any superfluous (.*) strings at the end as
2008-
// they'll confuse QFileDialog::getOpenFileNames()
2009-
2010-
myGdalDriverLongName.remove( QRegExp( "\\(.*\\)$" ) );
2011-
}
1990+
// This hacking around that removes '/' is no longer necessary with GDAL 2.3
1991+
extensions << QString( ext ).remove( '/' ).remove( '*' ).remove( '.' );
1992+
if ( !glob.isEmpty() )
1993+
glob += QLatin1String( " " );
1994+
glob += "*." + QString( ext ).replace( '/', QLatin1String( " *." ) );
20121995
}
20131996

2014-
// if we have both the file name extension and the long name,
2015-
// then we've all the information we need for the current
2016-
// driver; therefore emit a file filter string and move to
2017-
// the next driver
2018-
if ( !( myGdalDriverExtension.isEmpty() || myGdalDriverLongName.isEmpty() ) )
1997+
// Add only the first JP2 driver found to the filter list (it's the one GDAL uses)
1998+
if ( myGdalDriverDescription == QLatin1String( "JPEG2000" ) ||
1999+
myGdalDriverDescription.startsWith( QLatin1String( "JP2" ) ) ) // JP2ECW, JP2KAK, JP2MrSID
20192000
{
2020-
// XXX add check for SDTS; in that case we want (*CATD.DDF)
2021-
QString glob = "*." + myGdalDriverExtension.replace( '/', QLatin1String( " *." ) );
2022-
extensions << myGdalDriverExtension.remove( '/' ).remove( '*' ).remove( '.' );
2023-
// Add only the first JP2 driver found to the filter list (it's the one GDAL uses)
2024-
if ( myGdalDriverDescription == QLatin1String( "JPEG2000" ) ||
2025-
myGdalDriverDescription.startsWith( QLatin1String( "JP2" ) ) ) // JP2ECW, JP2KAK, JP2MrSID
2026-
{
2027-
if ( jp2Driver )
2028-
break; // skip if already found a JP2 driver
2001+
if ( jp2Driver )
2002+
continue; // skip if already found a JP2 driver
20292003

2030-
jp2Driver = myGdalDriver; // first JP2 driver found
2004+
jp2Driver = myGdalDriver; // first JP2 driver found
2005+
if ( !glob.contains( "j2k" ) )
2006+
{
20312007
glob += QLatin1String( " *.j2k" ); // add alternate extension
20322008
extensions << QStringLiteral( "j2k" );
20332009
}
2034-
else if ( myGdalDriverDescription == QLatin1String( "GTiff" ) )
2035-
{
2036-
glob += QLatin1String( " *.tiff" );
2037-
extensions << QStringLiteral( "tiff" );
2038-
}
2039-
else if ( myGdalDriverDescription == QLatin1String( "JPEG" ) )
2040-
{
2041-
glob += QLatin1String( " *.jpeg" );
2042-
extensions << QStringLiteral( "jpeg" );
2043-
}
2044-
else if ( myGdalDriverDescription == QLatin1String( "VRT" ) )
2045-
{
2046-
glob += QLatin1String( " *.ovr" );
2047-
extensions << QStringLiteral( "ovr" );
2048-
}
2049-
2050-
fileFiltersString += createFileFilter_( myGdalDriverLongName, glob );
2051-
2052-
break; // ... to next driver, if any.
2010+
}
2011+
else if ( myGdalDriverDescription == QLatin1String( "VRT" ) )
2012+
{
2013+
glob += QLatin1String( " *.ovr" );
2014+
extensions << QStringLiteral( "ovr" );
20532015
}
20542016

2055-
++myGdalDriverMetadata;
2017+
fileFiltersString += createFileFilter_( myGdalDriverLongName, glob );
2018+
2019+
}
20562020

2057-
} // each metadata item
20582021

20592022
//QgsDebugMsg(QString("got driver Desc=%1 LongName=%2").arg(myGdalDriverDescription).arg(myGdalDriverLongName));
20602023

2061-
if ( myGdalDriverExtension.isEmpty() && !myGdalDriverLongName.isEmpty() )
2024+
if ( myGdalDriverExtensions.isEmpty() && !myGdalDriverLongName.isEmpty() )
20622025
{
20632026
// Then what we have here is a driver with no corresponding
20642027
// file extension; e.g., GRASS. In which case we append the
@@ -2071,29 +2034,9 @@ void buildSupportedRasterFileFilterAndExtensions( QString &fileFiltersString, QS
20712034
// DMD_EXTENSION; so let's check for them here and handle
20722035
// them appropriately
20732036

2074-
// USGS DEMs use "*.dem"
2075-
if ( myGdalDriverDescription.startsWith( QLatin1String( "USGSDEM" ) ) )
2076-
{
2077-
fileFiltersString += createFileFilter_( myGdalDriverLongName, QStringLiteral( "*.dem" ) );
2078-
extensions << QStringLiteral( "dem" );
2079-
}
2080-
else if ( myGdalDriverDescription.startsWith( QLatin1String( "DTED" ) ) )
2081-
{
2082-
// DTED use "*.dt0, *.dt1, *.dt2"
2083-
QString glob = QStringLiteral( "*.dt0" );
2084-
glob += QLatin1String( " *.dt1" );
2085-
glob += QLatin1String( " *.dt2" );
2086-
fileFiltersString += createFileFilter_( myGdalDriverLongName, glob );
2087-
extensions << QStringLiteral( "dt0" ) << QStringLiteral( "dt1" ) << QStringLiteral( "dt2" );
2088-
}
2089-
else if ( myGdalDriverDescription.startsWith( QLatin1String( "MrSID" ) ) )
2090-
{
2091-
// MrSID use "*.sid"
2092-
fileFiltersString += createFileFilter_( myGdalDriverLongName, QStringLiteral( "*.sid" ) );
2093-
extensions << QStringLiteral( "sid" );
2094-
}
2095-
else if ( myGdalDriverDescription.startsWith( QLatin1String( "EHdr" ) ) )
2037+
if ( myGdalDriverDescription.startsWith( QLatin1String( "EHdr" ) ) )
20962038
{
2039+
// Fixed in GDAL 2.3
20972040
fileFiltersString += createFileFilter_( myGdalDriverLongName, QStringLiteral( "*.bil" ) );
20982041
extensions << QStringLiteral( "bil" );
20992042
}
@@ -2102,12 +2045,6 @@ void buildSupportedRasterFileFilterAndExtensions( QString &fileFiltersString, QS
21022045
fileFiltersString += createFileFilter_( myGdalDriverLongName, QStringLiteral( "hdr.adf" ) );
21032046
wildcards << QStringLiteral( "hdr.adf" );
21042047
}
2105-
else if ( myGdalDriverDescription == QLatin1String( "HDF4" ) )
2106-
{
2107-
// HDF4 extension missing in driver metadata
2108-
fileFiltersString += createFileFilter_( myGdalDriverLongName, QStringLiteral( "*.hdf" ) );
2109-
extensions << QStringLiteral( "hdf" );
2110-
}
21112048
else
21122049
{
21132050
catchallFilter << QString( GDALGetDescription( myGdalDriver ) );

‎src/providers/ogr/qgsogrdataitems.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,10 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
598598

599599
// Fast track: return item without testing if:
600600
// scanExtSetting or zipfile and scan zip == "Basic scan"
601-
if ( scanExtSetting ||
602-
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) )
601+
// netCDF files can be both raster or vector, so fallback to opening
602+
if ( ( scanExtSetting ||
603+
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) ) &&
604+
suffix != QLatin1String( "nc" ) )
603605
{
604606
// if this is a VRT file make sure it is vector VRT to avoid duplicates
605607
if ( suffix == QLatin1String( "vrt" ) )

‎src/providers/ogr/qgsogrprovider.cpp

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,9 @@ QString createFilters( const QString &type )
22392239
// open datasets with no explicitly defined file name extension.
22402240
QgsDebugMsg( QString( "Driver count: %1" ).arg( OGRGetDriverCount() ) );
22412241

2242+
bool kmlFound = false;
2243+
bool dwgFound = false;
2244+
bool dgnFound = false;
22422245
for ( int i = 0; i < OGRGetDriverCount(); ++i )
22432246
{
22442247
driver = OGRGetDriver( i );
@@ -2319,11 +2322,15 @@ QString createFilters( const QString &type )
23192322
sFileFilters += createFileFilter_( QObject::tr( "GeoRSS" ), QStringLiteral( "*.xml" ) );
23202323
sExtensions << QStringLiteral( "xml" );
23212324
}
2322-
else if ( driverName.startsWith( QLatin1String( "GML" ) ) )
2325+
else if ( driverName == QLatin1String( "GML" ) )
23232326
{
23242327
sFileFilters += createFileFilter_( QObject::tr( "Geography Markup Language [GML]" ), QStringLiteral( "*.gml" ) );
23252328
sExtensions << QStringLiteral( "gml" );
23262329
}
2330+
else if ( driverName == QLatin1String( "GMLAS" ) )
2331+
{
2332+
continue;
2333+
}
23272334
else if ( driverName.startsWith( QLatin1String( "GMT" ) ) )
23282335
{
23292336
sFileFilters += createFileFilter_( QObject::tr( "Generic Mapping Tools [GMT]" ), QStringLiteral( "*.gmt" ) );
@@ -2361,8 +2368,11 @@ QString createFilters( const QString &type )
23612368
{
23622369
sDatabaseDrivers += QObject::tr( "Ingres" ) + ",Ingres;";
23632370
}
2364-
else if ( driverName.startsWith( QLatin1String( "KML" ) ) )
2371+
else if ( driverName == QLatin1String( "KML" ) || driverName == QLatin1String( "LIBKML" ) )
23652372
{
2373+
if ( kmlFound )
2374+
continue;
2375+
kmlFound = true;
23662376
sFileFilters += createFileFilter_( QObject::tr( "Keyhole Markup Language [KML]" ), QStringLiteral( "*.kml *.kmz" ) );
23672377
sExtensions << QStringLiteral( "kml" ) << QStringLiteral( "kmz" );
23682378
}
@@ -2371,8 +2381,11 @@ QString createFilters( const QString &type )
23712381
sFileFilters += createFileFilter_( QObject::tr( "Mapinfo File" ), QStringLiteral( "*.mif *.tab" ) );
23722382
sExtensions << QStringLiteral( "mif" ) << QStringLiteral( "tab" );
23732383
}
2374-
else if ( driverName.startsWith( QLatin1String( "DGN" ) ) )
2384+
else if ( driverName == QLatin1String( "DGN" ) || driverName == QLatin1String( "DGNV8" ) )
23752385
{
2386+
if ( dgnFound )
2387+
continue;
2388+
dgnFound = true;
23762389
sFileFilters += createFileFilter_( QObject::tr( "Microstation DGN" ), QStringLiteral( "*.dgn" ) );
23772390
sExtensions << QStringLiteral( "dgn" );
23782391
}
@@ -2561,9 +2574,46 @@ QString createFilters( const QString &type )
25612574
}
25622575
else
25632576
{
2564-
// NOP, we don't know anything about the current driver
2565-
// with regards to a proper file filter string
2566-
QgsDebugMsg( QString( "Unknown driver %1 for file filters." ).arg( driverName ) );
2577+
if ( driverName == QLatin1String( "CAD" ) || driverName == QLatin1String( "DWG" ) )
2578+
{
2579+
if ( dwgFound )
2580+
continue;
2581+
dwgFound = true;
2582+
}
2583+
2584+
QString myGdalDriverExtensions = GDALGetMetadataItem( driver, GDAL_DMD_EXTENSIONS, "" );
2585+
QString myGdalDriverLongName = GDALGetMetadataItem( driver, GDAL_DMD_LONGNAME, "" );
2586+
if ( !( myGdalDriverExtensions.isEmpty() || myGdalDriverLongName.isEmpty() ) )
2587+
{
2588+
const QStringList splitExtensions = myGdalDriverExtensions.split( ' ', QString::SkipEmptyParts );
2589+
2590+
QString glob;
2591+
2592+
for ( const QString &ext : splitExtensions )
2593+
{
2594+
sExtensions << ext;
2595+
if ( !glob.isEmpty() )
2596+
glob += QLatin1String( " " );
2597+
glob += "*." + ext;
2598+
}
2599+
2600+
if ( driverName == QLatin1String( "JPEG2000" ) ||
2601+
driverName.startsWith( QLatin1String( "JP2" ) ) )
2602+
{
2603+
// Skip over JPEG2000 drivers, as their vector capabilities are just
2604+
// a marginal use case
2605+
continue;
2606+
}
2607+
2608+
sFileFilters += createFileFilter_( myGdalDriverLongName, glob );
2609+
2610+
}
2611+
else
2612+
{
2613+
// NOP, we don't know anything about the current driver
2614+
// with regards to a proper file filter string
2615+
QgsDebugMsg( QString( "Unknown driver %1 for file filters." ).arg( driverName ) );
2616+
}
25672617
}
25682618

25692619
} // each loaded OGR driver

0 commit comments

Comments
 (0)
Please sign in to comment.