Forms are listed under the Forms tab. Here you will see a subtree for each server database plus, as usual, the !Files entry. As noted earlier, Rekall allows you to store forms either in a server database (inside the __RekallObjects table), or in the file system. Entries for each appear in the appropriate subtree. The subtree also has a Create new form entry which can be double-clicked to create a new form.
One thing to remember is to be consistent. Rekall has the ability to open one form from another (typically when a button is clicked), and also to execute reports and copiers from a form, but currently the object which is to be opened must be in the same place as the form from which it is opened (ie., both must be in the same directory in the file system, or in the same server database.)
Rekall has a basic form creation which can be accessed via the Create new form using wizard item in the list of forms. You can use this wizard create a form; it will prompt you to specify where the data comes from in the database, how to lay it out, and so forth. Alernatively, you can create a form manually, or you can use the wizard and then customise the form to your exact needs. Which you choose is really a matter of personal preference and what you need from the form.
This section describes the creation of the Clients form from the Orders demonstration database. If you are happy to use the wizard you can skip this section, but you should return to it when your needs exceed the capabilities of the wizard, or you want to further modify a form.
Creating a New Form: The Form DialogDouble-clicking the appropriate Create new form item will first bring up a brief wizard to obtain a couple of important pieces of information. Note that is is not the form design wizard allueded to above.
This wizard asks for two pieces of information. The first, shown in the screenshot above, asks where the form should get data from. The description below applies to a table block, which gets data directly from a table in the database; the other possibilities, which are described later are a query block (which uses a Rekall-level query), an SQL block (which allows a query to be entered as free text or a menu block (which doesn't actually retrieve any data, and is used to design forms which are, typically, simple menus).
The second specifies the type of geometry management to be used. This section describes static geometry where, essentially, controls are positioned at specifix (x,y) coordinates and have specified sizes. This form of geometry management was the only form available prior to Rekall 2.3.x. The alternative is dynamic management. This is described later, but allows controls (and the forms that they are embedded in) to resize and to adjust their positions depending on things like the user's choice of font size.
The next dialog to appear is the form properties dialog. Property dialogs for Rekall objects - forms, and so forth - have the same structure. Properties are roughly grouped by type, and are organised by that type. The types are display, which covers display properties such as position and font; data which covers data related properties such as table columns and format; events which relate to scripting (see later in this manual); and other for anything which does the fit the above! If you want, you can expand the all branch and see all the properties at once.
To edit a property, expand the appropriate branch (you'll soon get used to which property is where!), and double-click the property name (the left-hand column); this will replace the right-hand column with a dialog area appropriate to the property being edited (you can also single-click a property and then click the Edit button). You can accept changes to a property with the Accept button, or ignore them with Ignore; however, until you click OK, no changes are made to the form (so Cancel cancels any individual property changes ( Also, the form as a whole is not actually saved in the server database or file system until you explicitely save it. ) .
Depending on which property is being edited, the Clear or Verify buttons may be enabled. The former is used to clear the property to its default state (that is, the state it was in when the object was first created). The latter is used when appropriate to check that a property is valid, for instance to check that some python script compiles correctly, or that a validation expression is itself a valid regular expression. In addition, Rekall will make what checks it can to make sure that properties are only set to sensible values. Lastly, when running KDE versions of Rekall the Help button may be enabled; when it is, clicking it will bring up a context help popup (note that this popup is not a modal dialog, so you do not need to close it to return to the properties dialog).
The screenshot below shows the property dialog part of the way through setting various properties; the table which follows lists the properties, their significance and their values. This dialog essentially asks about properties of the form itself. For brevity, properties which are not relevant here and are left blank are not listed.
Property | Significance | Setting |
Scripting language | Scripting language used in the form. This should always be py for python. | py |
Caption | Caption for form title bar. | Clients |
Top-level block type | Forms are constructed of nested blocks; this is the type of the top-level block. This is explained in more detail later. | table |
Modal | Execute the form modally, in the same way as a modal dialog. See below. | table |
The property dialogs for all objects will show a Notes setting. This is ignored by Rekall but can be used for arbitrary notes, for instance for documentation.
If the modal property is set, then the form will be executed modally, like a modal dialog; that is, once opened, the user can only do things in the form, and not in any window which was already open. This is useful, for instance, if you want to make sure that the user cannot make changes in other forms while this form is open. Note, however, that changing the modal setting does not take effect until the form is closed and reopened,
Making a form execute modally is particularly useful when using tkcRekall. On the Sharp Zaurus the Qtopia environment does not handle applications which open multiple windows very well. If you execute a form which is not modal, then switch to another application and back, you will find that the form is no longer visible, and is now "behind" Rekall's main database window. It can be returned to the top using the View/Show Window menu, but this is inconvenient at best.
If you visit the View/Options menu item on the main database window, and select the Modal tab, there are settings to create new forms with the modal setting initially on. This option is disabled by default on the desktop versions of Rekall, but is enabled by default for tkcRekall.
There is one further caveat. Later, the manual explains how you can open one form from another (typically by clicking a button). Suppose you have two forms, A and B, and that form B can be opened by clicking a button on form A. Then, if A is modal, then B should be modal as well. If not, then form B will open, but will be immediately placed behind form A, and will not be accessible!
Creating a New Form: The Query DialogOn clicking OK, a second similar dialog appears. This requests information about where the form should fetch its data from, in this case which table.
Property | Significance | Setting |
Server name | Name of the server database which contains the table. | Self (see below) |
Table name | Name of the table in the server database. | ClientID |
Unique key | Name of a table column which provides a unique key. This is preferrably the primary key column; the Auto setting will ask Rekall to work this out itself. | Auto |
Row order | SQL expression giving the order in which the generated query will return rows. later. | Company, Contact |
Where condition | Expression which is valid as the where part of an SQL select query. See below. | ${Filter} |
Setting the Server Name field to Self is interpreted to mean that the server database to be used is the same server database as the form is stored in (if the form is stored in the file system then for this to work the !Files entry in the server dialog must identify a server database. This setting is useful, since it means that you can copy the form to another server database, and provided that the second server database has compatible tables, etc., the form will work unchanged ( Self will appear in a number of places when using Rekall. Typically, there will be a list which includes each server database that you have defined, plus a !Files entry when !Files has a server database associated with it. Unless you really want a form which is stored in one server database to access a table in another server database, then Self is the option of choice. ) .
The next image shows the dialog when the Unique Key property is being edited. The Auto setting is usually OK, but sometimes you might need to force Rekall to do something special. This is probably the most complicated setting, and it is complicated because Rekall is designed firstly to work with as wide a range of server databases as possible, and secondly to work as well as possible with server databases that already exists (ie., not just ones that have been set up using Rekall). If you are not sure about this section, then selecting the Auto option is the best course, and you can skip on to the next section.
The upper combobox (showing Any unique column in the image) is used to select the sort of column that is of interest, where the options are listed below. Below this may appear a second combo box.
Auto | If this option is chosen, Rekall will select what it sees as the best column to use, either a primary key column or a unqiue column. |
Primary Key | In this case Rekall will only allow a primary key column to be used. A second combobox will appear containing just the primary key column, if any. When the form is run, Rekall will verify that the column is a primary key. |
Unique key | In this case, Rekall allows any unique column to be used. A second combobox will show all unique columns in the table, and will include the primary key column if any. When the form is run, Rekall will verify that the column is indeed unique. |
Any single column | Choosing this option will display a second combobox which shows all columns in the table. Rekall will then assume that the selected column is unique, whether or not it appears to be so in the database. It will also assume that an inserted or updated value is not changed by any server database triggers. |
Pre-expression | Use an SQL select expression to generate a key value. |
Post-expression | Use an SQL select expression to retrieve key value. |
The any single column setting is useful if you know that a particular column will always be unique. However, be warned that Rekall will use the value from this column when updating or deleting rows in the table; if the column turns out not to be unique then unexpected results may occur ( For instance, suppose you tell Rekall that column ClientCode in table ClientTable is unique, and then in a form you delete a row that has UNKNOWN as the value of the ClientCode column. To do this, Rekall will execute the SQL query delete from ClientTable where ClientCode = 'UNKNOWN'. This will delete as many rows as match, which might not just be the row you intended! ) .
The pre-expression setting allows you to specify an arbitrary SQL select query which Rekall will use to generate a key value, which is then used in an insert query. The select should return a single row containing a single column. This setting is useful if, for instance, you need to retrieve a key value from a sequence.
The post-expression setting is similar, except that the expression is evaluated after an insert and should return the key value. This can be used when inserting through a view where a database rule generates the key. For instance, using PostgreSQL with the rule defined below (which traps inserts into the view v_NoPKey_insert to insert into the underlying table NoPKey), the post-expression would be select currval('NoPKey_Seq').
create rule "v_NoPKey_insert" as on insert to "v_NoPKey" do instead insert into "NoPKey" (i, t) values (nextval('NoPKey_Seq'), new.t) |
Note: For any database designed prior to release 1.1.0-beta3, the specified unique column will be used with the same behaviour as in earlier releases. It will be used as specified if it provides sufficient information that rows can be inserted, updated and deleted. If not, then Rekall will use the Auto mode and choose the best column.
The value of the Where condition which has been set to ${Filter} is clearly not valid as part of an SQL select query! This is shown here since it as an example of a parameterized property, such as are used in several places of the demonstration Orders database. Briefly, when a form (or report) is executed, any properties that contain text of the form ${name} have that text replaced with the value of the paramater name, if it is defined. In this example, it gives a way of executing the form with a filter to select only clients that match some criteria. The whole area of paramaters will be returned to later in the manual.
Creating a New Form: The Block DialogThe third and final dialog requests information about the the way data is displayed and handled; this is the block dialog. Briefly, forms are constructed of nested blocks, where each block displays data which has been retrieved from somewhere in the server database. For instance, the classic form/subform arrangement is represented as an outer and an inner block. The form itself is a block, the block dialog appears.
Property | Significance | Setting |
Width | Form (block) width in pixels | 500 |
Height | Form (block) height in pixels | 400 |
Row count | The number of rows of data to be displayed; zero will show multiple rows depending in the block size. | 1 |
X-delta | X-offset between data controls when more than one row is displayed. Not relevant if only one row is displayed. | 0 |
Y-delta | Y-offset between data controls when more than one row is displayed. Not relevant if only one row is displayed. | 20 |
Y-delta | Y-offset between data controls when more than one row is displayed. Not relevant if only one row is displayed. | 20 |
Control name | Name of the block, used for scripting. Not relevant here. | UnnamedForm |
Show Scroll Bar | There are four options, which show (or hide) a scroll bar and/or a small navigation tool. | Yes |
Automatic update | If set to Yes (the default) then changes are automatically saved when moving to a new row. | Yes |
Up to this stage, clicking the Cancel button in a properties dialog will abort the form creation. Clicking OK for the third time will move you on to the point of a blank form appearing.
Adding Controls to the FormAt this stage, a blank design form appears, onto which controls can be placed. Newer versions of Rekall have a toolbox where you can choose the control you want to add. In previous versions, all controls are added by sweeping out an area with the mouse (ie., point to one corner, press and hold the left button, move to the opposite corner, and release) and then using the popup menu which appears, when the right button is clicked. Let's start by adding controls for each of the table columns other than the primary key (which the user does not need to see).
Later in the manual there is a complete list of the available controls and the properties that each has, but the table below is a basic list.
Control | Description |
Button | Clickable button. Can be used to trigger python scripts to perform actions. |
Label | Fixed text label (but can be changed from a script). |
Field | Simple text display and entry. |
Choice | Pick one value from a list, displays as a combobox. |
Link | Pick on value from a list, is linked to values in another table. |
Check | On/off selection, displays as a checkbox. |
Pixmap | Used to display images. Displays common formats like .bmp, .jpg and .png. |
Row Mark | Used to display row number and current row markers, as in table data view. |
Memo | Multi-line text edit control. |
Rich Text | Displays text in QT rich text format (a very-much stripped down HTML). |
Spin Box | Displays a numeric spin box control. Currently limited to simple numeric display. |
Graphic | This displays an image, like a Pixmap, but the image is static. Typically used for eye-candy. |
Tab Control | Provides a way of constructing a tabbed control, as in a tabbed dialog. |
If the grid tool towards the right of the tool-bar is turned on then controls will snap to the grid, which generally helps to make layout easier. You should also note that by default forms use fixed layouts. However, Rekall supports a limited resizing facility (which you may have noticed in the table design and display screen ( The table design and data display screens are really forms. The one for table design is embedded in the code, and the one for data display is generated at run time to match the table. ) ) which is described later.
When using popup-menus in design mode, the actual contents of the menu will vary depending on exactly what sorts of controls can be added (there are some restrictions). The menu will also have a New Block submenu, which can be ignored for this form.
Here we will add Fields (which are simple line-edits controls) for each column other than Salutation which will be a Choice (a combobox). In addition, there are labels to go with the fields. The two tables below show the settings for the first Field control and the Choice control.
Property | Significance | Setting |
X-position | X coordinate of the field | 140 |
Y-position | Y coordinate of the field | 20 |
Width | Field width in pixels | 280 |
Height | Field height in pixels | 20 |
Control name | A name which identifies the control in the enclosing block. Can be used it scripts. | Company |
Display expression | This is the expression that is used in the SQL query which retrieves data for this field. | Company |
Tab order | Tab order value when tabbing round fields. | 1 |
Text alignment | Text alignment in the field. | left |
Property | Significance | Setting |
X-position | X coordinate of the field | 140 |
Y-position | Y coordinate of the field | 50 |
Width | Choice control width in pixels | 100 |
Height | Choice control height in pixels | 20 |
Control name | A name which identifies the control in the enclosing block. Can be used it scripts. | Salutation |
Field name | The name of the column in the table whose contents are displayed. | Salutation |
Tab order | Tab order value when tabbing round fields. | 2 |
Values | The set of values that are offered. | Mr|Mrs|Miss |Dr|Sir|Lord |
The following screenshot shows the form after all these controls have been added. The blobs at the corners of each control can be used to move or resize the control (or groups of controls, as explained a little further on). The scrollbars to the right and bottom of the window can be used to pan the window, in case you want to design a form which is actually larger than the window. The vertical scrollbar in the design area appears if this is selected via the Show Scroll Bar property, and will be usable in data view (ie., when the form is actually running) to navigate through records. The rectangle to the bottom-left of the design area also appears when the small navigation tool is selected, and will show a record number, line Record 42 of 126, plus buttons to allow movement between records.
Double clicking a control brings up the properties dialog for the control ( Double-clicking for the properties dialog currently does not work on the QT3/KDE3 builds, due to internal QT changes. ) . Right-clicking in control (or in the block background) brings up a popup menu appropriate to the control or whatever, including options to Cut, Copy or Delete the control; the properties dialog can also be accessed from this menu. In the case of the background, this also includes options to insert new controls.
Positioning ControlsThere are a couple of shortcuts that can be used to speed up the addition of controls. After adding a control, its blobs will be in red (active). If you right-click in the background and select a new control type while holding down the shift key, then the new control will be the same size and a little below the active control (without shift it would be to the right). The newly added control will then become active and the previous control will be marked in green (a follower). Now if you right-click and select a control without bothering with the shift key, it will be positioned with an offset which is the same as that between the two previous controls. This allows you to work down a column (or across a row) quite quickly.
Controls can be aligned and sized either by using the mouse to move or resize them, or by opening their property dialogs, and explicitly editing the position and size properties. Also available on the toolbar are a pair of controls which assist positioning. The first Enable Snap to Grid is an on/off toggle; if on then controls will be automatically aligned and sized to the grid immediately after creation or after you manually move them. The second, Snap Controls to Grid will align and size all selected controls (ie., controls marked with the red active or green follower corner blobs) to the the grid. This is useful if automatic snapping is off, but you'd like to align some subset of the controls.
![]() |
Enable/disable automatic snapping. |
![]() |
Snap selected controls to grid. |
However, Rekall also allows you to align controls to one-another, and to make two or more controls the same size. If two or more controls are selected, then the alignment and same-size controls on the toolbar become active. In each case, the active control (the one with the red blobs) determines the alignment or size. The tools are shown below:
![]() |
Align controls to top |
![]() |
Align control to bottom |
![]() |
Align controls to left |
![]() |
Align controls to right |
![]() |
Make controls have the same width |
![]() |
Make the controls have the same height |
![]() |
Make the controls have the same size |
You can save the form by clicking on the Save tool or using the File/Save menu item. The first time you save you will be prompted for a name under which to save the form. If you are creating the form in the file system it will be stored as name.rkl.frm ; if created in the server database it will be stored in the objects table. By the way, forms (and reports) are stored in XML format, so if you are inquisitive and save the form to the file system, then you can have a look at it with an editor (and evey modify it; got the caption wrong? well, just fix it while you are there!)
Once saved, you can switch to data view (either via the View menu or using the left-hand most tool), in which case you should see any data that you entered into the table earlier. The various tools for record navigation appear on the tool bar.
Adding Navigation ButtonsTo finish the form, we'll add some buttons to allow record navigation without having to use the tool bar. Buttons are a bit like labels, in that they don't need to refer to a column in (or expression from) the table about the same, but the settings are a little more important.
There are three ways to add buttons such as those for navigation. The most general way is to add a button and to associate with it some script code to be executed when the button is clicked, and which does the required operation, such as moving to the previous or the next record; this is described in more detail in the chapters on scripting. The second way is to use a shortcut mechanism, described in the next section; this is the mechanism used in Rekall prior to version 2.0.0 and is described for completeness. However, the third and easiest way is to use a reusable component.
Rekall comes with a number of reusable components, including navigation buttons, which can be inserted into forms and reports. To insert a component, right-click at the point at which the component should be inserted, and select Paste component from the Edit menu. This will bring up the component dialog, illustrated below.
Components may be designed locally and stored in server databases or locally in your directory (these are described in a later chapter), but with the combobox at the top left showing Stock Components, those that come with Rekall are shown. Below this is a list of available components, grouped up loosely by function. Clicking on a component will show details of the component under the first tab to the right; in the illustration, the First button has been selected, and some descriptive text appears.
Clicking the second tab will show the component, in this case a button with the legend First. Clicking the third tab shows configuration options for the component. In the case of the first button (and, in fact, for all the buttons), the button's legend may be changed. If you change this and then go back to the second tab, the component will be displayed with the changed value, in this case the legend on the button. When you are happy, click OK and the button will appear in the form.
Once pasted into the form, the component is no different to any control that you constructed directly ( A feature of recent versions of Rekall is linked components. In this case changing the definition of a component will effect all forms that use the component. In the other case, described here, components are copied onto the form which is rather like copying and pasting text in a word processor; changing the copied text doesn't affect the pasted text, nor vice-versa. ) , and its properties can be changed in just the same way. So, for instance, in this example you can move the button around, and change its legend. You can also see its internal workings, such as the python script that actually makes the button work (this may be useful if you move on to writing your own scripts, as an example of how things can be done).
In the demonstration database, buttons have been added to the form with the First, Previous, Next and Last record navigation functions. In addition, a Find button handles the querying; clicking it once will clear the form, so that search criteria can be entered, clicking a second time will perform the search.
As noted, this section is included for completeness. You can probably skip it.
The table below shows the settings for a Next button using the shortcut mechanism.
Property | Significance | Setting |
X-position | X coordinate of the field | 200 |
Y-position | Y coordinate of the field | 350 |
Width | Choice control width in pixels | 50 |
Height | Choice control height in pixels | 40 |
Control name | A name which identifies the control in the enclosing block. Can be used it scripts. | Next |
Field name | The name of the column in the table whose contents are displayed. | > |
On Click | The action to perform when the user clicks the button. | #Click |
The two important settings are On Click and Control name. Without going into details, the On Click setting invokes a standard Rekall python function. The function gets the Control name setting and uses that to decide what to do, as listed in the next table. By the way, this mechanism is provided as a quick and convenient shortcut to add navigation buttons without having to write any python scripts (and there are some other similar shortcuts described a bit further on). The sections of this manual on python scripting describe how you could do the same thing without using the shortcuts, which then opens the way to providing much more complicated, application specific functionality.
Control name | Action |
First | Go to first record |
Previous | Go to previous record |
Next | Go to next record |
Last | Go to last record |
Add | Add (insert) a new record |
Save | Save changes to current record |
Delete | Delete current record |
Query | Start a query (ie., search) |
Execute | Execute a query |
Cancel | Cancel a query |
Below is an image of the finished form, with everything there, as it is in the demonstration Orders database (the image has a bit of Icelandic in it, we trust it doesn't say anything offensive!). There is actually one extra control there (the combobox below the main fields and above the buttons), which is the Navigation/Selector component, with some properties altered. This can be used as a quick way to navigate to a specific record.
You'll notice that the navigation buttons are enabled and disabled as you move through the records; for instance the First and Previous buttons are disabled when you are at the first record. This bit of magic is handled by the Event/Slot mechanism described after the chapter on scripting.