PDA

View Full Version : QNetworkAccessManager no finished() signal emitted



realperson
3rd May 2012, 15:48
Hello Folks,

I've a strange problem with QNetworkAccessManager, I read the documentation, but it doesn't work. My example hast only a few lines of code, so its really easy to follow it. I'm using Qt-4.8.1 under Ubuntu 11.10. At the internet I found some articles with the same issue but no solutions... so I'm posting here now.



void TmdbLookup::movieLookup()
{
bool ok = false;
QNetworkRequest request;
request.setUrl(QUrl("http://qt.nokia.com"));
manager_ = new QNetworkAccessManager(this);

ok = connect(manager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
qDebug() << "connect: " << ok;
manager_->get(request);
}

void TmdbLookup::replyFinished(QNetworkReply *reply)
{
qDebug() << "Request Finished";
reply->deleteLater();
}


The problem I've is the finished(QNetworkReply*) singal is never emitted, but the connect returns true. I never had any problems with signal / slots in qt. But the QNetworkAccessManager will not work and I can't find an other Example or a solution.

In my second try I'll connect the finish() signal not to the QNetworkAccessManager. I'll connect it directly to the QNetworkReply.



void TmdbLookup::movieLookup()
{
bool ok = false;
QNetworkRequest request;
request.setUrl(QUrl("http://qt.nokia.com"));
manager_ = new QNetworkAccessManager(this);

ok = connect(manager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
QNetworkReply *reply = manager_->get(request);
ok = connect(reply, SIGNAL(finished()), this, SLOT(readyRead()));
qDebug() << "connect: " << ok;
}

void TmdbLookup::readyRead()
{
qDebug() << "ready read";
}


The finished() signal is not emitted.

Can someone help me to solve my problem? I'm really confused, in these small examples there is no space for mistakes so what I'm doing wrong?

so long
realperson

ChrisW67
3rd May 2012, 23:59
Make sure you program is returning to the Qt event loop.

Try this complete example:


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

class Fetcher: public QObject
{
Q_OBJECT
public:
Fetcher(QObject *p = 0):
QObject(p),
nam(new QNetworkAccessManager(this)),
reply(0)
{
connect(nam, SIGNAL(finished(QNetworkReply*)), SLOT(namFinished(QNetworkReply*)));
}

void fetch(const QUrl &url) {
reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(slotError(QNetworkReply::NetworkError)));
}

public slots:
void slotError(QNetworkReply::NetworkError code) {
qDebug() << Q_FUNC_INFO << "Error" << code;
}

void namFinished(QNetworkReply *reply) {
qDebug() << Q_FUNC_INFO << reply;
}

void slotFinished() {
qDebug() << Q_FUNC_INFO << "Error" << reply->error();
QByteArray ba = reply->readAll();
qDebug() << Q_FUNC_INFO << "Bytes read" << ba.size();
reply->deleteLater();
reply = 0;

qApp->quit();
}

private:
QNetworkAccessManager *nam;
QNetworkReply *reply;
};


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

Fetcher f;
f.fetch(QUrl("http://qt.nokia.com"));

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


I have allocated my QNetworkAccessManager on the heap like your example although I normally would not. It receives both finished() signals and no error signal.

realperson
4th May 2012, 10:16
Hello ChrisW67,
Hello folks,

special thanks for your help through your code I found my bad mistake, the problem is really simple... I'll explain the problem and the solution.

You've a class called TmdbLookup. This class will create all necessary network stuff to make a lookup on a website. At the next step, we'll use our Lookup class from the QMainWindow, in a slot. So you click on a button and the slot will do the rest.

Lookup.h


class TmdbLookup : public QObject
{
Q_OBJECT
public:
explicit TmdbLookup(QObject *parent = 0);
void movieLookup();

public slots:
void replyFinished(QNetworkReply *reply);

private:
QNetworkAccessManager *manager_;
};


Lookup.cpp


#include "tmdblookup.h"

TmdbLookup::TmdbLookup(QObject *parent) :
QObject(parent)
{
}

void TmdbLookup::movieLookup()
{
qDebug() << "Lookup called";
QNetworkRequest request;
request.setUrl(QUrl("http://qt.nokia.com"));
manager_ = new QNetworkAccessManager(this);
connect(manager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager_->get(request);
}

void TmdbLookup::replyFinished(QNetworkReply *reply)
{
qDebug() << "Request Finished";
}


mainwindows.cpp


void MainWindow::lookup()
{
TmdbLookup tmdb(this);
tmdb.movieLookup();
}


This code compiles correctly without errors or warnings. If you execute the code, the TmdbLookup will create http traffic, so the basics will work, but the finished(QNetworkReply*) will never be emitted.

The Problem is this:


void MainWindow::lookup()
{
TmdbLookup tmdb(this);
tmdb.movieLookup();
}


If you execute this function, the TmdbLookup will be created. You call the additional lookup function to do the request. And then you're leaving the scope of the function.



TmdbLookup tmdb(this);


This will allocate TmdbLookup locally on the stack and the object will be destroyed before the signal was emitted. So you can solve this problem, with a member variable.



void MainWindow::lookup()
{
tmdb_ = new TmdbLookup(this);
tmdb_->movieLookup();
}

And now its works! The TmdbLookup will not destroyed to early. The code is not 100% complete for memory leaks follow the hints at the Qt-Documentation.

so long
realperson

dfaure
5th February 2014, 23:03
I had the same need, so I'm starting a Qt5-based tmdb access library, since I couldn't find one anywhere. It's currently at http://quickgit.kde.org/?p=scratch/dfaure/libtmdbqt.git

(if you read this in the far future and you can't find it, try http://quickgit.kde.org/?p=libtmdbqt.git)

Contributions welcome, there is much to do still (but at least I can query for movies and get results, already...)

dfaure
18th January 2018, 09:42
Updated URL: https://cgit.kde.org/libtmdbqt.git/