Rekall version 2.0.3 introduces the idea of persistent objects. Prior to this version, when an event function is executed, Rekall creates the python object which represents the Rekall object (that is, the first argument to the event function) immediately before the event function is called, and destroys it when the event function returns.
However, from Rekall 2.0.3, the python object is created the first time an event function for the Rekall object is called (not quite true, its better than this, so read on), and does not destroy it on return. This means that it is possible to preserve state information in the python object. For instance, here is an event function which can be associated with a button's OnClick event function, which displays how many times the button has been clicked:
def eventFunc (button) : try : button.count = button.count + 1 except : button.count = 1 RekallMain.messageBox(`button.count`) |
The count of clicks is maintained in button.count, and is incremented in each click. The trickery with the try ... except exceptions handler is needed since the first time the event is triggered, button.count does not exist - so we initialise it to one.
Here is a slightly more useful example. Suppose that the very first time a form retrieves data from the database, we only want records where a field named name contains the string Mike. The following code is associated with the block's PreQuery event:
def eventFunc (block) : try : block.flag except : block.getNamedCtrl('name').setValue(0,'Mike') block.flag = 1 |
The first time the function is executed, block.flag will not exist, so an exception is raised when the code on the third line tries to access it. The exception is trapped, the name field is set to Mike, and block.flag is set. On subsequent calls, block.flag exists, there is no exception, and the name field is left unchanged.
This becomes much more useful if we replace 'Mike' with '${initial_name}'. This is a parameter substitution - see the chapter on executing forms and reports with paramaters - but in essense an initial search value can be passed as a paramater when the form is opened. This could be worthwhile if the table has, say, 100000 records, and you want to allow the user to enter some initial search criteria, rather than have to wait until the 100000 records load.
Actually, the python object is created the first time the Rekall object is referenced in a script. Usually this will be as the first argument to an event function, but it can also be as a result of the getNamedCtrl method. Suppose you have two buttons, named buttonA and buttonB, and you want the event function for buttonB to be able to tell if buttonA has already been clicked. In this case, the OnClick event function for buttonA could be:
def eventFunc (button) : button.getNamedCtrl('../buttonB').clickedA = 1 |
Then the OnClick event function for buttonB might resemble the code below; here we again use the try ... except trick to trap the case where the flag variable clickedA has not been set.
def eventFunc (button) : try : clickedA RekallMain.messageBox('Button A clicked!!') except : pass |
Finally, all persistent python objects are destroyed when you close the form, or if you switch between data and design mode.