[Solved]How can I pause download in QEventLoop?
-
I have downloader and want to add pause/resume/abort functions, abortion is simple but I got stuck with pausing.
I have list of URLs so I run it in for loop and for reply I wait in QEventLoop. I wanted to connect clicked() signal of my button to pause slot with another QEventLoop where I wait till another button is pressed (resume or abort). But soon I released that won't work and now I am (again) stuck.
there is the loop
@
for(int b=0;b<urls4Download.count();b++){
if(!folder.endsWith("/"))folder.append("/");
QString st = FileList.at(fileIndex[b]);
st.replace(QRegExp("/"),QString(""));
file=new QFile(folder+st);
file->open(QIODevice::WriteOnly);
reply=nam.get(QNetworkRequest(QUrl(urls4Download.at(b))));
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(reply,SIGNAL(finished()),this,SLOT(saveFile()));
connect(reply,SIGNAL(readyRead()),this,SLOT(readyReadFile()));
connect(ui->pushButton_stop,SIGNAL(clicked()),&loop,SLOT(quit()));
connect(ui->pushButton_stop,SIGNAL(clicked()),this,SLOT(abort()));
connect(ui->pushButton_pause,SIGNAL(clicked()),this,SLOT(pause()));
loop.exec();
@
pause() function is here
@
void MainWindow::pause(){
QEventLoop loop;
connect(ui->pushButton_play,SIGNAL(clicked()),&loop_,SLOT(quit())); //button
connect(ui->actionResume,SIGNAL(triggered()),&loop_,SLOT(quit())); //there is same option in menu too
connect(ui->pushButton_stop,SIGNAL(clicked()),&loop_,SLOT(quit()));
connect(ui->pushButton_stop,SIGNAL(clicked()),this,SLOT(abort())); //in case user doesn't want resume
loop_.exec();
}
@
I see I have to quit QEventLoop in case I want to pause it and then wait until resume button (or stop) is pressed but how can I resume when it is in for loop? I was thinking about goto statement and put identifier before QEventLoop so I can return there after button press but that doesn't seems as good idea. -
Pausing does not hold open a connection and simply stop talking (transmitting acknowledgements).
The typical pause/resume download functionality in a web browser uses the server's HTTP 1.1 byte range capability to resume a download from part way through a resource. "Pausing" actually terminates the connection but does not discard the partial file. "Resuming" is actually a whole new request for the same file with a specified byte range (Range header) that starts at the byte after the last one in the partial file. The incoming data from the new request is appended to the existing partial file.
Have a look at [url=http://tools.ietf.org/html/rfc2616#section-14.35.2]RFC 2616 Section 14.35.2[/url] for the gory details.
-
So if I have understood it right I have to count bytes already transmitted each time readyReadFile() is called, and if pause is requested break the loop, save actual value of b in int b_value (set it to 0 by default) too so I can return to for loop and set loop to actual position of b (for(int b=b_value;...)) and set header like this :
@
QNetworkRequest request;
request.setUrl(QUrl(urls4Download.at(b));
request.setRawHeader("Range",byteCount);
reply=nam.get(request)));@I have no time to try it right now so it may help if I am wrong someone correct me till I come back to computer :)
-
I found this months ago, but you need to reimplement it with your QEventLoop beacuse it was designed to be asynchronous.
"kunalmaemo.blogspot.com":http://kunalmaemo.blogspot.com/2011/07/simple-download-manager-with-pause.html
"kunalmaemo.blogspot.com":http://kunalmaemo.blogspot.com/2010/05/simple-download-manager-in-qt-with.html -
[quote author="SetBetterPass" date="1362479708"]So if I have understood it right I have to count bytes already transmitted each time readyReadFile() is called, and if pause is requested break the loop, save actual value of b in int b_value (set it to 0 by default) too so I can return to for loop and set loop to actual position of b (for(int b=b_value;...)) and set header like this :
[/quote]No need to keep a count of received bytes (unless you use it for something else) or store that somewhere between pause and resume. Write received bytes to an actual file as they are received and close the file when paused. On resume open the partial file for append and use the actual file size to determine where to resume from.
This is what Code_ReaQtor's example does also.