Qtimer fires before QNetworkAccessManager finished - c++

Im making a connection every X sec. but in case net bandwidth is overloaded timer fires before QNetworkAccessManager sends finished signal and app crashes.
MainWindow::construct:
pTimer = new QTimer(this);
connect(pTimer, SIGNAL(timeout()), this, SLOT(connect()));
pTimer->start(5000);
MainWindow::connect()
pNetworkManager = new QNetworkAccessManager(this);
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(result(QNetworkReply*)));
pNetworkManager->get(QNetworkRequest(url));
MainWindow::result(QNetworkReply *reply) processes the response
how to check if QNetworkAccessManager isFinished before timer fires again?

Don't create a network manager per request, but only one network manager for your class. Otherwise you leak managers with each request until the mainwindow is destroyed.
QNetworkManager::get returns the pointer to the QNetworkReply representing the request. You can store that reply in a QPointer, connect to its signals, check QNetworkReply::isFinished() etc. to track whether the request is still running or not.

Why not simply launch timer after request finished?
pTimer = new QTimer(this);
pTimer->setSingleshot(true);
connect(pTimer, SIGNAL(timeout()), this, SLOT(connect()));
pTimer->start(5000);
pNetworkManager = new QNetworkAccessManager(this);
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(result(QNetworkReply*)));
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), pTimer, SLOT(start()));

Related

QNetworkAccessManager and cookies

I'm trying to download a website (youtube) that opens after user passes the consent page (accepting cookies). So i create QNetworkRequest request and set RawHeader to ("COOKIE" , "CONSENT=YES+42"). It works fine, but only with the first attempt to download. With every next attempt i bounce against the consent page. The problem is somehow bypassed when each time i use deleteLater() on QNetworkAccessManager object. But the documentation claims "One QNetworkAccessManager instance should be enough for the whole Qt application" (also creating new instance of QNetworkAccessManager for each use eventually results with not receiving a replay and rise of processor use). So my question is how to "reset" QNetworkAccessManager so with each next use, it acts as with the first request.
My code looks like this:
Youtube::Youtube(QObject *parent) : QObject(parent)
{
manager = new QNetworkAccessManager(this);
}
void Youtube::makeRequest(QString indexCore){
QNetworkReply *reply;
QNetworkRequest request;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotReadyRead(QNetworkReply*)));
request.setRawHeader("COOKIE" , "CONSENT=YES+42" ); //works
request.setUrl(QUrl("https://" + indexCore ));
reply = manager->get(request);
}
void Youtube::slotReadyRead(QNetworkReply *replay)
{
QByteArray dataTemp = replay->readAll();
website = dataTemp.toStdString();
replay->deleteLater();
}
OK.I just had to set and empty QNetworkCookieJar.

In Qt how can I delay a member function's return until a signal is received?

I want to use a recursive procedure to iterate through a large number of images in Qt: essentially the image is repeatedly quartered (up to a limit) and the user is asked whether the image passes or fails - ie if the image passes at large dimensions we call our function again with smaller dimensions (until we reach the limit), if it fails we return and so pass back up the hierarchy.
This approach seems to run into a roadblock with Qt's event-driven approach - I cannot see how I can pause the loop while waiting for the user input - ie there is nothing like a "wait_for_button_press" method.
I know that this sort of approach is regarded as an anti-pattern in event driven programming, but what is the alternative way that doesn't involve holding lots and lots of state on the heap (as opposed to getting it held for 'free' on the stack)?
QEventLoop maybe could help you. I start a http connection aside a timer with a timeout, all inside a thread. Then a wait for one of those had finish and return.
void MyThread::run(){
QNetworkAccessManager qnaManager;
bool isPost = false;
QUrl url(myUrl);
QNetworkRequest req(url);
QNetworkReply *reply;
req.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
req.setHeader(QNetworkRequest::ContentLengthHeader,
QVariant(postData.size()).toString());
reply = qnaManager.get(req);
QEventLoop eventLoop;
QTimer timer;
timer.setSingleShot(true);
const int timeout = 400;
timer.start(timeout);
connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec();
if (timer.isActive()){
//everything is ok
}else{
//timer elapsed, no replay
return;
}
}
For what it's worth, in the end I decided that the best route was to implement more message passing code - wait for the user input to dispatch a message. It was longer code than if I had used/had available the 'traditional' call back type paradigm, but it worked cleanly in the end.

QNetworkAccessManager used by QTimer causes falling

I am using QNetworkAccessManager in function, which is run periodically by QTimer. The code is:
QTimer* timer=new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(findUpdate()));
timer->setSingleShot(false);
timer->start(frequency*1800000);
void MainWindow::findUpdate()
{
for (int i=0;i<aplikace.count();i++){
QNetworkAccessManager* manager=new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(checkUpdate(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://www.gibucsoft.8u.cz/"+lang+"gibuclauncher/verze.php?ver="+aplikace.at(i))));
}
}
The compilation is fine and when I run my application from the Qt Creator it is OK as well but when I run it from the OS the program falls after a while (but not long enough for the timer to even start the function findUpdate). Sometimes before falling this error message shows:
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

using QNetworkAccessManager GET multiple times

I am writing an application to request a web page at equal intervals in order to get any changes in it (to check whether new data is received). here how i did it.
private:
QNetworkReply *r;
QNetworkAccessManager *m;
QNetworkRequest request;
QTimer *timer;
in the constructor ,
m = new QNetworkAccessManager(this);
timer = new QTimer(this);
connect(r , SIGNAL(readyRead()), this , SLOT(readit()));
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
readit function,
void MainWindow::readit(){
QString st;
st=r->readAll();
m->deleteResource(request);
ui->textBrowser->append(st);
}
update function,
void MainWindow::update()
{
request.setUrl(QUrl("http://localhost/test/default.php"));
r = m->get(request);
}
my problem is m->get(request) gets the request at its first call only, when it is called again it does nothing. I did several experiments but end up with no success results. i changed the second request to another web page using a button click but it did nothing too.
So I need help from an expert how to update the get request and get new reply multiple times.
and also i want to know am i doing a correct thing or is there mo reliable methods to get data on data change from the server than checking for the website at regular intervals.
I see following problems:
readyRead fires an arbitrary number of times per request - including zero times (!), but you treat it as if it fired exactly once. Use the finished signal, which is does what you want: fires once, no more, no less.
The update slot doesn't connect any slots to the request.

How to connect QNetworkReply signal to progress bar in qt

In the code below:
connect(network_access_manager_, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onRequestCompleted_progress(QNetworkReply *)));
network_access_manager_->get(request);
The point is that while the downloading the file via get(request) is in progress I'd like to connect the signal from QNetworkReply to progressBar but I simply don't see how am I suppose to do it? The QNetworkReply is unnamed.
Any ideas?
network_access_manager_->get(request); returns QNetworkReply*, so
QNetworkReply *reply = network_access_manager_->get(request);
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(......))
will serve.