File indexing completed on 2024-04-28 05:45:54

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
0003     SPDX-FileCopyrightText: 2009 Andrew Coles <andrew.i.coles@googlemail.com>
0004     SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
0005     SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-3.0-or-later
0008 */
0009 
0010 #include "jobs/job.h"
0011 
0012 #include "core/device.h"
0013 #include "core/copysource.h"
0014 #include "core/copytarget.h"
0015 #include "core/copysourcedevice.h"
0016 #include "core/copytargetdevice.h"
0017 
0018 #include "util/externalcommand.h"
0019 #include "util/report.h"
0020 
0021 #include <QIcon>
0022 #include <QTime>
0023 #include <QVariantMap>
0024 
0025 #include <KLocalizedString>
0026 
0027 Job::Job() :
0028     m_Report(nullptr),
0029     m_Status(Status::Pending)
0030 {
0031 }
0032 
0033 bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source)
0034 {
0035     m_Report = &report;
0036     ExternalCommand copyCmd;
0037     connect(&copyCmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection);
0038     connect(&copyCmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection);
0039     return copyCmd.copyBlocks(source, target);
0040 }
0041 
0042 bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource)
0043 {
0044     if (!origSource.overlaps(origTarget)) {
0045         report.line() << xi18nc("@info:progress", "Source and target for copying do not overlap: Rollback is not required.");
0046         return true;
0047     }
0048 
0049     try {
0050         CopySourceDevice& csd = dynamic_cast<CopySourceDevice&>(origSource);
0051         CopyTargetDevice& ctd = dynamic_cast<CopyTargetDevice&>(origTarget);
0052 
0053         // default: use values as if we were copying from front to back.
0054         qint64 undoSourceFirstByte = origTarget.firstByte();
0055         qint64 undoSourceLastByte = origTarget.firstByte() + origTarget.bytesWritten() - 1;
0056 
0057         qint64 undoTargetFirstByte = origSource.firstByte();
0058         qint64 undoTargetLastByte = origSource.firstByte() + origTarget.bytesWritten() - 1;
0059 
0060         if (origTarget.firstByte() > origSource.firstByte()) {
0061             // we were copying from back to front
0062             undoSourceFirstByte = origTarget.firstByte() + origSource.length() - origTarget.bytesWritten();
0063             undoSourceLastByte = origTarget.firstByte() + origSource.length() - 1;
0064 
0065             undoTargetFirstByte = origSource.lastByte() - origTarget.bytesWritten() + 1;
0066             undoTargetLastByte = origSource.lastByte();
0067         }
0068 
0069         report.line() << xi18nc("@info:progress", "Rollback from: First byte: %1, last byte: %2.", undoSourceFirstByte, undoSourceLastByte);
0070         report.line() << xi18nc("@info:progress", "Rollback to: First byte: %1, last byte: %2.", undoTargetFirstByte, undoTargetLastByte);
0071 
0072         CopySourceDevice undoSource(ctd.device(), undoSourceFirstByte, undoSourceLastByte);
0073         if (!undoSource.open()) {
0074             report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", ctd.device().deviceNode());
0075             return false;
0076         }
0077 
0078         CopyTargetDevice undoTarget(csd.device(), undoTargetFirstByte, undoTargetLastByte);
0079         if (!undoTarget.open()) {
0080             report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", csd.device().deviceNode());
0081             return false;
0082         }
0083 
0084         return copyBlocks(report, undoTarget, undoSource);
0085     } catch (...) {
0086         report.line() << xi18nc("@info:progress", "Rollback failed: Source or target are not devices.");
0087     }
0088 
0089     return false;
0090 }
0091 
0092 void Job::emitProgress(int i)
0093 {
0094     Q_EMIT progress(i);
0095 }
0096 
0097 void Job::updateReport(const QString& report)
0098 {
0099     m_Report->line() << report;
0100 }
0101 
0102 Report* Job::jobStarted(Report& parent)
0103 {
0104     Q_EMIT started();
0105 
0106     return parent.newChild(xi18nc("@info:progress", "Job: %1", description()));
0107 }
0108 
0109 void Job::jobFinished(Report& report, bool b)
0110 {
0111     setStatus(b ? Status::Success : Status::Error);
0112     Q_EMIT progress(numSteps());
0113     Q_EMIT finished();
0114 
0115     report.setStatus(xi18nc("@info:progress job status (error, warning, ...)", "%1: %2", description(), statusText()));
0116 }
0117 
0118 /** @return the Job's current status icon */
0119 QString Job::statusIcon() const
0120 {
0121     static const QString icons[] = {
0122         QStringLiteral("dialog-information"),
0123         QStringLiteral("dialog-ok"),
0124         QStringLiteral("dialog-error")
0125     };
0126 
0127     return icons[static_cast<int>(status())];
0128 }
0129 
0130 /** @return the Job's current status text */
0131 QString Job::statusText() const
0132 {
0133     static const QString s[] = {
0134         xi18nc("@info:progress job", "Pending"),
0135         xi18nc("@info:progress job", "Success"),
0136         xi18nc("@info:progress job", "Error")
0137     };
0138 
0139     return s[static_cast<int>(status())];
0140 }
0141 
0142 #include "moc_job.cpp"