2020-09-29 23:55:11 +01:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
|
|
|
|
SPDX-FileCopyrightText: 2009 Andrew Coles <andrew.i.coles@googlemail.com>
|
|
|
|
SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
|
|
|
|
SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
*/
|
2015-06-04 01:29:22 +01:00
|
|
|
|
|
|
|
#include "jobs/job.h"
|
|
|
|
|
|
|
|
#include "core/device.h"
|
|
|
|
#include "core/copysource.h"
|
|
|
|
#include "core/copytarget.h"
|
|
|
|
#include "core/copysourcedevice.h"
|
|
|
|
#include "core/copytargetdevice.h"
|
|
|
|
|
2018-01-24 15:45:19 +00:00
|
|
|
#include "util/externalcommand.h"
|
2015-06-04 01:29:22 +01:00
|
|
|
#include "util/report.h"
|
|
|
|
|
|
|
|
#include <QIcon>
|
|
|
|
#include <QTime>
|
2018-01-27 18:54:48 +00:00
|
|
|
#include <QVariantMap>
|
2015-06-04 01:29:22 +01:00
|
|
|
|
|
|
|
#include <KLocalizedString>
|
|
|
|
|
|
|
|
Job::Job() :
|
2018-01-27 18:54:48 +00:00
|
|
|
m_Report(nullptr),
|
2018-04-12 13:18:50 +01:00
|
|
|
m_Status(Status::Pending)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source)
|
|
|
|
{
|
2018-01-27 18:54:48 +00:00
|
|
|
m_Report = &report;
|
2018-03-22 17:29:40 +00:00
|
|
|
ExternalCommand copyCmd;
|
2018-01-24 15:45:19 +00:00
|
|
|
connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection);
|
2018-01-27 18:54:48 +00:00
|
|
|
connect(©Cmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection);
|
2018-10-21 17:50:00 +01:00
|
|
|
return copyCmd.copyBlocks(source, target);
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource)
|
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
if (!origSource.overlaps(origTarget)) {
|
2016-07-17 23:41:00 +01:00
|
|
|
report.line() << xi18nc("@info:progress", "Source and target for copying do not overlap: Rollback is not required.");
|
2015-07-13 15:16:36 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
CopySourceDevice& csd = dynamic_cast<CopySourceDevice&>(origSource);
|
|
|
|
CopyTargetDevice& ctd = dynamic_cast<CopyTargetDevice&>(origTarget);
|
|
|
|
|
|
|
|
// default: use values as if we were copying from front to back.
|
2017-10-26 16:20:21 +01:00
|
|
|
qint64 undoSourceFirstByte = origTarget.firstByte();
|
|
|
|
qint64 undoSourceLastByte = origTarget.firstByte() + origTarget.bytesWritten() - 1;
|
2015-07-13 15:16:36 +01:00
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
qint64 undoTargetFirstByte = origSource.firstByte();
|
|
|
|
qint64 undoTargetLastByte = origSource.firstByte() + origTarget.bytesWritten() - 1;
|
2015-07-13 15:16:36 +01:00
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
if (origTarget.firstByte() > origSource.firstByte()) {
|
2015-07-13 15:16:36 +01:00
|
|
|
// we were copying from back to front
|
2017-10-26 16:20:21 +01:00
|
|
|
undoSourceFirstByte = origTarget.firstByte() + origSource.length() - origTarget.bytesWritten();
|
|
|
|
undoSourceLastByte = origTarget.firstByte() + origSource.length() - 1;
|
2015-07-13 15:16:36 +01:00
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
undoTargetFirstByte = origSource.lastByte() - origTarget.bytesWritten() + 1;
|
|
|
|
undoTargetLastByte = origSource.lastByte();
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
report.line() << xi18nc("@info:progress", "Rollback from: First byte: %1, last byte: %2.", undoSourceFirstByte, undoSourceLastByte);
|
|
|
|
report.line() << xi18nc("@info:progress", "Rollback to: First byte: %1, last byte: %2.", undoTargetFirstByte, undoTargetLastByte);
|
2015-07-13 15:16:36 +01:00
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
CopySourceDevice undoSource(ctd.device(), undoSourceFirstByte, undoSourceLastByte);
|
2015-07-13 15:16:36 +01:00
|
|
|
if (!undoSource.open()) {
|
2016-07-17 23:41:00 +01:00
|
|
|
report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", ctd.device().deviceNode());
|
2015-07-13 15:16:36 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-10-26 16:20:21 +01:00
|
|
|
CopyTargetDevice undoTarget(csd.device(), undoTargetFirstByte, undoTargetLastByte);
|
2015-07-13 15:16:36 +01:00
|
|
|
if (!undoTarget.open()) {
|
2016-07-17 23:41:00 +01:00
|
|
|
report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", csd.device().deviceNode());
|
2015-07-13 15:16:36 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return copyBlocks(report, undoTarget, undoSource);
|
|
|
|
} catch (...) {
|
2016-07-17 23:41:00 +01:00
|
|
|
report.line() << xi18nc("@info:progress", "Rollback failed: Source or target are not devices.");
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Job::emitProgress(int i)
|
|
|
|
{
|
2020-09-15 02:36:46 +01:00
|
|
|
Q_EMIT progress(i);
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
2020-10-11 23:46:20 +01:00
|
|
|
void Job::updateReport(const QString& report)
|
2018-01-27 18:54:48 +00:00
|
|
|
{
|
2020-10-11 23:46:20 +01:00
|
|
|
m_Report->line() << report;
|
2018-01-27 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 01:29:22 +01:00
|
|
|
Report* Job::jobStarted(Report& parent)
|
|
|
|
{
|
2020-09-15 02:36:46 +01:00
|
|
|
Q_EMIT started();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-17 23:41:00 +01:00
|
|
|
return parent.newChild(xi18nc("@info:progress", "Job: %1", description()));
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Job::jobFinished(Report& report, bool b)
|
|
|
|
{
|
2018-04-12 13:18:50 +01:00
|
|
|
setStatus(b ? Status::Success : Status::Error);
|
2020-09-15 02:36:46 +01:00
|
|
|
Q_EMIT progress(numSteps());
|
|
|
|
Q_EMIT finished();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-17 23:41:00 +01:00
|
|
|
report.setStatus(xi18nc("@info:progress job status (error, warning, ...)", "%1: %2", description(), statusText()));
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return the Job's current status icon */
|
2017-09-08 15:05:55 +01:00
|
|
|
QString Job::statusIcon() const
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
static const QString icons[] = {
|
|
|
|
QStringLiteral("dialog-information"),
|
|
|
|
QStringLiteral("dialog-ok"),
|
|
|
|
QStringLiteral("dialog-error")
|
|
|
|
};
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2018-04-12 13:18:50 +01:00
|
|
|
return icons[static_cast<int>(status())];
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @return the Job's current status text */
|
|
|
|
QString Job::statusText() const
|
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
static const QString s[] = {
|
2016-07-17 23:41:00 +01:00
|
|
|
xi18nc("@info:progress job", "Pending"),
|
|
|
|
xi18nc("@info:progress job", "Success"),
|
|
|
|
xi18nc("@info:progress job", "Error")
|
2015-07-13 15:16:36 +01:00
|
|
|
};
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2018-04-12 13:18:50 +01:00
|
|
|
return s[static_cast<int>(status())];
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|