After you have a feeling for the Fx interfaces, it's easy to put together nice applications in a jiffy. As an example, let's add some custom features to our little Invoices application.
One useful function for invoices might be an auto-increment invoice number with a prefix, say ``HPC''. We would like to add a unique invoice number each time we add a new record, so we might add the following to our QddbScript:
;# ... [code value={ ;# implements autoincrement by 123, starting at 1000000, with ;# a prefix of "HPC". proc MyInvoiceNumber {prefix min increment} { global gv_attr set filename [qddb_schema path [menubar cget -schema]]/.nextinv if {[catch {open $filename r+} fd] != 0} { set next $min if {[catch {open $filename w+} fd] != 0} { Fx:Dialog .dialog "Cannot open $filename" return } qddb_util flock $fd LOCK_EX } else { qddb_util flock $fd LOCK_EX set next [read $fd] } set gv_attr(Number) "$prefix$next" incr next $increment seek $fd 0 start ;# rewind to beginning of file puts -nonewline $fd $next flush $fd qddb_util flock $fd LOCK_UN close $fd } menubar configure -afteraddmode { MyInvoiceNumber HPC 1000000 123 } }] ;# ... [epilogue]
Next, we might like to recalculate subtotal, tax, and total each time these fields change. For this purpose, it makes sense to perform the calculations each time the focus leaves one of the important fields:
;# ... [code value={ proc Recalculate {} { global fx:mode_variable myview if {"${fx:mode_variable}" != "Add Mode"} { return } set tuple [menubar cget -tuple] set view [qddb_view define $tuple { {Items.Qty myview(Items.Qty)} {Items.Taxable myview(Items.Taxable)} {Items.Price myview(Items.Price)} {Items.Total myview(Items.Total)} {Subtotal myview(Subtotal)} {Tax myview(Tax)} {AmountDue myview(AmountDue)} {PaymentAmount myview(PaymentAmount)} {Discounts myview(Discounts)} {Total myview(Total)} }] set max [qddb_instance maxnum $view Items] set myview(Tax) 0.00 set myview(Subtotal) 0.00 set myview(Total) 0.00 for {set i 1} {$i <= $max} {incr i} { qddb_instance switch $view Items $i catch { set myview(Items.Total) [expr \ $myview(Items.Qty) * $myview(Items.Price) \ ] set myview(Subtotal) [expr $myview(Subtotal) \ + $myview(Items.Total)] if {"$myview(Items.Taxable)" != "N"} { set myview(Tax) [format "%.2f" [expr $myview(Tax) \ + ($myview(Items.Total) * 0.06)]] } } } catch { set myview(Total) [expr $myview(Subtotal) + \ $myview(Tax) - $myview(Discounts)] } set myview(AmountDue) [expr $myview(Total) - $myview(PaymentAmount)] ;# force GUI to re-read variables qddb_view refresh [menubar cget -view] update idletasks qddb_view delete $view unset myview } bind Entry <FocusOut> {+Recalculate} bind Radiobutton <FocusOut> {+Recalculate} }] ;# ... [epilogue]
You can retrieve a full copy of this QddbScript and the associated Schema from ftp://ftp.hsdi.com/pub/qddb/sources/QddbScript-example.tar.gz. To try it out, simply unpack the archive in a newly created database directory.
qnewdb Invoices cd Invoices gunzip -c ~/QddbScript-example.tar.gz | tar -xvf - nxqddb .
Enjoy!
The Qddb Team