<?xml version="1.0"?> <!-- - FILE: testbasic.dui - - FUNCTION: - This is an example DWI database-to-glade scripting file. - It contains extensive documentation as to the DWI XML syntax. - - To actually run this example, you will need to create a database, - create an ODBC dataset description for it, and initialize the - database with the tables in the "testbasic.sql" file. Finally, - you might want to change the username and password (below) - to something reasonable; or review the "testlogin.dui" example - to see a better way of handling user logins. --> <!-- The <dwi> element is used to indicate the beginning of a new - DWI application. An application consists of one or more - <database> sections, each of which consists of one or more - <window> sections. The application windows themselves - interact with the user as a <report>, displaying data, - and/or as a <form>, collecting user input. - - A DWI application contains a rudimentary mechanism for - handling application state: a global set of key-value - pairs (implemented as a hash table). You can create - a key-value pair at any time, and later use the values - in database queries or in reports. - There are a reserved set of keys. These all start with /system/ - The currently defined keys are: - /system/datetime - the current date and time (iso8859) - - The keyword "name" identifies the application name. This - keyword is optional. Its not used for much at this time. --> <dwi name="testbasic"> <!-- The <database> element is used to identify the database that - will be used for the fetching and storage of data. A database - must be specified; otherwise the whole point of this is pointless. - Note that the host, dbname, username and authentication need not - be hard-coded in a DWI file; they can be obtained from the GUI. - See the "testlogin.dui" example to see how to do this. - - The keyword "provider" identifies the database driver. Currently - only 'odbc' is supported. - The keyword "dbname" identifies the database to connect to. It - must already exist and have tables defined within it. - The keyword "host" identifies the tcp/ip host that has the database - server running on it. - The keyword "username" identifies the username under which to log - into the database. - The keyword "passwd" provides an authentication token. Whether this - is a password or other token depends on how the database server - is configured. --> <database provider="odbc" dbname="testbasic" host="localhost" username="linas" passwd="asdf"> <!-- The <window> element is used to identify an application window and - the file which describes the window's graphical layout. - - The keyword "provider" identifies the graphical layout engine. - Currently, the only supported values are "glade" and "self". - (Other providers e.g. for web/PHP are envisioned.) - The "glade" provider requires a glade filename that defines - the user interface, and the root widget name. - The "self" provider i - The keyword "name" identifies this window for the purpose of having - forms and reports reference this window to read from and write - to it. - The keyword "filename" specifies the filepath to the Glade XML file. - The keyword "root_widget" specifies a root widget (typically a top - level window) under which the other widgets can be found. - The keyword "main" indicates whether or not this window is the main - application window. The use of this keyword is optional; if its - value is "yes", then this window will be displayed on application - startup. --> <window provider="glade" name="home page" main="yes" filename="testbasic.glade" root_widget="main window"> <!-- The <form> element is used specify how a set of data - values are obtained when a widget signal is received. - Typically, the widget signal is the press of the "submit" - button on a form, and the data values are a result of - a database query that this form specifies. Note, however - that the form is general enough that any signal, not - just a button press, will do. Note that forms are - general enough that a variety of actions can be performed; - these do not always cause SQL/database statements to be - issued. - - The example below specifies a database query statement - that is created out of the values obtained from a set of - input widgets. Specifically, it will cause an SQL SELECT - statement to be generated when the "search button" widget - is "clicked". - - The keyword "name" identifies this form by name. It is - used in other places to identify this form. - The keyword "type" identifies the SQL query type. Valid values - are "select" "insert" "update", "delete", "tables" or - "columns". The first four values - correspond to thier matching SQL statements. The fifth, - "tables", performs a database-specific query to list all - of the tables in this database. The sixth, "columns", - performs a database-specific query to list the columns - in a table. - The keyword "tables" identifies one or more SQL tables. These are - used in the SELECT..FROM tables construct. The list must be - comma-separated. - The keyword "tables_key" identifies a KVP key which contains the - table name to use. - The keyword "report" indicates the name of the form that will - be used to report the query results. - - The below will generate the SQL statement - SELECT notes.summary, notes.id FROM notes WHERE --> <form type="select" tables="notes" report="result list"> <!-- The <submit> element is used to hook up widget signals to - this form. This allows the database query to be generated - and submitted to the database server whenever some widget - is clicked (or some particular signal is received). - - The keyword "widget" identifies a widget (by name) that, - when clicked, launches the actual select operation. - The widget doesn't have to be a clickable button, - it can be any widget with a signal. - The keyword "signal" identifies the widget signal that - actually launches the select. It can be any valid - Gtk signal for the specified 'submit' widget. --> <submit widget="search button" signal="clicked"/> <!-- The <select> element specifies what fields will be retrieved - from the database. - The 'field' keyword can be 'table.fieldname' or simply 'fieldname', - or 'field AS othername' --> <select field="notes.summary" /> <select field="notes.id" /> <select field="fromdate" /> <select field="todate" /> <!-- The <where> element is used to control database record - matching. It determines the WHERE part of an SQL statement - "SELECT ... FROM ... WHERE ...". This part of an SQL statement - has the form of "field" "op" "value" where "field" is the - name of an SQL field (column label), "op" is an operator - (such as equals, less-than, etc.), and "value" is used by the - SQL server to find matching records. With DWI, the "value" - can be obtained from a widget: indeed, this is the central point - of DWI: that values can be obtained from widgets. Any of - the common value-specifying keywords can be used to specify - the value (see below, "COMMON VALUE SPECIFYING KEYWORDS"). - In addition to these, the following are also needed: - - The keyword "field" specifies the database field that will - be matched. This field is mandatory. - The keyword "op" specifies the relational operator to use - when matching. It can be any of the accepted SQL - operators appropriate for this field. If not specified, - it is assumed to be "=". Note that the current XML parser - does not allow "<" so you gotta "<" if you want "less - than". - - - COMMON VALUE SPECIFYING KEYWORDS - - - - - - - - - - - - - - - - - - - In general, a value can be obtained directly from a widget, - or from a global key-value store, or hard-coded in DWI. - Once a value has been obtained, it can be filtered before - it is used. Filters typically can check for null values, - change capitalization, change date strings and number - representations, etc. - - The following keywords are used to specify how to get a value: - - The keyword "widget" specifies the widget whose value - will be used. Either this, or the "key" keyword, - or the "value" keyword, must be present. - The keyword "column" is used to identify which column of - the widget contains the string. This keyword only - makes sense with widgets that have multiple columns - (such as GtkCList). - The keyword "data", if present, will cause the value to be - fetched not from the widget directly, but from the - GtkObject's data (using the gtk_object_get_data() call). - This allows arbitrary string data previously stored with - the widget to be used as a value. - The keyword "key" specifies the key of a key-value pair - in the global key-value store. A value must have been - previously stored under this key (else a null string will - be returned). Either this keyword, or the "value" keyword, - or the "widget" keyword must be present. - The keyword "value" specifies a hard-coded value that will - be used, in place of a value from a widget. Either - this keyword, or the "key" keyword, or the "widget" - keyword must be present. - The keyword "filter" names a string-handling function that - will be applied to the resultant value (fetched from - the widget or by KVP key or the hardcoded value). - The filter transforms the string in some way. There - are a number of pre-defined filters. - --> <where widget="ID text" field="notes.id" /> <where widget="From text" field="fromdate" op=">" /> <where widget="To text" field="todate" op="<" /> </form> <!-- This is a quickie little hack to hook up the clear button - so that the text fields are cleared when it is pressed. - This hack depends on reports (explained further below): - basically, we create a report, all of whose fields are - blanks. We then "report" these blanks on the finder tab. --> <form report="finder"> <submit widget="clear button" signal="clicked"/> </form> <report name="finder"> <entry widget="ID text" value=""/> <entry widget="From text" value=""/> <entry widget="To text" value=""/> </report> <!-- Another example of clearing fields in a window; this time - with some fancier tricks. - trick 1: we don't clear all the fields on this form. - trick 2: we use a non-null value to initialize the 'notes' widget. - trick 3: we use the '/system/datetime' key to auto-fill - in the current time. - trick 4: we use the 'show' signal on the application - main window to automatically run this report - on application startup. If we wanted to, we could - even launch an SQL query on startup in this way. --> <form report="new tab"> <submit widget="clear new button" signal="clicked"/> <submit widget="main window" signal="show" /> </form> <report name="new tab"> <entry widget="new notes" value="Enter a Note Here!"/> <entry widget="new to date" key="/system/datetime"/> </report> <!-- Another example of a form. This form allows the user to create - a new record in the database. - - The <insert> element is used to specify which widgets will - provide data for an SQL INSERT INTO ... VALUES ... statement. - Any of the "COMMON VALUE SPECIFYING KEYWORDS" (described above) - can be used. In addition to these, the following are needed: - - The keyword "field" specifies the database field that will - be matched. This field is mandatory. - - The <refresh> element is used to indicate other windows that need - to be redrawn when the form is activated. This is typically needed - when a form is modifying data that might be visible in other windows. - Without a refresh, the other windows will continue to show old data, - until the user manually refreshed them. - - The keyword "window" gives the name of a window that will be redrawn. - - The <chain> element is used to chain together several actions. - The first action in a chain to actually 'do something', i.e. - to generate a report that puts up a GUI, breaks the chain. At - this time, this is intended primarily for implementing 'prereq' - dialogs, to check for a missing or incorrect field before the - 'true' form is run. The example below illustrates this. - - The keyword "form" gives the name of the form that will be - run first, before this form. --> <form type="insert" tables="notes" report="submit ok"> <submit widget="submit button" signal="clicked"/> <insert widget="new from date" field="fromdate" /> <insert widget="new to date" field="todate" /> <insert widget="new summary" field="summary" /> <insert widget="new notes" field="notes" /> <chain form="check for null" /> <refresh window="result list" /> </form> <!-- Another example of a form. This form provides an example of - copying from a widget to the global KVP (key-value pair) table. - - The <wtokey> element is used to specify that a value is to be - gotten from the specified widget, and placed into the global - KVP (key-value-pair) table. Any of the "COMMON VALUE SPECIFYING - KEYWORDS" (describerd above) can be used. In addtion to these, - the following is also needed: - - The keyword "dst_key" specifies a key under which the resulting - value will be stored. - --> <form name="check for null" report="null from date"> <wtokey widget="new from date" dst_key="nulldate" /> </form> </window> <!-- The following is a very simple error message dialog to - state that the 'from date' field has been left blank. - It fetches the value associated with key "nulldate", - and applies the filter "is_whitespace_or_null" to it. - If it is, it will return true, and the "null msg" - popup will remind the user to not leave the date field - blank. If its not, the popup will not come up. Because - this is the result of a form that was chained, the next - form in the chain will run, accepting the user's input. --> <window provider="glade" name="null from date" filename="testbasic.glade" root_widget="null fromdate msg"> <report> <entry widget="null msg" key="nulldate" filter="is_whitespace_or_null"/> </report> </window> <!-- ============================================================ --> <!-- ============================================================ --> <!-- Move on to the next window. This window will serve primarily as - a place to display the results of queries specified by the previous - forms. --> <window provider = "glade" name="result list" filename="testbasic.glade" root_widget="query results"> <!-- The <report> element determines how data from the database - is shown on the screen. It is one-half of a report-form pair: - the form (shown previously) determines how the database is queried - for data. - - A report can show data in tabular format (by using, e.g. - the GtkCList or GtkCTree widgets) or individual widgets - (e.g. GtkLabel, or filling in a default value for GtkEntry). - - The keyword "name" identifies the report by name. It can be any - user-defined value (it does not need to be a widget name). - If the name isn't specified, the name of the parent window - is used to identify the report. --> <report> <!-- The "row" element is used to define a row iterator within - a report. The use of this element is optional; however, - without it, only one recordset (one 'row') of results can - be reported. Currently, only the GtkCList and the GtkCTree - widgets are supported. - - To use GtkCList, only the widgetname is needed. - - To use GtkCTree, a considerable number of extra keywords - are needed to correctly set up the hierarchical arrangement - of the tree. Basically, the idea is to find the parent - node of a set of child rows/nodes by matching a recordset - field to a value in one of the columns in the parent node. - If there's a match, then that node is used as the parent. - Note that parent rows must be defined before child rows. - (This is a temp limitation maybe ???) - - The keyword "widget" specifies a widget that can report - multiple rows of data. This keyword is required to be - present. - The keyword "name" identifies the row by name. The name - can be any user-defined name. When using a tree display, - this keyword is mandatory: it is used by the <form> - element to identify this row as the target of a query. - The keyword "nest" identifies a row definition that will - serve as the topmost, root row definition. Set - to zero to indicate its root, else non-zero ... - The keyword "match_column" specifies the tree column that - contains a value that will be matched to identify the - parent tree node. When using the tree display, this - keyword is mandatory. - The keyword "match_field" specifies the database recordset - field that contains the value that will be matched to - the tree column to identify the parent tree node. - When using a tree display, then either this keyword, - or the "match_key" keyword, or the "match_value" keyword - must be present. - The keyword "match_key" specifies the global hash table - key that stores the value that will be matched to the - tree column to identify the parent tree node. Either - this, or the "match_field" or the "match_value" keywords - must be present. - The keyword "match_val" specifies a constant value that - is used to match a column value to find the parent tree - node. Either this, or the "match_field" or the "match_key" - keywords must be present when using a tree display. --> <row widget="query clist"> <!-- The <entry> element is used to link specific database - fields to specific widgets or columns. In the example - below, database fields are hooked up to clist columns. - A different example comes a bit later in this file. - - The keyword "widget" specifies a widget that will report - the data. This keyword is optional if the entry - is nested inside a <row> element. - The keyword "column" specifies which column the value - will appear in. This keyword is optional, and - only makes sense when used with widgets that - support columns. If a column is not specified, - then a "widget" must be. - The keyword "data", if present, will cause the value - to not be displayed in the widget. Instead, - it will be stored with the widget (using the - gtk_object_set_data() call). The data keyword - specifies the key under which the value will - be stored. (In the case of multi-row widgets, - such as GtkCTree and GtkCList, which do not - support keyed data in rows, instead a hash - table will be created and stored as the row - data. The key-value will then be placed in - that row's hash table.) - The keyword "arg", if present, will cause the value - to not be displayed in the widget. Instead, - it will set the named widget arg (using the - gtk_object_set() call). Widget args allow - arbitrary widget characteristics to be set. - For example, the arg "GtkWidget::height" - can be used to set the widget height. - The keyword "field" specifies a database field from - which the reported data will be fetched. This - keyword is optional, however, if its absent, then - the either the "key" or the "value" keyword must - be present. - The keyword "key" specifies the key of a key-value - pair in the application hash table. The value - currently associated with that key will be used - to fill in the report widget. - The keyword "value" specifies a constant value that - this widget will report. Handy for blanking - or setting a default value in a widget (see - example below). --> <entry widget="query clist" column="0" field="notes.id"/> <entry widget="query clist" column="1" field="notes.fromdate"/> <entry widget="query clist" column="2" field="todate"/> <entry widget="query clist" column="3" field="summary"/> </row> </report> <!-- A listing of records is useless if one can't delete them - or modify them. The next <form> deletes a record from the - database. The deleted record must have a matching "notes.id" - which is read from column 1 of the highlighted row in the - clist widget. The SQL query generated by this form is - DELETE FROM notes WHERE notes.id='xxx'; --> <form type="delete" tables="notes" report="submit ok"> <submit widget="qdelete button" signal="clicked"/> <where widget="query clist" column="0" field="notes.id" /> <refresh window="result list" /> </form> <!-- View the details of the currently highlighted row. - This performs the following SQL query: - SELECT * FROM notes WHERE notes.id='xxx'; - The results of the query will be displayed in the - 'record viewer' window. --> <form type="select" tables="notes" report="record viewer"> <submit widget="qview button" signal="clicked"/> <select field="*" /> <where widget="query clist" column="0" field="notes.id" /> </form> <!-- The <sigaction> element is a generic signal escape mechanism. - It causes the indicated 'action' to be performed when the - indicated 'signal' on the 'widget' is received. Currently, - the supported actions are: - "close_window" closes the current window. - "main_quit" quits the application main loop --> <sigaction widget="qclose button" signal="clicked" action="close_window"/> </window> <!-- The following is a very simple "OK" dialog to confirm a - database update. --> <window provider="glade" name="submit ok" filename="testbasic.glade" root_widget="submit msg"> <report> <entry widget="submit msg" value="New Record Created"/> </report> </window> <!-- The Record viewer/editor window - Note how the report form doesn't use a <row> element. This is because we - assume that only one record/row is returned by the database query. --> <window provider="glade" name="record viewer" filename="testbasic.glade" root_widget="details window"> <report> <entry widget="record id label" field="id" /> <entry widget="fromdate entry" field="fromdate" /> <entry widget="todate entry" field="todate" /> <entry widget="summary entry" field="summary" /> <entry widget="notes text" field="notes" /> </report> <form type="update" tables="notes" report="submit ok"> <submit widget="edit submit button" signal="clicked"/> <insert widget="fromdate entry" field="fromdate" /> <insert widget="todate entry" field="todate" /> <insert widget="summary entry" field="summary" /> <insert widget="notes text" field="notes" /> <where widget="record id label" field="id" /> <refresh window="result list" /> </form> </window> </database> </dwi> <!-- ===================== END OF FILE ========================== -->