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.
Related
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.
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.
I'm using two ip cameras from Axis Communications for my application. I want to check if the cameras are ever disconnected. Is it possible to do so by the use of QNetworkAccessManager and QNetworkReply?
The prototype of what I tried is like the following way:
QNetworkAccessManager *m_networkAccessManager = new QNetworkAccessManager();
QNetworkReply *m_networkReply = m_networkAccessManager->get(QNetworkRequest(camUrl));
if (!m_networkReply)
{
delete m_networkAccessManager;
qDebug()<<"Camera not found"<<endl;
}
connect(m_networkReplyCam, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(cameraDisconnected(QNetworkReply::NetworkError)));
void MainWindow::cameraDisconnected(QNetworkReply::NetworkError)
{
qDebug()<<"Camera Disconected"<<endl;
}
But the slot cameraDisconnected never seem to gets invoked. I also tried connect with finished() signal from QNetworkReply like the following:
connect(m_networkReplyCam, SIGNAL(finished()), this, SLOT(cameraDisconnected()));
But even then the slot never gets called.
What am I doing wrong?
Thanks.
Your request will timeout after some time if the host is unreachable. There is no built-in way to set specific timeout in QNetworkRequestor QNetworkAccessManager so one possibility is to implement your own timer to abort after a particular time. There are multiple examples to do that like 1, 2 and 3.
I created a class called aTimer which inherits from QTimer. I want to be able to store the time elapsed into a variable called TimeElapsed of type int. I then want to have the timer automatically started when the main window opens and for it to display the time elapsed therein.
I think I'm using the wrong timer, and I am quite confused as to which tools to be using within Qt because there are different ways of handling time. Suffice it to say that I want a stop-watch kind of module that allows me to start and stop time manually without a cap (or an interval with the case of Timer). How shall I proceed? So far, attempts to use QTimer are fruitless.
You do not really need a derived class for this task. I'd probably use a QTimer and a QElapsedTimer.
Create them in your main window constructor and set the QTimers interval according to how often the time should be updated. Also connect its timeout() signal to a function updating the displayed value. In this function you can get the elapsed time from the QElapsedTimer and update the display.
// *.h
QTimer* timer;
QElapsedTimer *eltimer;
// *.cpp
constructor(){
this->timer = new QTimer(this);
this->timer->setInterval(1000);
connect(this->timer, SIGNAL(timeout()), this, SLOT(update_ui()));
this->timer->start();
this->eltimer = new QElapsedTimer(this);
this->eltimer->start();
}
SLOT update_ui(){
qint64 msecs_elapsed = this->eltimer->elapsed();
// Insert value into ui object
}
Of course you can create some buttons to start() and stop() the QTimer
so, I'm trying to run some simple code in Qt to return the contents of a given web page. After doing quick research, I was able to develop my own class to simplify the process:
WebFetch::WebFetch()
{
nam = new QNetworkAccessManager(this);
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
}
QString WebFetch::get(QString url)
{
nam->get(QNetworkRequest(QUrl(url)));
}
void WebFetch::finished(QNetworkReply* reply)
{
QByteArray data = reply->readAll();
QString str(data);
}
However, there big problem that I'm finding with the above code is that the call is asynchronous. I would like the "get" function to simply return the string after it is retrieved, which seems impossible on the account that it needs to wait for the finished signal, at which point there's no way of having "get" return whatever content is retrieved by the "finished" slot. Is there any alternative to the above method or is there a way I can get "get" to return the content retrieved by "finished"? Any help would be greatly appreciated. Thanks!
The call being asynchronous is not a problem - it's a big win. With a synchronous call, you're essentially wasting potentially hundreds ok KB of RAM, and an entire thread, just idly waiting for something to come back. You can't write such code while pretending that things happen synchronously or even "quickly" for that matter. I won't even comment on the insanity of running such synchronous code in the GUI thread. It's also a very bad idea to run a local event loop, since suddenly all of your GUI code becomes reentrant. My bet is that you neither design nor test for that.
You have to break down whatever code is expecting the result into two parts: the first part needs to place the request. The second part, in a slot, is notified when the request is finished and continues doing whatever is to be done.
If you wish to have it all in a single method, use C++11:
QNetworkAccessManager * mgr = ...;
QObject::connect(mgr, &QNetworkAccessManager::finished,
[this, mgr](QNetworkReply * reply){
// here you can do things with the reply
});
mgr->get(QNetworkRequest("....");
For a complete example, see this 300-line photographic mosaic generator that pulls random images from imgur. It extensively uses asynchronous, multithreaded processing and lambdas in the above style.