kpmcore/src/jobs/job.cpp

150 lines
5.6 KiB
C++
Raw Normal View History

/*************************************************************************
* Copyright (C) 2008, 2009, 2010 by Volker Lanz <vl@fidra.de> *
* Copyright (C) 2016-2018 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "jobs/job.h"
#include "core/device.h"
#include "core/copysource.h"
#include "core/copytarget.h"
#include "core/copysourcedevice.h"
#include "core/copytargetdevice.h"
#include "util/externalcommand.h"
#include "util/report.h"
#include <QIcon>
#include <QTime>
2018-01-27 18:54:48 +00:00
#include <QVariantMap>
#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)
{
}
bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source)
{
2018-01-27 18:54:48 +00:00
m_Report = &report;
ExternalCommand copyCmd;
connect(&copyCmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection);
2018-01-27 18:54:48 +00:00
connect(&copyCmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection);
2018-10-21 17:50:00 +01:00
return copyCmd.copyBlocks(source, target);
}
bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource)
{
2015-07-13 15:16:36 +01:00
if (!origSource.overlaps(origTarget)) {
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.
qint64 undoSourceFirstByte = origTarget.firstByte();
qint64 undoSourceLastByte = origTarget.firstByte() + origTarget.bytesWritten() - 1;
2015-07-13 15:16:36 +01:00
qint64 undoTargetFirstByte = origSource.firstByte();
qint64 undoTargetLastByte = origSource.firstByte() + origTarget.bytesWritten() - 1;
2015-07-13 15:16:36 +01:00
if (origTarget.firstByte() > origSource.firstByte()) {
2015-07-13 15:16:36 +01:00
// we were copying from back to front
undoSourceFirstByte = origTarget.firstByte() + origSource.length() - origTarget.bytesWritten();
undoSourceLastByte = origTarget.firstByte() + origSource.length() - 1;
2015-07-13 15:16:36 +01:00
undoTargetFirstByte = origSource.lastByte() - origTarget.bytesWritten() + 1;
undoTargetLastByte = origSource.lastByte();
2015-07-13 15:16:36 +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
CopySourceDevice undoSource(ctd.device(), undoSourceFirstByte, undoSourceLastByte);
2015-07-13 15:16:36 +01:00
if (!undoSource.open()) {
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;
}
CopyTargetDevice undoTarget(csd.device(), undoTargetFirstByte, undoTargetLastByte);
2015-07-13 15:16:36 +01:00
if (!undoTarget.open()) {
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 (...) {
report.line() << xi18nc("@info:progress", "Rollback failed: Source or target are not devices.");
2015-07-13 15:16:36 +01:00
}
return false;
}
void Job::emitProgress(int i)
{
2020-09-15 02:36:46 +01:00
Q_EMIT progress(i);
}
2018-01-27 18:54:48 +00:00
void Job::updateReport(const QVariantMap& reportString)
{
m_Report->line() << reportString[QStringLiteral("report")].toString();
}
Report* Job::jobStarted(Report& parent)
{
2020-09-15 02:36:46 +01:00
Q_EMIT started();
return parent.newChild(xi18nc("@info:progress", "Job: %1", description()));
}
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();
report.setStatus(xi18nc("@info:progress job status (error, warning, ...)", "%1: %2", description(), statusText()));
}
/** @return the Job's current status icon */
QString Job::statusIcon() const
{
2015-07-13 15:16:36 +01:00
static const QString icons[] = {
QStringLiteral("dialog-information"),
QStringLiteral("dialog-ok"),
QStringLiteral("dialog-error")
};
2018-04-12 13:18:50 +01:00
return icons[static_cast<int>(status())];
}
/** @return the Job's current status text */
QString Job::statusText() const
{
2015-07-13 15:16:36 +01:00
static const QString s[] = {
xi18nc("@info:progress job", "Pending"),
xi18nc("@info:progress job", "Success"),
xi18nc("@info:progress job", "Error")
2015-07-13 15:16:36 +01:00
};
2018-04-12 13:18:50 +01:00
return s[static_cast<int>(status())];
}