mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
add support for .tar/.tgz files and relevant tests ; delay scan of .tgz files and large .zip files until requested
This commit is contained in:
parent
4aab209400
commit
a4a85cbf37
@ -477,7 +477,6 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
|
||||
QVector<QgsDataItem*> children;
|
||||
QDir dir( mPath );
|
||||
QSettings settings;
|
||||
bool scanZip = ( settings.value( "/qgis/scanZipInBrowser", QVariant( "basic" ) ).toString() != "no" );
|
||||
|
||||
QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
|
||||
foreach( QString subdir, entries )
|
||||
@ -497,8 +496,10 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
|
||||
QString path = dir.absoluteFilePath( name );
|
||||
QFileInfo fileInfo( path );
|
||||
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( path );
|
||||
// vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
|
||||
if ( fileInfo.suffix() == "zip" && scanZip )
|
||||
if (( settings.value( "/qgis/scanZipInBrowser", QVariant( "basic" ) ).toString() != "no" ) &&
|
||||
( vsiPrefix == "/vsizip/" || vsiPrefix == "/vsitar/" ) )
|
||||
{
|
||||
QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name );
|
||||
if ( item )
|
||||
@ -747,6 +748,7 @@ QgsZipItem::QgsZipItem( QgsDataItem* parent, QString name, QString path )
|
||||
{
|
||||
mType = Collection; //Zip??
|
||||
mIcon = iconZip();
|
||||
mVsiPrefix = vsiPrefix( path );
|
||||
|
||||
if ( mProviderNames.size() == 0 )
|
||||
{
|
||||
@ -796,7 +798,6 @@ QgsZipItem::QgsZipItem( QgsDataItem* parent, QString name, QString path )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QgsZipItem::~QgsZipItem()
|
||||
@ -879,13 +880,12 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
|
||||
QVector<QgsDataItem*> children;
|
||||
QString tmpPath;
|
||||
QString childPath;
|
||||
|
||||
QSettings settings;
|
||||
QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser", "basic" ).toString();
|
||||
|
||||
mZipFileList.clear();
|
||||
|
||||
QgsDebugMsg( QString( "path = %1 name= %2 scanZipSetting= %3" ).arg( path() ).arg( name() ).arg( scanZipSetting ) );
|
||||
QgsDebugMsg( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path() ).arg( name() ).arg( scanZipSetting ).arg( mVsiPrefix ) );
|
||||
|
||||
// if scanZipBrowser == no: skip to the next file
|
||||
if ( scanZipSetting == "no" )
|
||||
@ -901,31 +901,14 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
|
||||
// return children;
|
||||
// }
|
||||
|
||||
// get list of files inside zip file
|
||||
QgsDebugMsg( QString( "Open file %1 with gdal vsi" ).arg( path() ) );
|
||||
char **papszSiblingFiles = VSIReadDirRecursive1( QString( "/vsizip/" + path() ).toLocal8Bit().constData() );
|
||||
if ( papszSiblingFiles )
|
||||
{
|
||||
for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
|
||||
{
|
||||
tmpPath = papszSiblingFiles[i];
|
||||
QgsDebugMsg( QString( "Read file %1" ).arg( tmpPath ) );
|
||||
// skip directories (files ending with /)
|
||||
if ( tmpPath.right( 1 ) != "/" )
|
||||
mZipFileList << tmpPath;
|
||||
}
|
||||
CSLDestroy( papszSiblingFiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "Error reading %1" ).arg( path() ) );
|
||||
}
|
||||
// first get list of files
|
||||
getZipFileList();
|
||||
|
||||
// loop over files inside zip
|
||||
foreach( QString fileName, mZipFileList )
|
||||
{
|
||||
QFileInfo info( fileName );
|
||||
tmpPath = "/vsizip/" + path() + "/" + fileName;
|
||||
tmpPath = mVsiPrefix + path() + "/" + fileName;
|
||||
QgsDebugMsg( "tmpPath = " + tmpPath );
|
||||
|
||||
// foreach( dataItem_t *dataItem, mDataItemPtr )
|
||||
@ -934,7 +917,7 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
|
||||
// ugly hack to remove .dbf file if there is a .shp file
|
||||
if ( mProviderNames[i] == "ogr" )
|
||||
{
|
||||
if ( info.suffix() == "dbf" )
|
||||
if ( info.suffix().toLower() == "dbf" )
|
||||
{
|
||||
if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
|
||||
continue;
|
||||
@ -976,20 +959,38 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
|
||||
return children;
|
||||
}
|
||||
|
||||
|
||||
QString QgsZipItem::vsiPrefix( QString path )
|
||||
{
|
||||
if ( path.startsWith( "/vsizip/", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".zip", Qt::CaseInsensitive ) )
|
||||
return "/vsizip/";
|
||||
else if ( path.startsWith( "/vsitar/", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".tar", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".tar.gz", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".tgz", Qt::CaseInsensitive ) )
|
||||
return "/vsitar/";
|
||||
else if ( path.startsWith( "/vsigzip/", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
return "/vsigzip/";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QString name )
|
||||
{
|
||||
QSettings settings;
|
||||
QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser", "basic" ).toString();
|
||||
QString vsizipPath = path;
|
||||
QString vsiPath = path;
|
||||
int zipFileCount = 0;
|
||||
QStringList zipFileList;
|
||||
QFileInfo fileInfo( path );
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( path );
|
||||
QgsZipItem * zipItem = 0;
|
||||
bool populated = false;
|
||||
|
||||
QgsDebugMsg( QString( "path = %1 name= %2 scanZipSetting= %3" ).arg( path ).arg( name ).arg( scanZipSetting ) );
|
||||
QgsDebugMsg( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path ).arg( name ).arg( scanZipSetting ).arg( vsiPrefix ) );
|
||||
|
||||
// if scanZipBrowser == no: skip to the next file
|
||||
// if scanZipBrowser == no: don't read the zip file
|
||||
if ( scanZipSetting == "no" )
|
||||
{
|
||||
return 0;
|
||||
@ -1007,29 +1008,47 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
|
||||
|
||||
if ( zipItem )
|
||||
{
|
||||
// force populate zipItem
|
||||
zipItem->populate();
|
||||
QgsDebugMsg( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path() ).arg( zipItem->name() ) );
|
||||
// force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
|
||||
// for other items populating will be delayed until item is opened
|
||||
// this might be polluting the tree with empty items but is necessary for performance reasons
|
||||
// could also accept all files smaller than a certain size and add options for file count and/or size
|
||||
|
||||
// first get list of files inside .zip or .tar files
|
||||
if ( path.endsWith( ".zip", Qt::CaseInsensitive ) ||
|
||||
path.endsWith( ".tar", Qt::CaseInsensitive ) )
|
||||
{
|
||||
zipFileList = zipItem->getZipFileList();
|
||||
}
|
||||
// force populate if less than 10 items
|
||||
if ( zipFileList.count() > 0 && zipFileList.count() <= 10 )
|
||||
{
|
||||
zipItem->populate();
|
||||
populated = true; // there is no QgsDataItem::isPopulated() function
|
||||
QgsDebugMsg( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path() ).arg( zipItem->name() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path() ).arg( zipItem->name() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// only display if has children
|
||||
// other option would be to delay until item is opened, but we would be polluting the tree with empty items
|
||||
if ( zipItem && zipItem->rowCount() > 1 )
|
||||
// only display if has children or if is not populated
|
||||
if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
|
||||
{
|
||||
QgsDebugMsg( "returning zipItem" );
|
||||
return zipItem;
|
||||
}
|
||||
// if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
|
||||
// if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
|
||||
else
|
||||
{
|
||||
if ( zipItem )
|
||||
{
|
||||
vsizipPath = zipItem->path();
|
||||
zipFileCount = zipItem->getZipFileList().count();
|
||||
vsiPath = zipItem->path();
|
||||
zipFileCount = zipFileList.count();
|
||||
delete zipItem;
|
||||
}
|
||||
|
||||
QgsDebugMsg( QString( "will try to create a normal dataItem from path= %2 or %3" ).arg( path ).arg( vsizipPath ) );
|
||||
QgsDebugMsg( QString( "will try to create a normal dataItem from path= %2 or %3" ).arg( path ).arg( vsiPath ) );
|
||||
|
||||
// try to open using registered providers (gdal and ogr)
|
||||
for ( int i = 0; i < mProviderNames.size(); i++ )
|
||||
@ -1047,7 +1066,7 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
|
||||
item = dataItem( path, parent );
|
||||
// try with /vsizip/
|
||||
if ( ! item )
|
||||
item = dataItem( vsizipPath, parent );
|
||||
item = dataItem( vsiPath, parent );
|
||||
if ( item )
|
||||
return item;
|
||||
}
|
||||
@ -1056,3 +1075,43 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QStringList & QgsZipItem::getZipFileList()
|
||||
{
|
||||
if ( ! mZipFileList.isEmpty() )
|
||||
return mZipFileList;
|
||||
|
||||
QString tmpPath;
|
||||
QSettings settings;
|
||||
QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser", "basic" ).toString();
|
||||
|
||||
QgsDebugMsg( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path() ).arg( name() ).arg( scanZipSetting ).arg( mVsiPrefix ) );
|
||||
|
||||
// if scanZipBrowser == no: skip to the next file
|
||||
if ( scanZipSetting == "no" )
|
||||
{
|
||||
return mZipFileList;
|
||||
}
|
||||
|
||||
// get list of files inside zip file
|
||||
QgsDebugMsg( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + path() ) );
|
||||
char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + path() ).toLocal8Bit().constData() );
|
||||
if ( papszSiblingFiles )
|
||||
{
|
||||
for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
|
||||
{
|
||||
tmpPath = papszSiblingFiles[i];
|
||||
QgsDebugMsg( QString( "Read file %1" ).arg( tmpPath ) );
|
||||
// skip directories (files ending with /)
|
||||
if ( tmpPath.right( 1 ) != "/" )
|
||||
mZipFileList << tmpPath;
|
||||
}
|
||||
CSLDestroy( papszSiblingFiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "Error reading %1" ).arg( path() ) );
|
||||
}
|
||||
|
||||
return mZipFileList;
|
||||
}
|
||||
|
@ -298,6 +298,7 @@ class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
QString mVsiPrefix;
|
||||
QStringList mZipFileList;
|
||||
|
||||
public:
|
||||
@ -305,17 +306,17 @@ class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem
|
||||
~QgsZipItem();
|
||||
|
||||
QVector<QgsDataItem*> createChildren();
|
||||
QStringList getFiles();
|
||||
const QStringList & getZipFileList();
|
||||
|
||||
static QVector<dataItem_t *> mDataItemPtr;
|
||||
static QStringList mProviderNames;
|
||||
|
||||
static QString vsiPrefix( QString uri );
|
||||
|
||||
static QgsDataItem* itemFromPath( QgsDataItem* parent, QString path, QString name );
|
||||
|
||||
static const QIcon &iconZip();
|
||||
|
||||
const QStringList & getZipFileList() const { return mZipFileList; }
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSDATAITEM_H
|
||||
|
@ -642,6 +642,14 @@ QString QgsMapLayer::styleURI( )
|
||||
// ideally we should look for .qml file inside zip file
|
||||
myURI.remove( 0, 8 );
|
||||
}
|
||||
else if ( myURI.startsWith( "/vsitar/", Qt::CaseInsensitive ) &&
|
||||
( myURI.endsWith( ".tar", Qt::CaseInsensitive ) ||
|
||||
myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) ||
|
||||
myURI.endsWith( ".tgz", Qt::CaseInsensitive ) ) )
|
||||
{
|
||||
// ideally we should look for .qml file inside tar file
|
||||
myURI.remove( 0, 8 );
|
||||
}
|
||||
|
||||
QFileInfo myFileInfo( myURI );
|
||||
QString key;
|
||||
@ -650,15 +658,18 @@ QString QgsMapLayer::styleURI( )
|
||||
{
|
||||
// if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
|
||||
if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
{
|
||||
myURI.chop( 3 );
|
||||
myFileInfo.setFile( myURI );
|
||||
}
|
||||
else if ( myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
|
||||
{
|
||||
myURI.chop( 4 );
|
||||
myFileInfo.setFile( myURI );
|
||||
}
|
||||
else if ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) )
|
||||
myURI.chop( 4 );
|
||||
else if ( myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
|
||||
myURI.chop( 7 );
|
||||
else if ( myURI.endsWith( ".tgz", Qt::CaseInsensitive ) )
|
||||
myURI.chop( 4 );
|
||||
else if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
myURI.chop( 3 );
|
||||
myFileInfo.setFile( myURI );
|
||||
// get the file name for our .qml style file
|
||||
key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
|
||||
}
|
||||
|
@ -399,10 +399,10 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
// zip settings + info
|
||||
QSettings settings;
|
||||
QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser", "basic" ).toString();
|
||||
bool is_vsizip = ( thePath.startsWith( "/vsizip/" ) ||
|
||||
thePath.endsWith( ".zip", Qt::CaseInsensitive ) );
|
||||
bool is_vsigzip = ( thePath.startsWith( "/vsigzip/" ) ||
|
||||
thePath.endsWith( ".gz", Qt::CaseInsensitive ) );
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( thePath );
|
||||
bool is_vsizip = ( vsiPrefix == "/vsizip/" );
|
||||
bool is_vsigzip = ( vsiPrefix == "/vsigzip/" );
|
||||
bool is_vsitar = ( vsiPrefix == "/vsitar/" );
|
||||
|
||||
// get suffix, removing .gz if present
|
||||
QString tmpPath = thePath; //path used for testing, not for layer creation
|
||||
@ -414,10 +414,11 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
info.setFile( thePath );
|
||||
QString name = info.fileName();
|
||||
|
||||
QgsDebugMsg( "thePath= " + thePath + " tmpPath= " + tmpPath + " name= " + name + " suffix= " + suffix );
|
||||
QgsDebugMsg( "thePath= " + thePath + " tmpPath= " + tmpPath + " name= " + name
|
||||
+ " suffix= " + suffix + " vsiPrefix= " + vsiPrefix );
|
||||
|
||||
// allow only normal files or VSIFILE items to continue
|
||||
if ( !info.isFile() && !is_vsizip && !is_vsigzip )
|
||||
if ( !info.isFile() && vsiPrefix == "" )
|
||||
return 0;
|
||||
|
||||
// get supported extensions
|
||||
@ -434,10 +435,6 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
!extensions.contains( "aux.xml" ) )
|
||||
return 0;
|
||||
|
||||
// skip .tar.gz files
|
||||
if ( thePath.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
|
||||
return 0;
|
||||
|
||||
// Filter files by extension
|
||||
if ( !extensions.contains( suffix ) )
|
||||
{
|
||||
@ -455,30 +452,27 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add /vsizip/ or /vsigzip/ to path if file extension is .zip or .gz
|
||||
if ( is_vsigzip )
|
||||
// fix vsifile path and name
|
||||
if ( vsiPrefix != "" )
|
||||
{
|
||||
if ( !thePath.startsWith( "/vsigzip/" ) )
|
||||
thePath = "/vsigzip/" + thePath;
|
||||
}
|
||||
else if ( is_vsizip )
|
||||
{
|
||||
if ( !thePath.startsWith( "/vsizip/" ) )
|
||||
thePath = "/vsizip/" + thePath;
|
||||
// add vsiPrefix to path if needed
|
||||
if ( !thePath.startsWith( vsiPrefix ) )
|
||||
thePath = vsiPrefix + thePath;
|
||||
// if this is a /vsigzip/path_to_zip.zip/file_inside_zip remove the full path from the name
|
||||
if ( thePath != "/vsizip/" + parentItem->path() )
|
||||
if (( is_vsizip || is_vsitar ) && ( thePath != vsiPrefix + parentItem->path() ) )
|
||||
{
|
||||
name = thePath;
|
||||
name = name.replace( "/vsizip/" + parentItem->path() + "/", "" );
|
||||
name = name.replace( vsiPrefix + parentItem->path() + "/", "" );
|
||||
}
|
||||
}
|
||||
|
||||
// return a /vsizip/ item without testing if:
|
||||
// zipfile and scan zip == "Basic scan"
|
||||
// not zipfile and scan items == "Check extension"
|
||||
if (( is_vsizip && scanZipSetting == "basic" ) ||
|
||||
( !is_vsizip && ( settings.value( "/qgis/scanItemsInBrowser",
|
||||
"extension" ).toString() == "extension" ) ) )
|
||||
if ((( is_vsizip || is_vsitar ) && scanZipSetting == "basic" ) ||
|
||||
( !is_vsizip && !is_vsitar &&
|
||||
( settings.value( "/qgis/scanItemsInBrowser",
|
||||
"extension" ).toString() == "extension" ) ) )
|
||||
{
|
||||
// if this is a VRT file make sure it is raster VRT to avoid duplicates
|
||||
if ( suffix == "vrt" )
|
||||
|
@ -111,19 +111,12 @@ QgsGdalProvider::QgsGdalProvider( QString const & uri )
|
||||
mGdalDataset = NULL;
|
||||
|
||||
// Try to open using VSIFileHandler (see qgsogrprovider.cpp)
|
||||
// TODO suppress error messages and report in debug, like in OGR provider
|
||||
// TODO use the file name of the file inside the zip, needs unzip.h
|
||||
if ( uri.endsWith( ".zip", Qt::CaseInsensitive ) )
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( uri );
|
||||
if ( vsiPrefix != "" )
|
||||
{
|
||||
if ( !uri.startsWith( "/vsizip/" ) )
|
||||
setDataSourceUri( "/vsizip/" + uri );
|
||||
QgsDebugMsg( QString( "Trying /vsizip syntax, uri= %1" ).arg( dataSourceUri() ) );
|
||||
}
|
||||
else if ( uri.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
{
|
||||
if ( !uri.startsWith( "/vsigzip/" ) )
|
||||
setDataSourceUri( "/vsigzip/" + uri );
|
||||
QgsDebugMsg( QString( "Trying /vsigzip syntax, uri= %1" ).arg( dataSourceUri() ) );
|
||||
if ( !uri.startsWith( vsiPrefix ) )
|
||||
setDataSourceUri( vsiPrefix + uri );
|
||||
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix ).arg( dataSourceUri() ) );
|
||||
}
|
||||
|
||||
// The uri is either a file name or encoded parameters for WCS
|
||||
@ -1920,8 +1913,9 @@ void buildSupportedRasterFileFilterAndExtensions( QString & theFileFiltersString
|
||||
{
|
||||
QString glob = "*.zip";
|
||||
glob += " *.gz";
|
||||
glob += " *.tar *.tar.gz *.tgz";
|
||||
theFileFiltersString += ";;[GDAL] " + QObject::tr( "GDAL/OGR VSIFileHandler" ) + " (" + glob.toLower() + " " + glob.toUpper() + ")";
|
||||
theExtensions << "zip" << "gz";
|
||||
theExtensions << "zip" << "gz" << "tar" << "tar.gz" << "tgz";
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1940,21 +1934,12 @@ QGISEXTERN bool isValidRasterFileName( QString const & theFileNameQString, QStri
|
||||
|
||||
// Try to open using VSIFileHandler (see qgsogrprovider.cpp)
|
||||
// TODO suppress error messages and report in debug, like in OGR provider
|
||||
if ( fileName.endsWith( ".zip", Qt::CaseInsensitive ) )
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( fileName );
|
||||
if ( vsiPrefix != "" )
|
||||
{
|
||||
if ( !fileName.startsWith( "/vsizip/" ) )
|
||||
{
|
||||
fileName = "/vsizip/" + fileName;
|
||||
}
|
||||
QgsDebugMsg( QString( "Trying /vsizip syntax, fileName= %1" ).arg( fileName ) );
|
||||
}
|
||||
if ( fileName.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
{
|
||||
if ( !fileName.startsWith( "/vsigzip/" ) )
|
||||
{
|
||||
fileName = "/vsigzip/" + fileName;
|
||||
}
|
||||
QgsDebugMsg( QString( "Trying /vsigzip syntax, fileName= %1" ).arg( fileName ) );
|
||||
if ( !fileName.startsWith( vsiPrefix ) )
|
||||
fileName = vsiPrefix + fileName;
|
||||
QgsDebugMsg( QString( "Trying %1 syntax, fileName= %2" ).arg( vsiPrefix ).arg( fileName ) );
|
||||
}
|
||||
|
||||
//open the file using gdal making sure we have handled locale properly
|
||||
|
@ -240,10 +240,10 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
// zip settings + info
|
||||
QSettings settings;
|
||||
QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser", "basic" ).toString();
|
||||
bool is_vsizip = ( thePath.startsWith( "/vsizip/" ) ||
|
||||
thePath.endsWith( ".zip", Qt::CaseInsensitive ) );
|
||||
bool is_vsigzip = ( thePath.startsWith( "/vsigzip/" ) ||
|
||||
thePath.endsWith( ".gz", Qt::CaseInsensitive ) );
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( thePath );
|
||||
bool is_vsizip = ( vsiPrefix == "/vsizip/" );
|
||||
bool is_vsigzip = ( vsiPrefix == "/vsigzip/" );
|
||||
bool is_vsitar = ( vsiPrefix == "/vsitar/" );
|
||||
|
||||
// get suffix, removing .gz if present
|
||||
QString tmpPath = thePath; //path used for testing, not for layer creation
|
||||
@ -255,10 +255,11 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
info.setFile( thePath );
|
||||
QString name = info.fileName();
|
||||
|
||||
QgsDebugMsg( "thePath= " + thePath + " tmpPath= " + tmpPath + " name= " + name + " suffix= " + suffix );
|
||||
QgsDebugMsg( "thePath= " + thePath + " tmpPath= " + tmpPath + " name= " + name
|
||||
+ " suffix= " + suffix + " vsiPrefix= " + vsiPrefix );
|
||||
|
||||
// allow only normal files or VSIFILE items to continue
|
||||
if ( !info.isFile() && !is_vsizip && !is_vsigzip )
|
||||
if ( !info.isFile() && vsiPrefix == "" )
|
||||
return 0;
|
||||
|
||||
QStringList myExtensions = fileExtensions();
|
||||
@ -272,10 +273,6 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
!myExtensions.contains( "shp.xml" ) )
|
||||
return 0;
|
||||
|
||||
// skip .tar.gz files
|
||||
if ( thePath.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
|
||||
return 0;
|
||||
|
||||
// We have to filter by extensions, otherwise e.g. all Shapefile files are displayed
|
||||
// because OGR drive can open also .dbf, .shx.
|
||||
if ( myExtensions.indexOf( suffix ) < 0 )
|
||||
@ -302,30 +299,27 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add /vsizip/ or /vsigzip/ to path if file extension is .zip or .gz
|
||||
if ( is_vsigzip )
|
||||
// fix vsifile path and name
|
||||
if ( vsiPrefix != "" )
|
||||
{
|
||||
if ( !thePath.startsWith( "/vsigzip/" ) )
|
||||
thePath = "/vsigzip/" + thePath;
|
||||
}
|
||||
else if ( is_vsizip )
|
||||
{
|
||||
if ( !thePath.startsWith( "/vsizip/" ) )
|
||||
thePath = "/vsizip/" + thePath;
|
||||
// add vsiPrefix to path if needed
|
||||
if ( !thePath.startsWith( vsiPrefix ) )
|
||||
thePath = vsiPrefix + thePath;
|
||||
// if this is a /vsigzip/path_to_zip.zip/file_inside_zip remove the full path from the name
|
||||
if ( thePath != "/vsizip/" + parentItem->path() )
|
||||
if (( is_vsizip || is_vsitar ) && ( thePath != vsiPrefix + parentItem->path() ) )
|
||||
{
|
||||
name = thePath;
|
||||
name = name.replace( "/vsizip/" + parentItem->path() + "/", "" );
|
||||
name = name.replace( vsiPrefix + parentItem->path() + "/", "" );
|
||||
}
|
||||
}
|
||||
|
||||
// return a /vsizip/ item without testing if:
|
||||
// zipfile and scan zip == "Basic scan"
|
||||
// not zipfile and scan items == "Check extension"
|
||||
if (( is_vsizip && scanZipSetting == "basic" ) ||
|
||||
( !is_vsizip && ( settings.value( "/qgis/scanItemsInBrowser",
|
||||
"extension" ).toString() == "extension" ) ) )
|
||||
if ((( is_vsizip || is_vsitar ) && scanZipSetting == "basic" ) ||
|
||||
( !is_vsizip && !is_vsitar &&
|
||||
( settings.value( "/qgis/scanItemsInBrowser",
|
||||
"extension" ).toString() == "extension" ) ) )
|
||||
{
|
||||
// if this is a VRT file make sure it is vector VRT to avoid duplicates
|
||||
if ( suffix == "vrt" )
|
||||
|
@ -264,26 +264,18 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
|
||||
|
||||
// Try to open using VSIFileHandler
|
||||
// see http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
|
||||
if ( mFilePath.endsWith( ".zip", Qt::CaseInsensitive ) )
|
||||
QString vsiPrefix = QgsZipItem::vsiPrefix( uri );
|
||||
if ( vsiPrefix != "" )
|
||||
{
|
||||
// GDAL>=1.8.0 has write support for zip, but read and write operations
|
||||
// cannot be interleaved, so for now just use read-only.
|
||||
openReadOnly = true;
|
||||
if ( !mFilePath.startsWith( "/vsizip/" ) )
|
||||
if ( !mFilePath.startsWith( vsiPrefix ) )
|
||||
{
|
||||
mFilePath = "/vsizip/" + mFilePath;
|
||||
mFilePath = vsiPrefix + mFilePath;
|
||||
setDataSourceUri( mFilePath );
|
||||
}
|
||||
QgsDebugMsg( QString( "Trying /vsizip syntax, mFilePath= %1" ).arg( mFilePath ) );
|
||||
}
|
||||
else if ( mFilePath.endsWith( ".gz", Qt::CaseInsensitive ) )
|
||||
{
|
||||
if ( !mFilePath.startsWith( "/vsigzip/" ) )
|
||||
{
|
||||
mFilePath = "/vsigzip/" + mFilePath;
|
||||
setDataSourceUri( mFilePath );
|
||||
}
|
||||
QgsDebugMsg( QString( "Trying /vsigzip syntax, mFilePath= %1" ).arg( mFilePath ) );
|
||||
QgsDebugMsg( QString( "Trying %1 syntax, mFilePath= %2" ).arg( vsiPrefix ).arg( mFilePath ) );
|
||||
}
|
||||
|
||||
QgsDebugMsg( "mFilePath: " + mFilePath );
|
||||
@ -1792,16 +1784,14 @@ QString createFilters( QString type )
|
||||
// VSIFileHandler (.zip and .gz files)
|
||||
// see http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
|
||||
// Requires GDAL>=1.6.0 with libz support, let's assume we have it.
|
||||
// For .zip this works only if there is one file (or dataset) in the root of the zip.
|
||||
// Only tested with tiff, shape (zip) and spatialite (zip and gz).
|
||||
// This does not work for some file types, see VSIFileHandler doc.
|
||||
// Ideally we should also add support for /vsitar/ (requires cpl_vsil_tar.cpp).
|
||||
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1600
|
||||
QSettings settings;
|
||||
if ( settings.value( "/qgis/scanZipInBrowser", "basic" ).toString() != "no" )
|
||||
{
|
||||
myFileFilters += createFileFilter_( QObject::tr( "GDAL/OGR VSIFileHandler" ), "*.zip *.gz" );
|
||||
myExtensions << "zip" << "gz";
|
||||
myFileFilters += createFileFilter_( QObject::tr( "GDAL/OGR VSIFileHandler" ), "*.zip *.gz *.tar *.tar.gz *.tgz" );
|
||||
myExtensions << "zip" << "gz" << "tar" << "tar.gz" << "tgz";
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -53,6 +53,7 @@ class TestZipLayer: public QObject
|
||||
bool testZipItem( QString myFileName, QString myChildName = "", QString myDriverName = "" );
|
||||
// get layer transparency to test for .qml loading
|
||||
int getLayerTransparency( QString myFileName, QString myProviderKey, QString myScanZipSetting = "basic" );
|
||||
bool testZipItemTransparency( QString myFileName, QString myProviderKey, int myTarget );
|
||||
|
||||
private slots:
|
||||
|
||||
@ -65,20 +66,28 @@ class TestZipLayer: public QObject
|
||||
// tests
|
||||
// test for .zip and .gz files using all options
|
||||
void testPassthruVectorZip();
|
||||
void testPassthruVectorTar();
|
||||
void testPassthruVectorGzip();
|
||||
void testPassthruRasterZip();
|
||||
void testPassthruRasterTar();
|
||||
void testPassthruRasterGzip();
|
||||
// test both "Basic Scan" and "Full scan" for .zip files
|
||||
void testZipItemRaster();
|
||||
void testTarItemRaster();
|
||||
void testZipItemVector();
|
||||
void testTarItemVector();
|
||||
void testZipItemAll();
|
||||
void testTarItemAll();
|
||||
// test that styles are loaded from .qml files outside zip files
|
||||
void testZipItemVectorTransparency();
|
||||
void testGZipItemVectorTransparency();
|
||||
void testTarItemVectorTransparency();
|
||||
void testGzipItemVectorTransparency();
|
||||
void testZipItemRasterTransparency();
|
||||
void testGZipItemRasterTransparency();
|
||||
void testTarItemRasterTransparency();
|
||||
void testGzipItemRasterTransparency();
|
||||
//make sure items inside subfolders can be read
|
||||
void testZipItemSubfolder();
|
||||
void testTarItemSubfolder();
|
||||
//make sure .vrt items are loaded by proper provider (gdal/ogr)
|
||||
void testZipItemVRT();
|
||||
};
|
||||
@ -225,6 +234,21 @@ int TestZipLayer::getLayerTransparency( QString myFileName, QString myProviderKe
|
||||
return myTransparency;
|
||||
}
|
||||
|
||||
bool TestZipLayer::testZipItemTransparency( QString myFileName, QString myProviderKey, int myTarget )
|
||||
{
|
||||
int myTransparency;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
myTransparency = getLayerTransparency( myFileName, myProviderKey, s );
|
||||
if ( myTransparency != myTarget )
|
||||
{
|
||||
QWARN( QString( "Transparency of %1 is %2, should be %3" ).arg( myFileName ).arg( myTransparency ).arg( myTarget ).toLocal8Bit().data() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// slots
|
||||
void TestZipLayer::initTestCase()
|
||||
@ -257,7 +281,6 @@ void TestZipLayer::cleanupTestCase()
|
||||
settings.setValue( "/qgis/scanZipInBrowser", mScanZipSetting );
|
||||
}
|
||||
|
||||
|
||||
void TestZipLayer::testPassthruVectorZip()
|
||||
{
|
||||
QSettings settings;
|
||||
@ -275,6 +298,21 @@ void TestZipLayer::testPassthruVectorZip()
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testPassthruVectorTar()
|
||||
{
|
||||
QSettings settings;
|
||||
QString myFileName = mDataDir + "points2.tar";
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
settings.setValue( "/qgis/scanZipInBrowser", s );
|
||||
QVERIFY( s == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItemPassthru( myFileName, "ogr" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testPassthruVectorGzip()
|
||||
{
|
||||
QSettings settings;
|
||||
@ -300,6 +338,20 @@ void TestZipLayer::testPassthruRasterZip()
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testPassthruRasterTar()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QSettings settings;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
settings.setValue( "/qgis/scanZipInBrowser", s );
|
||||
QVERIFY( s == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItemPassthru( mDataDir + "landsat_b1.tar", "gdal" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testPassthruRasterGzip()
|
||||
{
|
||||
QSettings settings;
|
||||
@ -322,6 +374,20 @@ void TestZipLayer::testZipItemRaster()
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testTarItemRaster()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QSettings settings;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
settings.setValue( "/qgis/scanZipInBrowser", s );
|
||||
QVERIFY( s == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItem( mDataDir + "testtar.tgz", "landsat_b1.tif" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testZipItemVector()
|
||||
{
|
||||
QSettings settings;
|
||||
@ -333,6 +399,20 @@ void TestZipLayer::testZipItemVector()
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testTarItemVector()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QSettings settings;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
settings.setValue( "/qgis/scanZipInBrowser", s );
|
||||
QVERIFY( s == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItem( mDataDir + "testtar.tgz", "points.shp" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testZipItemAll()
|
||||
{
|
||||
// test file contains invalid items (tmp1.tif, tmp1.txt and tmp1.xml)
|
||||
@ -345,55 +425,57 @@ void TestZipLayer::testZipItemAll()
|
||||
QVERIFY( testZipItem( mDataDir + "testzip.zip", "" ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testTarItemAll()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QSettings settings;
|
||||
settings.setValue( "/qgis/scanZipInBrowser", "full" );
|
||||
QVERIFY( "full" == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItem( mDataDir + "testtar.tgz", "" ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testZipItemVectorTransparency()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
int myTarget = 250;
|
||||
int myTransparency;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
myTransparency = getLayerTransparency( mDataDir + "points2.zip", "ogr", "basic" );
|
||||
QVERIFY2(( myTransparency == myTarget ), QString( "Transparency is %1, should be %2" ).arg( myTransparency ).arg( myTarget ).toLocal8Bit().data() );
|
||||
}
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "points2.zip", "ogr", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testGZipItemVectorTransparency()
|
||||
void TestZipLayer::testTarItemVectorTransparency()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "points2.tar", "ogr", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testGzipItemVectorTransparency()
|
||||
{
|
||||
#if GDAL_VERSION_NUM < 1700
|
||||
QSKIP( "This test requires GDAL >= 1.7", SkipSingle );
|
||||
#endif
|
||||
int myTarget = 250;
|
||||
int myTransparency;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
myTransparency = getLayerTransparency( mDataDir + "points3.geojson.gz", "ogr", s );
|
||||
QVERIFY2(( myTransparency == myTarget ), QString( "Transparency is %1, should be %2" ).arg( myTransparency ).arg( myTarget ).toLocal8Bit().data() );
|
||||
}
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "points3.geojson.gz", "ogr", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testZipItemRasterTransparency()
|
||||
{
|
||||
int myTarget = 250;
|
||||
int myTransparency;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
myTransparency = getLayerTransparency( mDataDir + "landsat_b1.zip", "gdal", s );
|
||||
QVERIFY2(( myTransparency == myTarget ), QString( "Transparency is %1, should be %2" ).arg( myTransparency ).arg( myTarget ).toLocal8Bit().data() );
|
||||
}
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "landsat_b1.zip", "gdal", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testGZipItemRasterTransparency()
|
||||
void TestZipLayer::testTarItemRasterTransparency()
|
||||
{
|
||||
int myTarget = 250;
|
||||
int myTransparency;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
myTransparency = getLayerTransparency( mDataDir + "landsat_b1.tif.gz", "gdal", s );
|
||||
QVERIFY2(( myTransparency == myTarget ), QString( "Transparency is %1, should be %2" ).arg( myTransparency ).arg( myTarget ).toLocal8Bit().data() );
|
||||
}
|
||||
#if GDAL_VERSION_NUM < 1800
|
||||
QSKIP( "This test requires GDAL >= 1.8", SkipSingle );
|
||||
#endif
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "landsat_b1.tar", "gdal", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testGzipItemRasterTransparency()
|
||||
{
|
||||
QVERIFY( testZipItemTransparency( mDataDir + "landsat_b1.tif.gz", "gdal", 250 ) );
|
||||
}
|
||||
|
||||
void TestZipLayer::testZipItemSubfolder()
|
||||
@ -407,6 +489,17 @@ void TestZipLayer::testZipItemSubfolder()
|
||||
}
|
||||
}
|
||||
|
||||
void TestZipLayer::testTarItemSubfolder()
|
||||
{
|
||||
QSettings settings;
|
||||
foreach( QString s, mScanZipSettings )
|
||||
{
|
||||
settings.setValue( "/qgis/scanZipInBrowser", s );
|
||||
QVERIFY( s == settings.value( "/qgis/scanZipInBrowser" ).toString() );
|
||||
QVERIFY( testZipItem( mDataDir + "testtar.tgz", "folder/folder2/landsat_b2.tif" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestZipLayer::testZipItemVRT()
|
||||
{
|
||||
|
BIN
tests/testdata/landsat_b1.tar
vendored
Normal file
BIN
tests/testdata/landsat_b1.tar
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/points2.tar
vendored
Normal file
BIN
tests/testdata/points2.tar
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/testtar.tgz
vendored
Normal file
BIN
tests/testdata/testtar.tgz
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user