PDA

View Full Version : Handling specific events only in the main loop



Patje
1st April 2011, 12:10
In my code I want to know at which event loop level I currently am. This is because I only want to perform some actions while I am in the main event loop, not when I'm in the event loop of a modal dialog (or in another event loop, or in a platform-specific modal popup/dialog).

The main reason I want this is because of the following:
My users can configure the application to execute certain procedures at regular intervals. These procedures could contain any functionality offered by the application (could be simple things like checking a file, or could be quite complex like saving to database or loading new data from database). I implemented this functionality by using a timer. The problem is that if any action (manually started by the application) shows a modal dialog on screen, the timers also go off, and the automatic procedure is executed while there is already an action running. These actions could be any action executed by the user (so not only these automatic procedures), and could be started via the menu, by clicking, by dragging, by any possible means offered by the application.

In my previoius windowing environment I could solve this by checking the 'depth' of the event loop, and only executing the automatic procedures in the timer if the depth was 1.

I have another application that's using only MFC and there I can solve these kind of problems using the WM_KICKIDLE event (which only goes off in MFC's main event loop).

According to some other posts and the documentation, I could use a timer with interval 0 to emulate these idle events, but they still come in while a modal dialog is open.

Things I tried so far:
- timers with zero interval, one-shot-timers: they also go off while a modal dialog is open
- postEvent: posted events are also delivered if a modal dialog is open
- checking QEvent::WindowBlocked/WindowUnblocked to see if a modal dialog is current open: this works for modal dialogs created by Qt, but does not help if the modal dialog is a non-Qt one (e.g. Windows' MessageBox, or a 3rd party modal dialog).
- using QCoreApplication::loopLevel: this only seems to supported on Qt3, and I don't want to use old Qt3 logic. The documentation also doesn't indicate which Qt4 functionality replaces this Qt3 functionality.
- QApplication::hasPendingEvents: also returns false if a modal dialog is open
- QWidget::isEnabled: if a modal dialog is open, the main window remains enabled
- QAbstractEventDispatcher::aboutToBlock/awake and keeping a counter: these methods don't seem to be called in pairs, which causes by counter to get the strangiest values

The last [dirty] trick that I see is to check the address of a stack variable, to determine whether we are 'deep' on the call stack or not. However, I would only use this if there is no decent solution possible.

Notice that almost all of the logic is currently executed in the main thread. Refactoring the application so that all logic is executed in a separate worker thread is currently impossible.

Anyone suggestions?

wysota
1st April 2011, 14:24
I would approach the problem from the other end - instead of trying to control the event loop, try to control the dialogs you pop up. Have some kind of registration mechanism where you register the handlers that will be called sequentially by your mechanism. Then you'll be sure that only one such dialog is active at all times. You could then block and unblock the mechanism when entering a piece of code that you wouldn't like to disrupt with such dialogs.