[SOLVED] QNetworkAccessManager does not emit finished() signal
-
I am writing a little test program so I could figure out how QNetworkAccessManager works and get a QProgressDialog working with a download. The download appears to work as I can see it downloading in wireshark and the progress is working. However, the reply never emits finished() and I do not believe readyRead() is emitting as well. The file is not being saved for some reason and I do not know what else to do. I would really appreciate some help here.
Here is the header:
@#ifndef QTDOWNLOADER_H
#define QTDOWNLOADER_H#include <QtGui/QMainWindow>
#include <QProgressDialog>
#include <QFile>
#include <QtNetwork>
#include <QUrl>
#include <QTime>
#include <QMessageBox>
#include "ui_qtdownloader.h"class QtDownloader : public QMainWindow, public Ui::QtDownloaderClass
{
Q_OBJECTpublic:
QtDownloader(QWidget *parent = 0, Qt::WFlags flags = 0);
~QtDownloader();public slots:
void downloadButtonPressed();
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void downloadFinished();
void downloadReadyRead();
void cancelDownload();private:
QNetworkAccessManager manager;
QFile *file;
QTime downloadTime;
QProgressDialog *progressDialog;
QNetworkReply *reply;
bool downloadRequestAborted;
};#endif // QTDOWNLOADER_H
@And here is the source:
@#include "qtdownloader.h"QtDownloader::QtDownloader(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
setupUi(this);
progressDialog = new QProgressDialog(this);
connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadButtonPressed()));
}QtDownloader::~QtDownloader()
{
delete progressDialog;
progressDialog = NULL;
}void QtDownloader::downloadButtonPressed()
{
QUrl url(urlLineEdit->text());
QString filename = QFileInfo(url.path()).fileName();if(QFile::exists(filename))
{
if(QMessageBox::question(this, tr("Downloader"),
tr("There already exists a file called %1 in "
"the current directory. Overwrite?").arg(filename),
QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
== QMessageBox::No)
return;
QFile::remove(filename);
}file = new QFile(filename);
if(!file->open(QIODevice::WriteOnly))
{
QMessageBox::information(this, "Downloader",
tr("Unable to save the file %1: %2.")
.arg(filename).arg(file->errorString()));
delete file;
file = NULL;
return;
}downloadRequestAborted = false;
reply = manager.get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SIGNAL(downloadFinished()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelDownload()));
connect(reply, SIGNAL(readyRead()), SIGNAL(downloadReadyRead()));progressDialog->setLabelText(tr("Downloading %1...").arg(filename));
downloadButton->setEnabled(false);
progressDialog->exec();
}void QtDownloader::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
if(downloadRequestAborted)
return;
progressDialog->setMaximum(bytesTotal);
progressDialog->setValue(bytesReceived);
}void QtDownloader::downloadFinished()
{
if(downloadRequestAborted)
{
if(file)
{
file->close();
file->remove();
delete file;
file = NULL;
}
reply->deleteLater();
progressDialog->hide();
return;
}progressDialog->hide();
file->flush();
file->close();if(reply->error())
{
//Download failed
QMessageBox::information(this, "Download failed", tr("Failed: %1").arg(reply->errorString()));
}reply->deleteLater();
reply = NULL;
delete file;
file = NULL;
}void QtDownloader::cancelDownload()
{
downloadRequestAborted = true;
reply->abort();
downloadButton->setEnabled(true);
}void QtDownloader::downloadReadyRead()
{
if(file)
file->write(reply->readAll());
}
@I know finished is not getting emitted as the download button is never re-enabled. It does however when I cancel the download. I am really at a loss of words here.
Thank you,
Curtis -
Also, if it helps, I am using Visual Studio Professional 2010 with the plugin and Qt version 4.7.3.
-
Hi,
You have the mistake in connect statements, please change this two lines:
@
connect(reply, SIGNAL(finished()), this, SIGNAL(downloadFinished()));
connect(reply, SIGNAL(readyRead()), SIGNAL(downloadReadyRead()));
@to
@
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
connect(reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
@ -
Thank you dakron! Wow, can't believe I did that. You know what they say, the more eyes the better.
Thank you again.
-
[quote]
I know finished is not getting emitted as the download button is never re-enabled. It does however when I cancel the download. I am really at a loss of words here.
[/quote]
First of all, you are not re-enabling the button in your code if the download is complete.
Second I would suggest you add a call to downloadReadyRead() to your downloadFinished method, just in case that signal arrives before readyRead(). -
[quote author="dakron" date="1310419284"]Hi,
You have the mistake in connect statements, please change this two lines:
@
connect(reply, SIGNAL(finished()), this, SIGNAL(downloadFinished()));
connect(reply, SIGNAL(readyRead()), SIGNAL(downloadReadyRead()));
@to
@
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
connect(reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
@
[/quote]Just as a side note, the this isn't needed.
[quote]
bool QObject::connect ( const QObject * sender, const char * signal, const char * method, Qt::ConnectionType type = Qt::AutoConnection ) constThis function overloads connect().
Connects signal from the sender object to this object's method.
Equivalent to connect(sender, signal, this, method, type).
[/quote] -
[quote author="loladiro" date="1310420216"][quote]
I know finished is not getting emitted as the download button is never re-enabled. It does however when I cancel the download. I am really at a loss of words here.
[/quote]
First of all, you are not re-enabling the button in your code if the download is complete.
Second I would suggest you add a call to downloadReadyRead() to your downloadFinished method, just in case that signal arrives before readyRead().
[/quote]- Yeah, I noticed I wasn't re-enabling the button after download once it was working so I already added that.
- When would that happen out of curiosity? When the download happens so quick (ex. small file)?
So something like this would be more appropriate?
@void QtDownloader::downloadFinished()
{
if(downloadRequestAborted)
{
if(file)
{
file->close();
file->remove();
delete file;
file = NULL;
}
reply->deleteLater();
progressDialog->hide();
downloadButton->setEnabled(true);
return;
}downloadReadyRead();
progressDialog->hide();
downloadButton->setEnabled(true);
file->flush();
file->close();if(reply->error())
{
//Download failed
QMessageBox::information(this, "Download failed", tr("Failed: %1").arg(reply->errorString()));
}reply->deleteLater();
reply = NULL;
delete file;
file = NULL;
}@ -
Concerning 2). I am actually not sure that it can happen (i have heard people say it does, but never experienced it myself - probably because I don't use it that much). The only way I could imagine that happening is that the order is mixed up, because of the threading within QNetworkAcccessManager. And I always thinks it's better to be safe than sorry ;)
-
[quote author="loladiro" date="1310420290"]
[quote]
bool QObject::connect ( const QObject * sender, const char * signal, const char * method, Qt::ConnectionType type = Qt::AutoConnection ) constThis function overloads connect().
Connects signal from the sender object to this object's method.
Equivalent to connect(sender, signal, this, method, type).
[/quote][/quote]
I noticed they were doing that in the "HTTP":http://doc.qt.nokia.com/latest/network-http.html example is some sections, but not in the startRequest part of the code. I just didn't really look to see why. Thank you for the info.
-
[quote author="loladiro" date="1310421072"]Concerning 2). I am actually not sure that it can happen (i have heard people say it does, but never experienced it myself - probably because I don't use it that much). The only way I could imagine that happening is that the order is mixed up, because of the threading within QNetworkAcccessManager. And I always thinks it's better to be safe than sorry ;)[/quote]
Fair enough, wish there was a little better explanation, but I fall in the same boat as you. Better safe then sorry :) and thank you for the information on that as well.