BASIC Developer & Support Resources > Scripting Languages

MTSB

(1/4) > >>

JRS:
I have been trying to get my arms around what my limitations are using the sbhttpd ScriptBasic HTTP protocol server in a desktop environment. In essence what sbhttpd offers is a client / server relationship using a HTTP 1.0 protocol to interact with it's clients. (a browser or anything else that can open a socket) So what this means is the that app-server can respond with a HTML response (if running in a browser) or a Glade XML response. (if a desktop GUI app)

The following is an example of using scriba (ScriptBasic console interpreter) and the cURL extension module to run a script on the server.

mtsbcurl.sb

--- Code: ---INCLUDE curl.bas

ch = curl::init()
curl::option ch,"URL","http://127.0.0.1:8080/mtsb/john.bas"
txt = curl::perform(ch)
PRINT txt
curl::finish ch

--- End code ---

john.bas

--- Code: ---PRINT "Status: 200\nContent-Type: text/html\n\n"
PRINT "Server Script\n"
FOR x = 1 TO 10
  PRINT x,"\n"
NEXT

--- End code ---

jrs@Laptop:~/SB/test$ scriba mtsbcurl.sb
Server Script
1
2
3
4
5
6
7
8
9
10
jrs@Laptop:~/SB/test$

I see this as a potential for common ground between web and desktop application development with the goal of reusable code.

JRS:
If the goal is to use sbhttpd to provide the client / server layer for both web and desktop applications, then it all starts with laying out the cookies. (if Santa did bring you anything, you may have left out this step)  :D

I have been using sbhttpd as a proxy application server for dynamic web applications for years and couldn't be happier. I will show how you can use sbhttpd to support desktop applications using the same application server (local or remote) the web clients use. The first thing on a list is to establish a session with the server. This is done with a cookie that contains a session ID the server generated and is used during the life of the session. The server needs to know the session ID before it can access previously stored variables or setting new ones. The following example gets one script to establish the session ID and then gets the second script telling sbhttpd what it's session ID is and retrieves the session variable set in the prior script along with printing its current session ID.

mtsbcurl.sb

--- Code: ---INCLUDE curl.bas

ch = curl::init()

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/svar.sb")
curl::option(ch,"COOKIEFILE","")
txt = curl::perform(ch)
PRINT txt,"\n"

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/svar.ovr")
curl::option(ch,"COOKIE","mtsb=" & CHOMP(txt) & ";")
txt = curl::perform(ch)
PRINT txt,"\n"

curl::finish(ch)

--- End code ---

svar.sb - 1st web script

--- Code: ---INCLUDE cgi.bas
INCLUDE mt.bas

session_id = mt::NewSessionId()
mt::SetSessionId(session_id)
mt::SetSessionVariable("myvar", "John")
cgi::Header(200, "text/html")
cgi::SetCookie("mtsb", session_id)
cgi::FinishHeader()
PRINT session_id

--- End code ---

svar.ovr - 2nd web script

--- Code: ---INCLUDE cgi.bas
INCLUDE mt.bas

session_id = cgi::Cookie("mtsb")
IF mt::CheckSessionId(session_id) THEN
  mt::SetSessionId(session_id)
  myvar = mt::GetSessionVariable("myvar")
  cgi::Header(200, "text/html")
  cgi::SetCookie("mtsb", session_id)
  cgi::FinishHeader()
  PRINT myvar,"\n"
  PRINT session_id,"\n"
ELSE
  cgi::Header(200, "text/html")
  cgi::FinishHeader()
  PRINT "Invalid Session ID\n"
END IF

--- End code ---

Results:

jrs@Laptop:~/SB/test$ scriba mtsbcurl.sb
amfdpfdhpdcdihhofgceeoajkcapckjf
John
amfdpfdhpdcdihhofgceeoajkcapckjf

jrs@Laptop:~/SB/test$


Note:  Curl has an option to create a COOKIEJAR that automates the cookie processing on the client (scriba) side but the SB curl extension module doesn't support that option currently. (hence the reason I'm printing the session ID to send back to the client in the first script. If FireFox didin't store their cookies in a SQLite DB, I could have pointed COOKIEFILE to it.  >:(


JRS:
I lucked out and adding COOKIEJAR was a one line change and recompile of the curl.so extension module. I'm glad the automated cookie handling is working and now I can move on to working with a shared database and submitting client form data to the server.

SB curl interface.c

--- Code: ---/*
Here you have to list all the CURL options that get char * parameter and are handles
transparently passed to CURL.

The macro is (re)defined
- in the string parameter declaration,
- initializing the parameters to NULL
- during parameter setting
- and release of memory when finish a curl handle.

That helps you to maintain new options because this is the only place where the name of
the new option is to be present.
*/
#define STRING_OPTIONS \
STRING_OPTION(PROXY)\
STRING_OPTION(URL)\
STRING_OPTION(USERPWD)\
STRING_OPTION(PROXYUSERPWD)\
STRING_OPTION(RANGE)\
STRING_OPTION(REFERER)\
STRING_OPTION(USERAGENT)\
STRING_OPTION(FTPPORT)\
STRING_OPTION(COOKIE)\
STRING_OPTION(SSLCERT)\
STRING_OPTION(SSLCERTPASSWD)\
STRING_OPTION(COOKIEFILE)\
STRING_OPTION(COOKIEJAR)\
STRING_OPTION(CUSTOMREQUEST)\
STRING_OPTION(INTERFACE)\
STRING_OPTION(KRB4LEVEL)\
STRING_OPTION(WRITEINFO)\
STRING_OPTION(CAINFO)\
STRING_OPTION(RANDOM_FILE)\
STRING_OPTION(EGDSOCKET)\

--- End code ---

mtsbcurl.sb

--- Code: ---INCLUDE curl.bas

ch = curl::init()

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/svar.sb")
curl::option(ch,"COOKIEJAR","/home/jrs/SB/test/cookie.txt")
txt = curl::perform(ch)
PRINT txt,"\n"

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/svar.ovr")
curl::option(ch,"COOKIE","mtsb")
txt = curl::perform(ch)
PRINT txt,"\n"

curl::finish(ch)

--- End code ---
Note: The printing of the session_id in this new version is for visual (debugging) validation only.

cookie.txt

--- Code: ---jrs@Laptop:~/SB/test$ scriba mtsbcurl.sb
fckbkipdoecbpekijkohgocnligejhlp
John
fckbkipdoecbpekijkohgocnligejhlp

jrs@Laptop:~/SB/test$ cat cookie.txt
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

127.0.0.1 FALSE /mtsb/ FALSE 0 mtsb fckbkipdoecbpekijkohgocnligejhlp
jrs@Laptop:~/SB/test$

--- End code ---

svar.sb

--- Code: ---NCLUDE cgi.bas
INCLUDE mt.bas

session_id = mt::NewSessionId()
mt::SetSessionId(session_id)
mt::SetSessionVariable("myvar", "John")
cgi::Header(200, "text/html")
cgi::SetCookie("mtsb", session_id)
cgi::FinishHeader()
PRINT session_id

--- End code ---

svar.ovr

--- Code: ---INCLUDE cgi.bas
INCLUDE mt.bas

session_id = cgi::Cookie("mtsb")
IF mt::CheckSessionId(session_id) THEN
  mt::SetSessionId(session_id)
  myvar = mt::GetSessionVariable("myvar")
  cgi::Header(200, "text/html")
  cgi::SetCookie("mtsb", session_id)
  cgi::FinishHeader()
  PRINT myvar,"\n"
  PRINT session_id,"\n"
ELSE
  cgi::Header(200, "text/html")
  cgi::FinishHeader()
  PRINT "Invalid Session ID\n"
END IF

--- End code ---

JRS:
I thought I would start off with the browser (HTML) version first to show how the flow of a CGI client/server application might look. Keep in mind there is no formating (CSS) or validation to keep this simple and easy to read.

webcustomer.sb

--- Code: ---' Program: webcustomer.sb
' Version: 1.0
'    Date: 2010-12-27
'      By: JRS

INCLUDE cgi.bas
INCLUDE mt.bas
INCLUDE mysql.bas

dbh = mysql::RealConnect("localhost","root","xxx","sbtest")

OPTION cgi$Method cgi::GET or cgi::POST

session_id = cgi::Cookie("webcust")

New_Session:

IF session_id = undef THEN
  session_id = mt::NewSessionId()
  mt::SetSessionId(session_id)
ELSE
  IF mt::CheckSessionId(session_id) = False THEN
    session_id = undef
    GOTO New_Session
  END IF
  mt::SetSessionId(session_id)
END IF

IF cgi::RequestMethod() = "GET" THEN GOTO Enter_Customer
cust_id = cgi::PostParam("cust_id")
cust_name = cgi::PostParam("cust_name")
cust_addr = cgi::PostParam("cust_addr")
cust_city = cgi::PostParam("cust_city")
cust_state = cgi::PostParam("cust_state")
cust_zip = cgi::PostParam("cust_zip")
cust_phone = cgi::PostParam("cust_phone")

SQL = "INSERT INTO customer (cust_id, cust_name, cust_addr, cust_city, cust_state, cust_zip, cust_phone) VALUES ('" & cust_id & "', '" & cust_name & "', '" & cust_addr & "', '" & cust_city & "', '" & cust_state & "', '" & cust_zip & "', '" & cust_phone & "')"   
mysql::query(dbh, SQL)

SQL = "SELECT * FROM customer"
mysql::query(dbh, SQL)

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()
PRINT """
<html>
<head>
<title>Customer Master File list</title>
</head>
<body>
<table border="1">
  <tr>
    <th>ID</th>
    <th>Name</th>
    <th>Address</th>
    <th>City</th>
    <th>State</th>
    <th>Zip</th>
    <th>Phone</th>
  </tr>
"""
WHILE mysql::FetchHash(dbh, dbcol)
  PRINT """
  <tr>
    <td>""" & dbcol{"cust_id"} & """</td>
    <td>""" & dbcol{"cust_name"} & """</td>
    <td>""" & dbcol{"cust_addr"} & """</td>
    <td>""" & dbcol{"cust_city"} & """</td>
    <td>""" & dbcol{"cust_state"} & """</td>
    <td>""" & dbcol{"cust_zip"} & """</td>
    <td>""" & dbcol{"cust_phone"} & """</td>
  </tr>
"""
WEND
PRINT """
  <tr>
    <td colspan=7 align="left"><br><input type="button" value="Add New Customer" onClick="parent.location='/mtsb/webcustomer.sb'"></td>
  </tr>
</table>
</body>
</html>
"""
END

Enter_Customer:

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()

PRINT """
<html>
<head>
<title>Customer Master File Maintenance</title>
</head>
<body>
<form name="custform" method="POST" action="/mtsb/webcustomer.sb">
<table border="0">
  <tr>
    <td align="right">ID</td>
    <td><input type="text" name="cust_id" size="5"></td>
  </tr>
  <tr>
    <td align="right">Name</td>
    <td><input type="text" name="cust_name" size="30"></td>
  </tr>
  <tr>
    <td align="right">Address</td>
    <td><input type="text" name="cust_addr" size="30"></td>
   </tr>
  <tr>
    <td align="right">City</td>
    <td><input type="text" name="cust_city" size="20"></td>
  </tr>
  <tr>
    <td align="right">State</td>
    <td><input type="text" name="cust_state" size="5"></td>
  </tr>
  <tr>
    <td align="right">Zip</td>
    <td><input type="text" name="cust_zip" size="5"></td>
  </tr>
  <tr>
    <td align="right">Phone</td>
    <td><input type="text" name="cust_phone" size="20"></td>
  </tr>
  <tr>
    <td colspan=2 align="center"><br><input type="submit" value="Add Customer"></td>
  </tr>
</table>
</form>
</body>
</html>
"""

--- End code ---

MySQL - customer table

--- Code: ---CREATE TABLE `sbtest`.`customer` (
`cust_id` VARCHAR( 5 ) NOT NULL ,
`cust_name` VARCHAR( 30 ) NULL ,
`cust_addr` VARCHAR( 30 ) NULL ,
`cust_city` VARCHAR( 20 ) NULL ,
`cust_state` VARCHAR( 5 ) NULL ,
`cust_zip` VARCHAR( 5 ) NULL ,
`cust_phone` VARCHAR( 20 ) NULL ,
PRIMARY KEY ( `cust_id` )
) ENGINE = MYISAM ;

--- End code ---

JRS:
Here is the old Address Book Code Challenge example I modified to use in this example. This version is using the MySQL API directly and not using the CGI client/server interface with the database. My next post will show the CGI version of the Gtk form.

gtkcustomer.sb

--- Code: ---' All Basic address book challenge - 9/15/2008
'
' Basic Language: ScriptBasic 2.1 (Windows / Linux)
'
' Authors: Peter van Eerten - www.gtk-server.org
'          John Spikowski - www.scriptbasic.org

' GTK-server extension module
INCLUDE gtk.bas

' MySQL extension module
INCLUDE mysql.bas

' Connect to MySQL database
dbh = mysql::RealConnect("localhost","root","xxxx","sbtest")

SUB Fill_Data

' clear the list
gtk_list_store_clear(List_Store)

mysql::query(dbh,"SELECT * FROM customer")

WHILE mysql::FetchHash(dbh, dbrow)

gtk_list_store_append(List_Store, List_Iter)
gtk_list_store_set(List_Store, List_Iter, 0, dbrow{"cust_id"}, -1)
gtk_list_store_set(List_Store, List_Iter, 1, dbrow{"cust_name"}, -1)
gtk_list_store_set(List_Store, List_Iter, 2, dbrow{"cust_addr"}, -1)
gtk_list_store_set(List_Store, List_Iter, 3, dbrow{"cust_city"}, -1)
gtk_list_store_set(List_Store, List_Iter, 4, dbrow{"cust_state"}, -1)
gtk_list_store_set(List_Store, List_Iter, 5, dbrow{"cust_zip"}, -1)
gtk_list_store_set(List_Store, List_Iter, 6, dbrow{"cust_phone"}, -1)

WEND

END SUB


SUB Add_Edit_Data

' determine which mode we are
IF Add_Edit_Mode = 1 THEN
    gtk_list_store_append(List_Store, List_Iter)
END IF

' Get the etries, currently no checking
info[0] = gtk_entry_get_text(EntryID)
info[1] = gtk_entry_get_text(EntryName)
info[2] = gtk_entry_get_text(EntryAddress)
info[3] = gtk_entry_get_text(EntryCity)
info[4] = gtk_entry_get_text(EntryState)
info[5] = gtk_entry_get_text(EntryZip)
info[6] = gtk_entry_get_text(EntryPhone)

' Add mode, store the info into the list widget
FOR i = 0 TO 6
    gtk_list_store_set(List_Store, List_Iter, i, info[i], -1)
NEXT i

' Delete the entries
gtk_editable_delete_text(EntryID, 0, -1)
gtk_editable_delete_text(EntryName, 0, -1)
gtk_editable_delete_text(EntryAddress, 0, -1)
gtk_editable_delete_text(EntryCity, 0, -1)
gtk_editable_delete_text(EntryState, 0, -1)
gtk_editable_delete_text(EntryZip, 0, -1)
gtk_editable_delete_text(EntryPhone, 0, -1)

' Edit mode? Hide dialog
IF Add_Edit_Mode = 2 THEN
    gtk_widget_hide(Entry_Field)
    SQL = "UPDATE customer SET cust_id = '" & info[0] & "', cust_name = '" & info[1] & "', cust_addr = '" & info[2] & "', cust_city = '" & info[3] & "', cust_state = '" & info[4] & "', cust_zip = '" & info[5] & "', cust_phone = '" & info[6] & "'"
ELSE
    SQL = "INSERT INTO customer (cust_id, cust_name, cust_addr, cust_city, cust_state, cust_zip, cust_phone) VALUES ('" & info[0] & "', '" & info[1] & "', '" & info[2] & "', '" & info[3] & "', '" & info[4] & "', '" & info[5] & "', '" & info[6] & "')"
END IF

mysql::query(dbh, SQL)

END SUB


SUB Del_Data

' Check if a row is selected
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "1" THEN
    gtk_list_store_remove(List_Store, List_Iter)
    SQL = "DELETE FROM customer WHERE cust_id = " & info[0]
    mysql::query(dbh, SQL)
ELSE
    gtk_widget_show_all(Error_Msg)
END IF

END SUB

' MAIN program

' Optionally enable GTK logging
gtk_server_cfg("-log=log.txt")

' Get GLADE definition
xml = glade_xml_new("form.glade")
glade_xml_signal_autoconnect(xml)

' Get main window ID and connect signal
Main_Window = glade_xml_get_widget(xml, "Main_Window")
gtk_server_connect(Main_Window, "delete-event", "Main_Window")

' Get button IDs and connect signals
Add_Button = glade_xml_get_widget(xml, "Add_Button")
gtk_server_connect(Add_Button, "clicked", "Add_Button")
Del_Button = glade_xml_get_widget(xml, "Del_Button")
gtk_server_connect(Del_Button, "clicked", "Del_Button")
Edit_Button = glade_xml_get_widget(xml, "Edit_Button")
gtk_server_connect(Edit_Button, "clicked", "Edit_Button")
Exit_Button = glade_xml_get_widget(xml, "Exit_Button")
gtk_server_connect(Exit_Button, "clicked", "Exit_Button")

' Get scrolled window
Scrolled_Window =  glade_xml_get_widget(xml, "Scrolled_Window")

' Define the list
List_Iter = gtk_server_opaque()
GTK::gtk("gtk_server_redefine gtk_list_store_new NONE WIDGET 8 INT INT INT INT INT INT INT INT")
List_Store = GTK::gtk("gtk_list_store_new 7 64 64 64 64 64 64 64")
List_Choice = gtk_tree_view_new_with_model(List_Store)
GTK::gtk("gtk_server_connect " & List_Choice & " button-press-event " & List_Choice & " 1")
gtk_tree_view_set_headers_visible(List_Choice, 1)
gtk_tree_view_set_headers_clickable(List_Choice, 1)
gtk_tree_view_set_grid_lines(List_Choice, 3)
gtk_tree_sortable_set_sort_column_id(List_Store, 0, 0)
Tree_Sel = gtk_tree_view_get_selection(List_Choice)
gtk_tree_selection_set_mode(Tree_Sel, 2)
Txt_Cell = gtk_cell_renderer_text_new()
List_Column0 = gtk_tree_view_column_new_with_attributes("ID", Txt_Cell, "text", 0, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column0)
gtk_tree_view_column_set_resizable(List_Column0, 1)
gtk_tree_view_column_set_clickable(List_Column0, 1)
List_Column1 = gtk_tree_view_column_new_with_attributes("Name", Txt_Cell, "text", 1, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column1)
gtk_tree_view_column_set_resizable(List_Column1, 1)
List_Column2 = gtk_tree_view_column_new_with_attributes("Address", Txt_Cell, "text", 2, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column2)
gtk_tree_view_column_set_resizable(List_Column2, 1)
List_Column3 = gtk_tree_view_column_new_with_attributes("City", Txt_Cell, "text", 3, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column3)
gtk_tree_view_column_set_resizable(List_Column3, 1)
List_Column4 = gtk_tree_view_column_new_with_attributes("State", Txt_Cell, "text", 4, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column4)
gtk_tree_view_column_set_resizable(List_Column4, 1)
List_Column5 = gtk_tree_view_column_new_with_attributes("ZIP", Txt_Cell, "text", 5, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column5)
gtk_tree_view_column_set_resizable(List_Column5, 1)
List_Column6 = gtk_tree_view_column_new_with_attributes("Phone", Txt_Cell, "text", 6, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column6)
gtk_tree_view_column_set_resizable(List_Column6, 1)
gtk_container_add(Scrolled_Window, List_Choice)
gtk_widget_show_all(Scrolled_Window)

' Add entry window
Entry_Field = glade_xml_get_widget(xml, "Entry_Field")
gtk_server_connect(Entry_Field, "delete-event", "Entry_Field")

' Get button ID and connect signal
Entry_Ok_Button = glade_xml_get_widget(xml, "Entry_Ok_Button")
gtk_server_connect(Entry_Ok_Button, "clicked", "Entry_Ok_Button")
Entry_Can_Button = glade_xml_get_widget(xml, "Entry_Can_Button")
gtk_server_connect(Entry_Can_Button, "clicked", "Entry_Can_Button")

' Get ID's for the textentries
EntryID = glade_xml_get_widget(xml, "EntryID")
EntryName = glade_xml_get_widget(xml, "EntryName")
EntryAddress = glade_xml_get_widget(xml, "EntryAddress")
EntryCity = glade_xml_get_widget(xml, "EntryCity")
EntryState = glade_xml_get_widget(xml, "EntryState")
EntryZip = glade_xml_get_widget(xml, "EntryZip")
EntryPhone = glade_xml_get_widget(xml, "EntryPhone")

' Warning dialog, define here because of a bug in Glade
Warning_Msg = gtk_message_dialog_new(Main_Window, 1, 1, 4, "\nAre you sure to delete this entry?", "''")
gtk_window_set_title(Warning_Msg, "Warning")
gtk_server_connect(Warning_Msg, "delete-event", "Warning_Msg")
gtk_server_connect(Warning_Msg, "response", "Warning_Msg_Response")

' Warning dialog, define here because of a bug in Glade
Error_Msg = gtk_message_dialog_new(Main_Window, 1, 3, 2, "\nSelect an entry first!", "''")
gtk_window_set_title(Error_Msg, "Error!")
gtk_server_connect(Error_Msg, "delete-event", "Error_Msg")

' Fill grid with data
CALL Fill_Data()

' Set sort flag
Sort_Flag = 0

' Set edit or add mode - 1=ADD, 2=EDIT
Add_Edit_Mode = 1

' Mainloop starts here
REPEAT

    ' Get event
    event = gtk_server_callback("wait")

    ' Add entry form
    IF event = "Add_Button" THEN
Add_Edit_Mode = 1
gtk_window_set_title(Entry_Field, "Add entry")
gtk_widget_show_all(Entry_Field)
gtk_widget_grab_focus(EntryID)
    END IF

    ' Edit entry form
    IF event = "Edit_Button" THEN
Add_Edit_Mode = 2
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "0" THEN
    gtk_widget_show_all(Error_Msg)
ELSE
    FOR i = 0 TO 6
info[i] = gtk_tree_model_get(List_Store, List_Iter, i, "''", -1)
    NEXT i

    ' Get the etries, currently no checking
    gtk_entry_set_text(EntryID, MID(info[0], 4))
    gtk_entry_set_text(EntryName, MID(info[1], 4))
    gtk_entry_set_text(EntryAddress, MID(info[2], 4))
    gtk_entry_set_text(EntryCity, MID(info[3], 4))
    gtk_entry_set_text(EntryState, MID(info[4], 4))
    gtk_entry_set_text(EntryZip, MID(info[5], 4))
    gtk_entry_set_text(EntryPhone, MID(info[6], 4))

    gtk_window_set_title(Entry_Field, "Edit entry")
    gtk_widget_show_all(Entry_Field)
    gtk_widget_grab_focus(EntryID)

END IF
    END IF

    ' These are the buttons on the entry form
    IF event = "Entry_Can_Button" OR event = "Entry_Field" THEN
gtk_widget_hide(Entry_Field)

' Delete the entries
gtk_editable_delete_text(EntryID, 0, -1)
gtk_editable_delete_text(EntryName, 0, -1)
gtk_editable_delete_text(EntryAddress, 0, -1)
gtk_editable_delete_text(EntryCity, 0, -1)
gtk_editable_delete_text(EntryState, 0, -1)
gtk_editable_delete_text(EntryZip, 0, -1)
gtk_editable_delete_text(EntryPhone, 0, -1)
    END IF
    IF event = "Entry_Ok_Button" THEN
CALL Add_Edit_Data()
    END IF

    ' Warning dialog
    IF event = "Del_Button" THEN
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "0" THEN
    gtk_widget_show_all(Error_Msg)
ELSE
    gtk_widget_show_all(Warning_Msg)
END IF
    END IF
    IF event = "Warning_Msg" THEN gtk_widget_hide(Warning_Msg)
    IF event = "Warning_Msg_Response" THEN
response = gtk_server_callback_value(1, "INT")
IF response = -8 THEN CALL Del_Data()
gtk_widget_hide(Warning_Msg)
    END IF

    ' Error dialog
    IF event = "Error_Msg" OR event = Error_Msg THEN gtk_widget_hide(Error_Msg)

    ' Sortable on key
    IF event = List_Column0 THEN
Sort_Flag = 1 - Sort_Flag
gtk_tree_sortable_set_sort_column_id(List_Store, 0, Sort_Flag)
    END IF

UNTIL event = "Main_Window" OR event = "Exit_Button"

' Cleanup resources
gtk_server_exit()

--- End code ---

form.glade

--- Code: ---<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.4 on Sun Aug 31 20:12:55 2008 -->
<glade-interface>
  <widget class="GtkWindow" id="Entry_Field">
    <property name="title" translatable="yes">Entry</property>
    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
    <property name="destroy_with_parent">True</property>
    <property name="icon">supertux.xpm</property>
    <property name="transient_for">Main_Window</property>
    <child>
      <widget class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <child>
          <placeholder/>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox1">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="LabelId">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">ID: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryID">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox2">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="labelNAME">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">Name: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryName">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox3">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="label1">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">Address: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryAddress">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">3</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox4">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="label2">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">City: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryCity">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">4</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox5">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="label3">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">State: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryState">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">5</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox6">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="label4">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">ZIP code: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryZip">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">6</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox7">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkLabel" id="label5">
                <property name="width_request">100</property>
                <property name="visible">True</property>
                <property name="xalign">1</property>
                <property name="label" translatable="yes">Phone: </property>
              </widget>
              <packing>
                <property name="expand">False</property>
              </packing>
            </child>
            <child>
              <widget class="GtkEntry" id="EntryPhone">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </widget>
              <packing>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </widget>
          <packing>
            <property name="padding">1</property>
            <property name="position">7</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHSeparator" id="hseparator1">
            <property name="visible">True</property>
          </widget>
          <packing>
            <property name="expand">False</property>
            <property name="padding">4</property>
            <property name="position">8</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox8">
            <property name="visible">True</property>
            <property name="border_width">3</property>
            <child>
              <widget class="GtkButton" id="Entry_Can_Button">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="label" translatable="yes">gtk-close</property>
                <property name="use_stock">True</property>
                <property name="response_id">0</property>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <widget class="GtkButton" id="Entry_Ok_Button">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="label" translatable="yes">gtk-save</property>
                <property name="use_stock">True</property>
                <property name="response_id">0</property>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="pack_type">GTK_PACK_END</property>
                <property name="position">2</property>
              </packing>
            </child>
          </widget>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="padding">1</property>
            <property name="pack_type">GTK_PACK_END</property>
            <property name="position">9</property>
          </packing>
        </child>
      </widget>
    </child>
  </widget>
  <widget class="GtkWindow" id="Main_Window">
    <property name="width_request">500</property>
    <property name="height_request">400</property>
    <property name="visible">True</property>
    <property name="title" translatable="yes">Customer File Maintence</property>
    <property name="icon">supertux.xpm</property>
    <child>
      <widget class="GtkVBox" id="vbox2">
        <property name="visible">True</property>
        <child>
          <widget class="GtkMenuBar" id="menubar1">
            <property name="visible">True</property>
            <child>
              <widget class="GtkMenuItem" id="menuitem5">
                <property name="visible">True</property>
                <property name="label" translatable="yes">_File</property>
                <property name="use_underline">True</property>
                <child>
                  <widget class="GtkMenu" id="menu4">
                    <property name="visible">True</property>
                    <child>
                      <widget class="GtkImageMenuItem" id="imagemenuitem15">
                        <property name="visible">True</property>
                        <property name="label" translatable="yes">gtk-quit</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </widget>
                    </child>
                  </widget>
                </child>
              </widget>
            </child>
            <child>
              <widget class="GtkMenuItem" id="menuitem8">
                <property name="visible">True</property>
                <property name="label" translatable="yes">_Help</property>
                <property name="use_underline">True</property>
                <child>
                  <widget class="GtkMenu" id="menu6">
                    <property name="visible">True</property>
                    <child>
                      <widget class="GtkImageMenuItem" id="imagemenuitem20">
                        <property name="visible">True</property>
                        <property name="label" translatable="yes">gtk-about</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </widget>
                    </child>
                  </widget>
                </child>
              </widget>
            </child>
          </widget>
          <packing>
            <property name="expand">False</property>
          </packing>
        </child>
        <child>
          <widget class="GtkHBox" id="hbox9">
            <property name="visible">True</property>
            <property name="border_width">5</property>
            <child>
              <widget class="GtkFrame" id="frame1">
                <property name="visible">True</property>
                <property name="label_xalign">0</property>
                <child>
                  <widget class="GtkAlignment" id="alignment1">
                    <property name="visible">True</property>
                    <property name="top_padding">5</property>
                    <property name="bottom_padding">5</property>
                    <property name="left_padding">5</property>
                    <property name="right_padding">5</property>
                    <child>
                      <widget class="GtkScrolledWindow" id="Scrolled_Window">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="extension_events">GDK_EXTENSION_EVENTS_CURSOR</property>
                        <property name="border_width">2</property>
                        <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                        <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
                        <child>
                          <placeholder/>
                        </child>
                      </widget>
                    </child>
                  </widget>
                </child>
                <child>
                  <placeholder/>
                  <packing>
                    <property name="type">label_item</property>
                  </packing>
                </child>
              </widget>
              <packing>
                <property name="padding">5</property>
              </packing>
            </child>
            <child>
              <widget class="GtkFrame" id="frame2">
                <property name="visible">True</property>
                <property name="label_xalign">0</property>
                <child>
                  <widget class="GtkVBox" id="vbox3">
                    <property name="visible">True</property>
                    <property name="border_width">5</property>
                    <child>
                      <widget class="GtkButton" id="Add_Button">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="label" translatable="yes">gtk-add</property>
                        <property name="use_stock">True</property>
                        <property name="response_id">0</property>
                      </widget>
                      <packing>
                        <property name="expand">False</property>
                        <property name="padding">2</property>
                      </packing>
                    </child>
                    <child>
                      <widget class="GtkButton" id="Del_Button">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="label" translatable="yes">gtk-remove</property>
                        <property name="use_stock">True</property>
                        <property name="response_id">0</property>
                      </widget>
                      <packing>
                        <property name="expand">False</property>
                        <property name="padding">2</property>
                        <property name="position">1</property>
                      </packing>
                    </child>
                    <child>
                      <widget class="GtkButton" id="Edit_Button">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="label" translatable="yes">gtk-edit</property>
                        <property name="use_stock">True</property>
                        <property name="response_id">0</property>
                      </widget>
                      <packing>
                        <property name="expand">False</property>
                        <property name="padding">2</property>
                        <property name="position">2</property>
                      </packing>
                    </child>
                    <child>
                      <placeholder/>
                    </child>
                    <child>
                      <widget class="GtkButton" id="Exit_Button">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="label" translatable="yes">gtk-quit</property>
                        <property name="use_stock">True</property>
                        <property name="response_id">0</property>
                      </widget>
                      <packing>
                        <property name="expand">False</property>
                        <property name="padding">2</property>
                        <property name="pack_type">GTK_PACK_END</property>
                        <property name="position">4</property>
                      </packing>
                    </child>
                  </widget>
                </child>
                <child>
                  <placeholder/>
                  <packing>
                    <property name="type">label_item</property>
                  </packing>
                </child>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="padding">5</property>
                <property name="position">1</property>
              </packing>
            </child>
          </widget>
          <packing>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <widget class="GtkStatusbar" id="statusbar1">
            <property name="visible">True</property>
            <property name="spacing">2</property>
          </widget>
          <packing>
            <property name="expand">False</property>
            <property name="position">2</property>
          </packing>
        </child>
      </widget>
    </child>
  </widget>
</glade-interface>

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version