Use signals and slots in console application? - c++

In my project, I need to download a 1.5MB file from a server. I was able to achieve this in my GUI application like this:
QNetworkAccessManager* m_NetworkMngr = new QNetworkAccessManager(this);
QNetworkReply *reply = m_NetworkMngr->get(QNetworkRequest(QUrl("someurl.com")));
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QUrl aUrl("someurl.com");
QFileInfo fileInfo=aUrl.path();
QFile file(aPathInClient+"\\"+fileInfo.fileName());//aPathInClient is predefined
file.open(QIODevice::WriteOnly);
file.write(reply->readAll());
delete reply;
I am getting the following error:
'connect' function does not take four arguments.
How can I modify the signals and slots to work in my console application?

My guess is that your code is correct with regards to establishing signal/slot connection, however compiler seems to be confused because of the connect() function name and cannot resolve it properly: whether it is QObject::connect() that takes at least 4 arguments, or it is another function with the same name, but different signature. I would suggest to try to explicitly tell compiler which function to use, i.e.:
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));

Related

Using QT events in the destructor of QApplication - hanging

I'm working with a QT GUI application which is having problems processing events during the QApplicaton destructor. A library I use (that I can't change) uses a QEventLoop. It has written some data to a socket and seems to be waiting for a response. The debugger shows that QEventDispatcherWin32::processEvents is looping and using up CPU.
I've managed to get it to work by deleting some particular widgets earlier on. However, this seems a bit random!
We are logging off our server when a widget is destroyed. Depending on what widgets are created, I sometimes get the hang and sometimes don't.
This is the exec call that hangs -
m_timedout = false;
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), this, SLOT(slt_timeout()));
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
timer.start(1800000);
connect(this, SIGNAL(sig_response(int, int, QByteArray)), &timer, SLOT(stop()));
connect(this, SIGNAL(sig_response(int, int, QByteArray)), &loop, SLOT(quit()));
loop.exec(QEventLoop::ExcludeUserInputEvents);
So what am I asking? I'm very new to QT and don't understand all the concepts but it sounds worrying to me that we are relying on QT event processing during the destructor of the application. Is that a valid thing to do? Won't QT have started to wind down?
Is there anything else that would cause that hang?

Qt: Program not responding despite separate thread

I have a program written with C++/Qt converting certain game files. This is the first time I've done something like this, so I'm not particularly experienced yet. I've had issues with the window occasionally showing the "Not responding..." message. After reading up on it, the problem seemed to be that the processing was done in the main thread, blocking the gui.
So I tried running a separate thread for the actual work being done, however the problem still occurs.
Here's the section creating the extra thread:
QThread* thread = new QThread;
WKConverter* converter = new WKConverter(settings);
converter->moveToThread(thread);
connect(converter, SIGNAL(log(std::string)), this, SLOT(log(std::string)));
connect(converter, SIGNAL(setInfo(std::string)), this, SLOT(setInfo(std::string)));
connect(converter, SIGNAL(createDialog(std::string)), this, SLOT(createDialog(std::string)));
connect(converter, SIGNAL(createDialog(std::string, std::string)), this, SLOT(createDialog(std::string, std::string)));
connect(converter, SIGNAL(createDialog(std::string, std::string, std::string)), this, SLOT(createDialog(std::string, std::string, std::string)));
connect(converter, SIGNAL(setProgress(int)), this, SLOT(setProgress(int)));
connect(converter, SIGNAL(increaseProgress(int)), this, SLOT(increaseProgress(int)));
connect(thread, SIGNAL(started()), converter, SLOT(run(bool)));
connect(converter, SIGNAL(finished()), thread, SLOT(quit()));
connect(converter, SIGNAL(finished()), converter, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
converter->run();
With signals/slots to push updates for a progress bar and a label indicating what's being worked on to the gui. Generally this works, but as said I still encounter the "Not responding..." issue (Though interestingly, this doesn't seem to happen if I'm debugging with Qt Creator, only when running the compiled exe afterwards)
Have I missed something? Is there something else I need to do? I would appreciate any pointers.
If it helps, here is the github for the project, though I have not pushed the work done on threading there yet: https://github.com/Jineapple/WololoKingdoms

Qt: connect a signal after a request is sent in QNetworkAccessManager [duplicate]

This question already has an answer here:
Qt signal slot connection - QNetworkAccessManager
(1 answer)
Closed 7 years ago.
I was checking some simple examples of using QNetworkAccessManager and I found this (Assuming that manager is a QNetworkAccessManager:
QNetworkRequest request;
request.setUrl(QUrl("http://www.someserver.com"));
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(slotSslErrors(QList<QSslError>)));
As far as I understand, the call to manager->get will send out a GET request. The slots to handle the answer to that request, however, are connected only after the call is sent, which does not seems to make sense for me. Here my question:
isn't it a problem to connect the slots to the signals after the request is done? Can it happen that the request is done and the signals are emitted before the connection takes place, and hence, that the signals are missed and never processed by the corresponding slots?
Thanks!
L.
UPDATE: As pointed out by cyber_raj, this question has been already answered here: Qt signal slot connection - QNetworkAccessManager
Not a problem.
The get call is asynchronous:
http://doc.qt.io/qt-5/qnetworkaccessmanager.html#details
QNetworkAccessManager queues the requests it receives, and runs 6 asynchronous tasks per time.
So there's no much room to an error as you point.
But if you're afraid you can try the first example, connecting the signals of the manager:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));

How do I process events on a QThread?

Normally if I am in a process intensive function I can call QCoreApplication::processEvents() or QEventLoop::processEvents() to ensure that my processing doesn't block other signals and slots.
However, if I create a new QThread and move a worker to that thread, then I don't have a QCoreApplication or a QEventLoop with which to call processEvents().
From my research, it seems that I should be able to install a QEventLoop on the new QThread I created, and then I can call processEvents() on that QEventLoop.
However, I can't figure out how to do this. I figure it might look something like this:
QThread *thread = new QThread(this);
Worker *worker = new Worker(this);
QEventLoop *loop = new QEventLoop();
connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(thread, SIGNAL(started()), worker, SLOT(startProcessing()));
connect(worker, SIGNAL(done()), thread, SLOT(quit()));
connect(worker, SIGNAL(done()), loop, SLOT(quit()));
worker->moveToThread(thread);
//loop->exec() // blocks processing of this thread
loop->moveToThread(thread);
//loop->exec() // loop is not a member of this thread anymore and even
// if it was, this would block the thread from starting
thread->start();
//loop->exec(); // loop is not a member of this thread anymore and even
// if it was, this would block this thread from continuing
Every place I try to start the loop has some sort of issue. But even if something like this worked, how would I call processEvents() on that QEventLoop()?
Alternatively, QThread also has a function setEventDispatcher() and QAbstractEventDispatcher has a processEvents() function, but I can't seem to find anything that subclasses QAbstractEventDispatcher.
What is the proper way to process events during an intensive worker function on a QThread?
According to the documentation, calling QCoreApplication::processEvents() processes events for whichever thread called it.
However, if I create a new QThread and move a worker to that thread, then I don't have a QCoreApplication or a QEventLoop with which to call processEvents().
Exactly - don't call it. You don't need it, you don't want it.

What is the parallelization mechanism in QNetworkAccessManager?

I am writing an HTTP access module for VLC 2.0 using QtNetwork from Qt 4.7.4. My code snips follow:
static int Open(vlc_object_t *p_this)
{
....
QNetworkAccessManager *nam = new QNetworkAccessManager;
QNetworkReply *reply = nam->get(QNetworkRequest("http://stackoverflow.com/"));
Q_ASSERT(reply);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit());
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit()));
loop.exec(); // -- BLOCKED HERE in Lion
....
}
The same code works well on Windows 7, but would get blocked on OS X Lion. The event loop after exec() never quit(). I also tried accessing reply->bytesAvailable() from another thread, which always returned 0. I guess the reason could be related to the parallel mechanism in QNetworkAccessManager, when nam couldn't get any time slots to work after the parent thread was blocked by QEventLoop.
Could anyone give me some suggestions why event loop would get blocked only on Mac, and what I could do to bypass such issue to make QNetworkAccessManager to work without creating another QThread?
BTW, the Qt being used is the latest version on macports built with Carbon framework (qt4-mac).
You may have to make periodic calls to QApplication::processEvents() to get the job done.