File indexing completed on 2024-04-21 04:56:44

0001 /**
0002  * SPDX-FileCopyrightText: 2019 Nicolas Fella <nicolas.fella@gmx.de>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "compositefiletransferjob.h"
0008 #include "filetransferjob.h"
0009 #include <KLocalizedString>
0010 #include <core_debug.h>
0011 #include <daemon.h>
0012 
0013 CompositeFileTransferJob::CompositeFileTransferJob(const QString &deviceId)
0014     : KCompositeJob()
0015     , m_deviceId(deviceId)
0016     , m_running(false)
0017     , m_currentJobNum(1)
0018     , m_totalJobs(0)
0019     , m_currentJobSentPayloadSize(0)
0020     , m_totalSentPayloadSize(0)
0021     , m_oldTotalSentPayloadSize(0)
0022     , m_totalPayloadSize(0)
0023     , m_currentJob(nullptr)
0024 {
0025     setCapabilities(Killable);
0026 }
0027 
0028 bool CompositeFileTransferJob::isRunning() const
0029 {
0030     return m_running;
0031 }
0032 
0033 void CompositeFileTransferJob::start()
0034 {
0035     QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
0036     m_running = true;
0037 }
0038 
0039 void CompositeFileTransferJob::startNextSubJob()
0040 {
0041     m_currentJob = qobject_cast<FileTransferJob *>(subjobs().at(0));
0042     m_currentJobSentPayloadSize = 0;
0043 
0044     Q_EMIT description(this,
0045                        i18ncp("@title job", "Receiving file", "Receiving files", m_totalJobs),
0046                        {i18nc("The source of a file operation", "Source"), Daemon::instance()->getDevice(this->m_deviceId)->name()},
0047                        {i18nc("The destination of a file operation", "Destination"), m_currentJob->destination().toDisplayString(QUrl::PreferLocalFile)});
0048 
0049     m_currentJob->start();
0050     connect(m_currentJob, &FileTransferJob::processedAmountChanged, this, &CompositeFileTransferJob::slotProcessedAmount);
0051 }
0052 
0053 bool CompositeFileTransferJob::addSubjob(KJob *job)
0054 {
0055     if (FileTransferJob *uploadJob = qobject_cast<FileTransferJob *>(job)) {
0056         const NetworkPacket *np = uploadJob->networkPacket();
0057 
0058         if (np->has(QStringLiteral("totalPayloadSize"))) {
0059             m_totalPayloadSize = np->get<quint64>(QStringLiteral("totalPayloadSize"));
0060             setTotalAmount(Bytes, m_totalPayloadSize);
0061         }
0062 
0063         if (np->has(QStringLiteral("numberOfFiles"))) {
0064             m_totalJobs = np->get<int>(QStringLiteral("numberOfFiles"));
0065             setTotalAmount(Files, m_totalJobs);
0066         }
0067 
0068         if (!hasSubjobs()) {
0069             QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
0070         }
0071 
0072         return KCompositeJob::addSubjob(job);
0073     } else {
0074         qCDebug(KDECONNECT_CORE) << "CompositeFileTransferJob::addSubjob() - you can only add FileTransferJob's, ignoring";
0075         return false;
0076     }
0077     return true;
0078 }
0079 
0080 bool CompositeFileTransferJob::doKill()
0081 {
0082     m_running = false;
0083     if (m_currentJob) {
0084         return m_currentJob->kill();
0085     }
0086     return true;
0087 }
0088 
0089 void CompositeFileTransferJob::slotProcessedAmount(KJob * /*job*/, KJob::Unit unit, qulonglong amount)
0090 {
0091     m_currentJobSentPayloadSize = amount;
0092     const auto totalSent = m_totalSentPayloadSize + m_currentJobSentPayloadSize;
0093 
0094     if (!m_reportTimer.isValid()) {
0095         m_reportTimer.start();
0096     }
0097     if (m_reportTimer.hasExpired(250)) {
0098         setProcessedAmount(unit, totalSent);
0099         m_reportTimer.restart();
0100     }
0101 
0102     if (!m_speedTimer.isValid()) {
0103         m_speedTimer.start();
0104     }
0105     if (m_speedTimer.hasExpired(1000)) {
0106         emitSpeed(1000 * (totalSent - m_oldTotalSentPayloadSize) / m_speedTimer.elapsed());
0107         m_oldTotalSentPayloadSize = totalSent;
0108         m_speedTimer.restart();
0109     }
0110 }
0111 
0112 void CompositeFileTransferJob::slotResult(KJob *job)
0113 {
0114     // Copies job error and errorText and emits result if job is in error otherwise removes job from subjob list
0115     KCompositeJob::slotResult(job);
0116 
0117     if (error() || !m_running) {
0118         return;
0119     }
0120 
0121     m_totalSentPayloadSize += m_currentJobSentPayloadSize;
0122 
0123     setProcessedAmount(Bytes, m_totalSentPayloadSize);
0124     setProcessedAmount(Files, m_currentJobNum);
0125 
0126     if (m_currentJobNum < m_totalJobs) {
0127         m_currentJobNum++;
0128         if (!subjobs().empty()) {
0129             startNextSubJob();
0130         }
0131     } else {
0132         emitResult();
0133     }
0134 }
0135 
0136 #include "moc_compositefiletransferjob.cpp"