File indexing completed on 2024-05-05 05:48:52

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
0003     SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
0004 
0005     SPDX-License-Identifier: GPL-3.0-or-later
0006 */
0007 
0008 #include "ops/operation_p.h"
0009 
0010 #include "core/partition.h"
0011 #include "core/device.h"
0012 #include "core/lvmdevice.h"
0013 
0014 #include "jobs/job.h"
0015 
0016 #include "util/report.h"
0017 
0018 #include <QDebug>
0019 #include <QIcon>
0020 #include <QString>
0021 
0022 #include <KLocalizedString>
0023 
0024 Operation::Operation() :
0025     d(std::make_unique<OperationPrivate>())
0026 {
0027     d->m_Status = StatusNone;
0028     d->m_ProgressBase = 0;
0029 }
0030 
0031 Operation::~Operation()
0032 {
0033     qDeleteAll(jobs());
0034     jobs().clear();
0035 }
0036 
0037 void Operation::insertPreviewPartition(Device& device, Partition& p)
0038 {
0039     Q_ASSERT(device.partitionTable());
0040 
0041     device.partitionTable()->removeUnallocated();
0042 
0043     if (p.parent()->insert(&p)) {
0044         if (device.type() == Device::Type::LVM_Device) {
0045             const LvmDevice& lvm = static_cast<const LvmDevice&>(device);
0046             lvm.setFreePE(lvm.freePE() - p.length());
0047         }
0048     }
0049     else
0050         qWarning() << "failed to insert preview partition " << p.deviceNode() << " at " << &p << ".";
0051 
0052     device.partitionTable()->updateUnallocated(device);
0053 }
0054 
0055 void Operation::removePreviewPartition(Device& device, Partition& p)
0056 {
0057     Q_ASSERT(device.partitionTable());
0058 
0059     if (p.parent()->remove(&p)) {
0060         if (device.type() == Device::Type::LVM_Device) {
0061             const LvmDevice& lvm = static_cast<const LvmDevice&>(device);
0062             lvm.setFreePE(lvm.freePE() + p.length());
0063         }
0064 
0065         device.partitionTable()->updateUnallocated(device);
0066     }
0067     else
0068         qWarning() << "failed to remove partition " << p.deviceNode() << " at " << &p << " from preview.";
0069 }
0070 
0071 /** @return text describing the Operation's current status */
0072 QString Operation::statusText() const
0073 {
0074     static const QString s[] = {
0075         xi18nc("@info:progress operation", "None"),
0076         xi18nc("@info:progress operation", "Pending"),
0077         xi18nc("@info:progress operation", "Running"),
0078         xi18nc("@info:progress operation", "Success"),
0079         xi18nc("@info:progress operation", "Warning"),
0080         xi18nc("@info:progress operation", "Error")
0081     };
0082 
0083     Q_ASSERT(status() >= 0 && static_cast<quint32>(status()) < sizeof(s) / sizeof(s[0]));
0084 
0085     if (status() < 0 || static_cast<quint32>(status()) >= sizeof(s) / sizeof(s[0])) {
0086         qWarning() << "invalid status " << status();
0087         return QString();
0088     }
0089 
0090     return s[status()];
0091 }
0092 
0093 /** @return icon for the current Operation's status */
0094 QString Operation::statusIcon() const
0095 {
0096     static const QString icons[] = {
0097         QString(),
0098         QStringLiteral("dialog-information"),
0099         QStringLiteral("dialog-information"),
0100         QStringLiteral("dialog-ok"),
0101         QStringLiteral("dialog-warning"),
0102         QStringLiteral("dialog-error")
0103     };
0104 
0105     Q_ASSERT(status() >= 0 && static_cast<quint32>(status()) < sizeof(icons) / sizeof(icons[0]));
0106 
0107     if (status() < 0 || static_cast<quint32>(status()) >= sizeof(icons) / sizeof(icons[0])) {
0108         qWarning() << "invalid status " << status();
0109         return QString();
0110     }
0111 
0112     if (status() == StatusNone)
0113         return QString();
0114 
0115     return icons[status()];
0116 }
0117 
0118 void Operation::addJob(Job* job)
0119 {
0120     if (job) {
0121         jobs().append(job);
0122         connect(job, &Job::started, this, &Operation::onJobStarted);
0123         connect(job, &Job::progress, this, &Operation::progress);
0124         connect(job, &Job::finished, this, &Operation::onJobFinished);
0125     }
0126 }
0127 
0128 void Operation::onJobStarted()
0129 {
0130     Job* job = qobject_cast<Job*>(sender());
0131 
0132     if (job)
0133         Q_EMIT jobStarted(job, this);
0134 }
0135 
0136 void Operation::onJobFinished()
0137 {
0138     Job* job = qobject_cast<Job*>(sender());
0139 
0140     if (job) {
0141         setProgressBase(progressBase() + job->numSteps());
0142         Q_EMIT jobFinished(job, this);
0143     }
0144 }
0145 
0146 /** @return total number of steps to run this Operation */
0147 qint32 Operation::totalProgress() const
0148 {
0149     qint32 result = 0;
0150 
0151     for (const auto &job : jobs())
0152         result += job->numSteps();
0153 
0154     return result;
0155 }
0156 
0157 /** Execute the operation
0158     @param parent the parent Report to create a new child for
0159     @return true on success
0160 */
0161 bool Operation::execute(Report& parent)
0162 {
0163     bool rval = false;
0164 
0165     Report* report = parent.newChild(description());
0166 
0167     const auto Jobs = jobs();
0168     for (const auto &job : Jobs)
0169         if (!(rval = job->run(*report)))
0170             break;
0171 
0172     setStatus(rval ? StatusFinishedSuccess : StatusError);
0173 
0174     report->setStatus(xi18nc("@info:status (success, error, warning...) of operation", "%1: %2", description(), statusText()));
0175 
0176     return rval;
0177 }
0178 
0179 Operation::OperationStatus Operation::status() const
0180 {
0181     return d->m_Status;
0182 }
0183 
0184 void Operation::setStatus(OperationStatus s)
0185 {
0186     d->m_Status = s;
0187 }
0188 
0189 QList<Job*>& Operation::jobs()
0190 {
0191     return d->m_Jobs;
0192 }
0193 
0194 const QList<Job*>& Operation::jobs() const
0195 {
0196     return d->m_Jobs;
0197 }
0198 
0199 void Operation::setProgressBase(qint32 i)
0200 {
0201     d->m_ProgressBase = i;
0202 }
0203 
0204 qint32 Operation::progressBase() const
0205 {
0206     return d->m_ProgressBase;
0207 }
0208 
0209 #include "moc_operation.cpp"