PDA

View Full Version : Ctrl-C interception



T_h_e_o
25th April 2012, 15:45
I presume this is a newbie question, but hey, this is the newbie forum, right?

I have a console application with two threads: a worker thread and a communication thread (communicates over a tcp socket). The program works fine, but if I press ctrl-c, it exits quite raw. What I want is that the worker thread intercepts the ctrl-c and instructs the commthread to send a final message, and then gracefully stop instead of exiting roughly (in the current situation I do not really see how the program flow is going when exiting).
How do I ensure that the worker thread intercepts the ctrl-c and not the commthread? And how do I intercept the ctrl-C at all?

I tried this:

bool MyApp::event(QEvent *evt)
{

if (evt->type() == QEvent::KeyPress)
{

// check for ctrl-c and if so, handle it and return true
}
return QObject::event(evt);

}

However it appears that I do not receive any keypress events at all, no matter what I hit on the keyboard...


Note: I know about the signal aboutToQuit, but I want to make sure that QCoreApplication::exec() returns normally so that anything following that is executed.

wysota
25th April 2012, 17:02
You need to use the signal() call with SIGINT.

T_h_e_o
26th April 2012, 07:37
You need to use the signal() call with SIGINT.

I figured that in the mean time, but thanks anyway. It works.
But I'm still stuck with the question: suppose I would want to stop the program if I hit a specific key, not ctrl-C. How do I do that? Polling std::cin from the main loop is ugly. There must be a way to intercept keypress events, right? I tried this:



bool MyApp::eventFilter(QObject *obj, QEvent *evt)
{
if (evt->type() == QEvent::keyPress)
{
if ( /* correct key pressed */ )
{
QCoreApplication::quit();
return true;
}
}
return QObject::eventFilter(obj, evt);
}


bool MyApp::event(QEvent *evt)
{
if (evt->type() == QEvent::keyPress)
{
if ( /* correct key pressed */ )
{
QCoreApplication::quit();
return true;
}
}
return QObject::event(evt);
}

The class MyApp is derived from QCoreApplication. I tried to call installEventFilter(this) in its constructor (seems a bit weird to install itself as filter but I tried it anyway), but neither of the two listed methods is ever called with a keypress event, whether or not I call installEventFilter.

So what am I doing wrong?

T_h_e_o
3rd May 2012, 20:21
Nobody?
Please, I would really like to know how I can intercept keystrokes!

wysota
4th May 2012, 08:23
For a key event to be delivered you need to have an active widget that accepts focus. Then this key event is delivered to that widget and will be intercepted by the global event filter.

yeye_olive
4th May 2012, 09:01
If you need a platform-independent way of solving your problem, you might need something like ncurses. If you are targeting POSIX-compliant systems, you may use QSocketNotifier to monitor input on stdin. This is a bit primitive, but it should work. For anything fancy I would recommend looking into ncurses (although I have never used it myself).

T_h_e_o
7th May 2012, 13:24
For a key event to be delivered you need to have an active widget that accepts focus. Then this key event is delivered to that widget and will be intercepted by the global event filter.

Wysota, the application is a console app. There is no widget. Is it in this case impossible to intercept keystrokes with eventFilter?


If you need a platform-independent way of solving your problem, you might need something like ncurses. If you are targeting POSIX-compliant systems, you may use QSocketNotifier to monitor input on stdin. This is a bit primitive, but it should work. For anything fancy I would recommend looking into ncurses (although I have never used it myself).

I'd rather not include another lib, but I will have look at QSocketNotifier to see if I understand how to use it to catch keystrokes. Whether it works or not: thanks for the suggestion!

wysota
7th May 2012, 15:25
Wysota, the application is a console app. There is no widget.
Exactly. Thus you will not get any key events. You can use QSocketNotifier on STDIN to get line-buffered input notifications.

T_h_e_o
15th May 2012, 20:20
Exactly. Thus you will not get any key events. You can use QSocketNotifier on STDIN to get line-buffered input notifications.

Aha, now I understand the earlier reply from yeye_olive. I don't know the class QSocketNotifier, but I'll look things up (when I have time: I'm too busy to spend much time on this - it's a hobby project, but work prevails!).

Thanks for the tip!