QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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"
29
30#include <QFileInfo>
31#include <QString>
32
33#include "moc_qgszipitem.cpp"
34
35using namespace Qt::StringLiterals;
36
38{
39 return QgsApplication::getThemeIcon( u"/mIconZip.svg"_s );
40}
41
42
43//-----------------------------------------------------------------------
44QStringList QgsZipItem::sProviderNames = QStringList();
45
46
47QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &path )
49{
51 init();
52}
53
54QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path, const QString &providerKey )
56 , mFilePath( filePath )
57{
58 init();
59}
60
61void QgsZipItem::init()
62{
64 mIconName = u"/mIconZip.svg"_s;
66
68
69 static std::once_flag initialized;
70 std::call_once( initialized, [] { sProviderNames << u"files"_s; } );
71}
72
74{
75 return true;
76}
77
79{
81 u.layerType = u"collection"_s;
82 u.uri = path();
83 u.filePath = path();
84 return { u };
85}
86
87QString QgsZipItem::vsiPrefix( const QString &uri )
88{
90}
91
92QVector<QgsDataItem *> QgsZipItem::createChildren()
93{
94 QVector<QgsDataItem *> children;
95 QString tmpPath;
96 const QgsSettings settings;
97 const QString scanZipSetting = settings.value( u"qgis/scanZipInBrowser2"_s, "basic" ).toString();
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 QgsSettings settings;
167 const QString scanZipSetting = settings.value( u"qgis/scanZipInBrowser2"_s, "basic" ).toString();
168 QStringList zipFileList;
169 const QString vsiPrefix = QgsGdalUtils::vsiPrefixForPath( filePath );
170 bool populated = false;
171
172 QgsDebugMsgLevel( u"path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4"_s.arg( path, name, scanZipSetting, vsiPrefix ), 3 );
173
174 // don't scan if scanZipBrowser == no
175 if ( scanZipSetting == "no"_L1 )
176 return nullptr;
177
178 // don't scan if this file is not a vsi container archive item
180 return nullptr;
181
182 auto zipItem = std::make_unique< QgsZipItem >( parent, name, filePath, path );
183 // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
184 // for other items populating will be delayed until item is opened
185 // this might be polluting the tree with empty items but is necessary for performance reasons
186 // could also accept all files smaller than a certain size and add options for file count and/or size
187
188 // first get list of files inside .zip or .tar files
189 if ( path.endsWith( ".zip"_L1, Qt::CaseInsensitive ) || path.endsWith( ".tar"_L1, Qt::CaseInsensitive ) )
190 {
191 zipFileList = zipItem->getZipFileList();
192 }
193 // force populate if less than 10 items
194 if ( !zipFileList.isEmpty() && zipFileList.count() <= 10 )
195 {
196 zipItem->populate( zipItem->createChildren() );
197 populated = true; // there is no QgsDataItem::isPopulated() function
198 QgsDebugMsgLevel( u"Got zipItem with %1 children, path=%2, name=%3"_s.arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
199 }
200 else
201 {
202 QgsDebugMsgLevel( u"Delaying populating zipItem with path=%1, name=%2"_s.arg( zipItem->path(), zipItem->name() ), 3 );
203 }
204
205 // only display if has children or if is not populated
206 if ( !populated || zipItem->rowCount() > 0 )
207 {
208 QgsDebugMsgLevel( u"returning zipItem"_s, 3 );
209 return zipItem.release();
210 }
211
212 return nullptr;
213}
214
216{
217 if ( !mZipFileList.isEmpty() )
218 return mZipFileList;
219
220 QString tmpPath;
221 const QgsSettings settings;
222 const QString scanZipSetting = settings.value( u"qgis/scanZipInBrowser2"_s, "basic" ).toString();
223
224 QgsDebugMsgLevel( u"mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4"_s.arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
225
226 // if scanZipBrowser == no: skip to the next file
227 if ( scanZipSetting == "no"_L1 )
228 {
229 return mZipFileList;
230 }
231
232 // get list of files inside zip file
233 QgsDebugMsgLevel( u"Open file %1 with gdal vsi"_s.arg( mVsiPrefix + mFilePath ), 3 );
234 char **papszSiblingFiles = VSIReadDirRecursive( QString( mVsiPrefix + mFilePath ).toUtf8().constData() );
235 if ( papszSiblingFiles )
236 {
237 for ( int i = 0; papszSiblingFiles[i]; i++ )
238 {
239 tmpPath = papszSiblingFiles[i];
240 QgsDebugMsgLevel( u"Read file %1"_s.arg( tmpPath ), 3 );
241 // skip directories (files ending with /)
242 if ( tmpPath.right( 1 ) != "/"_L1 )
243 mZipFileList << tmpPath;
244 }
245 CSLDestroy( papszSiblingFiles );
246 }
247 else
248 {
249 QgsDebugError( u"Error reading %1"_s.arg( mFilePath ) );
250 }
251
252 return mZipFileList;
253}
@ ItemRepresentsFile
Item's path() directly represents a file on disk.
Definition qgis.h:985
@ Collection
A collection of items.
Definition qgis.h:946
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
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.