QGIS API Documentation 4.1.0-Master (467af3bbe65)
Loading...
Searching...
No Matches
qgszipitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgszipitem.cpp
3 -------------------
4 begin : 2011-04-01
5 copyright : (C) 2011 Radim Blazek
6 email : radim dot blazek at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgszipitem.h"
19
20#include <cpl_string.h>
21#include <cpl_vsi.h>
22#include <mutex>
23
24#include "qgsapplication.h"
25#include "qgsdataitemprovider.h"
27#include "qgsgdalutils.h"
28#include "qgssettings.h"
30
31#include <QFileInfo>
32#include <QString>
33
34#include "moc_qgszipitem.cpp"
35
36using namespace Qt::StringLiterals;
37
39{
40 return QgsApplication::getThemeIcon( u"/mIconZip.svg"_s );
41}
42
43
44//-----------------------------------------------------------------------
45QStringList QgsZipItem::sProviderNames = QStringList();
46
47
48QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &path )
50{
52 init();
53}
54
55QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path, const QString &providerKey )
57 , mFilePath( filePath )
58{
59 init();
60}
61
62void QgsZipItem::init()
63{
65 mIconName = u"/mIconZip.svg"_s;
67
69
70 static std::once_flag initialized;
71 std::call_once( initialized, [] { sProviderNames << u"files"_s; } );
72}
73
75{
76 return true;
77}
78
80{
82 u.layerType = u"collection"_s;
83 u.uri = path();
84 u.filePath = path();
85 return { u };
86}
87
88QString QgsZipItem::vsiPrefix( const QString &uri )
89{
91}
92
93QVector<QgsDataItem *> QgsZipItem::createChildren()
94{
95 QVector<QgsDataItem *> children;
96 QString tmpPath;
97 const QString scanZipSetting = QgsSettingsRegistryCore::settingsScanZipInBrowser->value();
98
99 mZipFileList.clear();
100
101 QgsDebugMsgLevel( u"mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5"_s.arg( mFilePath, path(), name(), scanZipSetting, mVsiPrefix ), 3 );
102
103 // if scanZipBrowser == no: skip to the next file
104 if ( scanZipSetting == "no"_L1 )
105 {
106 return children;
107 }
108
109 // first get list of files
111
112 const QList<QgsDataItemProvider *> providers = QgsApplication::dataItemProviderRegistry()->providers();
113
114 // loop over files inside zip
115 const auto constMZipFileList = mZipFileList;
116 for ( const QString &fileName : constMZipFileList )
117 {
118 const QFileInfo info( fileName );
119 tmpPath = mVsiPrefix + mFilePath + '/' + fileName;
120 QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
121
122 for ( QgsDataItemProvider *provider : providers )
123 {
124 if ( !sProviderNames.contains( provider->name() ) )
125 continue;
126
127 // ugly hack to remove .dbf file if there is a .shp file
128 if ( provider->name() == "OGR"_L1 )
129 {
130 if ( info.suffix().compare( "dbf"_L1, Qt::CaseInsensitive ) == 0 )
131 {
132 if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
133 continue;
134 }
135 if ( info.completeSuffix().compare( "shp.xml"_L1, Qt::CaseInsensitive ) == 0 )
136 {
137 continue;
138 }
139 }
140
141 QgsDebugMsgLevel( u"trying to load item %1 with %2"_s.arg( tmpPath, provider->name() ), 3 );
142 QgsDataItem *item = provider->createDataItem( tmpPath, this );
143 if ( item )
144 {
145 // the item comes with zipped file name, set the name to relative path within zip file
146 item->setName( fileName );
147 children.append( item );
148 }
149 else
150 {
151 QgsDebugMsgLevel( u"not loaded item"_s, 3 );
152 }
153 }
154 }
155
156 return children;
157}
158
160{
161 return itemFromPath( parent, path, name, path );
162}
163
164QgsDataItem *QgsZipItem::itemFromPath( QgsDataItem *parent, const QString &filePath, const QString &name, const QString &path )
165{
166 const QString scanZipSetting = QgsSettingsRegistryCore::settingsScanZipInBrowser->value();
167 QStringList zipFileList;
168 const QString vsiPrefix = QgsGdalUtils::vsiPrefixForPath( filePath );
169 bool populated = false;
170
171 QgsDebugMsgLevel( u"path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4"_s.arg( path, name, scanZipSetting, vsiPrefix ), 3 );
172
173 // don't scan if scanZipBrowser == no
174 if ( scanZipSetting == "no"_L1 )
175 return nullptr;
176
177 // don't scan if this file is not a vsi container archive item
179 return nullptr;
180
181 auto zipItem = std::make_unique< QgsZipItem >( parent, name, filePath, path );
182 // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
183 // for other items populating will be delayed until item is opened
184 // this might be polluting the tree with empty items but is necessary for performance reasons
185 // could also accept all files smaller than a certain size and add options for file count and/or size
186
187 // first get list of files inside .zip or .tar files
188 if ( path.endsWith( ".zip"_L1, Qt::CaseInsensitive ) || path.endsWith( ".tar"_L1, Qt::CaseInsensitive ) )
189 {
190 zipFileList = zipItem->getZipFileList();
191 }
192 // force populate if less than 10 items
193 if ( !zipFileList.isEmpty() && zipFileList.count() <= 10 )
194 {
195 zipItem->populate( zipItem->createChildren() );
196 populated = true; // there is no QgsDataItem::isPopulated() function
197 QgsDebugMsgLevel( u"Got zipItem with %1 children, path=%2, name=%3"_s.arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
198 }
199 else
200 {
201 QgsDebugMsgLevel( u"Delaying populating zipItem with path=%1, name=%2"_s.arg( zipItem->path(), zipItem->name() ), 3 );
202 }
203
204 // only display if has children or if is not populated
205 if ( !populated || zipItem->rowCount() > 0 )
206 {
207 QgsDebugMsgLevel( u"returning zipItem"_s, 3 );
208 return zipItem.release();
209 }
210
211 return nullptr;
212}
213
215{
216 if ( !mZipFileList.isEmpty() )
217 return mZipFileList;
218
219 QString tmpPath;
220 const QString scanZipSetting = QgsSettingsRegistryCore::settingsScanZipInBrowser->value();
221
222 QgsDebugMsgLevel( u"mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4"_s.arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
223
224 // if scanZipBrowser == no: skip to the next file
225 if ( scanZipSetting == "no"_L1 )
226 {
227 return mZipFileList;
228 }
229
230 // get list of files inside zip file
231 QgsDebugMsgLevel( u"Open file %1 with gdal vsi"_s.arg( mVsiPrefix + mFilePath ), 3 );
232 char **papszSiblingFiles = VSIReadDirRecursive( QString( mVsiPrefix + mFilePath ).toUtf8().constData() );
233 if ( papszSiblingFiles )
234 {
235 for ( int i = 0; papszSiblingFiles[i]; i++ )
236 {
237 tmpPath = papszSiblingFiles[i];
238 QgsDebugMsgLevel( u"Read file %1"_s.arg( tmpPath ), 3 );
239 // skip directories (files ending with /)
240 if ( tmpPath.right( 1 ) != "/"_L1 )
241 mZipFileList << tmpPath;
242 }
243 CSLDestroy( papszSiblingFiles );
244 }
245 else
246 {
247 QgsDebugError( u"Error reading %1"_s.arg( mFilePath ) );
248 }
249
250 return mZipFileList;
251}
@ ItemRepresentsFile
Item's path() directly represents a file on disk.
Definition qgis.h:1006
@ Collection
A collection of items.
Definition qgis.h:967
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application's data item provider registry, which keeps a list of data item providers that...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
QgsDataCollectionItem(QgsDataItem *parent, const QString &name, const QString &path=QString(), const QString &providerKey=QString())
Constructor for QgsDataCollectionItem, with the specified parent item.
QList< QgsDataItemProvider * > providers() const
Returns the list of available providers.
Interface for providers that add custom data items to the browser tree.
Qgis::BrowserItemType mType
QVector< QgsDataItem * > children() const
QgsDataItem(Qgis::BrowserItemType type, QgsDataItem *parent, const QString &name, const QString &path, const QString &providerKey=QString())
Constructor for QgsDataItem, with the specified parent item.
QString mIconName
QString name() const
Returns the name of the item (the displayed text for the item).
QString path() const
virtual void setCapabilities(Qgis::BrowserItemCapabilities capabilities)
Sets the capabilities for the data item.
void setName(const QString &name)
Sets the name of the item (the displayed text for the item).
QgsDataItem * parent() const
Gets item parent.
QString providerKey() const
Returns the provider key that created this item (e.g.
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
static QString vsiPrefixForPath(const QString &path)
Returns a the vsi prefix which corresponds to a file path, or an empty string if the path is not asso...
static bool isVsiArchivePrefix(const QString &prefix)
Returns true if prefix is a supported archive style container prefix (e.g.
QList< QgsMimeDataUtils::Uri > UriList
static const QgsSettingsEntryString * settingsScanZipInBrowser
Settings entry for zip scanning behavior in browser.
static QIcon iconZip()
static Q_DECL_DEPRECATED QString vsiPrefix(const QString &uri)
QgsZipItem(QgsDataItem *parent, const QString &name, const QString &path)
Constructor.
QStringList mZipFileList
Definition qgszipitem.h:40
QStringList getZipFileList()
bool hasDragEnabled() const override
Returns true if the item may be dragged.
QgsMimeDataUtils::UriList mimeUris() const override
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
QString mFilePath
Definition qgszipitem.h:38
static QgsDataItem * itemFromPath(QgsDataItem *parent, const QString &path, const QString &name)
Creates a new data item from the specified path.
QString mVsiPrefix
Definition qgszipitem.h:39
QVector< QgsDataItem * > createChildren() override
Create children.
static QStringList sProviderNames
Definition qgszipitem.h:67
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59
QString filePath
Path to file, if uri is associated with a file.
QString uri
Identifier of the data source recognized by its providerKey.
QString layerType
Type of URI.