diff --git a/include/ProgressTrackingNetworkAccessManager.h b/include/ProgressTrackingNetworkAccessManager.h new file mode 100644 index 000000000..3bd95daf0 --- /dev/null +++ b/include/ProgressTrackingNetworkAccessManager.h @@ -0,0 +1,71 @@ +/* + * ProgressTrackingNetworkAccessManager.h - header file for + * ProgressTrackingNetworkAccessManager class + * + * Copyright (c) 2009 Tobias Doerffel + * + * This file is part of RuckTrack - http://rucktrack.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef _PROGRESS_TRACKING_NETWORK_ACCESS_MANAGER_H +#define _PROGRESS_TRACKING_NETWORK_ACCESS_MANAGER_H + +#include +#include + + +class ProgressTrackingNetworkAccessManager : public QNetworkAccessManager +{ + Q_OBJECT +public: + ProgressTrackingNetworkAccessManager( QObject * _parent ) : + QNetworkAccessManager( _parent ) + { + } + + virtual QNetworkReply * createRequest( Operation op, + const QNetworkRequest & req, + QIODevice * outgoingData = 0 ) + { + QNetworkReply * reply = + QNetworkAccessManager::createRequest( op, req, outgoingData ); + if( op == GetOperation ) + { + connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), + this, SLOT( updateProgress( qint64, qint64 ) ) ); + } + return reply; + } + + +public slots: + void updateProgress(qint64 done, qint64 total) + { + emit progressChanged( qBound( 0, done * 100 / + qMax( 1, total ), 100 ) ); + } + + +signals: + void progressChanged( int ); + +} ; + + +#endif // _PROGRESS_TRACKING_NETWORK_ACCESS_MANAGER_H diff --git a/include/WebResourceProvider.h b/include/WebResourceProvider.h index 303dd5abc..f583e9d13 100644 --- a/include/WebResourceProvider.h +++ b/include/WebResourceProvider.h @@ -29,9 +29,11 @@ #include "ResourceProvider.h" #include "ResourceItem.h" +#include "ProgressTrackingNetworkAccessManager.h" class QBuffer; +class QNetworkReply; class WebResourceProvider : public ResourceProvider @@ -64,7 +66,7 @@ public: private slots: - void finishDownload( int _id, bool ); + void finishDownload( QNetworkReply * _reply ); private: @@ -72,9 +74,11 @@ private: ResourceItem * _item ); void importNodeIntoDB( const QDomNode & n, ResourceItem::Relation * _parent ); - void download( const QString & _path, QBuffer * _target ) const; + void download( const QUrl & _url, QBuffer * _target ) const; + void downloadAsync( const QUrl & _url, QBuffer * _target ) const; - static QList m_downloadIDs; + typedef QMap DownloadMap; + static DownloadMap m_downloads; } ; diff --git a/src/core/WebResourceProvider.cpp b/src/core/WebResourceProvider.cpp index 9de3eb4c7..1cccd6add 100644 --- a/src/core/WebResourceProvider.cpp +++ b/src/core/WebResourceProvider.cpp @@ -26,13 +26,12 @@ #include #include #include -#include #include "WebResourceProvider.h" #include "ResourceDB.h" -QList WebResourceProvider::m_downloadIDs; +WebResourceProvider::DownloadMap WebResourceProvider::m_downloads; WebResourceProvider::WebResourceProvider( const QString & _url ) : @@ -84,9 +83,26 @@ QByteArray WebResourceProvider::fetchData( const ResourceItem * _item, -void WebResourceProvider::finishDownload( int _id, bool a ) +void WebResourceProvider::finishDownload( QNetworkReply * _reply ) { - m_downloadIDs << _id; + if( _reply->attribute( + QNetworkRequest::HttpStatusCodeAttribute ).toInt() == 302 ) + { + const QUrl newLocation = + _reply->attribute( + QNetworkRequest::RedirectionTargetAttribute ).toUrl(); + if( newLocation != _reply->url() ) + { + qDebug() << "HTTP forwarding to" << newLocation; + + download( newLocation, m_downloads[_reply] ); + } + } + else + { + m_downloads[_reply]->write( _reply->readAll() ); + } + m_downloads.remove( _reply ); } @@ -192,44 +208,41 @@ void WebResourceProvider::importNodeIntoDB( const QDomNode & _n, -void WebResourceProvider::download( const QString & _path, - QBuffer * _target ) const +void WebResourceProvider::download( const QUrl & _url, QBuffer * _target ) const { - // create local http object; - QHttp http; - connect( &http, SIGNAL( requestFinished( int, bool ) ), - this, SLOT( finishDownload( int, bool ) ) ); + ProgressTrackingNetworkAccessManager netAccMgr( NULL ); + connect( &netAccMgr, SIGNAL( finished( QNetworkReply * ) ), + this, SLOT( finishDownload( QNetworkReply * ) ) ); - // set current URL for http object - QUrl u( _path ); - http.setHost( u.host(), u.port() > 0 ? u.port() : 80 ); - - // start the download - const int id = http.get( _path, _target ); + QNetworkReply * activeDownload = netAccMgr.get( QNetworkRequest( _url ) ); + m_downloads[activeDownload] = _target; // wait for the download to finish - while( !m_downloadIDs.contains( id ) ) + while( m_downloads.contains( activeDownload ) ) { QCoreApplication::instance()->processEvents(); } - m_downloadIDs.removeAll( id ); - - if( http.lastResponse().statusCode() == 302 ) - { - const QString newLocation = - http.lastResponse().value( "location" ); - if( newLocation != _path ) - { - qDebug() << "HTTP forwarding to" << newLocation; - - _target->seek( 0 ); - _target->buffer().clear(); - download( newLocation, _target ); - } - } } -#include "moc_WebResourceProvider.cxx" + +void WebResourceProvider::downloadAsync( const QUrl & _url, + QBuffer * _target ) const +{ + ProgressTrackingNetworkAccessManager * netAccMgr = + new ProgressTrackingNetworkAccessManager( NULL ); + connect( netAccMgr, SIGNAL( finished( QNetworkReply * ) ), + this, SLOT( finishDownload( QNetworkReply * ) ) ); + connect( netAccMgr, SIGNAL( finished( QNetworkReply * ) ), + netAccMgr, SLOT( deleteLater() ) ); + + QNetworkReply * activeDownload = netAccMgr->get( QNetworkRequest( _url ) ); + m_downloads[activeDownload] = _target; +} + + + +#include "moc_WebResourceProvider.cxx" +#include "moc_ProgressTrackingNetworkAccessManager.cxx"