PDA

View Full Version : Getting data from a QNetworkReply



ttimt
2nd March 2014, 16:21
That is very long and intimidating.
Anyway, I got setcookiesforUrl() and cookiesforUrl() done without that.



But I don't want to use global variable and my read all data is in another function.
I want to return it like this :


QByteArray data = emit finished(QNetworkReply*);
connect(loginnam, finished(...), this, readdata(...);
QByteArray readdata()
{
reply->readall.....
}
//Want to return slot values



//This code below is the same cause can't get the return value
//In case someone said you can't emit finished or what lol
connect (loginnam, finished(), this, getdata())
QByteArray MainWindow::getdata()
{
//Emit here
QByteArray returnvalue = emit readdata();
return returnvalue;
}
QByteArray readdata()
{
reply->readall.....
}

There's no finished signal except using connect with sender as qnetworkaccessmanager object. So I can't use emit finished......
Is there any solutions to return the slot value with signal as finished? Other than private variables


It's unnecessary question cause I have two global variable to be used globally already, but I would like to know how to do it.:cool:

anda_skoa
2nd March 2014, 16:43
That doesn't make any sense or I don' understand at all what you are trying to do.

How is that related to the cookies? Is that for loading the cookies? Where do you see a need for signals?

Cheers,
_

ttimt
2nd March 2014, 17:25
That doesn't make any sense or I don' understand at all what you are trying to do.

How is that related to the cookies? Is that for loading the cookies? Where do you see a need for signals?

Cheers,
_

Well I mean the QNetworkAccessManager, a little bit related to cookie, I believe is unnecessary to create new thread

I use connect(accessmanager, finished(...), this, readdata(...))
What readdata does is only read QNetworkReply->readAll and save it in a QByteArray variable,
and I want to return it to use it in the function, don't want to use global variable

What I know to get return value from slot is like : Qbytearray data = emit->signal()

Thus, I want to emit finished() to save the return value.
But finished is QNetworkReply signal, not a signal I implemented myself
I definitely can't add something like this to the header file

signals:
void QNetworkReply::finished();
So what i'm asking is there anyway to get the slot value since I can't use emit on finished() and I don't want to use a global variable

anda_skoa
2nd March 2014, 20:26
Well I mean the QNetworkAccessManager, a little bit related to cookie, I believe is unnecessary to create new thread

It is not related to the other thread at all, created a new thread.



I use connect(accessmanager, finished(...), this, readdata(...))
What readdata does is only read QNetworkReply->readAll and save it in a QByteArray variable,
and I want to return it to use it in the function, don't want to use global variable

What does "the function" mean?
Do you mean main()?



What I know to get return value from slot is like : Qbytearray data = emit->signal()

While not impossible, it is very unlikely that you have a variable called "emit" in a Qt program :-)



Thus, I want to emit finished() to save the return value.

Don't see a problem with that, your finished() signal can easily transport a QByteArray.



But finished is QNetworkReply signal, not a signal I implemented myself

Obviously



I definitely can't add something like this to the header file

signals:
void QNetworkReply::finished();

True, but you can call your own signal finished() as well. Signal names do not need to be globally unique.



So what i'm asking is there anyway to get the slot value since I can't use emit on finished() and I don't want to use a global variable
What do you mean with "slot value"? The return value of a method that is marked as a slot? Or a value created inside a slot?

Cheers,
_

Infinity
3rd March 2014, 02:12
Your code is very confused.
To get an idea how QNetworkReply and related classes have to be used, you can check out the several network examples (of course in addition to reading the documentation):
http://qt-project.org/doc/qt-5.0/qtnetwork/examples-network.html

ttimt
3rd March 2014, 05:06
Ok my question is really just how to read/get the return value if the function is ran by connect(),

I only know how to get it using data = emit signal() but I can't emit finished() cause it's not mine.
Also not data = emit->signal(). Maybe typo or what


Anyway, I believe the code below will work


//Don't want this connect cause can't get the value returned by readdata()
//connect(loginnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(readdata(QNetworkReply*)));
QNetworkReply *a = loginnam->get(*request);

while(!a->isFinished())
{
}

data = readdata(a);

ChrisW67
3rd March 2014, 05:34
Ok my question is really just how to read/get the return value if the function is ran by connect(),

I only know how to get it using data = emit signal() but I can't emit finished() cause it's not mine.

Que?

From the trusty documentation we get the unequivocal:


Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void).


Frankly, you seem very confused. If you want to know that a network request has finished then you have no choice but to listen for the finished() signal from the QNetworkReply or QNetworkAccessManager. If you busy-wait on the request like you suggest then your application will not function: the request will not be sent until a Qt event loop is running again. You can use QEventLoop (connect reply->finished() to loop exit()) to block and maintain some responsiveness but a blocking design is really not the Qt way.

When the request is successful then the data from the response can be read from the QNetworkReply. What you do with it then has nothing to do with the QNetworkReply signal/slot connection. You can choose to expose that data through an interface on your class, or send it on to another QObject(s) by emitting a signal of your own which can, as anda_skoa pointed out, happily carry a QByteArray payload.

ttimt
3rd March 2014, 09:41
If you want to know that a network request has finished then you have no choice but to listen for the finished() signal from the QNetworkReply or QNetworkAccessManager. If you busy-wait on the request like you suggest then your application will not function: the request will not be sent until a Qt event loop is running again. You can use QEventLoop (connect reply->finished() to loop exit()) to block and maintain some responsiveness but a blocking design is really not the Qt way.

So while(isfinished()) would not work? Maybe I'll will try an event loop.

So maybe here's a "simplier" form of my question.
After I do reply->readAll() in a function/method named readdata, I want to store it in a variable called "data" and use it in another function. And the way I ran the readdata function is by connect( loginnam, finished(), this, readdata()). So there's no way I could get the return value?

The important thing is the (loginnam, finished(),,), this is the only way I know, my "knowledge" of listening/waiting for the finished() signal, not sure if there's other, not to use connect, so I can return the value from readdata()





Que?

From the trusty documentation we get the unequivocal:

Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void).

Que? Googled, is that Spanish?



I didn't go to the trusty documentation and read everything, but I did some googling.

First link :
http://qt-project.org/forums/viewthread/37451
Saw some argument, or debate, there's a guy called "raven-worx" a certified specialist with rank "Mad Scientist" said :

Thats just NOT true.
Not Practicable, maybe I can use disconnect? I'm doing GUI


Second link :
http://stackoverflow.com/questions/5842124/can-qt-signals-return-a-value
The rated +15 answer said it is possible, of course by changing slot and signal to non void, he/she also said you'll only get the last value.
This is not a web browser or what, I could get some data from the readAll and append it to a list.


Third link:
http://stackoverflow.com/questions/11890644/qt-return-value-of-signal-works-why-is-the-official-doc-saying-it-is-impossibl
Stackoverflow again. i'm using QByteArray not some double/float.


Fourth link :
http://stackoverflow.com/questions/112861/qt-meaning-of-slot-return-value
And this, one of them mentioned about Qmetaobject::invokemethod.
Also saw this function metioned in this forum in some thread that wysota posted. But I think invokemethod cant't listen to signals. I don't know yet
I'll take a look at that later but it's unfamiliar to me. I used some basic Qt method not like all of them.
and the documentation :

bool QMetaObject::invokeMethod ( QObject * obj, const char * member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument( 0 ), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument() ) [static]
So it takes time :eek:


Fifth link:
http://www.qtcentre.org/threads/18833-slot-return-type
This! The global variable! Maybe is what i'm talking about, don't want to use global variable or class member, just local.
Spirit suggested to use class member, and QMetaObject::InvokeMethod again


Sixth link:
http://www.qtcentre.org/threads/26724-Slot-with-a-return-value
Slot with a return value! QMetaObject::invokeMethod()




From stackoverflow and qt-project, they used signal slot as non void.
And as I stated above, i'm not sure whether invokemethod can listen to signals, will read its documentation later.
My real question goes back to this post's first paragraph.


And, after those 6 links, maybe I misinterpreted all of them again, or maybe they're discussing different things, cause maybe like you said :
I might be really really really confused.

Also, in the end, if i'm really confused, class member like spirit suggested or global variable will work just fine! :)

anda_skoa
3rd March 2014, 14:38
So maybe here's a "simplier" form of my question.
After I do reply->readAll() in a function/method named readdata, I want to store it in a variable called "data" and use it in another function.

You can call the other function and pass data, or, if both functions are methods of the same class, store data as a member variable and access it from both methods, or if not, store data in an object that both functions have acess to.

Not really a question of Qt though, that applies to C++ in general.

Lets do an example


class Foo : public QObject
{
Q_OBJECT
public:
void login(const LoginData &loginData);

signals:
void receivedLoginResponse(const QByteArray &data);

private:
void doSomething(const QByteArray &data);
void doSomethingElse();

private:
QByteArray m_data;

private slots:
void loginiFinished(QNetworkReply *reply);
};




void Foo::login(const LoginData &loginData)
{
// prepare QNetworkRequest

QNetworkReply *reply = networkAccessManager->get(...);
connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(loginFinished(QNetworkReply*)));
}

void Foo::doSomething(const QByteArray &data)
{
qDebug() << Q_FUNC_INFO << "data .length=" << data.length();
}

void Foo::doSomethingElse()
{
qDebug() << Q_FUNC_INFO << "m_data .length=" << m_data.length();
}

void Foo::loginFinished(QNetworkReply *reply)
{
QByteArray data = reply->readAll();


// call a function with data
doSomething(data);

// call a method of same object, share data as member
m_data = data;
doSomethingElse();

// let some other class handle the data
emit receivedLoginResponse(data);
}


Cheers,
_