Handle language change events in widgets.
[maemo-rb.git] / rbutil / rbutilqt / base / ziputil.cpp
blobca921eb7086ca5ba4b9e86bff308921801eb34b2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2011 Dominik Riebeling
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
19 #include <QtCore>
20 #include <QDebug>
21 #include "ziputil.h"
22 #include "progressloggerinterface.h"
24 #include "quazip/quazip.h"
25 #include "quazip/quazipfile.h"
26 #include "quazip/quazipfileinfo.h"
29 ZipUtil::ZipUtil(QObject* parent) : QObject(parent)
31 m_zip = NULL;
35 ZipUtil::~ZipUtil()
37 if(m_zip) {
38 delete m_zip;
42 //! @brief open zip file.
43 //! @param zipfile path to zip file
44 //! @param mode open mode (see QuaZip::Mode)
45 //! @return true on success, false otherwise
46 bool ZipUtil::open(QString& zipfile, QuaZip::Mode mode)
48 m_zip = new QuaZip(zipfile);
49 return m_zip->open(mode);
53 //! @brief close zip file.
54 //! @return true on success, false otherwise
55 bool ZipUtil::close(void)
57 if(!m_zip) {
58 return false;
61 int error = UNZ_OK;
62 if(m_zip->isOpen()) {
63 m_zip->close();
64 error = m_zip->getZipError();
66 delete m_zip;
67 m_zip = NULL;
68 return (error == UNZ_OK) ? true : false;
72 //! @brief extract currently opened archive
73 //! @brief dest path to extract archive to, can be filename when extracting a
74 //! single file.
75 //! @brief file file to extract from archive, full archive if empty.
76 //! @return true on success, false otherwise
77 bool ZipUtil::extractArchive(QString& dest, QString file)
79 qDebug() << "[ZipUtil] extractArchive" << dest << file;
80 bool result = true;
81 if(!m_zip) {
82 return false;
84 QuaZipFile *currentFile = new QuaZipFile(m_zip);
85 int entries = m_zip->getEntriesCount();
86 int current = 0;
87 // construct the filename when extracting a single file from an archive.
88 // if the given destination is a full path use it as output name,
89 // otherwise use it as path to place the file as named in the archive.
90 QString singleoutfile;
91 if(!file.isEmpty() && QFileInfo(dest).isDir()) {
92 singleoutfile = dest + "/" + file;
94 else if(!file.isEmpty()){
95 singleoutfile = dest;
97 for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile())
99 ++current;
100 // if the entry is a path ignore it. Path existence is ensured separately.
101 if(m_zip->getCurrentFileName().split("/").last() == "")
102 continue;
103 // some tools set the MS-DOS file attributes. Check those for D flag,
104 // since in some cases a folder entry does not end with a /
105 QuaZipFileInfo fi;
106 currentFile->getFileInfo(&fi);
107 if(fi.externalAttr & 0x10) // FAT entry bit 4 indicating directory
108 continue;
110 QString outfilename;
111 if(!singleoutfile.isEmpty()
112 && QFileInfo(m_zip->getCurrentFileName()).fileName() == file) {
113 outfilename = singleoutfile;
115 else if(singleoutfile.isEmpty()) {
116 outfilename = dest + "/" + m_zip->getCurrentFileName();
118 if(outfilename.isEmpty())
119 continue;
120 QFile outputFile(outfilename);
121 // make sure the output path exists
122 if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) {
123 result = false;
124 emit logItem(tr("Creating output path failed"), LOGERROR);
125 qDebug() << "[ZipUtil] creating output path failed for:"
126 << outfilename;
127 break;
129 if(!outputFile.open(QFile::WriteOnly)) {
130 result = false;
131 emit logItem(tr("Creating output file failed"), LOGERROR);
132 qDebug() << "[ZipUtil] creating output file failed:"
133 << outfilename;
134 break;
136 currentFile->open(QIODevice::ReadOnly);
137 outputFile.write(currentFile->readAll());
138 if(currentFile->getZipError() != UNZ_OK) {
139 result = false;
140 emit logItem(tr("Error during Zip operation"), LOGERROR);
141 qDebug() << "[ZipUtil] QuaZip error:" << currentFile->getZipError()
142 << "on file" << currentFile->getFileName();
143 break;
145 currentFile->close();
146 outputFile.close();
148 emit logProgress(current, entries);
150 delete currentFile;
151 emit logProgress(1, 1);
153 return result;
157 //! @brief append a folder to current archive
158 //! @param source source folder
159 //! @param basedir base folder for archive. Will get stripped from zip paths.
160 //! @return true on success, false otherwise
161 bool ZipUtil::appendDirToArchive(QString& source, QString& basedir)
163 bool result = true;
164 if(!m_zip || !m_zip->isOpen()) {
165 qDebug() << "[ZipUtil] Zip file not open!";
166 return false;
168 // get a list of all files and folders. Needed for progress info and avoids
169 // recursive calls.
170 QDirIterator iterator(source, QDirIterator::Subdirectories);
171 QStringList fileList;
172 while(iterator.hasNext()) {
173 iterator.next();
174 // skip folders, we can't add them.
175 if(!QFileInfo(iterator.filePath()).isDir()) {
176 fileList.append(iterator.filePath());
179 qDebug() << "[ZipUtil] Adding" << fileList.size() << "files to archive";
181 int max = fileList.size();
182 for(int i = 0; i < max; i++) {
183 QString current = fileList.at(i);
184 if(!appendFileToArchive(current, basedir)) {
185 qDebug() << "[ZipUtil] Error appending file" << current
186 << "to archive" << m_zip->getZipName();
187 result = false;
188 break;
190 emit logProgress(i, max);
192 return result;
196 //! @brief append a single file to current archive
198 bool ZipUtil::appendFileToArchive(QString& file, QString& basedir)
200 bool result = true;
201 if(!m_zip || !m_zip->isOpen()) {
202 qDebug() << "[ZipUtil] Zip file not open!";
203 return false;
205 // skip folders, we can't add them.
206 QFileInfo fileinfo(file);
207 if(fileinfo.isDir()) {
208 return false;
210 QString infile = fileinfo.canonicalFilePath();
211 QString newfile = infile;
212 newfile.remove(QDir(basedir).canonicalPath() + "/");
214 QuaZipFile fout(m_zip);
215 QFile fin(file);
217 if(!fin.open(QFile::ReadOnly)) {
218 qDebug() << "[ZipUtil] Could not open file for reading:" << file;
219 return false;
221 if(!fout.open(QIODevice::WriteOnly, QuaZipNewInfo(newfile, infile))) {
222 fin.close();
223 qDebug() << "[ZipUtil] Could not open file for writing:" << newfile;
224 return false;
227 result = (fout.write(fin.readAll()) < 0) ? false : true;
228 fin.close();
229 fout.close();
230 return result;
234 //! @brief calculate total size of extracted files
235 qint64 ZipUtil::totalUncompressedSize(unsigned int clustersize)
237 qint64 uncompressed = 0;
239 QList<QuaZipFileInfo> items = contentProperties();
240 if(items.size() == 0) {
241 return -1;
243 int max = items.size();
244 if(clustersize > 0) {
245 for(int i = 0; i < max; ++i) {
246 qint64 item = items.at(i).uncompressedSize;
247 uncompressed += (item + clustersize - (item % clustersize));
250 else {
251 for(int i = 0; i < max; ++i) {
252 uncompressed += items.at(i).uncompressedSize;
255 if(clustersize > 0) {
256 qDebug() << "[ZipUtil] calculation rounded to cluster size for each file:"
257 << clustersize;
259 qDebug() << "[ZipUtil] size of archive files uncompressed:"
260 << uncompressed;
261 return uncompressed;
265 QStringList ZipUtil::files(void)
267 QList<QuaZipFileInfo> items = contentProperties();
268 QStringList fileList;
269 if(items.size() == 0) {
270 return fileList;
272 int max = items.size();
273 for(int i = 0; i < max; ++i) {
274 fileList.append(items.at(i).name);
276 return fileList;
280 QList<QuaZipFileInfo> ZipUtil::contentProperties()
282 QList<QuaZipFileInfo> items;
283 if(!m_zip || !m_zip->isOpen()) {
284 qDebug() << "[ZipUtil] Zip file not open!";
285 return items;
287 QuaZipFileInfo info;
288 QuaZipFile currentFile(m_zip);
289 for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile())
291 currentFile.getFileInfo(&info);
292 if(currentFile.getZipError() != UNZ_OK) {
293 qDebug() << "[ZipUtil] QuaZip error:" << currentFile.getZipError()
294 << "on file" << currentFile.getFileName();
295 return QList<QuaZipFileInfo>();
297 items.append(info);
299 return items;