@@ -477,7 +477,6 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
477
477
QVector<QgsDataItem*> children;
478
478
QDir dir ( mPath );
479
479
QSettings settings;
480
- bool scanZip = ( settings.value ( " /qgis/scanZipInBrowser" , QVariant ( " basic" ) ).toString () != " no" );
481
480
482
481
QStringList entries = dir.entryList ( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
483
482
foreach ( QString subdir, entries )
@@ -497,8 +496,10 @@ QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
497
496
QString path = dir.absoluteFilePath ( name );
498
497
QFileInfo fileInfo ( path );
499
498
499
+ QString vsiPrefix = QgsZipItem::vsiPrefix ( path );
500
500
// vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
501
- if ( fileInfo.suffix () == " zip" && scanZip )
501
+ if (( settings.value ( " /qgis/scanZipInBrowser" , QVariant ( " basic" ) ).toString () != " no" ) &&
502
+ ( vsiPrefix == " /vsizip/" || vsiPrefix == " /vsitar/" ) )
502
503
{
503
504
QgsDataItem * item = QgsZipItem::itemFromPath ( this , path, name );
504
505
if ( item )
@@ -747,6 +748,7 @@ QgsZipItem::QgsZipItem( QgsDataItem* parent, QString name, QString path )
747
748
{
748
749
mType = Collection; // Zip??
749
750
mIcon = iconZip ();
751
+ mVsiPrefix = vsiPrefix ( path );
750
752
751
753
if ( mProviderNames .size () == 0 )
752
754
{
@@ -796,7 +798,6 @@ QgsZipItem::QgsZipItem( QgsDataItem* parent, QString name, QString path )
796
798
}
797
799
}
798
800
}
799
-
800
801
}
801
802
802
803
QgsZipItem::~QgsZipItem ()
@@ -879,13 +880,12 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
879
880
QVector<QgsDataItem*> children;
880
881
QString tmpPath;
881
882
QString childPath;
882
-
883
883
QSettings settings;
884
884
QString scanZipSetting = settings.value ( " /qgis/scanZipInBrowser" , " basic" ).toString ();
885
885
886
886
mZipFileList .clear ();
887
887
888
- QgsDebugMsg ( QString ( " path = %1 name= %2 scanZipSetting= %3" ).arg ( path () ).arg ( name () ).arg ( scanZipSetting ) );
888
+ QgsDebugMsg ( QString ( " path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4 " ).arg ( path () ).arg ( name () ).arg ( scanZipSetting ). arg ( mVsiPrefix ) );
889
889
890
890
// if scanZipBrowser == no: skip to the next file
891
891
if ( scanZipSetting == " no" )
@@ -901,31 +901,14 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
901
901
// return children;
902
902
// }
903
903
904
- // get list of files inside zip file
905
- QgsDebugMsg ( QString ( " Open file %1 with gdal vsi" ).arg ( path () ) );
906
- char **papszSiblingFiles = VSIReadDirRecursive1 ( QString ( " /vsizip/" + path () ).toLocal8Bit ().constData () );
907
- if ( papszSiblingFiles )
908
- {
909
- for ( int i = 0 ; i < CSLCount ( papszSiblingFiles ); i++ )
910
- {
911
- tmpPath = papszSiblingFiles[i];
912
- QgsDebugMsg ( QString ( " Read file %1" ).arg ( tmpPath ) );
913
- // skip directories (files ending with /)
914
- if ( tmpPath.right ( 1 ) != " /" )
915
- mZipFileList << tmpPath;
916
- }
917
- CSLDestroy ( papszSiblingFiles );
918
- }
919
- else
920
- {
921
- QgsDebugMsg ( QString ( " Error reading %1" ).arg ( path () ) );
922
- }
904
+ // first get list of files
905
+ getZipFileList ();
923
906
924
907
// loop over files inside zip
925
908
foreach ( QString fileName, mZipFileList )
926
909
{
927
910
QFileInfo info ( fileName );
928
- tmpPath = " /vsizip/ " + path () + " /" + fileName;
911
+ tmpPath = mVsiPrefix + path () + " /" + fileName;
929
912
QgsDebugMsg ( " tmpPath = " + tmpPath );
930
913
931
914
// foreach( dataItem_t *dataItem, mDataItemPtr )
@@ -934,7 +917,7 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
934
917
// ugly hack to remove .dbf file if there is a .shp file
935
918
if ( mProviderNames [i] == " ogr" )
936
919
{
937
- if ( info.suffix () == " dbf" )
920
+ if ( info.suffix (). toLower () == " dbf" )
938
921
{
939
922
if ( mZipFileList .indexOf ( fileName.left ( fileName.count () - 4 ) + " .shp" ) != -1 )
940
923
continue ;
@@ -976,20 +959,38 @@ QVector<QgsDataItem*> QgsZipItem::createChildren( )
976
959
return children;
977
960
}
978
961
979
-
962
+ QString QgsZipItem::vsiPrefix ( QString path )
963
+ {
964
+ if ( path.startsWith ( " /vsizip/" , Qt::CaseInsensitive ) ||
965
+ path.endsWith ( " .zip" , Qt::CaseInsensitive ) )
966
+ return " /vsizip/" ;
967
+ else if ( path.startsWith ( " /vsitar/" , Qt::CaseInsensitive ) ||
968
+ path.endsWith ( " .tar" , Qt::CaseInsensitive ) ||
969
+ path.endsWith ( " .tar.gz" , Qt::CaseInsensitive ) ||
970
+ path.endsWith ( " .tgz" , Qt::CaseInsensitive ) )
971
+ return " /vsitar/" ;
972
+ else if ( path.startsWith ( " /vsigzip/" , Qt::CaseInsensitive ) ||
973
+ path.endsWith ( " .gz" , Qt::CaseInsensitive ) )
974
+ return " /vsigzip/" ;
975
+ else
976
+ return " " ;
977
+ }
980
978
981
979
QgsDataItem* QgsZipItem::itemFromPath ( QgsDataItem* parent, QString path, QString name )
982
980
{
983
981
QSettings settings;
984
982
QString scanZipSetting = settings.value ( " /qgis/scanZipInBrowser" , " basic" ).toString ();
985
- QString vsizipPath = path;
983
+ QString vsiPath = path;
986
984
int zipFileCount = 0 ;
985
+ QStringList zipFileList;
987
986
QFileInfo fileInfo ( path );
987
+ QString vsiPrefix = QgsZipItem::vsiPrefix ( path );
988
988
QgsZipItem * zipItem = 0 ;
989
+ bool populated = false ;
989
990
990
- QgsDebugMsg ( QString ( " path = %1 name= %2 scanZipSetting= %3" ).arg ( path ).arg ( name ).arg ( scanZipSetting ) );
991
+ QgsDebugMsg ( QString ( " path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4 " ).arg ( path ).arg ( name ).arg ( scanZipSetting ). arg ( vsiPrefix ) );
991
992
992
- // if scanZipBrowser == no: skip to the next file
993
+ // if scanZipBrowser == no: don't read the zip file
993
994
if ( scanZipSetting == " no" )
994
995
{
995
996
return 0 ;
@@ -1007,29 +1008,47 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
1007
1008
1008
1009
if ( zipItem )
1009
1010
{
1010
- // force populate zipItem
1011
- zipItem->populate ();
1012
- QgsDebugMsg ( QString ( " Got zipItem with %1 children, path=%2, name=%3" ).arg ( zipItem->rowCount () ).arg ( zipItem->path () ).arg ( zipItem->name () ) );
1011
+ // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1012
+ // for other items populating will be delayed until item is opened
1013
+ // this might be polluting the tree with empty items but is necessary for performance reasons
1014
+ // could also accept all files smaller than a certain size and add options for file count and/or size
1015
+
1016
+ // first get list of files inside .zip or .tar files
1017
+ if ( path.endsWith ( " .zip" , Qt::CaseInsensitive ) ||
1018
+ path.endsWith ( " .tar" , Qt::CaseInsensitive ) )
1019
+ {
1020
+ zipFileList = zipItem->getZipFileList ();
1021
+ }
1022
+ // force populate if less than 10 items
1023
+ if ( zipFileList.count () > 0 && zipFileList.count () <= 10 )
1024
+ {
1025
+ zipItem->populate ();
1026
+ populated = true ; // there is no QgsDataItem::isPopulated() function
1027
+ QgsDebugMsg ( QString ( " Got zipItem with %1 children, path=%2, name=%3" ).arg ( zipItem->rowCount () ).arg ( zipItem->path () ).arg ( zipItem->name () ) );
1028
+ }
1029
+ else
1030
+ {
1031
+ QgsDebugMsg ( QString ( " Delaying populating zipItem with path=%1, name=%2" ).arg ( zipItem->path () ).arg ( zipItem->name () ) );
1032
+ }
1013
1033
}
1014
1034
1015
- // only display if has children
1016
- // other option would be to delay until item is opened, but we would be polluting the tree with empty items
1017
- if ( zipItem && zipItem->rowCount () > 1 )
1035
+ // only display if has children or if is not populated
1036
+ if ( zipItem && ( !populated || zipItem->rowCount () > 1 ) )
1018
1037
{
1019
1038
QgsDebugMsg ( " returning zipItem" );
1020
1039
return zipItem;
1021
1040
}
1022
- // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1041
+ // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1023
1042
else
1024
1043
{
1025
1044
if ( zipItem )
1026
1045
{
1027
- vsizipPath = zipItem->path ();
1028
- zipFileCount = zipItem-> getZipFileList () .count ();
1046
+ vsiPath = zipItem->path ();
1047
+ zipFileCount = zipFileList .count ();
1029
1048
delete zipItem;
1030
1049
}
1031
1050
1032
- QgsDebugMsg ( QString ( " will try to create a normal dataItem from path= %2 or %3" ).arg ( path ).arg ( vsizipPath ) );
1051
+ QgsDebugMsg ( QString ( " will try to create a normal dataItem from path= %2 or %3" ).arg ( path ).arg ( vsiPath ) );
1033
1052
1034
1053
// try to open using registered providers (gdal and ogr)
1035
1054
for ( int i = 0 ; i < mProviderNames .size (); i++ )
@@ -1047,7 +1066,7 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
1047
1066
item = dataItem ( path, parent );
1048
1067
// try with /vsizip/
1049
1068
if ( ! item )
1050
- item = dataItem ( vsizipPath , parent );
1069
+ item = dataItem ( vsiPath , parent );
1051
1070
if ( item )
1052
1071
return item;
1053
1072
}
@@ -1056,3 +1075,43 @@ QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, QString path, QStrin
1056
1075
1057
1076
return 0 ;
1058
1077
}
1078
+
1079
+ const QStringList & QgsZipItem::getZipFileList ()
1080
+ {
1081
+ if ( ! mZipFileList .isEmpty () )
1082
+ return mZipFileList ;
1083
+
1084
+ QString tmpPath;
1085
+ QSettings settings;
1086
+ QString scanZipSetting = settings.value ( " /qgis/scanZipInBrowser" , " basic" ).toString ();
1087
+
1088
+ QgsDebugMsg ( QString ( " path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg ( path () ).arg ( name () ).arg ( scanZipSetting ).arg ( mVsiPrefix ) );
1089
+
1090
+ // if scanZipBrowser == no: skip to the next file
1091
+ if ( scanZipSetting == " no" )
1092
+ {
1093
+ return mZipFileList ;
1094
+ }
1095
+
1096
+ // get list of files inside zip file
1097
+ QgsDebugMsg ( QString ( " Open file %1 with gdal vsi" ).arg ( mVsiPrefix + path () ) );
1098
+ char **papszSiblingFiles = VSIReadDirRecursive1 ( QString ( mVsiPrefix + path () ).toLocal8Bit ().constData () );
1099
+ if ( papszSiblingFiles )
1100
+ {
1101
+ for ( int i = 0 ; i < CSLCount ( papszSiblingFiles ); i++ )
1102
+ {
1103
+ tmpPath = papszSiblingFiles[i];
1104
+ QgsDebugMsg ( QString ( " Read file %1" ).arg ( tmpPath ) );
1105
+ // skip directories (files ending with /)
1106
+ if ( tmpPath.right ( 1 ) != " /" )
1107
+ mZipFileList << tmpPath;
1108
+ }
1109
+ CSLDestroy ( papszSiblingFiles );
1110
+ }
1111
+ else
1112
+ {
1113
+ QgsDebugMsg ( QString ( " Error reading %1" ).arg ( path () ) );
1114
+ }
1115
+
1116
+ return mZipFileList ;
1117
+ }
0 commit comments