[OpenDocString] kdeconnect-kde (cpp)
compositefiletransferjob.cpp
CompositeFileTransferJob::CompositeFileTransferJob(const QString &deviceId)
    : KCompositeJob()
    , m_deviceId(deviceId)
    , m_running(false)
    , m_currentJobNum(1)
    , m_totalJobs(0)
    , m_currentJobSentPayloadSize(0)
    , m_totalSentPayloadSize(0)
    , m_oldTotalSentPayloadSize(0)
    , m_totalPayloadSize(0)
    , m_currentJob(nullptr)
{
    setCapabilities(Killable);
}
This constructor builds a composite file transfer job object and sets capabilities.
bool CompositeFileTransferJob::isRunning() const
{
    return m_running;
}
This implements checking if the transfer job is running.
void CompositeFileTransferJob::start()
{
    QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
    m_running = true;
}
This starts the next transfer job in the queue. It is called by the startNextSubJob method of the base class, and sets m_running to true.
void CompositeFileTransferJob::startNextSubJob()
{
    m_currentJob = qobject_cast(subjobs().at(0));
    m_currentJobSentPayloadSize = 0;

    Q_EMIT description(this,
                       i18ncp("@title job", "Receiving file", "Receiving files", m_totalJobs),
                       {i18nc("The source of a file operation", "Source"), Daemon::instance()->getDevice(this->m_deviceId)->name()},
                       {i18nc("The destination of a file operation", "Destination"), m_currentJob->destination().toDisplayString(QUrl::PreferLocalFile)});

    m_currentJob->start();
#ifdef SAILFISHOS
    connect(m_currentJob, SIGNAL(processedAmount(KJob *, KJob::Unit, qulonglong)), this, SLOT(slotProcessedAmount(KJob *, KJob::Unit, qulonglong)));
#else
    connect(m_currentJob,
            QOverload::of(&FileTransferJob::processedAmount),
            this,
            &CompositeFileTransferJob::slotProcessedAmount);
#endif
}
This constructs a new file transfer job object and starts it. It creates another job object, sets m_currentJobSentPayloadSize to 0, and sets m_currentJob to the last job in the list. It also connects the signal signal to the slotProcessedAmount signal, and the overload function.
bool CompositeFileTransferJob::addSubjob(KJob *job)
{
    if (FileTransferJob *uploadJob = qobject_cast(job)) {
        const NetworkPacket *np = uploadJob->networkPacket();

        if (np->has(QStringLiteral("totalPayloadSize"))) {
            m_totalPayloadSize = np->get(QStringLiteral("totalPayloadSize"));
            setTotalAmount(Bytes, m_totalPayloadSize);
        }

        if (np->has(QStringLiteral("numberOfFiles"))) {
            m_totalJobs = np->get(QStringLiteral("numberOfFiles"));
            setTotalAmount(Files, m_totalJobs);
        }

        if (!hasSubjobs()) {
            QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
        }

        return KCompositeJob::addSubjob(job);
    } else {
        qCDebug(KDECONNECT_CORE) << "CompositeFileTransferJob::addSubjob() - you can only add FileTransferJob's, ignoring";
        return false;
    }
    return true;
}
This adds a subjob to the current list of jobs. It takes the upload job object from the internal list of jobs, and sets the total payload size and number of files to the total jobs value, and starts a new subjob if it doesn't exist. It returns true on the first successful attempt.
bool CompositeFileTransferJob::doKill()
{
    m_running = false;
    if (m_currentJob) {
        return m_currentJob->kill();
    }
    return true;
}
This kills the current job if it exists. It returns true on the first successful attempt. If the current job is not in the list, it returns false.
void CompositeFileTransferJob::slotProcessedAmount(KJob *job, KJob::Unit unit, qulonglong amount)
{
    Q_UNUSED(job);

    m_currentJobSentPayloadSize = amount;
    const auto totalSent = m_totalSentPayloadSize + m_currentJobSentPayloadSize;

    if (!m_reportTimer.isValid()) {
        m_reportTimer.start();
    }
    if (m_reportTimer.hasExpired(250)) {
        setProcessedAmount(unit, totalSent);
        m_reportTimer.restart();
    }

    if (!m_speedTimer.isValid()) {
        m_speedTimer.start();
    }
    if (m_speedTimer.hasExpired(1000)) {
        emitSpeed(1000 * (totalSent - m_oldTotalSentPayloadSize) / m_speedTimer.elapsed());
        m_oldTotalSentPayloadSize = totalSent;
        m_speedTimer.restart();
    }
}
This sets the processed amount of the given job and emits the speed if the report timer is not valid or the speed timer has expired. It also sets the processed amount on the job and updates the old total sent payload size accordingly.
void CompositeFileTransferJob::slotResult(KJob *job)
{
    // Copies job error and errorText and emits result if job is in error otherwise removes job from subjob list
    KCompositeJob::slotResult(job);

    if (error() || !m_running) {
        return;
    }

    m_totalSentPayloadSize += m_currentJobSentPayloadSize;

    setProcessedAmount(Bytes, m_totalSentPayloadSize);
    setProcessedAmount(Files, m_currentJobNum);

    if (m_currentJobNum < m_totalJobs) {
        m_currentJobNum++;
        if (!subjobs().empty()) {
            startNextSubJob();
        }
    } else {
        emitResult();
    }
}
This code sets the processed amount of the job and starts a new subjob if it is not in an error state, and emits the result. It also starts a new subjob if the total jobs list is reached, and sets the processed amount to the total payload size, and emits the result.