DownloadManager.cpp Example File
downloadmanager/src/DownloadManager.cpp
 
    
    #include "DownloadManager.hpp"
    #include <QtCore/QFileInfo>
    #include <QtCore/QTimer>
    #include <QtNetwork/QNetworkReply>
    #include <QtNetwork/QNetworkRequest>
    DownloadManager::DownloadManager(QObject *parent)
        : QObject(parent), m_currentDownload(0), m_downloadedCount(0), m_totalCount(0), m_progressTotal(0), m_progressValue(0)
    {
    }
    QString DownloadManager::errorMessage() const
    {
        return m_errorMessage.join("\n");
    }
    QString DownloadManager::statusMessage() const
    {
        return m_statusMessage.join("\n");
    }
    int DownloadManager::activeDownloads() const
    {
        return m_downloadQueue.count();
    }
    int DownloadManager::progressTotal() const
    {
        return m_progressTotal;
    }
    int DownloadManager::progressValue() const
    {
        return m_progressValue;
    }
    QString DownloadManager::progressMessage() const
    {
        return m_progressMessage;
    }
    void DownloadManager::downloadUrl(const QString &url)
    {
        append(QUrl(url));
    }
    void DownloadManager::append(const QUrl &url)
    {
        
        if (m_downloadQueue.isEmpty() && !m_currentDownload)
            QTimer::singleShot(0, this, SLOT(startNextDownload()));
        
        m_downloadQueue.enqueue(url);
        emit activeDownloadsChanged();
        
        ++m_totalCount;
    }
    QString DownloadManager::saveFileName(const QUrl &url)
    {
        
        const QString path = url.path();
        
        QString basename = QFileInfo(path).fileName();
        if (basename.isEmpty())
            basename = "download";
        
        basename = "tmp/" + basename; 
        
        if (QFile::exists(basename)) {
            
            int i = 0;
            basename += '.';
            while (QFile::exists(basename + QString::number(i)))
                ++i;
            basename += QString::number(i);
        }
        return basename;
    }
    void DownloadManager::addErrorMessage(const QString &message)
    {
        m_errorMessage.append(message);
        emit errorMessageChanged();
    }
    void DownloadManager::addStatusMessage(const QString &message)
    {
        m_statusMessage.append(message);
        emit statusMessageChanged();
    }
    void DownloadManager::startNextDownload()
    {
        
        if (m_downloadQueue.isEmpty()) {
            addStatusMessage(QString("%1/%2 files downloaded successfully").arg(m_downloadedCount).arg(m_totalCount));
            return;
        }
        
        const QUrl url = m_downloadQueue.dequeue();
        
        const QString filename = saveFileName(url);
        
        m_output.setFileName(filename);
        if (!m_output.open(QIODevice::WriteOnly)) {
            addErrorMessage(QString("Problem opening save file '%1' for download '%2': %3").arg(filename, url.toString(), m_output.errorString()));
            startNextDownload();
            return; 
        }
        
        QNetworkRequest request(url);
        
        m_currentDownload = m_manager.get(request);
        
        connect(m_currentDownload, SIGNAL(downloadProgress(qint64, qint64)),
                SLOT(downloadProgress(qint64, qint64)));
        connect(m_currentDownload, SIGNAL(finished()), SLOT(downloadFinished()));
        connect(m_currentDownload, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
        
        addStatusMessage(QString("Downloading %1...").arg(url.toString()));
        
        m_downloadTime.start();
    }
    void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
    {
        
        m_progressTotal = bytesTotal;
        m_progressValue = bytesReceived;
        emit progressTotalChanged();
        emit progressValueChanged();
        
        double speed = bytesReceived * 1000.0 / m_downloadTime.elapsed();
        QString unit;
        if (speed < 1024) {
            unit = "bytes/sec";
        } else if (speed < 1024 * 1024) {
            speed /= 1024;
            unit = "kB/s";
        } else {
            speed /= 1024 * 1024;
            unit = "MB/s";
        }
        
        m_progressMessage = QString("%1 %2").arg(speed, 3, 'f', 1).arg(unit);
        emit progressMessageChanged();
    }
    void DownloadManager::downloadFinished()
    {
        
        m_progressTotal = 0;
        m_progressValue = 0;
        m_progressMessage.clear();
        emit progressValueChanged();
        emit progressTotalChanged();
        emit progressMessageChanged();
        
        m_output.close();
        
        if (m_currentDownload->error()) {
            addErrorMessage(QString("Failed: %1").arg(m_currentDownload->errorString()));
        } else {
            addStatusMessage("Succeeded.");
            ++m_downloadedCount;
        }
        
        m_currentDownload->deleteLater();
        m_currentDownload = 0;
        emit activeDownloadsChanged();
        
        startNextDownload();
    }
    void DownloadManager::downloadReadyRead()
    {
        
        m_output.write(m_currentDownload->readAll());
    }