Using the function sqlite-query, we can now interact programmatically with SQLITE. For end users, we need to design a user friendly GUI. The EMACS widget library is about as friendly as EMACS will get. There is very limited information on how to use the EMACS widgets. You can read about the widget library within EMACS info, or on the web. Ye Wenbin also has a useful tutorial. Should you find other resources, please let me know. Essentially you create a form with a widget for each field, such as a text field, dropdown, radio button etc. Once the user has populated the fields, a button assembles and submits the SQL statement. Here is a simple example with widgets for some of the fields in our “ab” database table:
1 | (require 'widget) |
To use the form, issue the command (add-antibody), which is also connected to one of the menu items discussed the the sqlite-mode section. Once the data has been entered, a “submit” button is pressed which will assemble the sql statement:
1 | (setq sql-command (concat "INSERT INTO ab VALUES(NULL, '" (car (cdr (split-string selected-gene-id "\t"))) "','" |
Note that any input through a text field is processed with chomp to remove whitespace.
Handling Checkbox user input
Here is a truncated example showing 2 of 6 checkboxes on one of my forms:
1 | (widget-create 'checkbox |
First set up variables to hold the status of each element in the check box list, as well as a variable to hold the final semicolon delimited string. I am showing all six variables.
1 | ;;antibody application variables |
Next is the function to be invoked when the user clicks the “OK” or similar button on the form. Items that are selected can be cons into a list for further processing. Here I simply concatenate the list using semicolon as a separator for the purpose of storage in the database and reporting.
1 | (defun create-ab-applications-list () |
Populating dropdown lists on-the-fly from database content
Quite often you wish to give the user a prepopulated dropdown where the content comes from a field in the database. Here is an example of form code for a dropdown:
1 | (widget-create 'menu-choice |
The dropdown content is:
1 | '(item "mouse") |
Suppose rather than hard coding I want to pull out all the species available in the ab.host field in my database? Using my sqlite-query command, it would be easy enough to get the list:
( “mouse” “rabbit” “goat” “donkey” )
1 | (setq sql-command "SELECT host FROM ab;") |
But how to I convert that to the format shown above for dropdown content? The dropdown content shown above is equivalent to:
‘(item “mouse”) ‘(item “rabbit”) ‘(item “goat”) ‘(item “donkey”)
which is equivalent to:
(quote (item “mouse”)) (quote (item “rabbit”)) (quote (item “goat”)) (quote (item “donkey”))
Note that this is not a list, as it does not have circumscribed parentheses. Since we want to write code, a macro is the way to go. This is what it looks like:
1 | (defmacro multi-item () |
I mapcar over my host-species list, creating the statement (quote (item “element”)) for each element of the list, then splice that into my backquoted widget-create code. With this code, it is easy now to create a dropdown the contents of which depend on other selections in the form e.g. an initial dropdown, checkbox, or radio button. The notify statement of the initial selection should set a variable and then refresh the form, invoking the query that will populate the dependant dropdown list. You could, for example, make the second list visible only after the initial selection.
Though the widget library is crude by current standards, it will meet most needs either directly or with a hack.