summaryrefslogblamecommitdiffstats
path: root/src/downloadmanager.cpp
blob: c7727768830101cce4df857496817f4630f9fb38 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11



                                    
                                                                                                          





                                                          
 
                                     

                 
                                                                                                          
































                                                                            
 

                                                   
                                              
 


                                                                                                          


                                                             
 
                                                                                                          

                                                         
 


                                                                                                          














                                                                       
 
                                                                                                          
                                           
                                                   






                                                                               
 

                                    
 


                                                   
 









                                                                             
 





                                                                           
 














                                                                               
 


                                                                                                          







                                                                            
 
                                                                                                          


                                              
 
                                                                                                          











                                                                           

                      

                             
                      










                                                                                
 
                                                                                                          











                                                                                 
                                       




















                                                                    
 
#include "downloadmanager.h"
#include "fbgui.h"

int DownloadManager::downloaded = 0;
// -------------------------------------------------------------------------------------------------------
DownloadManager::DownloadManager() {
    qxtLog->debug() << "Initializing download manager...";
    checkDownloadDirectory();
    _qnam = new QNetworkAccessManager();
    //_qnam->moveToThread(&dmThread);
    dip = false;
}
DownloadManager::~DownloadManager() {
    delete _qnam;
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::checkDownloadDirectory() {
    // check if downloadPath exists, if not create it.
    downloadDir = QDir(downloadPath);
    if (!downloadDir.exists()) {
        qxtLog->debug() << "[dm] Download directory: " << downloadDir.path()
                << " doesn't exist.";
        // try to create the directory
        if (QDir::current().mkdir(downloadPath))
            qxtLog->debug() << "[dm] Created download directory: "
                    << downloadDir.path();
        else {
            qxtLog->debug() << "[dm] Failed to create directory: "
                    << downloadDir.path();
            // try to save to /tmp/fbgui
            downloadDir.setPath(QDir::tempPath() + "/fbgui");
            if (!downloadDir.exists()) {
                if (QDir::current().mkdir(QDir::tempPath() + "/fbgui"))
                    qxtLog->debug() << "[dm] Successfully created: "
                            << downloadDir.absolutePath();
                else {
                    // just in case
                    qxtLog->debug() << "[dm] Failed to create: "
                            << downloadDir.absolutePath();
                    qxtLog->debug() << "[dm] Exiting...";
                    exit( EXIT_FAILURE);
                }
            } else
                qxtLog->debug() << "[dm] " << downloadDir.absolutePath()
                        << " already exists.";
        }
    } else
        qxtLog->debug() << "[dm] Download directory: "
                << downloadDir.absolutePath() << " already exists.";

    qxtLog->debug() << "[dm] Saving downloads to: "
            << downloadDir.absolutePath();
    downloadPath = downloadDir.absolutePath();
}
// -------------------------------------------------------------------------------------------------------
//                                         Public access
// -------------------------------------------------------------------------------------------------------
void DownloadManager::downloadFile(const QString& filename) {
    QUrl fileUrl(baseURL.resolved(QUrl(filename)));
    this->processDownloadRequest(fileUrl);
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::downloadFile(const QUrl& fileUrl) {
    this->processDownloadRequest(fileUrl);
}
// -------------------------------------------------------------------------------------------------------
//                    Private functions handling download requests and queueing
// -------------------------------------------------------------------------------------------------------
void DownloadManager::processDownloadRequest(const QUrl& url) {
    if (url.isEmpty()) {
        qxtLog->debug() << "[dm] No URL specified for download.";
        return;
    }
    qxtLog->debug() << "[dm] Enqueueing: " << url.toString();
    dlQ.enqueue(url);
    if (dip) {
        // download in progress, return.
        qxtLog->debug() << "[dm] Download in progress! Queued:"
                << url.toString() << "(" << dlQ.size() << " in queue)";
        return;
    }
    // no running downloads: start next in queue
    startNextDownload();
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::startNextDownload() {
    QWSServer::instance()->setCursorVisible(false);
    if (dlQ.isEmpty()) {
        emit downloadQueueEmpty();
        qxtLog->debug() << "[dm] Download manager ready. (1)";
        return;
    }
    qxtLog->debug() << "[dm] Starting next download: " << dlQ.head().toString()
            << "  (" << dlQ.size() - 1 << " in queue.)";

    // dequeue next URL to download.
    QUrl url = dlQ.dequeue();

    // get filename from URL.
    QString tmp = url.path();
    tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1);

    // check if filename exists on target file system
    if (downloadDir.exists(tmp)) {
        qxtLog->debug() << "[dm] File already exists: "
                << downloadDir.absoluteFilePath(tmp);
        outfile.setFileName(
                QString(downloadDir.absolutePath() + "/" + tmp + ".\%1").arg(
                        downloaded));
    } else
        outfile.setFileName(downloadDir.absoluteFilePath(tmp));
    qxtLog->debug() << "[dm] Saving to: " << outfile.fileName();

    // try to open for writing
    if (!outfile.open(QIODevice::WriteOnly)) {
        qxtLog->debug() << "[dm] No write access to " << outfile.fileName()
                << " . Skipping download...";
        return;
    }

    // send the request for the file
    QNetworkRequest request(url);
    currentDownload = _qnam->get(request);
    lastProgress = 0;
    currentProgress = 0;
    dip = true;
    _time.start();
    QObject::connect(currentDownload, SIGNAL(readyRead()), this,
            SLOT(downloadReady()));
    QObject::connect(currentDownload, SIGNAL(metaDataChanged()), this,
            SLOT(processMetaInfo()));
    QObject::connect(currentDownload, SIGNAL(downloadProgress(qint64, qint64)),
            this, SLOT(downloadProgress(qint64, qint64)));
    QObject::connect(currentDownload, SIGNAL(finished()), this,
            SLOT(downloadFinished()));
}
// -------------------------------------------------------------------------------------------------------
//                           Private slots to handle a download in progress
// -------------------------------------------------------------------------------------------------------
void DownloadManager::processMetaInfo() {
    // fetch filesize from header & filename from URL (for now)
    const QByteArray cltag = "Content-Length";
    QByteArray clinfo = currentDownload->rawHeader(cltag);
    QFileInfo fi(outfile);
    qxtLog->debug() << "[dm] Download Info: " << fi.fileName() << " (Size: "
            << clinfo.toDouble() << ")";
    emit downloadInfo(fi.fileName(), clinfo.toDouble());
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::downloadReady() {
    // data ready, save it
    outfile.write(currentDownload->readAll());
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::downloadProgress(qint64 bytesIn, qint64 bytesTotal) {
    if (bytesIn > bytesTotal || bytesTotal <= 0) {
        qxtLog->debug() << "[dm] downloadProgress invalid values:" << "In:"
                << bytesIn << " / Total: " << bytesTotal;
        return;
    }
    // calculate current speed
    double speed = bytesIn * 1000 / _time.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";
    }
    // update progress only if difference higher than the updateInterval setting
    currentProgress = ((bytesIn * 100) / bytesTotal);
    if (currentProgress - lastProgress >= updateInterval) {
        lastProgress = currentProgress;
        emit
        updateProgress(currentProgress, speed, unit);
        qxtLog->debug() << "[dm] Download progress of "
                << currentDownload->url().toString() << ": " << bytesIn << "/"
                << bytesTotal << "(" << currentProgress << "\%)";
    }
}
// -------------------------------------------------------------------------------------------------------
void DownloadManager::downloadFinished() {
    // check for errors
    if (currentDownload->error()) {
        outfile.close();
        outfile.remove();
        int statusCode = currentDownload->attribute(
                QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qxtLog->debug() << "[dm] Download of "
                << currentDownload->url().toString()
                << " failed with HTTP error code: " << statusCode;
        emit
        notify(QString("Download failed! HTTP Status Code: %1").arg(statusCode));
        currentDownload->deleteLater();
    } else {
        // end download
        outfile.close();
        downloaded++;
        qxtLog->debug() << "[dm] Download of "
                << currentDownload->url().toString()
                << " finished. (downloaded = " << downloaded << ")";
        emit
        notify(
                QString("Successfully downloaded %1").arg(
                        currentDownload->url().toString()));
        currentDownload->deleteLater();
    }
    dip = false;
    // process next in queue, if any
    if (dlQ.isEmpty()) {
        emit downloadQueueEmpty();
        qxtLog->debug() << "[dm] Download manager ready. (2)";
        return;
    }
    startNextDownload();
}