diff --git a/images/images.qrc b/images/images.qrc
index 8f435e8357d..fbf67f1702a 100644
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -193,6 +193,7 @@
themes/default/mIconWms.png
themes/default/mIconWmsLayer.png
themes/default/mIconWarn.png
+ themes/default/mIconZip.png
themes/default/mMapserverExport.png
themes/default/plugin.png
themes/default/propertyicons/action.png
diff --git a/images/themes/default/mIconZip.png b/images/themes/default/mIconZip.png
new file mode 100644
index 00000000000..9934c351913
Binary files /dev/null and b/images/themes/default/mIconZip.png differ
diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp
index 7a409f5c978..34244f43e31 100644
--- a/src/app/qgsoptions.cpp
+++ b/src/app/qgsoptions.cpp
@@ -196,6 +196,14 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
cmbPromptRasterSublayers->addItem( tr( "Load all" ) );
cmbPromptRasterSublayers->setCurrentIndex( settings.value( "/qgis/promptForRasterSublayers", 0 ).toInt() );
+ // Scan for contents of compressed files (.zip) in browser dock
+ cmbScanZipInBrowser->clear();
+ cmbScanZipInBrowser->addItem( tr( "No" ) ); // 0
+ cmbScanZipInBrowser->addItem( tr( "Basic scan" ) ); // 1
+ cmbScanZipInBrowser->addItem( tr( "Passthru" ) ); // 2
+ cmbScanZipInBrowser->addItem( tr( "Full scan" ) ); // 3
+ cmbScanZipInBrowser->setCurrentIndex( settings.value( "/qgis/scanZipInBrowser", 1 ).toInt() );
+
// set the display update threshold
spinBoxUpdateThreshold->setValue( settings.value( "/Map/updateThreshold" ).toInt() );
//set the default projection behaviour radio buttongs
@@ -628,6 +636,7 @@ void QgsOptions::saveOptions()
settings.setValue( "/qgis/attributeTableBehaviour", cmbAttrTableBehaviour->currentIndex() );
settings.setValue( "/qgis/attributeTableRowCache", spinBoxAttrTableRowCache->value() );
settings.setValue( "/qgis/promptForRasterSublayers", cmbPromptRasterSublayers->currentIndex() );
+ settings.setValue( "/qgis/scanZipInBrowser", cmbScanZipInBrowser->currentIndex() );
settings.setValue( "/qgis/dockIdentifyResults", cbxIdentifyResultsDocked->isChecked() );
settings.setValue( "/qgis/dockSnapping", cbxSnappingOptionsDocked->isChecked() );
settings.setValue( "/qgis/addPostgisDC", cbxAddPostgisDC->isChecked() );
diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp
index e60548440ac..181545909a8 100644
--- a/src/core/qgsdataitem.cpp
+++ b/src/core/qgsdataitem.cpp
@@ -35,6 +35,10 @@
#include "qgslogger.h"
#include "qgsproviderregistry.h"
+// use internal quazip for /vsizip support
+#define QUAZIP_STATIC
+#include
+
// shared icons
const QIcon &QgsLayerItem::iconPoint()
{
@@ -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 )
{
@@ -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 );
@@ -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 )
@@ -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;
@@ -373,7 +392,7 @@ QgsDataCollectionItem::~QgsDataCollectionItem()
}
//-----------------------------------------------------------------------
-QVector QgsDirectoryItem::mProviders = QVector();
+// QVector QgsDirectoryItem::mProviders = QVector();
QVector QgsDirectoryItem::mLibraries = QVector();
@@ -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 );
}
@@ -425,11 +445,14 @@ QVector QgsDirectoryItem::createChildren( )
{
QVector 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
@@ -442,6 +465,20 @@ QVector 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
@@ -475,6 +512,7 @@ QVector QgsDirectoryItem::createChildren( )
}
}
}
+
return children;
}
@@ -669,3 +707,238 @@ QVector QgsFavouritesItem::createChildren( )
return children;
}
+
+//-----------------------------------------------------------------------
+QStringList QgsZipItem::mProviderNames = QStringList();
+QVector QgsZipItem::mDataItemPtr = QVector();
+
+
+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 QgsZipItem::createChildren( )
+{
+ QVector 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;
+}
diff --git a/src/core/qgsdataitem.h b/src/core/qgsdataitem.h
index 388a0eee109..c24b80740e4 100644
--- a/src/core/qgsdataitem.h
+++ b/src/core/qgsdataitem.h
@@ -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
{
@@ -236,7 +235,7 @@ class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem
virtual QWidget * paramWidget();
- static QVector mProviders;
+ /* static QVector mProviders; */
static QVector mLibraries;
};
@@ -281,8 +280,28 @@ class CORE_EXPORT QgsFavouritesItem : public QgsDataCollectionItem
~QgsFavouritesItem();
QVector 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 createChildren();
+ QStringList getFiles();
+
+ static QVector mDataItemPtr;
+ static QStringList mProviderNames;
+
+ static QgsDataItem* itemFromPath( QgsDataItem* parent, QString path, QString name );
+
+ static const QIcon &iconZip();
+};
+
#endif // QGSDATAITEM_H
diff --git a/src/providers/gdal/qgsgdaldataitems.cpp b/src/providers/gdal/qgsgdaldataitems.cpp
index 9ee7967ce42..97b9239069c 100644
--- a/src/providers/gdal/qgsgdaldataitems.cpp
+++ b/src/providers/gdal/qgsgdaldataitems.cpp
@@ -3,6 +3,7 @@
#include "qgslogger.h"
#include
+#include
// defined in qgsgdalprovider.cpp
void buildSupportedRasterFileFilterAndExtensions( QString & theFileFiltersString, QStringList & theExtensions, QStringList & theWildcards );
@@ -90,6 +91,7 @@ QVector QgsGdalLayerItem::createChildren( )
// ---------------------------------------------------------------------------
+static QString filterString;
static QStringList extensions = QStringList();
static QStringList wildcards = QStringList();
@@ -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( " " ) );
- }
-
- // 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 .tar.gz files
- if ( thePath.right( 7 ) == ".tar.gz" )
- return 0;
-
- // Filter files by extension
- if ( extensions.indexOf( info.suffix().toLower() ) < 0 )
- {
- bool matches = false;
- foreach( QString wildcard, wildcards )
- {
- QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
- if ( rx.exactMatch( info.fileName() ) )
- {
- matches = true;
- break;
- }
- }
- 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" )
- {
- if ( thePath.left( 8 ) != "/vsizip/" )
- thePath = "/vsizip/" + thePath;
- }
- else if ( thePath.right( 3 ) == ".gz" )
- {
- if ( thePath.left( 9 ) != "/vsigzip/" )
- thePath = "/vsigzip/" + thePath;
- }
-
- GDALAllRegister();
- GDALDatasetH hDS = GDALOpen( TO8F( thePath ), GA_ReadOnly );
-
- if ( !hDS )
- return 0;
-
- // get layers list now so we can pass it to item
- QStringList sublayers = QgsGdalProvider::subLayers( hDS );
-
- GDALClose( hDS );
-
- QgsDebugMsg( "GdalDataset opened " + thePath );
-
- //extract basename with extension
- QString name = info.completeBaseName() + "." + info.suffix();
- QString uri = thePath;
-
- QgsLayerItem * item = new QgsGdalLayerItem( parentItem, name, thePath, uri,
- &sublayers );
-
- return item;
+ buildSupportedRasterFileFilterAndExtensions( filterString, extensions, wildcards );
+ QgsDebugMsg( "extensions: " + extensions.join( " " ) );
+ QgsDebugMsg( "wildcards: " + wildcards.join( " " ) );
}
- 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;
+
+ // Filter files by extension
+ if ( extensions.indexOf( info.suffix().toLower() ) < 0 )
+ {
+ bool matches = false;
+ foreach( QString wildcard, wildcards )
+ {
+ QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
+ if ( rx.exactMatch( info.fileName() ) )
+ {
+ matches = true;
+ break;
+ }
+ }
+ if ( !matches )
+ return 0;
+ }
+
+ // 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() )
+ {
+ 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 )
+ {
+ 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;
+ }
+ }
+
+ // 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;
+ }
+
+ // 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 );
+
+ if ( ! hDS )
+ {
+ QgsDebugMsg( QString( "GDALOpen error # %1 : %2 " ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
+ return 0;
+ }
+
+ QStringList sublayers = QgsGdalProvider::subLayers( hDS );
+
+ GDALClose( hDS );
+
+ QgsDebugMsg( "GdalDataset opened " + thePath );
+
+ QgsLayerItem * item = new QgsGdalLayerItem( parentItem, name, thePath, thePath,
+ &sublayers );
+
+ return item;
}
diff --git a/src/providers/gdal/qgsgdalprovider.cpp b/src/providers/gdal/qgsgdalprovider.cpp
index d262ba99522..eb46014ced0 100644
--- a/src/providers/gdal/qgsgdalprovider.cpp
+++ b/src/providers/gdal/qgsgdalprovider.cpp
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include "gdalwarper.h"
#include "ogr_spatialref.h"
@@ -1077,7 +1078,7 @@ bool QgsGdalProvider::identify( const QgsPoint& thePoint, QMap
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++ )
{
@@ -1093,7 +1094,7 @@ bool QgsGdalProvider::identify( const QgsPoint& thePoint, QMap
}
//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 ) )
@@ -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";
@@ -1995,3 +1998,4 @@ QGISEXTERN void buildSupportedRasterFileFilter( QString & theFileFiltersString )
QStringList wildcards;
buildSupportedRasterFileFilterAndExtensions( theFileFiltersString, exts, wildcards );
}
+
diff --git a/src/providers/ogr/qgsogrdataitems.cpp b/src/providers/ogr/qgsogrdataitems.cpp
index 8d138736ccd..93554285d63 100644
--- a/src/providers/ogr/qgsogrdataitems.cpp
+++ b/src/providers/ogr/qgsogrdataitems.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#include
@@ -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();
@@ -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/" )
@@ -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 );
@@ -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 );
diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp
index 8b7bf7e1c07..7287b90f7f3 100644
--- a/src/providers/ogr/qgsogrprovider.cpp
+++ b/src/providers/ogr/qgsogrprovider.cpp
@@ -35,6 +35,7 @@ email : sherman at mrcc.com
#include
#include
#include
+#include
#include "qgsapplication.h"
#include "qgsdataitem.h"
@@ -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" );
diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui
index e0e8cedad44..79556a6fc98 100644
--- a/src/ui/qgsoptionsbase.ui
+++ b/src/ui/qgsoptionsbase.ui
@@ -602,6 +602,33 @@
+ -
+
+
-
+
+
+ Scan for contents of compressed files (.zip) in browser dock
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+