How to emit signals with an interval in Qt? - 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.)

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

QTimer timeout processing when Qt main event queue is blocked

What happens if I start a QTimer firing at regular intervals but the slot reacting to the timeout signal blocks the main loop for longer than another timer interval. Will the timout signals then be stacked on the Qt main event loop and processed one after another as soon as the event loop runs again?
If yes, what happens if multiple timeout events are stacked on the event queue but the timer is deactivated before they can be processed?
If QTimer object and the signal receiver belong to one thread, no queuing happens. timeout() signal will not (and cannot) be sent again until control flow goes to the event loop, and that won't happen until the slot is completely executed (unless QApplication::processEvents is called in the slot, which can turn this into a mess). But if your slot was being executed longer than the timer's interval, timeout() will be sent once the event loop is free, so your slot will be immedately called again. But QTimer will not send two timeout() signals closer than its interval.
If QTimer is in another thread, and that thread is not busy with something else, it will send timeout() signals regularly regardless of how well slot in another thread goes. This is where Qt's signal-slot system comes in. And it will queue emitted signals. If your slot is slow, it will call it multiple times without delay. If you stop the timer, it won't undo already sent signals and the slot may be called multiple times after it. Additionally, if you stop the timer, there is always a possibility that another signal is being sent just in this moment and your slot will be called once again.
If you want strict intervals between slot invocations regardless of the slot's executing time, you should use single-shot timers. At the end of your slot, start a single-shot timer. When it's timed out, it will invoke your slot and deactivate, so you can start it again at the end of the slot.
If your program's logic depends on the timer's state, you should check that the timer is active at the start of your slot. It's not guaranteed that the timer is active when the slot is being executed.

Using QNetworkAccessManager::authenticationRequired with own input widget / asynchronously

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)

When are slots processed in Qt?

I am developing a consequent program which is very sensitive to time (based on delayed video streams), and since I'm not sure about how the signals and slots are implemented within Qt, I don't know when they are executed. Are they really executed in real time like callbacks would do, or are they processed before the next iteration of some kind of main loop?
My question would be about timers in particular: when a timer times out (which must be another thread), does it connect to the signal "instantaneously" (next instruction for example) nearly like an interrupt would do, or does it wait for the end of some loop?
Thanks for your insight,
Regards,
Mister Mystère
The last argument of QObject::connect is the connection type, which determines when slot will be executed. From the documentation:
Qt::AutoConnection - If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as
Qt::QueuedConnection. Otherwise, the slot is invoked directly,
behaving as Qt::DirectConnection. The type of connection is determined
when the signal is emitted.
Qt::DirectConnection - The slot is invoked immediately, when the signal is emitted.
Qt::QueuedConnection - The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in
the receiver's thread.
Qt::BlockingQueuedConnection - Same as QueuedConnection, except the current thread blocks until the slot returns. This connection type
should only be used where the emitter and receiver are in different
threads.
http://woboq.com/blog/how-qt-signals-slots-work.html
This seems to be quite a good description, though I haven't read it in detail.
Main point: there's direct connections and deferred connections. Direct connections are executed immediately.
You can be quite sure the timer is not implemented in a different thread but instead is handled inside the event loop. Which means that when the timer fires, it is instantly connected. However the granularity for the timer to fire is your main problem.
If your timer were to emit the signal in a different thread, the slot would be called in the thread the receiving object belongs to. Which means that it would be deferred to the event loop. (As you can see it would not help to have the timer operate in a thread of its own.)
And additionally in Qt5 you can set QTimer's precision: Qt::TimerType

Set priority to events

I am making an application in QT. I use QExtSerialPort to receive data from the serial port of my comp (whenever the readyread() signal is emitted). I also have some timers running doing other stuff at certain intervals. Now I noticed that when the timers are turned on, not all the data of the readyread signal is emitted a lot less, then when the timers are not turned on. Is there a way in QT to make sure that all the data of the serial port is received? Maybe by setting a high priority to the readyread event or something like that?
There is difference between signal-slot connections and event system. Signal emitting and slot triggering are not separate things — when signal is emitted, connected slots begin to work. So they (signals) can't be lost.
All events are sent through application, and also are received, but it can happen later. When control returns to the main event loop, all events that are stored in the queue, will be processed.
If you are posting events yourself, you can use
static void QCoreApplication::postEvent ( QObject* receiver, QEvent* event, int priority ); method.
Events are sorted in descending priority order, i.e. events with a high priority are queued before events with a lower priority. The priority can be any integer value, i.e. between INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more details. Events with equal priority will be processed in the order posted.

Resources