mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
add support for reading datasets inside zip file in browser using quazip
This commit is contained in:
parent
9c0cfe941f
commit
90108d81d0
@ -193,6 +193,7 @@
|
||||
<file>themes/default/mIconWms.png</file>
|
||||
<file>themes/default/mIconWmsLayer.png</file>
|
||||
<file>themes/default/mIconWarn.png</file>
|
||||
<file>themes/default/mIconZip.png</file>
|
||||
<file>themes/default/mMapserverExport.png</file>
|
||||
<file>themes/default/plugin.png</file>
|
||||
<file>themes/default/propertyicons/action.png</file>
|
||||
|
BIN
images/themes/default/mIconZip.png
Normal file
BIN
images/themes/default/mIconZip.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 966 B |
@ -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() );
|
||||
|
@ -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()
|
||||
{
|
||||
@ -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<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
|
||||
// QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
|
||||
QVector<QLibrary*> QgsDirectoryItem::mLibraries = QVector<QLibrary*>();
|
||||
|
||||
|
||||
@ -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<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
|
||||
@ -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
|
||||
@ -475,6 +512,7 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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<QgsDataProvider*> mProviders;
|
||||
/* static QVector<QgsDataProvider*> mProviders; */
|
||||
static QVector<QLibrary*> mLibraries;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "qgslogger.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
|
||||
// defined in qgsgdalprovider.cpp
|
||||
void buildSupportedRasterFileFilterAndExtensions( QString & theFileFiltersString, QStringList & theExtensions, QStringList & theWildcards );
|
||||
@ -90,6 +91,7 @@ QVector<QgsDataItem*> 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;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <QFile>
|
||||
#include <QHash>
|
||||
#include <QTime>
|
||||
#include <QSettings>
|
||||
|
||||
#include "gdalwarper.h"
|
||||
#include "ogr_spatialref.h"
|
||||
@ -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++ )
|
||||
{
|
||||
@ -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 ) )
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTextStream>
|
||||
#include <QSettings>
|
||||
|
||||
#include <ogr_srs_api.h>
|
||||
#include <cpl_error.h>
|
||||
@ -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 );
|
||||
|
@ -35,6 +35,7 @@ email : sherman at mrcc.com
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QTextCodec>
|
||||
#include <QSettings>
|
||||
|
||||
#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" );
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user