[ This was previously posted to qtforum.org ]

We are currently developing a somewhat large Qt application. One of our requirements is to include a facility for recording each user action. For example, there should be a log entry for each time the user presses a button, or edits the text in a line edit, or moves a slider. These log records should have a time stamp indicating when the user action took place.

Given that this application has a lot of displays, we looked into some way of automating the process of creating this log. To do this, we created recorder classes that exist solely to record the user actions of its parent widget. For example, we created a push button recorder class whose instances are children of push buttons. When the push button recorder is created, it connects a slot to its parent's clicked() signal. When the parent button is clicked, the push button recorder creates the corresponding user action record. We created similar classes for recording line edit widgets, sliders, combo boxes, and other widgets.

We then created and an event filter and installed it on the application object. This event filter does not filter any events; we use this filter to process Polish events. When a widget is polished, we look at its class (using the qobject_cast template) and create a corresponding recording object if possible.

This worked well in some aspects. By writing a moderate amount of centralized code, we were able to record user actions for everything in our application, including actions in predefined dialogs such as instances of QMessageBox and QWizard. But we found a serious problem with this scheme: the actions are sometimes recorded out of order with incorrect time stamps.

To explain why this is so, imagine that we have a form with a push button labeled "Build Rome". When the user presses the "Build Rome" button, a complex wizard appears so that the user can enter parameters for the city of Rome. The "Build Rome" button's clicked() signal will have two slots connected to it:

- The push button recorder slot for recording the button clicks; and
- The slot used for the button action, i.e. presenting the city of Rome parameters wizard.

As the QT documentation indicates, when a signal is emitted, the order in which the connected signals and slots are called is not guaranteed. Assume the user clicks the "Build Rome" button. The two slots listed above will be called in some order. If the push button recorder slot is called first, then the user action log looks OK. But what happens if the slot that presents the city of Rome parameters wizard is called first? Then the log will record the user actions on the wizard dialog before it records the "Build Rome" button click! Moreover, the time stamp for the "Build Rome" button click will actually be the time when the other slot returns, which can be considerably later than when the user clicked the button.

Can this approach be salvaged? If not, is there another approach to creating a log of the user actions? One cannot help but think that we are not the first developers who needed to do something like this.