Mega Code Archive

 
Categories / C++ / Qt
 

Download manager

/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file.  Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights.  These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file.  Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TEXTPROGRESSBAR_H #define TEXTPROGRESSBAR_H #include <QString> class TextProgressBar { public:     TextProgressBar();     void clear();     void update();     void setMessage(const QString &message);     void setStatus(qint64 value, qint64 maximum); private:     QString message;     qint64 value;     qint64 maximum;     int iteration; }; #endif #include "textprogressbar.h" #include <QByteArray> #include <stdio.h> TextProgressBar::TextProgressBar()     : value(0), maximum(-1), iteration(0) { } void TextProgressBar::clear() {     printf("\n");     fflush(stdout);     iteration = 0;     value = 0;     maximum = -1; } void TextProgressBar::update() {     ++iteration;     if (maximum > 0) {         // we know the maximum         // draw a progress bar         int percent = value * 100 / maximum;         int hashes = percent / 2;         QByteArray progressbar(hashes, '#');         if (percent % 2)             progressbar += '>';         printf("\r[%-50s] %3d%% %s     ",                progressbar.constData(),                percent,                qPrintable(message));     } else {         // we don't know the maximum, so we can't draw a progress bar         int center = (iteration % 48) + 1; // 50 spaces, minus 2         QByteArray before(qMax(center - 2, 0), ' ');         QByteArray after(qMin(center + 2, 50), ' ');         printf("\r[%s###%s]      %s      ",                before.constData(), after.constData(), qPrintable(message));     } } void TextProgressBar::setMessage(const QString &m) {     message = m; } void TextProgressBar::setStatus(qint64 val, qint64 max) {     value = val;     maximum = max; } #ifndef DOWNLOADMANAGER_H #define DOWNLOADMANAGER_H #include <QFile> #include <QObject> #include <QQueue> #include <QTime> #include <QUrl> #include <QNetworkAccessManager> #include "textprogressbar.h" class DownloadManager: public QObject {     Q_OBJECT public:     DownloadManager(QObject *parent = 0);     void append(const QUrl &url);     void append(const QStringList &urlList);     QString saveFileName(const QUrl &url); signals:     void finished(); private slots:     void startNextDownload();     void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);     void downloadFinished();     void downloadReadyRead(); private:     QNetworkAccessManager manager;     QQueue<QUrl> downloadQueue;     QNetworkReply *currentDownload;     QFile output;     QTime downloadTime;     TextProgressBar progressBar;     int downloadedCount;     int totalCount; }; #endif #include "downloadmanager.h" #include <QFileInfo> #include <QNetworkRequest> #include <QNetworkReply> #include <QString> #include <QStringList> #include <QTimer> #include <stdio.h> DownloadManager::DownloadManager(QObject *parent)     : QObject(parent), downloadedCount(0), totalCount(0) { } void DownloadManager::append(const QStringList &urlList) {     foreach (QString url, urlList)         append(QUrl::fromEncoded(url.toLocal8Bit()));     if (downloadQueue.isEmpty())         QTimer::singleShot(0, this, SIGNAL(finished())); } void DownloadManager::append(const QUrl &url) {     if (downloadQueue.isEmpty())         QTimer::singleShot(0, this, SLOT(startNextDownload()));     downloadQueue.enqueue(url);     ++totalCount; } QString DownloadManager::saveFileName(const QUrl &url) {     QString path = url.path();     QString basename = QFileInfo(path).fileName();     if (basename.isEmpty())         basename = "download";     if (QFile::exists(basename)) {         // already exists, don't overwrite         int i = 0;         basename += '.';         while (QFile::exists(basename + QString::number(i)))             ++i;         basename += QString::number(i);     }     return basename; } void DownloadManager::startNextDownload() {     if (downloadQueue.isEmpty()) {         printf("%d/%d files downloaded successfully\n", downloadedCount, totalCount);         emit finished();         return;     }     QUrl url = downloadQueue.dequeue();     QString filename = saveFileName(url);     output.setFileName(filename);     if (!output.open(QIODevice::WriteOnly)) {         fprintf(stderr, "Problem opening save file '%s' for download '%s': %s\n",                 qPrintable(filename), url.toEncoded().constData(),                 qPrintable(output.errorString()));         startNextDownload();         return;                 // skip this download     }     QNetworkRequest request(url);     currentDownload = manager.get(request);     connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)),             SLOT(downloadProgress(qint64,qint64)));     connect(currentDownload, SIGNAL(finished()),             SLOT(downloadFinished()));     connect(currentDownload, SIGNAL(readyRead()),             SLOT(downloadReadyRead()));     // prepare the output     printf("Downloading %s...\n", url.toEncoded().constData());     downloadTime.start(); } void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {     progressBar.setStatus(bytesReceived, bytesTotal);     // calculate the download speed     double speed = bytesReceived * 1000.0 / 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";     }     progressBar.setMessage(QString::fromLatin1("%1 %2")                            .arg(speed, 3, 'f', 1).arg(unit));     progressBar.update(); } void DownloadManager::downloadFinished() {     progressBar.clear();     output.close();     if (currentDownload->error()) {         // download failed         fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString()));     } else {         printf("Succeeded.\n");         ++downloadedCount;     }     currentDownload->deleteLater();     startNextDownload(); } void DownloadManager::downloadReadyRead() {     output.write(currentDownload->readAll()); } #include <QCoreApplication> #include <QStringList> #include "downloadmanager.h" #include <stdio.h> int main(int argc, char **argv) {     QCoreApplication app(argc, argv);     QStringList arguments = app.arguments();     arguments.takeFirst();      // remove the first argument, which is the program's name     if (arguments.isEmpty()) {         printf("Qt Download example\n"                "Usage: downloadmanager url1 [url2... urlN]\n"                "\n"                "Downloads the URLs passed in the command-line to the local directory\n"                "If the target file already exists, a .0, .1, .2, etc. is appended to\n"                "differentiate.\n");         return 0;     }     DownloadManager manager;     manager.append(arguments);     QObject::connect(&manager, SIGNAL(finished()), &app, SLOT(quit()));     app.exec(); }