Page MenuHome GnuPG

No OneTemporary

diff --git a/src/crypto/checksumsutils_p.h b/src/crypto/checksumsutils_p.h
new file mode 100644
index 000000000..c2d849a3b
--- /dev/null
+++ b/src/crypto/checksumsutils_p.h
@@ -0,0 +1,124 @@
+/* -*- mode: c++; c-basic-offset:4 -*-
+ crypto/checksumesutils_p.h
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#pragma once
+
+#include <QFile>
+
+#include <Libkleo/ChecksumDefinition>
+#include "kleopatra_debug.h"
+
+#ifdef Q_OS_UNIX
+// can we use QAbstractFileEngine::caseSensitive()?
+static const Qt::CaseSensitivity fs_cs = Qt::CaseSensitive;
+#else
+static const Qt::CaseSensitivity fs_cs = Qt::CaseInsensitive;
+#endif
+
+static QList<QRegExp> get_patterns(const std::vector< std::shared_ptr<Kleo::ChecksumDefinition> > &checksumDefinitions)
+{
+ QList<QRegExp> result;
+ for (const std::shared_ptr<Kleo::ChecksumDefinition> &cd : checksumDefinitions)
+ if (cd) {
+ const auto patterns = cd->patterns();
+ for (const QString &pattern : patterns) {
+ result.push_back(QRegExp(pattern, fs_cs));
+ }
+ }
+ return result;
+}
+
+namespace
+{
+
+struct matches_any : std::unary_function<QString, bool> {
+ const QList<QRegExp> m_regexps;
+ explicit matches_any(const QList<QRegExp> &regexps) : m_regexps(regexps) {}
+ bool operator()(const QString &s) const
+ {
+ return std::any_of(m_regexps.cbegin(), m_regexps.cend(),
+ [s](const QRegExp &rx) { return rx.exactMatch(s); });
+ }
+};
+}
+
+namespace
+{
+struct File {
+ QString name;
+ QByteArray checksum;
+ bool binary;
+};
+}
+
+static QString decode(const QString &encoded)
+{
+ QString decoded;
+ decoded.reserve(encoded.size());
+ bool shift = false;
+ for (QChar ch : encoded)
+ if (shift) {
+ switch (ch.toLatin1()) {
+ case '\\': decoded += QLatin1Char('\\'); break;
+ case 'n': decoded += QLatin1Char('\n'); break;
+ default:
+ qCDebug(KLEOPATRA_LOG) << "invalid escape sequence" << '\\' << ch << "(interpreted as '" << ch << "')";
+ decoded += ch;
+ break;
+ }
+ shift = false;
+ } else {
+ if (ch == QLatin1Char('\\')) {
+ shift = true;
+ } else {
+ decoded += ch;
+ }
+ }
+ return decoded;
+}
+
+static std::vector<File> parse_sum_file(const QString &fileName)
+{
+ std::vector<File> files;
+ QFile f(fileName);
+ if (f.open(QIODevice::ReadOnly)) {
+ QTextStream s(&f);
+ QRegExp rx(QLatin1String("(\\?)([a-f0-9A-F]+) ([ *])([^\n]+)\n*"));
+ while (!s.atEnd()) {
+ const QString line = s.readLine();
+ if (rx.exactMatch(line)) {
+ Q_ASSERT(!rx.cap(4).endsWith(QLatin1Char('\n')));
+ const File file = {
+ rx.cap(1) == QLatin1String("\\") ? decode(rx.cap(4)) : rx.cap(4),
+ rx.cap(2).toLatin1(),
+ rx.cap(3) == QLatin1String("*"),
+ };
+ files.push_back(file);
+ }
+ }
+ }
+ return files;
+}
+
+
+static std::shared_ptr<Kleo::ChecksumDefinition> filename2definition(const QString &fileName,
+ const std::vector< std::shared_ptr<Kleo::ChecksumDefinition> > &checksumDefinitions)
+{
+ for (const std::shared_ptr<Kleo::ChecksumDefinition> &cd : checksumDefinitions) {
+ if (cd) {
+ const auto patterns = cd->patterns();
+ for (const QString &pattern : patterns) {
+ if (QRegExp(pattern, fs_cs).exactMatch(fileName)) {
+ return cd;
+ }
+ }
+ }
+ }
+ return std::shared_ptr<Kleo::ChecksumDefinition>();
+}
diff --git a/src/crypto/createchecksumscontroller.cpp b/src/crypto/createchecksumscontroller.cpp
index dcd0fbc8d..656a5d086 100644
--- a/src/crypto/createchecksumscontroller.cpp
+++ b/src/crypto/createchecksumscontroller.cpp
@@ -1,719 +1,609 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/createchecksumscontroller.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "createchecksumscontroller.h"
+#include "checksumsutils_p.h"
#include <utils/input.h>
#include <utils/output.h>
#include <utils/kleo_assert.h>
#include <Libkleo/Stl_Util>
-#include <Libkleo/ChecksumDefinition>
#include <Libkleo/Classify>
#include <KLocalizedString>
-#include "kleopatra_debug.h"
#include <QTemporaryFile>
#include <KConfigGroup>
#include <KSharedConfig>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include <QPointer>
#include <QFileInfo>
#include <QThread>
#include <QMutex>
#include <QProgressDialog>
#include <QDir>
#include <QProcess>
#include <gpg-error.h>
#include <deque>
#include <map>
#include <limits>
#include <functional>
using namespace Kleo;
using namespace Kleo::Crypto;
namespace
{
class ResultDialog : public QDialog
{
Q_OBJECT
public:
ResultDialog(const QStringList &created, const QStringList &errors, QWidget *parent = nullptr, Qt::WindowFlags f = {})
: QDialog(parent, f),
createdLB(created.empty()
? i18nc("@info", "No checksum files have been created.")
: i18nc("@info", "These checksum files have been successfully created:"), this),
createdLW(this),
errorsLB(errors.empty()
? i18nc("@info", "There were no errors.")
: i18nc("@info", "The following errors were encountered:"), this),
errorsLW(this),
buttonBox(QDialogButtonBox::Ok, Qt::Horizontal, this),
vlay(this)
{
KDAB_SET_OBJECT_NAME(createdLB);
KDAB_SET_OBJECT_NAME(createdLW);
KDAB_SET_OBJECT_NAME(errorsLB);
KDAB_SET_OBJECT_NAME(errorsLW);
KDAB_SET_OBJECT_NAME(buttonBox);
KDAB_SET_OBJECT_NAME(vlay);
createdLW.addItems(created);
QRect r;
for (int i = 0; i < created.size(); ++i) {
r = r.united(createdLW.visualRect(createdLW.model()->index(0, i)));
}
createdLW.setMinimumWidth(qMin(1024, r.width() + 4 * createdLW.frameWidth()));
errorsLW.addItems(errors);
vlay.addWidget(&createdLB);
vlay.addWidget(&createdLW, 1);
vlay.addWidget(&errorsLB);
vlay.addWidget(&errorsLW, 1);
vlay.addWidget(&buttonBox);
if (created.empty()) {
createdLW.hide();
}
if (errors.empty()) {
errorsLW.hide();
}
connect(&buttonBox, &QDialogButtonBox::accepted, this, &ResultDialog::accept);
connect(&buttonBox, &QDialogButtonBox::rejected, this, &ResultDialog::reject);
readConfig();
}
~ResultDialog() override
{
writeConfig();
}
void readConfig()
{
KConfigGroup dialog(KSharedConfig::openStateConfig(), "ResultDialog");
const QSize size = dialog.readEntry("Size", QSize(600, 400));
if (size.isValid()) {
resize(size);
}
}
void writeConfig()
{
KConfigGroup dialog(KSharedConfig::openStateConfig(), "ResultDialog");
dialog.writeEntry("Size", size());
dialog.sync();
}
private:
QLabel createdLB;
QListWidget createdLW;
QLabel errorsLB;
QListWidget errorsLW;
QDialogButtonBox buttonBox;
QVBoxLayout vlay;
};
}
-#ifdef Q_OS_UNIX
-static const bool HAVE_UNIX = true;
-#else
-static const bool HAVE_UNIX = false;
-#endif
-
-static const Qt::CaseSensitivity fs_cs = HAVE_UNIX ? Qt::CaseSensitive : Qt::CaseInsensitive; // can we use QAbstractFileEngine::caseSensitive()?
-
static QStringList fs_sort(QStringList l)
{
std::sort(l.begin(), l.end(), [](const QString &lhs, const QString &rhs) {
return QString::compare(lhs, rhs, fs_cs) < 0;
});
return l;
}
static QStringList fs_intersect(QStringList l1, QStringList l2)
{
fs_sort(l1);
fs_sort(l2);
QStringList result;
std::set_intersection(l1.begin(), l1.end(),
l2.begin(), l2.end(),
std::back_inserter(result),
[](const QString &lhs, const QString &rhs) {
return QString::compare(lhs, rhs, fs_cs) < 0;
});
return result;
}
-static QList<QRegExp> get_patterns(const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
-{
- QList<QRegExp> result;
- for (const std::shared_ptr<ChecksumDefinition> &cd : checksumDefinitions)
- if (cd) {
- const auto patterns = cd->patterns();
- for (const QString &pattern : patterns) {
- result.push_back(QRegExp(pattern, fs_cs));
- }
- }
- return result;
-}
-
-namespace
-{
-
-struct matches_any : std::unary_function<QString, bool> {
- const QList<QRegExp> m_regexps;
- explicit matches_any(const QList<QRegExp> &regexps) : m_regexps(regexps) {}
- bool operator()(const QString &s) const
- {
- return std::any_of(m_regexps.cbegin(), m_regexps.cend(),
- [s](const QRegExp &rx) { return rx.exactMatch(s); });
- }
-};
-}
-
class CreateChecksumsController::Private : public QThread
{
Q_OBJECT
friend class ::Kleo::Crypto::CreateChecksumsController;
CreateChecksumsController *const q;
public:
explicit Private(CreateChecksumsController *qq);
~Private() override;
Q_SIGNALS:
void progress(int, int, const QString &);
private:
void slotOperationFinished()
{
#ifndef QT_NO_PROGRESSDIALOG
if (progressDialog) {
progressDialog->setValue(progressDialog->maximum());
progressDialog->close();
}
#endif // QT_NO_PROGRESSDIALOG
auto const dlg = new ResultDialog(created, errors);
dlg->setAttribute(Qt::WA_DeleteOnClose);
q->bringToForeground(dlg);
if (!errors.empty())
q->setLastError(gpg_error(GPG_ERR_GENERAL),
errors.join(QLatin1Char('\n')));
q->emitDoneOrError();
}
void slotProgress(int current, int total, const QString &what)
{
qCDebug(KLEOPATRA_LOG) << "progress: " << current << "/" << total << ": " << qPrintable(what);
#ifndef QT_NO_PROGRESSDIALOG
if (!progressDialog) {
return;
}
progressDialog->setMaximum(total);
progressDialog->setValue(current);
progressDialog->setLabelText(what);
#endif // QT_NO_PROGRESSDIALOG
}
private:
void run() override;
private:
#ifndef QT_NO_PROGRESSDIALOG
QPointer<QProgressDialog> progressDialog;
#endif
mutable QMutex mutex;
const std::vector< std::shared_ptr<ChecksumDefinition> > checksumDefinitions;
std::shared_ptr<ChecksumDefinition> checksumDefinition;
QStringList files;
QStringList errors, created;
bool allowAddition;
volatile bool canceled;
};
CreateChecksumsController::Private::Private(CreateChecksumsController *qq)
: q(qq),
#ifndef QT_NO_PROGRESSDIALOG
progressDialog(),
#endif
mutex(),
checksumDefinitions(ChecksumDefinition::getChecksumDefinitions()),
checksumDefinition(ChecksumDefinition::getDefaultChecksumDefinition(checksumDefinitions)),
files(),
errors(),
created(),
allowAddition(false),
canceled(false)
{
connect(this, SIGNAL(progress(int,int,QString)),
q, SLOT(slotProgress(int,int,QString)));
connect(this, &Private::progress,
q, &Controller::progress);
connect(this, SIGNAL(finished()),
q, SLOT(slotOperationFinished()));
}
CreateChecksumsController::Private::~Private()
{
qCDebug(KLEOPATRA_LOG);
}
CreateChecksumsController::CreateChecksumsController(QObject *p)
: Controller(p), d(new Private(this))
{
}
CreateChecksumsController::CreateChecksumsController(const std::shared_ptr<const ExecutionContext> &ctx, QObject *p)
: Controller(ctx, p), d(new Private(this))
{
}
CreateChecksumsController::~CreateChecksumsController()
{
qCDebug(KLEOPATRA_LOG);
}
void CreateChecksumsController::setFiles(const QStringList &files)
{
kleo_assert(!d->isRunning());
kleo_assert(!files.empty());
const QList<QRegExp> patterns = get_patterns(d->checksumDefinitions);
if (!std::all_of(files.cbegin(), files.cend(), matches_any(patterns)) &&
!std::none_of(files.cbegin(), files.cend(), matches_any(patterns))) {
throw Exception(gpg_error(GPG_ERR_INV_ARG), i18n("Create Checksums: input files must be either all checksum files or all files to be checksummed, not a mixture of both."));
}
const QMutexLocker locker(&d->mutex);
d->files = files;
}
void CreateChecksumsController::setAllowAddition(bool allow)
{
kleo_assert(!d->isRunning());
const QMutexLocker locker(&d->mutex);
d->allowAddition = allow;
}
bool CreateChecksumsController::allowAddition() const
{
const QMutexLocker locker(&d->mutex);
return d->allowAddition;
}
void CreateChecksumsController::start()
{
{
const QMutexLocker locker(&d->mutex);
#ifndef QT_NO_PROGRESSDIALOG
d->progressDialog = new QProgressDialog(i18n("Initializing..."), i18n("Cancel"), 0, 0);
applyWindowID(d->progressDialog);
d->progressDialog->setAttribute(Qt::WA_DeleteOnClose);
d->progressDialog->setMinimumDuration(1000);
d->progressDialog->setWindowTitle(i18nc("@title:window", "Create Checksum Progress"));
connect(d->progressDialog.data(), &QProgressDialog::canceled, this, &CreateChecksumsController::cancel);
#endif // QT_NO_PROGRESSDIALOG
d->canceled = false;
d->errors.clear();
d->created.clear();
}
d->start();
}
void CreateChecksumsController::cancel()
{
qCDebug(KLEOPATRA_LOG);
const QMutexLocker locker(&d->mutex);
d->canceled = true;
}
namespace
{
struct Dir {
QDir dir;
QString sumFile;
QStringList inputFiles;
quint64 totalSize;
std::shared_ptr<ChecksumDefinition> checksumDefinition;
};
}
static QStringList remove_checksum_files(QStringList l, const QList<QRegExp> &rxs)
{
QStringList::iterator end = l.end();
for (const QRegExp &rx : rxs) {
end = std::remove_if(l.begin(), end,
[rx](const QString &str) {
return rx.exactMatch(str);
});
}
l.erase(end, l.end());
return l;
}
-namespace
-{
-struct File {
- QString name;
- QByteArray checksum;
- bool binary;
-};
-}
-
-static QString decode(const QString &encoded)
-{
- QString decoded;
- decoded.reserve(encoded.size());
- bool shift = false;
- for (QChar ch : encoded)
- if (shift) {
- switch (ch.toLatin1()) {
- case '\\': decoded += QLatin1Char('\\'); break;
- case 'n': decoded += QLatin1Char('\n'); break;
- default:
- qCDebug(KLEOPATRA_LOG) << "invalid escape sequence" << '\\' << ch << "(interpreted as '" << ch << "')";
- decoded += ch;
- break;
- }
- shift = false;
- } else {
- if (ch == QLatin1Char('\\')) {
- shift = true;
- } else {
- decoded += ch;
- }
- }
- return decoded;
-}
-
-static std::vector<File> parse_sum_file(const QString &fileName)
-{
- std::vector<File> files;
- QFile f(fileName);
- if (f.open(QIODevice::ReadOnly)) {
- QTextStream s(&f);
- QRegExp rx(QLatin1String("(\\?)([a-f0-9A-F]+) ([ *])([^\n]+)\n*"));
- while (!s.atEnd()) {
- const QString line = s.readLine();
- if (rx.exactMatch(line)) {
- Q_ASSERT(!rx.cap(4).endsWith(QLatin1Char('\n')));
- const File file = {
- rx.cap(1) == QLatin1String("\\") ? decode(rx.cap(4)) : rx.cap(4),
- rx.cap(2).toLatin1(),
- rx.cap(3) == QLatin1String("*"),
- };
- files.push_back(file);
- }
- }
- }
- return files;
-}
-
static quint64 aggregate_size(const QDir &dir, const QStringList &files)
{
quint64 n = 0;
for (const QString &file : files) {
n += QFileInfo(dir.absoluteFilePath(file)).size();
}
return n;
}
-static std::shared_ptr<ChecksumDefinition> filename2definition(const QString &fileName,
- const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
-{
- for (const std::shared_ptr<ChecksumDefinition> &cd : checksumDefinitions) {
- if (cd) {
- const auto patterns = cd->patterns();
- for (const QString &pattern : patterns) {
- if (QRegExp(pattern, fs_cs).exactMatch(fileName)) {
- return cd;
- }
- }
- }
- }
- return std::shared_ptr<ChecksumDefinition>();
-}
-
static std::vector<Dir> find_dirs_by_sum_files(const QStringList &files, bool allowAddition,
const std::function<void(int)> &progress,
const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
const QList<QRegExp> patterns = get_patterns(checksumDefinitions);
std::vector<Dir> dirs;
dirs.reserve(files.size());
int i = 0;
for (const QString &file : files) {
const QFileInfo fi(file);
const QDir dir = fi.dir();
const QStringList entries = remove_checksum_files(dir.entryList(QDir::Files), patterns);
QStringList inputFiles;
if (allowAddition) {
inputFiles = entries;
} else {
const std::vector<File> parsed = parse_sum_file(fi.absoluteFilePath());
QStringList oldInputFiles;
oldInputFiles.reserve(parsed.size());
std::transform(parsed.cbegin(), parsed.cend(), std::back_inserter(oldInputFiles),
std::mem_fn(&File::name));
inputFiles = fs_intersect(oldInputFiles, entries);
}
const Dir item = {
dir,
fi.fileName(),
inputFiles,
aggregate_size(dir, inputFiles),
filename2definition(fi.fileName(), checksumDefinitions)
};
dirs.push_back(item);
if (progress) {
progress(++i);
}
}
return dirs;
}
namespace
{
struct less_dir : std::binary_function<QDir, QDir, bool> {
bool operator()(const QDir &lhs, const QDir &rhs) const
{
return QString::compare(lhs.absolutePath(), rhs.absolutePath(), fs_cs) < 0;
}
};
}
static std::vector<Dir> find_dirs_by_input_files(const QStringList &files, const std::shared_ptr<ChecksumDefinition> &checksumDefinition, bool allowAddition,
const std::function<void(int)> &progress,
const std::vector< std::shared_ptr<ChecksumDefinition> > &checksumDefinitions)
{
Q_UNUSED(allowAddition)
if (!checksumDefinition) {
return std::vector<Dir>();
}
const QList<QRegExp> patterns = get_patterns(checksumDefinitions);
std::map<QDir, QStringList, less_dir> dirs2files;
// Step 1: sort files by the dir they're contained in:
std::deque<QString> inputs(files.begin(), files.end());
int i = 0;
while (!inputs.empty()) {
const QString file = inputs.front();
inputs.pop_front();
const QFileInfo fi(file);
if (fi.isDir()) {
QDir dir(file);
dirs2files[ dir ] = remove_checksum_files(dir.entryList(QDir::Files), patterns);
const auto entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
std::transform(entryList.cbegin(), entryList.cend(),
std::inserter(inputs, inputs.begin()),
[&dir](const QString &entry) {
return dir.absoluteFilePath(entry);
});
} else {
dirs2files[fi.dir()].push_back(file);
}
if (progress) {
progress(++i);
}
}
// Step 2: convert into vector<Dir>:
std::vector<Dir> dirs;
dirs.reserve(dirs2files.size());
for (auto it = dirs2files.begin(), end = dirs2files.end(); it != end; ++it) {
const QStringList inputFiles = remove_checksum_files(it->second, patterns);
if (inputFiles.empty()) {
continue;
}
const Dir dir = {
it->first,
checksumDefinition->outputFileName(),
inputFiles,
aggregate_size(it->first, inputFiles),
checksumDefinition
};
dirs.push_back(dir);
if (progress) {
progress(++i);
}
}
return dirs;
}
static QString process(const Dir &dir, bool *fatal)
{
const QString absFilePath = dir.dir.absoluteFilePath(dir.sumFile);
QTemporaryFile out;
QProcess p;
if (!out.open()) {
return QStringLiteral("Failed to open Temporary file.");
}
p.setWorkingDirectory(dir.dir.absolutePath());
p.setStandardOutputFile(out.fileName());
const QString program = dir.checksumDefinition->createCommand();
dir.checksumDefinition->startCreateCommand(&p, dir.inputFiles);
p.waitForFinished();
qCDebug(KLEOPATRA_LOG) << "[" << &p << "] Exit code " << p.exitCode();
if (p.exitStatus() != QProcess::NormalExit || p.exitCode() != 0) {
if (fatal && p.error() == QProcess::FailedToStart) {
*fatal = true;
}
if (p.error() == QProcess::UnknownError)
return i18n("Error while running %1: %2", program,
QString::fromLocal8Bit(p.readAllStandardError().trimmed().constData()));
else {
return i18n("Failed to execute %1: %2", program, p.errorString());
}
}
QFileInfo fi(absFilePath);
if (!(fi.exists() && !QFile::remove(absFilePath)) && QFile::copy(out.fileName(), absFilePath)) {
return QString();
}
return xi18n("Failed to overwrite <filename>%1</filename>.", dir.sumFile);
}
namespace
{
static QDebug operator<<(QDebug s, const Dir &dir)
{
return s << "Dir(" << dir.dir << "->" << dir.sumFile << "<-(" << dir.totalSize << ')' << dir.inputFiles << ")\n";
}
}
void CreateChecksumsController::Private::run()
{
QMutexLocker locker(&mutex);
const QStringList files = this->files;
const std::vector< std::shared_ptr<ChecksumDefinition> > checksumDefinitions = this->checksumDefinitions;
const std::shared_ptr<ChecksumDefinition> checksumDefinition = this->checksumDefinition;
const bool allowAddition = this->allowAddition;
locker.unlock();
QStringList errors;
QStringList created;
if (!checksumDefinition) {
errors.push_back(i18n("No checksum programs defined."));
locker.relock();
this->errors = errors;
return;
} else {
qCDebug(KLEOPATRA_LOG) << "using checksum-definition" << checksumDefinition->id();
}
//
// Step 1: build a list of work to do (no progress):
//
const QString scanning = i18n("Scanning directories...");
Q_EMIT progress(0, 0, scanning);
const bool haveSumFiles = std::all_of(files.cbegin(), files.cend(), matches_any(get_patterns(checksumDefinitions)));
const auto progressCb = [this, &scanning](int c) { Q_EMIT progress(c, 0, scanning); };
const std::vector<Dir> dirs = haveSumFiles
? find_dirs_by_sum_files(files, allowAddition, progressCb, checksumDefinitions)
: find_dirs_by_input_files(files, checksumDefinition, allowAddition, progressCb, checksumDefinitions);
for (const Dir &dir : dirs) {
qCDebug(KLEOPATRA_LOG) << dir;
}
if (!canceled) {
Q_EMIT progress(0, 0, i18n("Calculating total size..."));
const quint64 total = kdtools::accumulate_transform(dirs.cbegin(), dirs.cend(),
std::mem_fn(&Dir::totalSize),
Q_UINT64_C(0));
if (!canceled) {
//
// Step 2: perform work (with progress reporting):
//
// re-scale 'total' to fit into ints (wish QProgressDialog would use quint64...)
const quint64 factor = total / std::numeric_limits<int>::max() + 1;
quint64 done = 0;
for (const Dir &dir : dirs) {
Q_EMIT progress(done / factor, total / factor,
i18n("Checksumming (%2) in %1", dir.checksumDefinition->label(), dir.dir.path()));
bool fatal = false;
const QString error = process(dir, &fatal);
if (!error.isEmpty()) {
errors.push_back(error);
} else {
created.push_back(dir.dir.absoluteFilePath(dir.sumFile));
}
done += dir.totalSize;
if (fatal || canceled) {
break;
}
}
Q_EMIT progress(done / factor, total / factor, i18n("Done."));
}
}
locker.relock();
this->errors = errors;
this->created = created;
// mutex unlocked by QMutexLocker
}
#include "moc_createchecksumscontroller.cpp"
#include "createchecksumscontroller.moc"

File Metadata

Mime Type
text/x-diff
Expires
Sun, Feb 22, 6:42 PM (1 d, 13 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
c7/0f/379bb9c7eb2e3c1fd24b962be4bc

Event Timeline