287 changes: 280 additions & 7 deletions src/core/qgsdataitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include "qgslogger.h"
#include "qgsproviderregistry.h"

// use internal quazip for /vsizip support
#define QUAZIP_STATIC
#include <quazip/quazip.h>

// shared icons
const QIcon &QgsLayerItem::iconPoint()
{
Expand Down Expand Up @@ -125,14 +129,25 @@ const QIcon &QgsDataCollectionItem::iconDir()
const QIcon &QgsFavouritesItem::iconFavourites()
{
static QIcon icon;

if ( icon.isNull() )
icon = QIcon( getThemePixmap( "/mIconFavourites.png" ) );
// this icon added by ET, modfied mIconNew and set colour to that of folder icon

return icon;
}

const QIcon &QgsZipItem::iconZip()
{
static QIcon icon;

if ( icon.isNull() )
icon = QIcon( getThemePixmap( "/mIconZip.png" ) );
// icon from http://www.softicons.com/free-icons/application-icons/mega-pack-icons-1-by-nikolay-verin/winzip-folder-icon

return icon;
}


QgsDataItem::QgsDataItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path )
: QObject( parent ), mType( type ), mParent( parent ), mPopulated( false ), mName( name ), mPath( path )
{
Expand All @@ -144,8 +159,10 @@ QPixmap QgsDataItem::getThemePixmap( const QString theName )
{
QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName;
QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName;
//QgsDebugMsg( "myPreferredPath = " + myPreferredPath );
//QgsDebugMsg( "myDefaultPath = " + myDefaultPath );

// QgsDebugMsg( "theName = " + theName );
// QgsDebugMsg( "myPreferredPath = " + myPreferredPath );
// QgsDebugMsg( "myDefaultPath = " + myDefaultPath );
if ( QFile::exists( myPreferredPath ) )
{
return QPixmap( myPreferredPath );
Expand Down Expand Up @@ -214,7 +231,7 @@ bool QgsDataItem::hasChildren()

void QgsDataItem::addChildItem( QgsDataItem * child, bool refresh )
{
QgsDebugMsg( QString( "add child #%1 - %2" ).arg( mChildren.size() ).arg( child->mName ) );
QgsDebugMsg( QString( "add child #%1 - %2 - %3" ).arg( mChildren.size() ).arg( child->mName ).arg( child->mType ) );

int i;
if ( type() == Directory )
Expand Down Expand Up @@ -334,6 +351,8 @@ QgsLayerItem::QgsLayerItem( QgsDataItem* parent, QString name, QString path, QSt
case Point: mIcon = iconPoint(); break;
case Line: mIcon = iconLine(); break;
case Polygon: mIcon = iconPolygon(); break;
// TODO add a new icon for generic Vector layers
case Vector : mIcon = iconPolygon(); break;
case TableLayer: mIcon = iconTable(); break;
case Raster: mIcon = iconRaster(); break;
default: mIcon = iconDefault(); break;
Expand Down Expand Up @@ -373,7 +392,7 @@ QgsDataCollectionItem::~QgsDataCollectionItem()
}

//-----------------------------------------------------------------------
QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
// QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
QVector<QLibrary*> QgsDirectoryItem::mLibraries = QVector<QLibrary*>();


Expand Down Expand Up @@ -406,6 +425,7 @@ QgsDirectoryItem::QgsDirectoryItem( QgsDataItem* parent, QString name, QString p
QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
continue;
}

QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
mLibraries.append( library );
}
Expand All @@ -425,11 +445,14 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
{
QVector<QgsDataItem*> children;
QDir dir( mPath );
QSettings settings;
bool scanZip = ( settings.value( "/qgis/scanZipInBrowser", 1 ).toInt() != 0 );

QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
foreach( QString subdir, entries )
{
QString subdirPath = dir.absoluteFilePath( subdir );
qDebug( "creating subdir: %s", subdirPath.toAscii().data() );
QgsDebugMsg( QString( "creating subdir: %1" ).arg( subdirPath ) );

QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath );
// propagate signals up to top
Expand All @@ -442,6 +465,20 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
{
QString path = dir.absoluteFilePath( name );
QFileInfo fileInfo( path );

// vsizip support was added to GDAL/OGR 1.6 but this symbol not available here
// #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1600
if ( fileInfo.suffix() == "zip" && scanZip )
{
QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name );
if ( item )
{
children.append( item );
continue;
}
}
// #endif

foreach( QLibrary *library, mLibraries )
{
// we could/should create separate list of providers for each purpose
Expand Down Expand Up @@ -475,6 +512,7 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
}
}
}

return children;
}

Expand Down Expand Up @@ -669,3 +707,238 @@ QVector<QgsDataItem*> QgsFavouritesItem::createChildren( )

return children;
}

//-----------------------------------------------------------------------
QStringList QgsZipItem::mProviderNames = QStringList();
QVector<dataItem_t *> QgsZipItem::mDataItemPtr = QVector<dataItem_t*>();


QgsZipItem::QgsZipItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mType = Collection; //Zip??
mIcon = iconZip();

if ( mProviderNames.size() == 0 )
{
// QStringList keys = QgsProviderRegistry::instance()->providerList();
// only use GDAL and OGR providers as we use the VSIFILE mechanism
QStringList keys;
// keys << "ogr" << "gdal";
keys << "gdal" << "ogr";

QStringList::const_iterator i;
for ( i = keys.begin(); i != keys.end(); ++i )
{
QString k( *i );
QgsDebugMsg( "provider " + k );
// some providers hangs with empty uri (Postgis) etc...
// -> using libraries directly
QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( k );
if ( library )
{
dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) );
if ( !dataCapabilities )
{
QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
continue;
}
if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
{
QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
continue;
}
QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );

dataItem_t * dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) );
if ( ! dataItem )
{
QgsDebugMsg( library->fileName() + " does not have dataItem" );
continue;
}

// mLibraries.append( library );
mDataItemPtr.append( dataItem );
mProviderNames.append( k );
}
else
{
//QgsDebugMsg ( "Cannot get provider " + k );
}
}
}

}

QgsZipItem::~QgsZipItem()
{
}

QVector<QgsDataItem*> QgsZipItem::createChildren( )
{
QVector<QgsDataItem*> children;
QStringList fileList;
QString tmpPath;
QString childPath;

QSettings settings;
int scanZipSetting = settings.value( "/qgis/scanZipInBrowser", 1 ).toInt();

if ( scanZipSetting == 0 )
{
return children;
}
// if scanZipBrowser == "Passthru": do not scan zip and allow to open directly with /vsigzip/
if ( scanZipSetting == 2 )
{
mPath = "/vsizip/" + path(); // should check for extension
QgsDebugMsg( "set path to " + path() );
return children;
}

// get list of files inside zip file
QuaZip zip( path() );
if ( ! zip.open( QuaZip::mdUnzip ) || ! zip.isOpen() )
{
QgsDebugMsg( QString( "Zip error: %1" ).arg( zip.getZipError() ) );
}
else
{
for ( bool more = zip.goToFirstFile(); more; more = zip.goToNextFile() )
{
// tmpPath = "/vsizip/" + path() + "/" + zip.getCurrentFileName();
// QgsDebugMsg( QString( "file %1 - %2" ).arg( zip.getCurrentFileName() ).arg( tmpPath ) );
tmpPath = zip.getCurrentFileName();
// skip directories (files ending with /)
if ( tmpPath.right( 1 ) != "/" )
fileList << tmpPath;
}
}
zip.close();
if ( zip.getZipError() != UNZ_OK )
{
QgsDebugMsg( QString( "Zip error: %1" ).arg( zip.getZipError() ) );
}

// loop over files inside zip
foreach( QString fileName, fileList )
{
QFileInfo info( fileName );
tmpPath = "/vsizip/" + path() + "/" + fileName;
QgsDebugMsg( "tmpPath = " + tmpPath );

// foreach( dataItem_t *dataItem, mDataItemPtr )
for ( int i = 0; i < mProviderNames.size(); i++ )
{
// ugly hack to remove .dbf file if there is a .shp file
if ( mProviderNames[i] == "ogr" )
{
if ( info.suffix() == "dbf" )
{
if ( fileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
continue;
}
if ( info.completeSuffix().toLower() == "shp.xml" )
{
continue;
}
}

// try to get data item from provider
dataItem_t *dataItem = mDataItemPtr[i];
if ( dataItem )
{
QgsDebugMsg( QString( "trying to load item %1 with %2" ).arg( tmpPath ).arg( mProviderNames[i] ) );
QgsDataItem * item = dataItem( tmpPath, this );
if ( item )
{
QgsDebugMsg( "loaded item" );
childPath = tmpPath;
children.append( item );
break;
}
else
{
QgsDebugMsg( "not loaded item" );
}
}
}

}

if ( children.size() == 1 )
{
// save the name of the only child so we can get a normal data item from it
mPath = childPath;
}

return children;
}



QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QString name )
{

QSettings settings;
int scanZipSetting = settings.value( "/qgis/scanZipInBrowser", 1 ).toInt();
QFileInfo fileInfo( path );
QString tmpPath = path;
QgsZipItem * zipItem = 0;

QgsDebugMsg( "path = " + path + " name= " + name );

// if scanZipBrowser == 0 (No): skip to the next file
if ( scanZipSetting == 0 )
{
return 0;
}
// if scanZipBrowser == 2 (Passthru): do not scan zip and allow to open directly with /vsigzip/
else if ( scanZipSetting == 2 )
{
tmpPath = "/vsizip/" + path;
zipItem = 0;
}
else
{
zipItem = new QgsZipItem( parent, name, path );
}

if ( zipItem )
{
QgsDebugMsg( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).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 )
{
QgsDebugMsg( "returning zipItem" );
return zipItem;
}
// if 1 or 0 child found, create a data item using the full path given by QgsZipItem
else
{
if ( zipItem )
{
tmpPath = zipItem->path();
delete zipItem;
}

QgsDebugMsg( QString( "will try to create a normal dataItem from path= %2" ).arg( tmpPath ) );

// try to open using registered providers (gdal and ogr)
for ( int i = 0; i < mProviderNames.size(); i++ )
{
dataItem_t *dataItem = mDataItemPtr[i];
if ( dataItem )
{
QgsDataItem *item = dataItem( tmpPath, parent );
if ( item )
return item;
}
}
}

return 0;
}
23 changes: 21 additions & 2 deletions src/core/qgsdataitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ typedef int dataCapabilities_t();
typedef QgsDataItem * dataItem_t( QString, QgsDataItem* );



/** base class for all items in the model */
class CORE_EXPORT QgsDataItem : public QObject
{
Expand Down Expand Up @@ -236,7 +235,7 @@ class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem

virtual QWidget * paramWidget();

static QVector<QgsDataProvider*> mProviders;
/* static QVector<QgsDataProvider*> mProviders; */
static QVector<QLibrary*> mLibraries;
};

Expand Down Expand Up @@ -281,8 +280,28 @@ class CORE_EXPORT QgsFavouritesItem : public QgsDataCollectionItem
~QgsFavouritesItem();

QVector<QgsDataItem*> createChildren();

static const QIcon &iconFavourites();
};

/** A zip file: contains layers, using GDAL/OGR VSIFILE mechanism */
class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsZipItem( QgsDataItem* parent, QString name, QString path );
~QgsZipItem();

QVector<QgsDataItem*> createChildren();
QStringList getFiles();

static QVector<dataItem_t *> mDataItemPtr;
static QStringList mProviderNames;

static QgsDataItem* itemFromPath( QgsDataItem* parent, QString path, QString name );

static const QIcon &iconZip();
};

#endif // QGSDATAITEM_H

140 changes: 87 additions & 53 deletions src/providers/gdal/qgsgdaldataitems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "qgslogger.h"

#include <QFileInfo>
#include <QSettings>

// defined in qgsgdalprovider.cpp
void buildSupportedRasterFileFilterAndExtensions( QString & theFileFiltersString, QStringList & theExtensions, QStringList & theWildcards );
Expand Down Expand Up @@ -90,6 +91,7 @@ QVector<QgsDataItem*> QgsGdalLayerItem::createChildren( )

// ---------------------------------------------------------------------------

static QString filterString;
static QStringList extensions = QStringList();
static QStringList wildcards = QStringList();

Expand All @@ -103,79 +105,111 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
if ( thePath.isEmpty() )
return 0;

QgsDebugMsg( "thePath= " + thePath );

QString uri = thePath;
QFileInfo info( thePath );
if ( info.isFile() )
QSettings settings;
//extract basename with extension
QString name = info.fileName();
int scanZipSetting = settings.value( "/qgis/scanZipInBrowser", 1 ).toInt();

// allow normal files or VSIFILE items to pass
if ( ! info.isFile() &&
thePath.left( 8 ) != "/vsizip/" &&
thePath.left( 9 ) != "/vsigzip/" )
return 0;

// get supported extensions
if ( extensions.isEmpty() )
{
// get supported extensions
if ( extensions.isEmpty() )
{
QString filterString;
buildSupportedRasterFileFilterAndExtensions( filterString, extensions, wildcards );
QgsDebugMsg( "extensions: " + extensions.join( " " ) );
QgsDebugMsg( "wildcards: " + wildcards.join( " " ) );
}
buildSupportedRasterFileFilterAndExtensions( filterString, extensions, wildcards );
QgsDebugMsg( "extensions: " + extensions.join( " " ) );
QgsDebugMsg( "wildcards: " + wildcards.join( " " ) );
}

// skip *.aux.xml files (GDAL auxilary metadata files)
// unless that extension is in the list (*.xml might be though)
if ( thePath.right( 8 ) == ".aux.xml" &&
extensions.indexOf( "aux.xml" ) < 0 )
return 0;
// skip *.aux.xml files (GDAL auxilary metadata files)
// unless that extension is in the list (*.xml might be though)
if ( thePath.right( 8 ).toLower() == ".aux.xml" &&
extensions.indexOf( "aux.xml" ) < 0 )
return 0;

// skip .tar.gz files
if ( thePath.right( 7 ) == ".tar.gz" )
return 0;
// skip .tar.gz files
if ( thePath.right( 7 ) == ".tar.gz" )
return 0;

// Filter files by extension
if ( extensions.indexOf( info.suffix().toLower() ) < 0 )
// Filter files by extension
if ( extensions.indexOf( info.suffix().toLower() ) < 0 )
{
bool matches = false;
foreach( QString wildcard, wildcards )
{
bool matches = false;
foreach( QString wildcard, wildcards )
QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
if ( rx.exactMatch( info.fileName() ) )
{
QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
if ( rx.exactMatch( info.fileName() ) )
{
matches = true;
break;
}
matches = true;
break;
}
if ( !matches )
return 0;
}
if ( !matches )
return 0;
}

// try to open using VSIFileHandler
// TODO use the file name of the file inside the zip for layer name
if ( thePath.right( 4 ) == ".zip" )
// vsifile : depending on options we should just add the item without testing
if ( thePath.left( 8 ) == "/vsizip/" )
{
// if this is a /vsigzip/path.zip/file_inside_zip change the name
if ( thePath != "/vsizip/" + parentItem->path() )
{
if ( thePath.left( 8 ) != "/vsizip/" )
thePath = "/vsizip/" + thePath;
name = thePath;
name = name.replace( "/vsizip/" + parentItem->path() + "/", "" );
}
else if ( thePath.right( 3 ) == ".gz" )

// unless setting== 2 (passthru) or 3 (Full scan), return an item without testing
if ( scanZipSetting != 2 && scanZipSetting != 3 )
{
if ( thePath.left( 9 ) != "/vsigzip/" )
thePath = "/vsigzip/" + thePath;
QStringList sublayers;
QgsDebugMsg( QString( "adding item name=%1 thePath=%2 uri=%3" ).arg( name ).arg( thePath ).arg( uri ) );
QgsLayerItem * item = new QgsGdalLayerItem( parentItem, name, thePath, thePath, &sublayers );
if ( item )
return item;
}
}

GDALAllRegister();
GDALDatasetH hDS = GDALOpen( TO8F( thePath ), GA_ReadOnly );
// try to open using VSIFileHandler
if ( thePath.right( 4 ) == ".zip" )
{
if ( thePath.left( 8 ) != "/vsizip/" )
thePath = "/vsizip/" + thePath;
}
else if ( thePath.right( 3 ) == ".gz" )
{
if ( thePath.left( 9 ) != "/vsigzip/" )
thePath = "/vsigzip/" + thePath;
}

if ( !hDS )
return 0;
// test that file is valid with GDAL
GDALAllRegister();
// do not print errors, but write to debug
CPLErrorHandler oErrorHandler = CPLSetErrorHandler( CPLQuietErrorHandler );
CPLErrorReset();
GDALDatasetH hDS = GDALOpen( TO8F( thePath ), GA_ReadOnly );
CPLSetErrorHandler( oErrorHandler );

// get layers list now so we can pass it to item
QStringList sublayers = QgsGdalProvider::subLayers( hDS );
if ( ! hDS )
{
QgsDebugMsg( QString( "GDALOpen error # %1 : %2 " ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
return 0;
}

GDALClose( hDS );
QStringList sublayers = QgsGdalProvider::subLayers( hDS );

QgsDebugMsg( "GdalDataset opened " + thePath );
GDALClose( hDS );

//extract basename with extension
QString name = info.completeBaseName() + "." + info.suffix();
QString uri = thePath;
QgsDebugMsg( "GdalDataset opened " + thePath );

QgsLayerItem * item = new QgsGdalLayerItem( parentItem, name, thePath, uri,
&sublayers );
QgsLayerItem * item = new QgsGdalLayerItem( parentItem, name, thePath, thePath,
&sublayers );

return item;
}
return 0;
return item;
}
8 changes: 6 additions & 2 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <QFile>
#include <QHash>
#include <QTime>
#include <QSettings>

#include "gdalwarper.h"
#include "ogr_spatialref.h"
Expand Down Expand Up @@ -1077,7 +1078,7 @@ bool QgsGdalProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>
int col = ( int ) floor(( x - mExtent.xMinimum() ) / xres );
int row = ( int ) floor(( mExtent.yMaximum() - y ) / yres );

QgsDebugMsg( "row = " + QString::number( row ) + " col = " + QString::number( col ) );
// QgsDebugMsg( "row = " + QString::number( row ) + " col = " + QString::number( col ) );

for ( int i = 1; i <= GDALGetRasterCount( mGdalDataset ); i++ )
{
Expand All @@ -1093,7 +1094,7 @@ bool QgsGdalProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>
}

//double value = readValue( data, type, 0 );
QgsDebugMsg( QString( "value=%1" ).arg( value ) );
// QgsDebugMsg( QString( "value=%1" ).arg( value ) );
QString v;

if ( mValidNoDataValue && ( fabs( value - mNoDataValue[i-1] ) <= TINY_VALUE || value != value ) )
Expand Down Expand Up @@ -1842,6 +1843,8 @@ void buildSupportedRasterFileFilterAndExtensions( QString & theFileFiltersString

// VSIFileHandler (see qgsogrprovider.cpp)
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1600
// QSettings settings;
// if ( settings.value( "/qgis/scanZipInBrowser", 1 ).toInt() != 0 )
if ( 1 )
{
QString glob = "*.zip";
Expand Down Expand Up @@ -1995,3 +1998,4 @@ QGISEXTERN void buildSupportedRasterFileFilter( QString & theFileFiltersString )
QStringList wildcards;
buildSupportedRasterFileFilterAndExtensions( theFileFiltersString, exts, wildcards );
}

50 changes: 44 additions & 6 deletions src/providers/ogr/qgsogrdataitems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <QFileInfo>
#include <QTextStream>
#include <QSettings>

#include <ogr_srs_api.h>
#include <cpl_error.h>
Expand Down Expand Up @@ -225,8 +226,17 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
if ( thePath.isEmpty() )
return 0;

QgsDebugMsg( "thePath: " + thePath );

QFileInfo info( thePath );
if ( !info.isFile() )
QString name = info.fileName();
QSettings settings;
int scanZipSetting = settings.value( "/qgis/scanZipInBrowser", 1 ).toInt();

// allow normal files or VSIFILE items to pass
if ( ! info.isFile() &&
thePath.left( 8 ) != "/vsizip/" &&
thePath.left( 9 ) != "/vsigzip/" )
return 0;

QStringList myExtensions = fileExtensions();
Expand Down Expand Up @@ -261,7 +271,27 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
return 0;
}

// try to open using the /vsizip mechanism
// vsifile : depending on options we should just add the item without testing
if ( thePath.left( 8 ) == "/vsizip/" )
{
// if this is a /vsigzip/path.zip/file_inside_zip change the name
if ( thePath.left( 8 ) == "/vsizip/" &&
thePath != "/vsizip/" + parentItem->path() )
{
name = thePath;
name = name.replace( "/vsizip/" + parentItem->path() + "/", "" );
}

// unless setting== 2 (Passthru) or 3 (Full scan), return an item without testing
if ( scanZipSetting != 2 && scanZipSetting != 3 )
{
QgsLayerItem * item = new QgsOgrLayerItem( parentItem, name, thePath, thePath, QgsLayerItem::Vector );
if ( item )
return item;
}
}

// try to open using VSIFileHandler
if ( thePath.right( 4 ) == ".zip" )
{
if ( thePath.left( 8 ) != "/vsizip/" )
Expand All @@ -273,12 +303,20 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
thePath = "/vsigzip/" + thePath;
}

// test that file is valid with OGR
OGRRegisterAll();
OGRSFDriverH hDriver;
// do not print errors, but write to debug
CPLErrorHandler oErrorHandler = CPLSetErrorHandler( CPLQuietErrorHandler );
CPLErrorReset();
OGRDataSourceH hDataSource = OGROpen( TO8F( thePath ), false, &hDriver );
CPLSetErrorHandler( oErrorHandler );

if ( !hDataSource )
if ( ! hDataSource )
{
QgsDebugMsg( QString( "OGROpen error # %1 : %2 " ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
return 0;
}

QString driverName = OGR_Dr_GetName( hDriver );
QgsDebugMsg( "OGR Driver : " + driverName );
Expand All @@ -289,13 +327,13 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )

if ( numLayers == 1 )
{
//extract basename with extension
QString name = info.completeBaseName() + "." + QFileInfo( thePath ).suffix();
QgsDebugMsg( QString( "using name = %1" ).arg( name ) );
item = dataItemForLayer( parentItem, name, thePath, hDataSource, 0 );
}
else if ( numLayers > 1 )
{
item = new QgsOgrDataCollectionItem( parentItem, info.fileName(), thePath );
QgsDebugMsg( QString( "using name = %1" ).arg( name ) );
item = new QgsOgrDataCollectionItem( parentItem, name, thePath );
}

OGR_DS_Destroy( hDataSource );
Expand Down
10 changes: 6 additions & 4 deletions src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ email : sherman at mrcc.com
#include <QMap>
#include <QString>
#include <QTextCodec>
#include <QSettings>

#include "qgsapplication.h"
#include "qgsdataitem.h"
Expand Down Expand Up @@ -1778,11 +1779,12 @@ QString createFilters( QString type )
// 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 shape (zip) and spatialite (zip and gz).
// Ideally we should add a new subclass of QgsCollectionItem (or QgsDirItem), say QgsZipItem
// and read the files inside the zip (requires unzip.h or cpl_minizip_unzip.h)
// and also add support for /vsitar/ (requires cpl_vsil_tar.cpp).
// 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", 1 ).toInt() != 0 )
if ( 1 )
{
myFileFilters += createFileFilter_( QObject::tr( "GDAL/OGR VSIFileHandler" ), "*.zip *.gz" );
Expand Down
27 changes: 27 additions & 0 deletions src/ui/qgsoptionsbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,33 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QLabel" name="label_24">
<property name="text">
<string>Scan for contents of compressed files (.zip) in browser dock</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="cmbScanZipInBrowser"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
Expand Down