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"