I have a code that will download a package from the web. I want such code to run a html5viewer (or a window, it will be the same) after the download has finished, meaning I have to handle the finished() signal, here is my code:
main.cpp
#include <QApplication>
#include "html5applicationviewer.h"
#include "networkmanager.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
NetworkManager manager;
//manager.setFile("http://listadomedicamentos.aemps.gob.es/prescripcion.zip");
manager.setFile("http://listadomedicamentos.aemps.gob.es/prescripcion.zip");
/*
Html5ApplicationViewer viewer;
viewer.setOrientation(Html5ApplicationViewer::ScreenOrientationAuto);
viewer.showMaximized();
viewer.loadFile(QLatin1String("html/index.html"));*/
return app.exec();
}
networkmanager.h
#include <QObject>
#include "html5applicationviewer.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
#include <QStringList>
class NetworkManager : public QObject
{
Q_OBJECT
public:
explicit NetworkManager(QObject *parent = 0);
virtual ~NetworkManager();
void setFile(QString fileURL);
private:
QNetworkAccessManager *manager;
QNetworkReply *reply;
QFile *file;
private slots:
void onDownloadProgress(qint64, qint64);
void onFinished(QNetworkReply *reply);
void onReadyRead();
void onReplyFinished();
};
networkmanager.cpp
#include "networkmanager.h"
#include "html5applicationviewer.h"
#include <QDir>
#include <QStandardPaths>
#include <QDebug>
NetworkManager::NetworkManager(QObject *parent) :
QObject(parent)
{
manager = new QNetworkAccessManager;
}
NetworkManager::~NetworkManager()
{
manager->deleteLater();
}
void NetworkManager::setFile(QString fileURL)
{
QString filePath = fileURL;
QString saveFilePath;
QString savePath;
QStringList filePathList = filePath.split('/');
QString fileName = filePathList.at(filePathList.count() - 1);
savePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
if (QDir(savePath).exists())
{
qDebug() << "Archivos locales para almacenar la base de datos existentes.";
}
else
{
qDebug() << "Creando los archivos locales para almacenar la base de datos...";
QDir().mkdir(savePath);
}
saveFilePath = QString(savePath + "/" + fileName );
QNetworkRequest request;
request.setUrl(QUrl(fileURL));
reply = manager->get(request);
file = new QFile;
file->setFileName(saveFilePath);
file->open(QIODevice::WriteOnly);
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this,
SLOT(onDownloadProgress(qint64,qint64)));
connect(manager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(onFinished(QNetworkReply*)));
connect(reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished()));
}
void NetworkManager::onDownloadProgress(qint64 bytesRead, qint64 bytesTotal)
{
qDebug() << QString::number(bytesRead).toLatin1() + " bytes descargados de " +
QString::number(bytesTotal).toLatin1() + " bytes totales";
}
void NetworkManager::onFinished(QNetworkReply *reply)
{
switch (reply->error())
{
case QNetworkReply::NoError:
{
qDebug() << "El archivo se ha descargado con éxito.";
}
break;
default:
qDebug() << reply->errorString().toLatin1();
}
if (file->isOpen())
{
file->close();
file->deleteLater();
}
}
void NetworkManager::onReadyRead()
{
file->write(reply->readAll());
}
void NetworkManager::onReplyFinished()
{
if (file->isOpen())
{
file->close();
file->deleteLater();
}
}
I have tried doing
connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished(Html5ApplicationViewer&)));
void NetworkManager::onReplyFinished(Html5ApplicationViewer &viewer)
{
viewer.show();
if (file->isOpen())
{
file->close();
file->deleteLater();
}
}
But it will tell me that:
QObject::connect: Incompatible sender/receiver arguments
QNetworkReplyHttpImpl::finished() --> NetworkManager::startViewer(Html5ApplicationViewer&)
How could I make this viewer or window start with that finished() signal?
You are facing issue because, QNetworkAccessManager's finished signal does not have any parameter while you are connecting it with slot which takes Html5ApplicationViewer as parameter.
which is not compatible and thus you are getting warning.
If you want to have access to Html5ApplicationViewer pointer then you will need to assign or create pointer inside your NetworkManager class.
Related
I have a class that creates a server with multithreading. With the help of multithreading, I can connect several users at the same time. In one stream, the QByteArray Data is written, but I need this variable in the lane or in the lane heder, so that I can output this line (i.e., QByteArray Data). How I can tranfer var Data in my main function or header main?
I want write Data in QLable or somthing...
main.c
#include "groundstation.h"
#include <QApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GroundStation w;
Server wServer;
wServer.StartServer();
//qDebug() << ServerThread::getString();
// QLabel *label = new QLabel();
//label->setText((QString));
w.show();
return a.exec();
}
server.cpp
#include "server.h"
Server::Server(QObject *parent) :
QTcpServer (parent)
{
}
void Server::StartServer(){
if(!this->listen(QHostAddress::Any, 1234)){
qDebug() << "Could not start server";
}
else {
qDebug() << "Listening...";
}
}
void Server::incomingConnection(int socketDescriptor){
qDebug() << socketDescriptor << "Connecting...";
ServerThread *thread = new ServerThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
sever.h
#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
#include <QDebug>
#include "serverthread.h"
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
void StartServer();
signals:
public slots:
protected:
void incomingConnection(int socketDescriptor);
};
#endif // SERVER_H
serverthread.cpp
#include "serverthread.h"
ServerThread::ServerThread(int id, QObject *parent) :
QThread (parent)
{
this->socketDescriptor = id;
}
void ServerThread::run(){
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)){
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
qDebug() << socketDescriptor << " Client connected";
//make this thread a loop
exec();
}
void ServerThread::readyRead(){
Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void ServerThread::disconnected(){
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
serverthread.h
#ifndef SERVERTHREAD_H
#define SERVERTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QDebug>
class ServerThread : public QThread
{
Q_OBJECT
public:
QByteArray Data;
explicit ServerThread(int id, QObject *parent = 0);
void run();
signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void readyRead();
void disconnected();
public slots:
private:
QTcpSocket *socket;
int socketDescriptor;
};
#endif // SERVERTHREAD_H
i am a beginner in c++ and i am trying to retrieve data from a website using http request and to download the data in a file .
I am using the classes :
QMainWindow
QtNetwork/QNetworkAccessManager
QtNetwork/QNetworkRequest
QtNetwork/QNetworkReply
QUrl
The thing is that the file is created but there is no data in the file and i am getting an error that i don't understand . I searched through the forum found some similar kind of problems but did not understand as i am a beginner . Please help me its a school project and i am really stuck here.
Here is the httpWindow.h code
#ifndef HTTPWINDOW_H
#define HTTPWINDOW_H
#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QUrl>
#include <QString>
class QFile;
namespace Ui {
class httpWindow;
}
class httpWindow : public QMainWindow
{
Q_OBJECT
public:
explicit httpWindow(QWidget *parent = 0);
~httpWindow();
void request(QUrl url);
private slots:
void downloadFile();
void httpFinished();
void httpReadyRead();
private:
Ui::httpWindow *ui;
QUrl url;
QNetworkAccessManager *manager;
QNetworkRequest requete;
QNetworkReply *reply;
QFile *file;
int httpGetId;
bool httpRequestAborted;
};
#endif // HTTPWINDOW_H
Here is the httpwindow.cpp
#include <QtWidgets>
#include <qnetwork.h>
#include <QString>
#include "httpwindow.h"
#include "ui_httpwindow.h"
httpWindow::httpWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::httpWindow)
{
ui->setupUi(this);
downloadFile();
}
httpWindow::~httpWindow()
{
delete ui;
}
void httpWindow::request(QUrl url)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished()),
this, SLOT(httpFinished()));
//requete.setUrl(QUrl("http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide"));
requete.setUrl(url);
reply = manager->get(requete);
connect(reply, SIGNAL(&reply::readyRead()), this, SLOT(httpReadyRead()));
}
void httpWindow::downloadFile()
{
QMessageBox msg ;
QUrl url("http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide") ;
qDebug() << url.toString();
QFileInfo fileInfo(url.path());
//msg.setText("fileInfo = " + fileInfo);
QString fileName = "C:\\testQt\\" + fileInfo.fileName();
msg.setText("fileName = " + fileName);
if (fileName.isEmpty()){
fileName = "C:\testQt\fichier.html";
msg.setText(" création d'un nouveau fichier fichier.html ");
}
if (QFile::exists(fileName)) {
QFile::remove(fileName);
return;
}
file = new QFile(fileName);
msg.setText(" QFile::exists(fileName) == true , file : ");
if (!file->open(QIODevice::WriteOnly)) {
delete file;
file = 0;
return;
}
// schedule the request
httpRequestAborted = false;
request(url);
}
void httpWindow::httpFinished()
{
if (httpRequestAborted) {
if (file) {
file->close();
file->remove();
delete file;
file = 0;
}
reply->deleteLater();
return;
}
file->flush();
file->close();
QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error()) {
file->remove();
// QMessageBox::information(this, tr("HTTP"),
// tr("Download failed: %1.")
// .arg(reply->errorString()));
// downloadButton->setEnabled(true);
} else if (!redirectionTarget.isNull()) {
QUrl newUrl = url.resolved(redirectionTarget.toUrl());
// if (QMessageBox::question(this, tr("HTTP"),
// tr("Redirect to %1 ?").arg(newUrl.toString()),
// QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
url = newUrl;
reply->deleteLater();
file->open(QIODevice::WriteOnly);
file->resize(0);
request(url);
return;
}
reply->deleteLater();
reply = 0;
delete file;
file = 0;
}
void httpWindow::httpReadyRead()
{
// this slot gets called every time the QNetworkReply has new data.
// We read all of its new data and write it into the file.
// That way we use less RAM than when reading it at the finished()
// signal of the QNetworkReply
if (file)
file->write(reply->readAll());
}
Here is the main.cpp code
#include "httpwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
httpWindow w;
w.show();
return a.exec();
}
The errors :
can't find linker symbol for virtual table for `QMessageBox' value
found `RGB_MASK' instead
can't find linker symbol for virtual table for `QMessageBox' value
found `RGB_MASK' instead
"http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide"
QObject::connect: No such signal QNetworkAccessManager::finished() in ..\ppe3_trading_test\httpwindow.cpp:24
QObject::connect: (receiver name: 'httpWindow')
QObject::connect: No such signal QNetworkReplyHttpImpl::&reply::readyRead() in ..\ppe3_trading_test\httpwindow.cpp:31
QObject::connect: (receiver name: 'httpWindow')
Please do help me its really important for my schooling .
connect(reply, SIGNAL(&reply::readyRead()), this, SLOT(httpReadyRead()));
You're mixing up old syntax and new syntax, it should be
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
or better yet using new syntax(Qt5 only):
connect(reply, &QNetworkReply::readyRead, this, &httpWindow::httpReadyRead);
QNetworkAccessManager doesn't have a finished() signal it has a finished(QNetworkReply*) signal, read the docs.
I am trying to implement http://developer.nokia.com/community/wiki/Creating_an_HTTP_network_request_in_Qt and my code compiles without error but does not function. I have a warning that reply in "QNetworkReply* reply = nam->get(QNetworkRequest(url));" is not being used. I am sure this is my error and I am not setting up my HTTP GET correctly, but I am unsure of how to correct it.
//coreEng.h
#ifndef COREENG_H
#define COREENG_H
#include <QObject>
#include <QNetworkAccessManager>
class coreEng : public QObject
{
Q_OBJECT
public:
//coreEng(QObject);
coreEng(QObject *parent = 0) :
QObject(parent)
{
nam = new QNetworkAccessManager();
}
private slots:
public slots:
void connect();
void url(QNetworkReply *reply);
void finishedSlot(QNetworkReply* reply);
private:
QNetworkAccessManager* nam;
};
#endif // COREENG_H
//coreEng.cpp
"coreeng.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
void coreEng::connect(){
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
}
void coreEng::url(QNetworkReply*){
QUrl url("http://www.nyctelecomm.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void coreEng::finishedSlot(QNetworkReply* reply){
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
QImage pic = imageReader.read();
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
}
else
{
}
//delete reply();
}
//main.cpp
#include <QCoreApplication>
#include "coreeng.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
coreEng mConnect;
mConnect.connect();
return a.exec();
}
changed void coreEng::url(QNetworkReply*) to void coreEng::url()
changed void url(QNetworkReply *reply); to void url();
added mConnect.url(); to main.cpp and I could see the http packet with wireshark exit the NIC and begin the session.
I am trying to get data out of a web page, but the signal finished() never gets emitted!!! I know I must be doing something wrong, but can't figure out what it is.
# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
public:
QByteArray data;
};
#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req;
emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
if (finished->error() != QNetworkReply::NoError)
{
emit networkError(finished->error());
return;
}
data = finished->readAll();
qDebug() << data;
}
data never gets assigned a value as expected.
You aren't passing the url to the QNetworkRequest you create. Try:
QNetworkRequest req(url);
inside WebService::getRequest().
As requested, here's the source modified to allow it compile and work inside QtCreator as a single main.cpp file in a console application project:
#include <QCoreApplication>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QByteArray>
#include <QString>
#include <QDebug>
//# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
public:
QByteArray data;
};
//#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req(url);
emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
if (finished->error() != QNetworkReply::NoError)
{
qDebug() << "QNetworkReply error: " << finished->error();
emit networkError(finished->error());
return;
}
data = finished->readAll();
qDebug() << data;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WebService web;
web.getRequest("http://www.google.com");
return a.exec();
}
#include "main.moc"
The minor modifications that were made:
added necessary headers
added a main() that called WebService::getRequest() with an appropriate URL
added #include "main.moc" to the end of the main.cpp file so qmake would "moc-ify" it properly as a single, self-contained .cpp file
made the fix mentioned above in the answer to the question
added a qDebug() output in the error case
One final thing that needed to be done was to add QT += network in the .pro file for the project so the Qt networking modules get added to the link step and to the header search path.
Update 15 Oct 2013
From your comments, it looks like you want the QNetworkAccessManager::get() call to be synchronous. I've added another version of your example program that will block in WebService::getRequest() until the request's finished signal is received. Note that this example doesn't perform much in the way of error handling, and would probably perform very badly if the netwrok request fails to complete in a timely manner. Dealing apprpriately with errors and timeouts would be necessary for anything but example or study code.
The basic idea in this example is that the signals emitted in the asynchronous Qt networking model are driven by the framework's event loop. So when a request is made, a new 'nested' event loop is created and the WebService::getRequest() function execs that loop (and stays there) until the handler of the finished signal tells the event loop to exit.
#include <QCoreApplication>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QEventLoop>
#include <QByteArray>
#include <QString>
#include <QDebug>
//# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
//void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
QEventLoop request_event_loop;
public:
QByteArray data;
};
//#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req(url);
netMgr->get(req);
request_event_loop.exec(); // wait here until the WebService::parseNetworkResponse() slot runs
// emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
qDebug() << "enter parseNetworkResponse()";
if (finished->error() != QNetworkReply::NoError)
{
qDebug() << "QNetworkReply error: " << finished->error();
emit networkError(finished->error());
}
else {
data = finished->readAll();
qDebug() << data;
}
qDebug() << "request_event_loop.exit()";
request_event_loop.exit();
qDebug() << "exit parseNetworkResponse()";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WebService web;
qDebug() << "main() getRequest()";
web.getRequest("http://www.stackoverflow.com");
qDebug() << "main() getRequest() completed";
return a.exec();
}
#include "main.moc"
I don't know what the problem is...The compiler (Qt) runs program without errors, but the file is not downloaded...
Can you tell me please tell what is wrong?
I made by example "download", which is located in the qt folder. The only difference is that they have is a console, and I have windows application.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtNetwork>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
class DownloadManager: public QObject
{
Q_OBJECT
QNetworkAccessManager manager;
QList<QNetworkReply *> currentDownloads;
public:
DownloadManager();
void doDownload(const QUrl &url);
QString saveFileName(const QUrl &url);
bool saveToDisk(const QString &filename, QIODevice *data);
public slots:
void execute();
void downloadFinished(QNetworkReply *reply);
};
#endif // MAINWINDOW_H
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QStringList>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QStringList>
#include <QTimer>
#include <QUrl>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
#if defined(Q_WS_S60)
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}
DownloadManager::DownloadManager()
{
connect(&manager, SIGNAL(finished(QNetworkReply*)),
SLOT(downloadFinished(QNetworkReply*)));
}
void DownloadManager::doDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
currentDownloads.append(reply);
}
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;
}
bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Could not open %s for writing: %s\n",
qPrintable(filename),
qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void DownloadManager::execute()
{
QStringList args = QCoreApplication::instance()->arguments();
args[0]="http://www.google.ru/images/srpr/logo3w.png";
QString arg=args[0];
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit());
doDownload(url);
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error()) {
fprintf(stderr, "Download of %s failed: %s\n",
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
printf("Download of %s succeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}
currentDownloads.removeAll(reply);
reply->deleteLater();
if (currentDownloads.isEmpty())
// all downloads finished
QCoreApplication::instance()->quit();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
QTimer::singleShot(0, &manager, SLOT(execute()));
}
The problem is at that point of your code:
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
}
QNetworkAccessManager is asynchronous, so it needs an event loop to do any downloading. But when the function on_pushButton_clicked() returns and gives the control back to the event loop, the QNetworkAccessManager is already destroyed, and didn't have the time to do anything.
When you add a QMessageBox in DownloadManager::execute, you are in fact running another event loop withing the slot on_pushButton_clicked(), and it gives the opportunity to the QNetworkAccessManager to do its work.
The correct solution would be to allocate DownloadManager dynamically, and eventually to make it destroy itself when it has finished all downloads.
void MainWindow::on_pushButton_clicked()
{
DownloadManager *manager = new DownloadManager(this);
manager->execute();
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
...
if (currentDownloads.isEmpty())
this->deleteLater();
}