Application preferences with gnocl::keyFile

Its easy enough to load/save script settings as some form of serialization on an array, but what if we want to conform to Gtk+ standards and save settings as an *.ini file? The following script shows how this can be done.

https://lh3.googleusercontent.com/-pTBnyYEhr_Q/T7jBDV6xNmI/AAAAAAAABAE/9Uq6VysbhAw/s800/Screenshot-test-keyfile-2.tcl.png

#---------------
# test-keyfile.tcl
#---------------
# William J Giddings, 19/05/2012
#---------------

#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl

#---------------
# manipulate application preferences
#---------------
# preferences stored in global two-dimensional array name "prefs"
# array names are equivalent to the group/key pairings required for keyFile
#---------------
# args
#    cmd        one of load, edit, save
#    keyfile    name of keyfile to load/save, ignored for edit
# returns
#   none
#---------------
proc preferences {cmd {keyFile {} } } {

 global prefs

 switch $cmd {

    load {

        set kf [gnocl::keyFile load $keyFile]
        set prefs(comment) [$kf get comment]
       
        foreach group [$kf get groups] {
            foreach key [$kf get keys -group $group] {
                # assign each value
                set prefs($group,$key) [$kf get value -group $group -key $key]
                }
            }
        }

    edit {
       
        # make a copy of the prefs, might need undoing
        global _prefs
        foreach item [array names prefs] { set _prefs($item) $prefs($item) }

        # dialog response proc
        proc _responseProc {v} {
            global prefs _prefs
            switch $v {
                No {
                    foreach item [array names _prefs] { set prefs($item) $_prefs($item) }
                }
            }
            array unset _prefs
        } ;# _responseProc
       
        # preferences edit gui
        set box [gnocl::box -orientation vertical]
        set notebook [gnocl::notebook]
        set lgroup ""
        foreach item [lsort [array names prefs]] {
            if {$item == "comment"} { continue }
            foreach {group key} [split $item ,] {
                if { $group != $lgroup } {
                    set table($group) [gnocl::table -homogeneous 0]
                    $notebook addPage $table($group) $group
                }
                $table($group) addRow \
                    [list [gnocl::label -text $key -align right -maxWidthChars 10 -widthGroup 1] \
                          [gnocl::entry -variable prefs($group,$key) -data $prefs($group,$key)] ] \
                    -fill 1 -expand {0 0}
                set lgroup $group
            }
        }
        gnocl::dialog \
            -child $notebook \
            -buttons "{{%_C_ancel} %#No} {{%_O_kay} %#Yes}" \
            -onResponse "_responseProc %v"
        }

    save {
        set kf [gnocl::keyFile new]
        $kf set comment -value $prefs(comment)
        foreach item [array names prefs] {
            foreach {group key} [split $item ,] {
                $kf set string -group $group -key $key -value $prefs($item)
            }
        }
        $kf write $keyFile
        $kf free
        }
 } ;# end switch
   
}


if {1} {
    # create as sample .ini file
    set fp [open "sample_config.ini" w]
    puts $fp {
#---------------
# sample_config.ini
#---------------
# this is just an example
# there can be comments before the first group

[Batch]
base=/
path=

[Crop]
top=0
bottom=100
center=50
sides=100

[Scan]
type=tif
resolution=400
threshold=128
mode=binary
format=tiff
x=210
y=297
l=0
t=0
i=0
prefix=img-
last=0

[Page]
width=2480
height=3508
}

    close $fp

    preferences load sample_config.ini
    preferences edit

    parray prefs

    set prefs(comment) "---------------\n\tmy new tmp.ini\n---------------"
    preferences save tmp.ini
}