2
votes

I am currently working on an application that launches separate processes which display additional dialogs. The feature I am trying to implement is simulating modal behavior of these dialogs. More specifically, I need the application to stop processing all input, both mouse and keyboard, when the dialog is launched, and resume when it's closed.

It is not so important for the dialog to remain on top of the application, although if you can suggest how to do that without resorting to Always-On-Top behavior, that would be nice as well.

To note, the application is compiled under both Windows and Linux. Also, it is not an option to launch the dialogs directly. They are in separate executables. Also the application is a pretty complex piece of software, so disabling widgets individually is not an option, or at least a not very viable one.

I found lock() and unlock() functions in QApplication class in Qt 3.3. We are currently using Qt 4.5, which doesn't seem to have that API. As a matter of fact, Qt 4.5 QApplication class doesn't seem to provide access to the Event Loop either.

To summarize: How do I disable/enable user input in a Qt Application, both mouse and keyboard shortcuts?

3

3 Answers

5
votes

gj already proposed this solution but I thought I'd paste my implementation just for reference:

Implement a filter class that will absorb user input actions.

class BusyAppFilter : public QObject
{
protected:
    bool eventFilter( QObject *obj, QEvent *event );
};


bool BusyAppFilter::eventFilter(QObject *obj, QEvent *event)
{
    switch ( event->type() )
    {
    case QEvent::KeyPress:
    case QEvent::KeyRelease:
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonDblClick:
    case QEvent::MouseMove:
    case QEvent::HoverEnter:
    case QEvent::HoverLeave:
    case QEvent::HoverMove:
    case QEvent::DragEnter:
    case QEvent::DragLeave:
    case QEvent::DragMove:
    case QEvent::Drop:
        return true;
    default:
        return QObject::eventFilter( obj, event );
    }
}

Then place this code your QApplication class:

QCursor busyCursor( Qt::WaitCursor );
setOverrideCursor( busyCursor );

BusyAppFilter filter;
installEventFilter( &filter ) ;

//... do the process stuff ...

removeEventFilter( &filter );

restoreOverrideCursor();
4
votes

To get full access to the application wide events, use QObject::installEventFilter() or QCoreApplication::setEventFilter() on your application object.
If your filter function returns true, Qt stops further processing of the event.

To not get too platform specific with the forwarding of the events to your other applications, i'd go for a suitable IPC mechanism.

1
votes

As an alternative answer, you can create your own event loop and start running it if necessary. You would need to create a QEventLoop object, connect a signal from another process to its quit() slot (such as from a QProcess that you are running your other program in), then exec() the loop. If I read things correctly, nothing will be handled by your main event loop while that loop is running.