Skip to main content

Working with application preferences using 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.



#---------------
# 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
}

Comments

Popular posts from this blog

gnocl::calendar

Given this module some attention today. Added some of the more package wide options to the module and created customised handler for setting the month. (For some odd reason months are are counted 0-11 whereas days are 1-31.) There's still a little more to do to this one including the addition of code to store diary details. Here's the working test script to show the range of options at work. The percentage substitution string item %e explores something that I've been toying with, the name of the signal/event that initiated the call. Ok, a script can keep its own internal trace but who knows, it might prove useful. #--------------- # calendarTest.tcl #--------------- # Author:   William J Giddings # Date:     07/05/09 #--------------- #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" #--------------- package require Gnocl set cal [gnocl::calendar] $cal configure -day 8 -month 7 -year 1956 $cal configure -rowHeight 1 -colWidth 1 $ca

Gnocl Dashboard

Over the past few programming sessions I've been working on producing a central point, a dashboard, around which it's possible to see the various Gnocl widgets and commands in operation. In many ways like the demo script which shipped with the earlier releases of Gnocl but offers much more. The introspection functionality provides details of the various options and sub-commands of each Gnocl procedure which are displayed under the associated tab. Sample scripts are included for each item which offers newcomers a clearer insight into how make the most of what's on offer.

Changing Namespaces

I've been toying with the idea of changing the namespace used by gnocl, to something simplier, a proposition much more appealing now that I've begun migration to Gtk3 and soon to Gtk4. The changes from Gtk2 to Gtk4 will be subtantial due to many chages occuring within the Gtk api. Before committing myself, I thought how it would be useful to swap namespaces on the fly. So, here's a first quick solution:   package require -exact Gnocl 0.9.96 proc xxxx {ns1 ns2}  {     namespace eval ::${ns2} {}     set map [list $ns1 $ns2]          foreach type {commands vars procs } {         foreach item [info $type ${ns1}::*] {             set err ""             catch { rename $item [string map $map $item] } err             if { $err != "" } { puts $err }         }     }          namespace delete $ns1 } xxxx g set b1 [g::button -text BUTTON] set w1 [g::window -child $b1] set l1 [g::label -text rename] $w1 configure -child $l1 -title TEST