311 lines
8.5 KiB
C++
311 lines
8.5 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "minizinterface.h"
|
|
#include "progresswidget.h"
|
|
|
|
#include <QDir>
|
|
#include <QDirIterator>
|
|
#include <QFileInfo>
|
|
#include <QDebug>
|
|
#include <QWidget>
|
|
#include <QApplication>
|
|
|
|
MinizInterface::MinizInterface(ProgressWidget * progress, const ProgressCalcMethod progressMethod, const int & logLevel) :
|
|
QObject(nullptr),
|
|
progress(progress),
|
|
progressMethod(progressMethod),
|
|
progressValue(0),
|
|
logLevel(logLevel),
|
|
path(""),
|
|
archiveFile(""),
|
|
stopping(false)
|
|
{
|
|
reportProgress(tr("Progress calculation method: file %1").arg(progressMethod == PCM_COUNT ? tr("count") : tr("size")), QtDebugMsg);
|
|
}
|
|
|
|
MinizInterface::~MinizInterface()
|
|
{
|
|
|
|
}
|
|
|
|
bool MinizInterface::zipPathToFile(const QString & sourcePath, const QString & archiveFile, bool append)
|
|
{
|
|
if (progress)
|
|
progress->setInfo(tr("Compressing %1 to %2 with append %3").arg(sourcePath, archiveFile, append ? "true" : "false"));
|
|
else
|
|
qDebug() << QString("Compressing %1 to %2 with append %3").arg(sourcePath, archiveFile, append ? "true" : "false");
|
|
|
|
reportProgress(tr("Miniz version: %1").arg(MZ_VERSION), QtDebugMsg);
|
|
|
|
progressValue = 0;
|
|
path = sourcePath;
|
|
this->archiveFile = archiveFile;
|
|
mz_zip_zero_struct(&zip_archive);
|
|
|
|
QFileInfo afi(archiveFile);
|
|
|
|
if (afi.exists() && !append)
|
|
reportProgress(tr("Existing archive will be overwritten"), QtCriticalMsg);
|
|
|
|
if (afi.exists() && append) {
|
|
if (!mz_zip_reader_init_file(&zip_archive, qPrintable(archiveFile), 0)) {
|
|
reportProgress(tr("Unable to open existing archive"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
else
|
|
reportProgress(tr("Existing archive opened"), QtDebugMsg);
|
|
|
|
if (!mz_zip_writer_init_from_reader(&zip_archive, qPrintable(archiveFile))) {
|
|
reportProgress(tr("Unable to write to existing archive"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
else
|
|
reportProgress(tr("Existing archive initialised"), QtDebugMsg);
|
|
}
|
|
else {
|
|
if (!mz_zip_writer_init_file(&zip_archive, qPrintable(archiveFile), 0)) {
|
|
reportProgress(tr("Failure to initialise archive"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
else
|
|
reportProgress(tr("Archive initialised"), QtDebugMsg);
|
|
}
|
|
|
|
QFileInfo pfi(path);
|
|
|
|
int fileCount = 0;
|
|
|
|
if (pfi.isDir()) {
|
|
if (progressMethod == PCM_COUNT) {
|
|
reportProgress(tr("Calculating number of items to archive"), QtDebugMsg);
|
|
|
|
QDirIterator itcnt(path, QDirIterator::Subdirectories);
|
|
|
|
while (itcnt.hasNext()) {
|
|
fileCount++;
|
|
}
|
|
}
|
|
|
|
if (progress) {
|
|
if (progressMethod == PCM_COUNT)
|
|
progress->setMaximum(fileCount);
|
|
else
|
|
progress->setMaximum(pfi.size());
|
|
}
|
|
|
|
fileCount = 0;
|
|
QDirIterator it(path, QDirIterator::Subdirectories);
|
|
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
if (!addFileToArchive(it.filePath()))
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
fileCount = 1;
|
|
|
|
if (progress) {
|
|
if (progressMethod == PCM_COUNT)
|
|
progress->setMaximum(fileCount);
|
|
else
|
|
progress->setMaximum(pfi.size());
|
|
}
|
|
|
|
if (!addFileToArchive(path))
|
|
return false;
|
|
}
|
|
|
|
if (!mz_zip_writer_finalize_archive(&zip_archive)) {
|
|
mz_zip_writer_end(&zip_archive);
|
|
reportProgress(tr("Failure to finalise archive"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
mz_zip_writer_end(&zip_archive);
|
|
|
|
if (progress)
|
|
progress->setValue(progress->maximum());
|
|
|
|
reportProgress(tr("Compress complete"));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MinizInterface::addFileToArchive(const QString & path)
|
|
{
|
|
if (!mz_zip_writer_add_file(&zip_archive, qPrintable(archiveFile), qPrintable(path), NULL, 0, MZ_DEFAULT_COMPRESSION)) {
|
|
mz_zip_writer_end(&zip_archive);
|
|
reportProgress(tr("Failure to add %1").arg(path), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
if (progressMethod == PCM_COUNT)
|
|
++progressValue;
|
|
else
|
|
progressValue += QFileInfo(path).size();
|
|
|
|
if (progress)
|
|
progress->setValue(progressValue);
|
|
|
|
reportProgress(tr("Added file: %1").arg(path), QtDebugMsg);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MinizInterface::unzipArchiveToPath(const QString & archiveFile, const QString & destinationPath)
|
|
{
|
|
QFileInfo file(archiveFile);
|
|
|
|
if (progress)
|
|
progress->setInfo(tr("Decompressing %1").arg(file.fileName()));
|
|
else
|
|
qDebug() << QString("Decompressing %1 to %2").arg(archiveFile, destinationPath);
|
|
|
|
reportProgress(tr("Miniz version: %1").arg(MZ_VERSION), QtDebugMsg);
|
|
|
|
progressValue = 0;
|
|
path = destinationPath;
|
|
this->archiveFile = archiveFile;
|
|
mz_zip_zero_struct(&zip_archive);
|
|
|
|
if (!mz_zip_reader_init_file(&zip_archive, qPrintable(archiveFile), 0)) {
|
|
reportProgress(tr("File does not appear to be a compressed archive"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive);
|
|
|
|
if (fileCount == 0) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
reportProgress(tr("Compressed archive does not contain any files"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
if (progress) {
|
|
if (progressMethod == PCM_COUNT)
|
|
progress->setMaximum(fileCount);
|
|
else
|
|
progress->setMaximum(QFileInfo(archiveFile).size());
|
|
}
|
|
|
|
mz_zip_archive_file_stat file_stat;
|
|
|
|
if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
reportProgress(tr("File status error"), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < fileCount; i++) {
|
|
if (isStopping()) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
reportProgress(tr("Decompression interrupted"), QtWarningMsg);
|
|
return false;
|
|
}
|
|
|
|
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
reportProgress(tr("Unable to obtain file status for index: %1").arg(i), QtFatalMsg);
|
|
return false;
|
|
}
|
|
|
|
QString destPath = path % "/" % QString(file_stat.m_filename);
|
|
|
|
if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) {
|
|
if (!createDirectory(destPath)) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
QFileInfo dfi(destPath);
|
|
if (!createDirectory(dfi.absolutePath())) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
return false;
|
|
}
|
|
|
|
if (!mz_zip_reader_extract_to_file(&zip_archive, i, qPrintable(destPath), 0)) {
|
|
mz_zip_reader_end(&zip_archive);
|
|
reportProgress(tr("Failed to extract %1 to %2").arg(dfi.fileName(), dfi.absolutePath()), QtFatalMsg);
|
|
return false;
|
|
}
|
|
else {
|
|
if (dfi.size() != (qint64)file_stat.m_uncomp_size) {
|
|
reportProgress(tr("File %1 extracted size %2 does not match original %3").arg(file_stat.m_filename).arg(dfi.size()).arg((qint64)file_stat.m_uncomp_size), QtFatalMsg);
|
|
// return false; disable until testing complete as there maybe some adjustment factor or even OS strangeness
|
|
}
|
|
}
|
|
|
|
if (progressMethod == PCM_COUNT)
|
|
++progressValue;
|
|
else
|
|
progressValue += file_stat.m_comp_size;
|
|
|
|
if (progress)
|
|
progress->setValue(progressValue);
|
|
|
|
reportProgress(tr("Extracted file: %1").arg(file_stat.m_filename), QtDebugMsg);
|
|
// to assist in responsiveness and allow stop signal to be received and processed
|
|
QApplication::processEvents();
|
|
}
|
|
}
|
|
|
|
mz_zip_reader_end(&zip_archive);
|
|
|
|
if (progress)
|
|
progress->setValue(progress->maximum());
|
|
|
|
reportProgress(tr("Decompress complete"), QtDebugMsg);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MinizInterface::createDirectory(const QString & path)
|
|
{
|
|
if (!QDir(path).exists()) {
|
|
if (!QDir().mkpath(path)) {
|
|
reportProgress(tr("Failed to create directory: %1").arg(path), QtFatalMsg);
|
|
return false;
|
|
}
|
|
else
|
|
reportProgress(tr("Created directory: %1").arg(path), QtDebugMsg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void MinizInterface::reportProgress(const QString & text, const int & type, bool richText)
|
|
{
|
|
if (type >= logLevel) {
|
|
if (progress)
|
|
progress->addMessage(text, type);
|
|
else
|
|
qDebug() << text;
|
|
}
|
|
}
|
|
|
|
void MinizInterface::stop()
|
|
{
|
|
stopping = true;
|
|
}
|