PDA

View Full Version : Problems with QNetworkRequest, it does not send signals.



nilhcraiv
19th October 2011, 22:51
Hello, I have a problem with my program, I hope you could help me!

I have written this code for download a file from internet. The problem is that it does not get download the file. I think that's code
reply = qnam.get(QNetworkRequest(url)); does not emit the signal ReadyRead, such as say the oficial documentation.


Posts a request to obtain the contents of the target request and returns a new QNetworkReply object opened for reading which emits the readyRead() signal whenever new data arrives.

Which is the problem of the code?

updates.h



#include <QString>
#include <QFile>
#include <QNetworkReply>
#include <QtNetwork/QtNetwork>
#include <QtNetwork/QNetworkAccessManager>
#include <QWidget>
#include <QObject>
#include <QMainWindow>
#include <QProgressDialog>

class updates : public QMainWindow
{
Q_OBJECT

public:
updates(QWidget *parent = 0);
void checkUpdates(QString version);
private:
QString fileNameUpdate,versionInstalled,pathDownload;
QFile *file;
QNetworkReply *reply;
QNetworkAccessManager qnam;
bool httpRequestAborted;
int iVersion;

void download(QString textUpdate);

QProgressDialog *dialog;

private slots:
void httpFinished();
void httpFinishedDownload();
void httpReadyRead();
void replyErrorActualizaciones(QNetworkReply::NetworkEr ror code);
void updateDataReadProgress(qint64,qint64);
};




updates.cpp



#include <QUrl>
#include <QFileInfo>
//#include <QObject>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QProcess>
#include <QStringList>

#include "updates.h"

updates::updates (QWidget *parent) :
QMainWindow(parent)
{
iVersion =0;
}


void updates::checkUpdates(QString version)
{
httpRequestAborted=false;

//Variables
QUrl url("http://weblink.link/link");
QFileInfo fileInfo(url.path());//url.path() devuelve a partir del .es/ .com/ .org/
fileNameUpdate.append(fileInfo.fileName());//nombre del arvhivo //.fileinfo -Returns the name of the file, excluding the path.

file = new QFile(fileNameUpdate);
file->open(QIODevice::WriteOnly);
//Hasta aqui simplemente creo el archivo para poder escribir en el
versionInstalled = version;

reply = qnam.get(QNetworkRequest(url));//se supone que esto emite la readyRead(), pero no funciona!!
qDebug() << reply;

connect(reply, SIGNAL(finished()),this, SLOT(httpFinished()));
connect(reply, SIGNAL(readyRead()),this, SLOT(httpReadyRead()));
connect(reply,SIGNAL(error(QNetworkReply::NetworkE rror)),this,SLOT(replyErrorActualizaciones(QNetwor kReply::NetworkError)));

}//checkUpdate


//Private slots

void updates::httpFinished()
{
//Variables
QString text,auxiliar;
bool ok;
double versionServidor;
QFile fileToRead;

if (httpRequestAborted)
{
if (file)
{
file->close();
file->remove();
delete file;
file = 0;
}
reply->deleteLater();
return;
}//if

file->close();

.
.
.
.
.

void updates::httpReadyRead()
{
if (file)
file->write(reply->readAll());

qDebug() << "Ready";
}//httpReadyRead

void updates::replyErrorActualizaciones(QNetworkReply:: NetworkError code)
{
qDebug() << "Download error: " << code;
httpRequestAborted = true;
}//replyErrorActualizaciones

void updates::httpFinishedDownload()
{
if (httpRequestAborted)
{
if (file)
{
file->close();
file->remove();
delete file;
file = 0;
}
reply->deleteLater();
.
.
.
.
.


I use that class from MainWindow.cpp

MainWindow.cpp



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
connect(ui->actionActualizaciones,SIGNAL(triggered()),SLOT(slo tCheckUpdates()));
}

.
.
.
.

void MainWindow::slotCheckUpdates()
{
updates a(this);
a.checkUpdates(version);
}//updates


I have thought a long time why it does not work and can not find the reason, I hope you could help me!

Thanks!

ChrisW67
19th October 2011, 23:57
It does emit the signals the docs list under the conditions that the docs list. What makes you say it does not? All we have at the moment is "it doesn't work", which is not very useful.

If no data is received then readyRead() is never emitted: this could happen because, for example, the host name in the URL is wrong (I assume that is not the real URL in your code). Is replyErrorActualizaciones() being called? Even with a successful connection the server may simply close it again (server error) and send nothing back. Have you verified the request returns something outside of Qt?

Is it just that you see no data in the file you are expecting to see written? Have you verified the file is open successfully? Is it in a writeable location? if replyErrorActualizaciones() is called, regardless of error code (maybe NoError?), then httpRequestAborted will be set and the file will be deleted when the finished signal is emitted.

nilhcraiv
20th October 2011, 18:29
Sorry for not very well detailed the problem, I have problems with English because it is not my native language.

Referring to your comments:
The url is working properly, I checked by other means and it works correctly, in addition I have written the same code in another program and it works, I think that the error is because the code is written in different class of mainwindow.cpp. In the program that works, I have written the code in the file mainwindow.cpp everything.

replyErrorActualizaciones () is called. I've found that does not emit signals because I have written code in the three private slops and does not run. For example, I had written
qDebug() << "Test"; in the private slots, but it do not work.

The file has been perfect for writing, I checked it.

ChrisW67
21st October 2011, 00:37
Try this summary of your code with the Google URL and your URL:


#include <QtCore>
#include <QtNetwork>
#include <QDebug>

static const QUrl url("http://www.google.com");

class DoIt: public QObject {
Q_OBJECT
public:
DoIt(QObject *p = 0): QObject(p), m_reply(0), m_file(0) { }

void go() {
m_file = new QFile("output.txt", this);
if (m_file->open(QIODevice::WriteOnly)) {

QNetworkRequest request(url);
m_reply = m_nam.get(request);

connect(m_reply, SIGNAL(finished()), SLOT(httpFinished()));
connect(m_reply, SIGNAL(readyRead()), SLOT(httpReadyRead()));
connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(replyErrorActualizaciones(QNetworkReply::Netw orkError)));
}
}

private slots:
void httpFinished() {
qDebug() << __func__;
m_file->close();
m_reply->deleteLater();
qApp->quit();
}

void httpReadyRead() {
quint64 bytes = m_file->write( m_reply->readAll() );
qDebug() << __func__ << "wrote" << bytes << "bytes";
}

void replyErrorActualizaciones(QNetworkReply::NetworkEr ror code) {
qDebug() << __func__ << code;
}

private:
QNetworkAccessManager m_nam;
QNetworkReply *m_reply;
QFile *m_file;
};

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

DoIt d;
d.go();

return app.exec();
}
#include "main.moc"

Do you see the output from the slots?

With your code, do you get warnings about connect() calls when you run it?

hugh_lou
21st October 2011, 03:10
when the slotCheckUpdates is finished, the instances of class updates is destroyed.
All connections to that instance are invalid.
Try to keep the instance of updates as a member of the main window.

nilhcraiv
21st October 2011, 20:00
Hey thanks ChrisW67 for your code! It works correctly, but I have used your code on my program and it don't works. The problem is that the private slot "
void MainWindow::slotCheckUpdates() " finished before of that the class updates download the file, i. e. "updates" don't have time to emit signals and download the file.(Thank you hugh_lou) How I can write a signal to work it? I have checked it with this:


void MainWindow::slotCheckUpdates()
{
updates a(this);
a.checkUpdates(version);
QMessageBox::information(this,"h","kl");
}//updates


and my code works correctly!

Is it possible write something for fix it, to not display the QMessageBox?

Thank you!

Added after 40 minutes:

How I can emit a signal public? I have try with this:
In updates.h


signals:
void senyal();


in updates.cpp


emit senyal(); //when I need it


the problem is that the signal is private, How I can it do?