So, I used the same behavior I find in the fast food restaurant. I make an order and take a ticket with a number. When an order is ready, they call for the number of it's ticket. If it is mine, I go and get it.
Here are the important methods:
[DownloadQueue]
public: int addUrl(QUrl url); bool removeUrl(int index); QByteArray getData(int index); bool removeData(int index); int getCurrentIndex(); bool clear(); signals: void downloadFinished(int index);
When I want to make a new download, I add the url to the DownloadQueue class and get an index to the added url. I can remove the url if I need, using the same index.
Whenever a download is finished, the class emits a signal with its index, so I should make a slot to listen for these 'announcements'. If the announced index is the one I ordered, I can get its ready data by using getData() method.
Beware that the received data resides in the memory until you remove it, even though you called getData().
Another method is for checking the current processed index, just to know if my order is taking long or going to be next...etc. And the clear method to empty all the queue.
Another twist is made to make the same queue accessible by all classes. So the class is a singleton. And an instance is made like this
//example DownloadQueue *d = DownloadQueue::getInstance();Thanks to Mahmoud Mamdouh for helping me with the singleton thing.
Here is the complete class:
(Download)
[DownloadQueue.h]
#ifndef DOWNLOADQUEUE_H #define DOWNLOADQUEUE_H #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> #include <QObject> #include <QTimer> #include <QUrl> class DownloadQueue : public QObject { Q_OBJECT public: static DownloadQueue* getInstance(); int addUrl(QUrl url); bool removeUrl(int index); QByteArray getData(int index); bool removeData(int index); int getCurrentIndex(); bool clear(); private: DownloadQueue(QObject *parent = 0); static DownloadQueue *_instance; int _index; QTimer _timer; QUrl _url; QList<QUrl> _urlList; QList<QByteArray> _dataList; QNetworkAccessManager _manager; signals: void downloadFinished(int index); private slots: void handleNetworkReply(QNetworkReply *reply); void downloadNext(); }; #endif // DOWNLOADQUEUE_H
[DownloadQueue.cpp]
#include "downloadqueue.h" DownloadQueue * DownloadQueue::_instance = 0; DownloadQueue* DownloadQueue::getInstance() { if(_instance == 0) _instance = new DownloadQueue(); return _instance; } DownloadQueue::DownloadQueue(QObject *parent): QObject(parent) { _urlList.clear(); _dataList.clear(); connect(&_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkReply(QNetworkReply*))); _index = 0; connect(&_timer, SIGNAL(timeout()), this, SLOT(downloadNext())); _timer.setInterval(500); _timer.start(); } int DownloadQueue::addUrl(QUrl url) { _urlList << url; QByteArray data; _dataList << data; return _urlList.length()-1; } bool DownloadQueue::removeUrl(int index) { if((index < _urlList.length()) || (index != _index)) { _urlList.replace(index, QUrl("")); return true; } return false; } QByteArray DownloadQueue::getData(int index) { QByteArray data; if(index < _dataList.length()) data = _dataList.at(index); return data; } bool DownloadQueue::removeData(int index) { if(index < _dataList.length()) { QByteArray data; _dataList.replace(index, data); return true; } return false; } int DownloadQueue::getCurrentIndex() { return _index; } bool DownloadQueue::clear() { _timer.stop(); _urlList.clear(); _dataList.clear(); return true; } void DownloadQueue::handleNetworkReply(QNetworkReply *reply) { QByteArray data = reply->readAll(); _dataList.replace(_index, data); emit downloadFinished(_index); _index++; _timer.start(); } void DownloadQueue::downloadNext() { if(_index < _urlList.length()) { _timer.stop(); _manager.get(QNetworkRequest(_urlList.at(_index))); } }
Here is a dummy example to show the basic use of the class.(click me)
Blog Example by Mahmoud Adly Ezzat is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
No comments:
Post a Comment