File indexing completed on 2024-05-19 09:41:57
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(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); 0038 connect(©Cmd, &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"