Using QNetworkAccessManager::authenticationRequired with own input widget / asynchronously - qt

I'm currently developing a browser with Qt which has a vim-like input bar:
This is basically just a QHBoxLayout with a QLineEdit and some QLabels in it.
Now I'd like to handle HTTP authentication. The usual thing I see in other projects is opening a modal QDialog and then calling exec() on it inside the slot connected to the authenticationRequired signal.
Now I'd like to use the same statusbar to ask the user for authentication information, i.e. displaying some prompt and then using the QLineEdit to enter the information.
My problem is the authenticationRequired slot blocks, I can't simply continue to run in the mainloop and continue the request with authentication information added when the user is done.
I've thought about two solutions:
Implementing some function which gets the values from the statusbar while calling QCoreApplication::processEvents while there's no reply from the user yet. However I'm not sure if that's a good idea, and if the application will hog a lot of CPU until I'm back to the real eventloop.
Somehow saving and aborting the request, asking the user for authentication, and then re-creating the request as soon as the authentication information is added. But it seems I can't simply clone a QNetworkReply and then call abort() on the original reply and resume it later.
Looking at how QDialog::exec() is implemented it seems they create a new QEventLoop with an undocumented value of QEventLoop::DialogExec passed. I wonder if I could do the same, but then I'm not sure how I'd quit the event loop once the user input is there.
Which of these ideas sounds like the most sane one?

You can just use a QEventLoop without any special undocumented values. Instead you'll have something like:
QEventLoop loop;
connect(editBox, SIGNAL(finishedEditing()), &loop, SLOT(quit()));
loop.exec();
And that will start a new event loop that blocks, waiting for your input (without hogging as much cpu as processEvents)

Related

QTcpSocket readyRead() signal emits multiple times

I'm new to Qt and currently learning to code with QTcpServer and QTcpSocket.
My code to process data is like
Myclass()
{
connect(&socket, &QTcpSocket::readyRead, this, &MyClass::processData);
}
void MyClass::processData()
{
/* Process the data which may be time-consuming */
}
Is it the correct way to use the signal like that? As I'm reading the documentation that in the same thread the slot is invoked immediately, which means if my processing work hasn't finished and new data comes, Qt will pause on the current work and enter the processData() again. That is not exactly what I want to do, So should I QueueConnection in the signal/slot connection?
Or could you please provide some good methods that I should adopt in this case?
Qt will not pause your current work when data comes in, it will call processData() only when the event loop is free and waiting for new events.
so, when your application is busy executing your code, the application will appear to be unresponsive, because it can't respond to external events, so processData() won't get called if some data is received on the socket until the current function (that may contain your heavy code) returns, and the control is back in the event loop, that has to process the queued events (these events may contain the received data on the socket, or the user clicks on some QPushButton, etc) .
in short, that's why you always have to make your code as short and optimized as possible, in order not to block the event loop for a long time.
With the event delivery stuck, widgets won't update themselves (QPaintEvent objects will sit in the queue), no further interaction with widgets is possible (for the same reason), timers won't fire and networking communications will slow down and stop. Moreover, many window managers will detect that your application is not handling events any more and tell the user that your application isn't responding. That's why is so important to quickly react to events and return to the event loop as soon as possible!
see https://wiki.qt.io/Threads_Events_QObjects

How to emit signals with an interval in Qt?

I'm writing a simple port communication program. On the GUI side of the application I have a panel with 12 buttons that send signals to the parallel port interface. The communication with the port is done and working. What I need now is an automatic switching between buttons. The goal is to start kind of screensaver that will periodically activate the buttons and send signals to the port. In practice it would look like this: a timer is started for 2 minutes and if any event occurs it is restarted. Otherwise if timer reaches timeout() the qt signal is emitted, the switching begins and the buttons are automatically click()'ed with the interval of 5 seconds.
My questions are:
How to enable a starting timer that will be reseted if any key/mouse event occurs?
How to define a transition between the buttons with a sleep interval?
Use QTimer for the timing part.
For the "screen-saver"-like one, create a single-shot timer, connect it to a custom slot of yours, and set it's interval to two minutes.
activeTimer = new QTimer(this);
activeTimer->setInterval(2*60*1000);
activeTimer->setSingleShot(true);
connect(activeTimer, SIGNAL(timeout()), this, SLOT(activateAutoClick()));
activeTimer->start();
In that custom slot, start a second, non-single shot timer connected to a second custom slot
void YourThing::activateAutoClick() {
autoTimer->setInterval(5*1000);
autoTimer->setSingleShot(false);
connect(autoTimer, SIGNAL(timeout()), this, SLOT(autoClick()));
autoTimer->start();
}
And do whatever you want in terms of sending signals to your port in autoClick.
To cancel either timer, simply call their stop() method/slot.
To implement the "screen-saver" behavior, create a function that:
Calls autoTimer->stop() to disable auto clicks
Calls activeTimerr->start(2*60*1000) to restart that one
And call that function whenever needed. You can do that from already existing slots for your buttons, or reimplement event handlers like QWidget's mouseMoveEvent, keyPressedEvent and such. (Be sure to read the documentation for the handlers, some require specific preparation.)

Qt: setting an override cursor from a non-GUI thread

A while ago I wrote a little RAII class to wrap the setOverrideCursor() and restoreOverrideCursor() methods on QApplication. Constructing this class would set the cursor and the destructor would restore it. Since the override cursor is a stack, this worked quite well, as in:
{
CursorSentry sentry;
// code that takes some time to process
}
Later on, I found that in some cases, the processing code would sometimes take a perceptible time to process (say more than half a second) and other times it would be near instantaneous (because of caching). It is difficult to determine before hand which case will happen, so it still always sets the wait cursor by making a CursorSentry object. But this could cause an unpleasant "flicker" where the cursor would quickly turn from the wait cursor to the normal cursor.
So I thought I'd be smart and I added a separate thread to manage the cursor override. Now, when a CursorSentry is made, it puts in a request to the cursor thread to go to the wait state. When it is destroyed it tells the thread to return to the normal state. If the CursorSentry lives longer than some amount of time (50 milliseconds), then the cursor change is processed and the override cursor is set. Otherwise, the change request is discarded.
The problem is, the cursor thread can't technically change the cursor because it's not the GUI thread. In most cases, it does happen to work, but sometimes, if I'm really unlucky, the call to change the cursor happens when the GUI thread gets mixed in with some other X11 calls, and the whole application gets deadlocked. This usually only happens if the GUI thread finishes processing at nearly the exact moment the cursor thread decides to set the override cursor.
So, does anyone know of a safe way to set the override cursor from a non-GUI thread. Keep in mind that most of the time, the GUI thread is going to be busy processing stuff (that's why the wait cursor is needed after all), so I can't just put an event into the GUI thread queue, because it won't be processed until its too late. Also, it is impractical to move the processing I'm talking about to a separate thread, because this is happening during a paint event and it needs to do GUI work when its done (figuring out what to draw).
Any other ideas for adding a delay to setting the override cursor would be good, too.
I don't think there is any other way besides a Signal-Slot connection going to the GUI thread followed by a qApp->processEvents() call, but like you said, this would probably not work well when the GUI thread is tied up.
The documentation for QCoreApplication::processEvents also has some recommended usages with long event processing:
This function overloads processEvents(). Processes pending events for
the calling thread for maxtime milliseconds or until there are no more
events to process, whichever is shorter.
You can call this function
occasionally when you program is busy doing a long operation (e.g.
copying a file).
Calling this function processes events only for the
calling thread.
If possible break up the long calls in the paint event and have it periodically check to see how long it has been taking. And in any of those checks, have it set the override cursor then from in the GUI Thread.
Often a QProgressBar can go a long way to convey the same information to the user.
Another option that could help quite a bit would be to render outside of the GUI thread onto a QImage buffer and then post it to the GUI when it is done.

How delete and deleteLater works with regards to signals and slots in Qt?

There is an object of class QNetworkReply. There is a slot (in some other object) connected to its finished() signal. Signals are synchronous (the default ones). There is only one thread.
At some moment of time I want to get rid of both of the objects. No more signals or anything from them. I want them gone.
Well, I thought, I'll use
delete obj1; delete obj2;
But can I really?
The specs for ~QObject say:
Deleting a QObject while pending events are waiting to be delivered can cause a crash.
What are the 'pending events'?
Could that mean that while I'm calling my delete, there are already some 'pending events' to be delivered and that they may cause a crash and I cannot really check if there are any?
So let's say I call:
obj1->deleteLater(); obj2->deleteLater();
To be safe.
But, am I really safe? The deleteLater adds an event that will be handled in the main loop when control gets there. Can there be some pending events (signals) for obj1 or obj2 already there, waiting to be handled in the main loop before deleteLater will be handled? That would be very unfortunate. I don't want to write code checking for 'somewhat deleted' status and ignoring the incoming signal in all of my slots.
Deleting QObjects is usually safe (i.e. in normal practice; there might be pathological cases I am not aware of atm), if you follow two basic rules:
Never delete an object in a slot or method that is called directly or indirectly by a (synchronous, connection type "direct") signal from the object to be deleted.
E.g. if you have a class Operation with a signal Operation::finished() and a slot Manager::operationFinished(), you don't want delete the operation object that emitted the signal in that slot. The method emitting the finished() signal might continue accessing "this" after the emit (e.g. accessing a member), and then operate on an invalid "this" pointer.
Likewise, never delete an object in code that is called synchronously from the object's event handler. E.g. don't delete a SomeWidget in its SomeWidget::fooEvent() or in methods/slots you call from there. The event system will continue operating on the already deleted object -> Crash.
Both can be tricky to track down, as the backtraces usually look strange (Like crash while accessing a POD member variable), especially when you have complicated signal/slot chains where a deletion might occur several steps down originally initiated by a signal or event from the object that is deleted.
Such cases are the most common use case for deleteLater(). It makes sure that the current event can be completed before the control returns to the event loop, which then deletes the object. Another, I find often better way is defer the whole action by using a queued connection/QMetaObject::invokeMethod( ..., Qt::QueuedConnection ).
The next two lines of your referred docs says the answer.
From ~QObject,
Deleting a QObject while pending events are waiting to be delivered can cause a crash. You must not delete the QObject directly if it exists in a different thread than the one currently executing. Use deleteLater() instead, which will cause the event loop to delete the object after all pending events have been delivered to it.
It specifically says us to not to delete from other threads. Since you have a single threaded application, it is safe to delete QObject.
Else, if you have to delete it in a multi-threaded environment, use deleteLater() which will delete your QObject once the processing of all the events have been done.
You can find answer to your question reading about one of the Delta Object Rules which states this:
Signal Safe (SS).
It must be safe to
call methods on the object, including
the destructor, from within a slot
being called by one of its signals.
Fragment:
At its core, QObject supports being
deleted while signaling. In order to
take advantage of it you just have to
be sure your object does not try to
access any of its own members after
being deleted. However, most Qt
objects are not written this way, and
there is no requirement for them to be
either. For this reason, it is
recommended that you always call
deleteLater() if you need to delete an
object during one of its signals,
because odds are that ‘delete’ will
just crash the application.
Unfortunately, it is not always clear
when you should use ‘delete’ vs
deleteLater(). That is, it is not
always obvious that a code path has a
signal source. Often, you might have a
block of code that uses ‘delete’ on
some objects that is safe today, but
at some point in the future this same
block of code ends up getting invoked
from a signal source and now suddenly
your application is crashing. The only
general solution to this problem is to
use deleteLater() all the time, even
if at a glance it seems unnecessary.
Generally I regard Delta Object Rules as obligatory read for every Qt developer. It's excellent reading material.
As far as I know, this is mainly an issue if the objects exist in different threads. Or maybe while you are actually processing the signals.
Otherwise deleting a QObject will first disconnect all signals and slots and remove all pending events. As a call to disconnect() would do.

QNetworkAccessManager handling asynchronous thread

I am new to QT. I have created object class QNetworkAccessManager main window as parent. Also registered to SIGNAL finished. It is working fine.
But I want to know in which thread it will run. Will it block the main thread. If i need to perform sequence of get operation how should I need to write the code.
Please give me some sample to understand concept properly.
It certainly does not run in the main thread, the calls to get() are asynchronous.
For example this would keep firing get requests:
while (condition) {
QNetworkRequest request;
request.setUrl(QUrl(m_ServerURL);
m_httpGetUpdatedFile->get(request);
}
You then have the slot for the finished signal which is processing the QNetworkReply. That slot basically should be getting called for each get request you make (even if it fails). If you need to keep track of when all your get requests have finished, you need to keep a track of how many you posted and then have your own finished flag or signal.
QNAM does use threads in the background, but this is completely invisible for your application code. Everything you see will run in the main thread.
QNAM works in the usual Qt way, it will emit signals when things happen, and you connect these signals to slots in your own code, which do things as much as they can. If they don't for example have enough data, then your slots must not block to wait for new data, instead they must return. And then they will be called again when/if there's more data (or you'll get another signal if for example connection was terminated).
Some links, in case you have not read these:
Qt signal & slot documentation
Qt networking documentation

Resources