Initial revision
authorarjen <arjen>
Tue, 19 Nov 2002 19:21:18 +0000 (19:21 +0000)
committerarjen <arjen>
Tue, 19 Nov 2002 19:21:18 +0000 (19:21 +0000)
12 files changed:
src/coconf/README [new file with mode: 0644]
src/coconf/TODO [new file with mode: 0644]
src/coconf/coconf [new file with mode: 0755]
src/coconf/coconf.pyw [new file with mode: 0644]
src/coconf/cotest1.ccf [new file with mode: 0644]
src/coconf/cotest2.ccf [new file with mode: 0644]
src/coconf/cotest3.ccf [new file with mode: 0644]
src/coconf/cotest4.ccf [new file with mode: 0644]
src/coconf/cotk.py [new file with mode: 0644]
src/coconf/cotkwidget.py [new file with mode: 0644]
src/coconf/coxmlfile.py [new file with mode: 0644]
src/coconf/textbase.py [new file with mode: 0644]

diff --git a/src/coconf/README b/src/coconf/README
new file mode 100644 (file)
index 0000000..3359efb
--- /dev/null
@@ -0,0 +1,17 @@
+This is a testversion of CoConf, (c) Copyright 2002, Peter Roozemaal.
+
+    GnuCoMo/CoConf is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version. See the file COPYING.
+
+CoConf runs under Python 1.5 and later versions; it requires tkinter and xml
+support. Visit www.python.org for more information about Python or to download
+Python.
+
+The author can be contacted as mathfox@xs4all.nl.
+
+Known problems:
+    RedHat 7.3 + Python 2.2 (python2)
+        SystemError: Py_UNICODE and Tcl_UniChar differ in size
+        Workaround: use Python 1.5 (python)
diff --git a/src/coconf/TODO b/src/coconf/TODO
new file mode 100644 (file)
index 0000000..bd07da4
--- /dev/null
@@ -0,0 +1,5 @@
+TODO:
+    implement types <integer> and <float>
+    make a parser for expression evaluation
+    implement valid and enabled tags
+    check and improve documentation
diff --git a/src/coconf/coconf b/src/coconf/coconf
new file mode 100755 (executable)
index 0000000..51b25b5
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+# $Id: coconf,v 1.1 2002-11-19 19:21:18 arjen Exp $
+
+if [ -f coconf.pyw ]
+then
+       COCONFDIR=`pwd`
+elif [ -d /usr/local/share/coconf ]
+then
+       COCONFDIR=/usr/local/share/coconf 
+elif [ -d /opt/coconf ]
+then
+       COCONFDIR=/opt/coconf 
+elif [ -d /usr/share/coconf ]
+then
+       COCONFDIR=/usr/share/coconf 
+else
+       COCONFDIR=`pwd`
+fi
+
+export COCONFDIR
+
+python -OO ${COCONFDIR}/coconf.pyw "$@"
diff --git a/src/coconf/coconf.pyw b/src/coconf/coconf.pyw
new file mode 100644 (file)
index 0000000..adb3c9d
--- /dev/null
@@ -0,0 +1,19 @@
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+import sys
+import cotk
+from textbase import txt
+
+_id = "$Id: coconf.pyw,v 1.1 2002-11-19 19:21:18 arjen Exp $"
+
+if len(sys.argv) > 2:
+    print stderr, txt("usage", "usage: coconf [<file>]")
+main = cotk.Main()
+if len(sys.argv) == 2:
+    main.load(sys.argv[1])
+main.mainloop()
diff --git a/src/coconf/cotest1.ccf b/src/coconf/cotest1.ccf
new file mode 100644 (file)
index 0000000..86f619a
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<form name="form1" language="en" title="My first cocola form">
+       <translate language="nl" title="Mijn eerste cocola formulier"/>
+       <help language="en">
+               This is form level help text in english.
+       </help>
+       <help language="nl">
+               Dit is nederlandstalige hulp voor het formulier.
+       </help>
+       <boolean name="bool1" language="en" label="a toggle">
+               <translate language="nl" label="een aan/uit schakelaar"/>
+               <help language="en">
+                       Just try to toggle it!
+               </help>
+               <help language="nl">
+                       Druk eens op de schakelaar!
+               </help>
+       </boolean>
+       <boolean name="bool2" language="en" label="another toggle">
+               <translate language="nl" label="nog een schakelaar"/>
+               <help language="en">
+                       Try this one too!
+               </help>
+               <help language="nl">
+                       Probeer deze ook eens!
+               </help>
+       </boolean>
+</form>
diff --git a/src/coconf/cotest2.ccf b/src/coconf/cotest2.ccf
new file mode 100644 (file)
index 0000000..9e79a3d
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<form name="form1" language="en" title="My first cocola form">
+       <translate language="nl" title="Mijn eerste cocola formulier"/>
+       <help language="en">
+               This is form level help text in english.
+       </help>
+       <help language="nl">
+               Dit is nederlandstalige hulp voor het formulier.
+       </help>
+       <boolean name="bool1" language="en" label="a toggle">
+               <translate language="nl" label="een aan/uit schakelaar"/>
+               <help language="en">
+                       Just try to toggle it!
+               </help>
+               <help language="nl">
+                       Druk eens op de schakelaar!
+               </help>
+       </boolean>
+       <string name="str1" language="en" label="a stringfield">
+               <translate language="nl" label="tekst invoer"/>
+               <help language="en">
+                       Please enter some random text.
+               </help>
+               <help language="nl">
+                       Tik maar wat.
+               </help>
+       </string>
+</form>
diff --git a/src/coconf/cotest3.ccf b/src/coconf/cotest3.ccf
new file mode 100644 (file)
index 0000000..f05e87c
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<form name="form1" language="en" title="My first cocola form">
+       <translate language="nl" title="Mijn eerste cocola formulier"/>
+       <help language="en">
+               This is form level help text in english.
+       </help>
+       <help language="nl">
+               Dit is nederlandstalige hulp voor het formulier.
+       </help>
+       <boolean name="bool1" language="en" label="a toggle outside the group">
+               <translate language="nl" label="een aan/uit schakelaar buiten de groep"/>
+               <help language="en">
+                       Just try to toggle it!
+               </help>
+               <help language="nl">
+                       Druk eens op de schakelaar!
+               </help>
+       </boolean>
+    <group name="group1">
+        <boolean name="bool2" language="en" label="a toggle in a group">
+            <translate language="nl" label="een aan/uit schakelaar in een groep"/>
+            <help language="en">
+                Just try to toggle it!
+            </help>
+            <help language="nl">
+                Druk eens op de schakelaar!
+            </help>
+        </boolean>
+        <string name="str2" language="en" label="a stringfield in a group">
+            <translate language="nl" label="tekst invoer in een groep"/>
+            <help language="en">
+                Please enter some random text.
+            </help>
+            <help language="nl">
+                Tik maar wat.
+            </help>
+        </string>
+        <group name="nested">
+            <boolean name="bool1" language="en" label="a toggle (nested)">
+                <translate language="nl" label="een aan/uit schakelaar"/>
+                <help language="en">
+                    Just try to toggle it!
+                </help>
+                <help language="nl">
+                    Druk eens op de schakelaar!
+                </help>
+            </boolean>
+            <boolean name="bool2" language="en" label="another nested toggle">
+                <translate language="nl" label="nog een schakelaar"/>
+                <help language="en">
+                    Try this one too!
+                </help>
+                <help language="nl">
+                    Probeer deze ook eens!
+                </help>
+            </boolean>
+        </group>
+    </group>
+       <string name="str1" language="en" label="a stringfield outside the group">
+               <translate language="nl" label="tekst invoer buiten de groep"/>
+               <help language="en">
+                       Please enter some random text.
+               </help>
+               <help language="nl">
+                       Tik maar wat.
+               </help>
+       </string>
+</form>
diff --git a/src/coconf/cotest4.ccf b/src/coconf/cotest4.ccf
new file mode 100644 (file)
index 0000000..a3901d2
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<form name="form1" language="en" title="My first cocola form">
+       <translate language="nl" title="Mijn eerste cocola formulier"/>
+       <help language="en">
+               This is form level help text in english.
+       </help>
+       <help language="nl">
+               Dit is nederlandstalige hulp voor het formulier.
+       </help>
+       <boolean name="bool1" language="en" label="a toggle outside the group">
+               <translate language="nl" label="een aan/uit schakelaar buiten de groep"/>
+               <help language="en">
+                       Just try to toggle it!
+               </help>
+               <help language="nl">
+                       Druk eens op de schakelaar!
+               </help>
+       </boolean>
+    <ruler/>
+    <group name="group1">
+        <ruler/>
+        <boolean name="bool2" language="en" label="a toggle in a group">
+            <translate language="nl" label="een aan/uit schakelaar in een groep"/>
+            <help language="en">
+                Just try to toggle it!
+            </help>
+            <help language="nl">
+                Druk eens op de schakelaar!
+            </help>
+        </boolean>
+        <string name="str2" language="en" label="a stringfield in a group">
+            <translate language="nl" label="tekst invoer in een groep"/>
+            <help language="en">
+                Please enter some random text.
+            </help>
+            <help language="nl">
+                Tik maar wat.
+            </help>
+        </string>
+        <ruler/>
+        <group name="nested">
+            <ruler/>
+            <boolean name="bool1" language="en" label="a toggle (nested)">
+                <translate language="nl" label="een aan/uit schakelaar"/>
+                <help language="en">
+                    Just try to toggle it!
+                </help>
+                <help language="nl">
+                    Druk eens op de schakelaar!
+                </help>
+            </boolean>
+            <boolean name="bool2" language="en" label="another nested toggle">
+                <translate language="nl" label="nog een schakelaar"/>
+                <help language="en">
+                    Try this one too!
+                </help>
+                <help language="nl">
+                    Probeer deze ook eens!
+                </help>
+            </boolean>
+            <ruler/>
+        </group>
+        <ruler/>
+    </group>
+    <ruler/>
+       <string name="str1" language="en" label="a stringfield outside the group">
+               <translate language="nl" label="tekst invoer buiten de groep"/>
+               <help language="en">
+                       Please enter some random text.
+               </help>
+               <help language="nl">
+                       Tik maar wat.
+               </help>
+       </string>
+</form>
diff --git a/src/coconf/cotk.py b/src/coconf/cotk.py
new file mode 100644 (file)
index 0000000..425f379
--- /dev/null
@@ -0,0 +1,232 @@
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+# TODO: error handling
+
+import string
+import Tkinter
+import tkFileDialog
+import tkMessageBox
+import coxmlfile
+import cotkwidget
+import textbase
+import tkFont
+from textbase import txt
+
+_id = "$Id: cotk.py,v 1.1 2002-11-19 19:21:18 arjen Exp $"
+
+version = "0.0.1 $Date: 2002-11-19 19:21:18 $"
+
+copy = "Copyright (C) 2002, Peter Roozemaal"
+
+licence = txt("lice", "CoConf is free software; you may distribute it under the terms of the GNU General Public License")
+
+ids = ( "CoConf Version "+version, "", copy, licence, "",
+        _id, cotkwidget._id, coxmlfile._id, textbase._id )
+
+def is_a_form(dom):
+    return dom.documentElement.tagName == "form"
+
+# toplevel window
+class Main(Tkinter.Frame):
+    # TODO: translation
+    filetypes_forms = (
+        ( "Cocola forms", ".ccf" ),
+        ( "All files", ".*" )
+    )
+    filetypes_load = (
+        ( "Coconf files", ".ccs" ),
+        ( "Coconf files", ".ccx" ),
+        ( "Coconf files", ".gcm" ),
+        ( "Coconf save files", ".ccs" ),
+        ( "Coconf export files", ".ccx" ),
+        ( "Gnucomo configuration files", ".gcm" ),
+        ( "All files", ".*" )
+    )
+    filetypes_save = (
+        ( "Coconf save files", ".ccs" ),
+        ( "All files", ".*" )
+    )
+    filetypes_exp = (
+        ( "Coconf export files", ".ccx" ),
+        ( "Gnucomo configuration files", ".gcm" ),
+        ( "All files", ".*" )
+    )
+    def __init__(self, master=None):
+        Tkinter.Frame.__init__(self, master)
+        # The following command is important for security; it disables
+        # remote control and spying via the send command.
+        try:
+            self.tk.call(("rename", "send", ""))
+        except Tkinter.TclError:
+            pass
+        self.pack(expand=1, fill="both")
+        self.master.title(txt("ctitle", "Coconf configuration editor"))
+        self.menubar = MenuBar(self)
+        self.menubar.pack(side="top", fill="x")
+        self.status = StatusBar(self)
+        self.status.pack(side="bottom", fill="x")
+        self.main = MainFrame(self)
+        self.main.pack(side="top", fill="both", expand=1)
+        self.filename = ""
+        self.formname = ""
+    def load(self, file):
+        dom = coxmlfile.load_from_file(file)
+        if is_a_form(dom):
+            self.main.new_form(dom)
+            self.status.set_formname(file)
+            self.formname = file
+            self.menubar.helpmenu.entryconfigure(2, state="normal")
+        # TODO: process datafiles
+        dom.unlink()
+    def save(self, file, export):
+        document = coxmlfile.Document()
+        self.main.value_dom(document, export)
+        if not export:
+            document.documentElement.setAttribute("formfile", self.formname)
+        f = open(file, "w")
+        document.writexml(f)
+        f.close()
+        document.unlink()
+    def load_form(self):
+        filename = tkFileDialog.askopenfilename(filetypes=self.filetypes_forms)
+        if filename:
+            self.load(filename)
+    def load_file(self):
+        filename = tkFileDialog.askopenfilename(filetypes=self.filetypes_load)
+        if filename:
+            self.load(filename)
+    def save_file(self):
+        if self.filename:
+            self.save(self.filename, 0)
+        else:
+            self.save_as()
+    def save_copy(self):
+        filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_save,
+                                                   defaultextension=".ccs")
+        if filename:
+            self.save(filename, 0)
+    def save_as(self):
+        filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_save,
+                                                   defaultextension=".ccs")
+        if filename:
+            self.save(filename, 0)
+            self.filename = filename
+    def export(self):
+        filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_exp,
+                                                   defaultextension=".ccx")
+        if filename:
+            self.save(filename, 1)
+    def formhelp(self):
+        self.main.form.provide_help()
+    def about(self):
+        cotkwidget.HelpWin("About CoConf", string.join(ids, '\n'))
+    def help(self):
+        tkMessageBox.showerror(title=txt("sorry", "Sorry"),
+                               message=txt("findhelp", "Can't find helpfile."))
+
+# menu bar
+class MenuBar(Tkinter.Frame):
+    def __init__(self, master):
+        Tkinter.Frame.__init__(self, master, relief="raised", borderwidth=2)
+
+        self.file = Tkinter.Menubutton(self, text=txt("mfile", "File"))
+        self.file.pack(side="left")
+        self.filemenu = Tkinter.Menu(self.file)
+        self.filemenu.add_command(label=txt("mform", "Form..."),
+                                   command=master.load_form)
+        self.filemenu.add_command(label=txt("mopen", "Open..."),
+                                   command=master.load_file)
+        self.filemenu.add_command(label=txt("msave", "Save"),
+                                   command=master.save_file)
+        self.filemenu.add_command(label=txt("msaveas", "Save as..."),
+                                   command=master.save_as)
+        self.filemenu.add_command(label=txt("msavecopy", "Save copy..."),
+                                   command=master.save_as)
+        self.filemenu.add_command(label=txt("mexport", "Export..."),
+                                   command=master.export)
+        self.filemenu.add_command(label=txt("mquit", "Quit"),
+                                   command=master.quit)
+        self.file["menu"] = self.filemenu
+
+        self.set = Tkinter.Menubutton(self, text=txt("mset", "Settings"),
+                                      state="disabled")
+        self.set.pack(side="left")
+
+        self.help = Tkinter.Menubutton(self, text=txt("mhelp", "Help"))
+        self.help.pack(side="right")
+        self.helpmenu = Tkinter.Menu(self.help)
+        self.helpmenu.add_command(label=txt("mwork", "Working..."),
+                                   command=master.help)
+        self.helpmenu.add_command(label=txt("mform", "Form..."),
+                                   state="disabled", command=master.formhelp)
+        self.helpmenu.add_separator()
+        self.helpmenu.add_command(label=txt("mabout", "About..."),
+                                   command=master.about)
+        self.help["menu"] = self.helpmenu
+
+# main form window with scrollbars
+class MainFrame(Tkinter.Frame):
+    def __init__(self, master):
+        Tkinter.Frame.__init__(self, master)
+        self.canvas = Tkinter.Canvas(self, scrollregion=(0, 0, 200, 200))
+        self.canvas.grid(row=0, column=0, sticky="news")
+        self.scrollY = Tkinter.Scrollbar(self, orient=Tkinter.VERTICAL,
+                                         command=self.canvas.yview)
+        self.scrollY.grid(row=0, column=1, sticky="ns")
+        self.canvas["yscrollcommand"] = self.scrollY.set
+        self.scrollX = Tkinter.Scrollbar(self, orient=Tkinter.HORIZONTAL,
+                                         command=self.canvas.xview)
+        self.scrollX.grid(row=1, column=0, sticky="ew")
+        self.canvas["xscrollcommand"] = self.scrollX.set
+        self.grid_columnconfigure(0, weight=1, minsize=0)
+        self.grid_rowconfigure(0, weight=1, minsize=0)
+        self.formid = None
+        self.form = None
+    def new_form(self, dom):
+        if self.formid != None:
+            self.canvas.delete(self.formid)
+        if self.form != None:
+            self.form.cleanup()
+        self.form = cotkwidget.FormWin(self.canvas, dom.documentElement)
+        self.formid = self.canvas.create_window(0, 0, window=self.form,
+                                                anchor="nw")
+        self.canvas.update();
+        self.canvas["scrollregion"] = self.canvas.bbox("all")
+    def value_dom(self, dom, flags):
+        self.form.value_dom(dom, dom, flags)
+
+# the status bar
+class StatusBar(Tkinter.Frame):
+    def __init__(self, master):
+        Tkinter.Frame.__init__(self, master, relief="raised", borderwidth=2)
+        self.lform = Tkinter.Label(self, text=txt("noform", "<no form>"),
+                                   relief="sunken", borderwidth=2)
+        self.lform.pack(side="left")
+        self.lfile = Tkinter.Label(self, text=txt("nofile", "<no file>"),
+                                   relief="sunken", borderwidth=2)
+        self.lfile.pack(side="left")
+        self.modinc = Tkinter.Label(self, text=" ", relief="sunken",
+                                    borderwidth=2)
+        self.modinc.pack(side="left")
+        self.filler = Tkinter.Label(self, relief="sunken", borderwidth=2)
+        self.filler.pack(side="right", fill="x", expand=1)
+    def set_filename(self, name):
+        if name:
+            self.lfile["text"] = name
+        else:
+            self.lfile["text"] = txt("nofile", "<no file>")
+    def set_formname(self, name):
+        if name:
+            self.lform["text"] = name
+        else:
+            self.lform["text"] = txt("noform", "<no form>")
+    def set_modified(self, mod):
+        if mod:
+            self.modinc["text"] = "*"
+        else:
+            self.modinc["text"] = " "
diff --git a/src/coconf/cotkwidget.py b/src/coconf/cotkwidget.py
new file mode 100644 (file)
index 0000000..21dc381
--- /dev/null
@@ -0,0 +1,222 @@
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+"The widget definitions that build a form"
+
+import string
+import os
+import Tkinter
+import tkMessageBox
+import ScrolledText
+from textbase import txt
+
+_id = "$Id: cotkwidget.py,v 1.1 2002-11-19 19:21:18 arjen Exp $"
+
+_helpwins = {}
+
+class HelpWin(Tkinter.Toplevel):
+    def __init__(self, item, text):
+        global _helpwins
+        Tkinter.Toplevel.__init__(self)
+        self.title(txt("helpon","help on")+" "+item)
+        _helpwins[item] = self
+        self.name = item
+        self.bind("<Destroy>", self.cleanup)
+        self.textwin = ScrolledText.ScrolledText(self, takefocus=0, wrap="word")
+        self.textwin.pack(side="top")
+        self.textwin.insert("1.0", text)
+        self.textwin["state"] = "disabled"
+        self.button = Tkinter.Button(self, text=txt("thanks", "Thank You"),
+                                     relief="groove", borderwidth=4,
+                                     command=self.destroy)
+        self.button.pack(side="bottom")
+    def cleanup(self, event):
+        if _helpwins.has_key(self.name):
+            del _helpwins[self.name]
+
+class _BaseWidget:
+    widgetname = ""
+    curhelp = ""
+    defhelp = ""
+    help = {}
+
+    def cleanup(self):
+        self.destroy()
+
+    def readDom(self, dom):
+        self.widgetname = dom.getAttribute("name")
+        for i in self.translate:
+            att = dom.getAttribute(i)
+            setattr(self, "cur"+i, att)
+            setattr(self, "def"+i, att)
+            setattr(self, i, {})
+            getattr(self, i)[dom.getAttribute("language")] = att
+        el = dom.firstChild
+        while el != None:
+            if el.nodeType == el.ELEMENT_NODE:
+                if el.tagName == "help":
+                    self.readHelp(el)
+                elif el.tagName == "translate":
+                    self.readTrans(el)
+                else:
+                    print self.widgetname, "bad element:", el.tagName
+            #else:
+                #print self.widgetname, "bad xml node:", el.nodeName
+            el = el.nextSibling
+
+    def readHelp(self, dom):
+        lang = dom.getAttribute("language")
+        text = ""
+        el = dom.firstChild
+        while el != None:
+            if el.nodeType == el.TEXT_NODE:
+                text = text + el.data
+            el = el.nextSibling
+        text = string.join(string.split(text))
+        if self.curhelp == "":
+            self.curhelp = text
+        if self.defhelp == "":
+            self.defhelp = text
+        self.help[lang] = text
+
+    def readTrans(self, dom):
+        pass
+
+    def provide_help(self):
+        if _helpwins.has_key(self.widgetname):
+            _helpwins[self.widgetname].lift()
+        elif self.curhelp:
+            HelpWin(self.widgetname, self.curhelp)
+        else:
+            tkMessageBox.showinfo(title=txt("sorry", "Sorry"),
+                                  message=txt("nohelp", "The creator of the form didn't provide a help message."))
+
+    def value_dom(self, document, parent, flags):
+        #TODO: check flags
+        node = document.createElement("variable")
+        node.setAttribute("name", self.widgetname)
+        #the next line isn't OO clean
+        node.setAttribute("value", str(self.variable.get()))
+        parent.appendChild(node)
+
+class _ComposedWidget(_BaseWidget):
+    def readDom(self, dom):
+        self.widgetname = dom.getAttribute("name")
+        for i in self.translate:
+            att = dom.getAttribute(i)
+            setattr(self, "cur"+i, att)
+            setattr(self, "def"+i, att)
+            setattr(self, i, {})
+            getattr(self, i)[dom.getAttribute("language")] = att
+        el = dom.firstChild
+        while el != None:
+            if el.nodeType == el.ELEMENT_NODE:
+                if el.tagName == "help":
+                    self.readHelp(el)
+                elif el.tagName == "translate":
+                    self.readTrans(el)
+                elif _subwidgets.has_key(el.tagName):
+                    w = _subwidgets[el.tagName](self, el)
+                    self.add_widget(w)
+                else:
+                    print self.widgetname, "bad element:", el.tagName
+            #else:
+                #print self.widgetname, "bad xml node:", el.nodeName
+            el = el.nextSibling
+
+class FormWin(Tkinter.Frame, _ComposedWidget):
+    translate = ( "title", )
+    def __init__(self, master, dom):
+        Tkinter.Frame.__init__(self, master)
+        self.wlist = []
+        self.readDom(dom)
+    def cleanup(self):
+        for sub in self.wlist:
+            sub.cleanup()
+        self.destroy()
+    def add_widget(self, wid):
+        self.wlist.append(wid)
+        wid.pack(side="top", fill="x")
+    def value_dom(self, document, parent, flags):
+        if flags:
+            node = document.createElement("export")
+        else:
+            node = document.createElement("save")
+        node.setAttribute("form", self.widgetname)
+        parent.appendChild(node)
+        for sub in self.wlist:
+            sub.value_dom(document, node, flags)
+
+class Group(Tkinter.Frame, _ComposedWidget):
+    translate = ()
+    def __init__(self, master, dom):
+        Tkinter.Frame.__init__(self, master)
+        self.wlist = []
+        self.filler = Tkinter.Frame(self, width="7m")
+        self.filler.pack(side="left", fill="y")
+        self.inner = Tkinter.Frame(self)
+        self.inner.pack(side="right", fill="both", expand=1)
+        self.readDom(dom)
+    def cleanup(self):
+        for sub in self.wlist:
+            sub.cleanup()
+        self.destroy()
+    def add_widget(self, wid):
+        self.wlist.append(wid)
+        wid.pack(side="top", fill="x", in_=self.inner)
+    def value_dom(self, document, parent, flags):
+        #TODO: check flags
+        node = document.createElement("group")
+        node.setAttribute("name", self.widgetname)
+        parent.appendChild(node)
+        for sub in self.wlist:
+            sub.value_dom(document, node, flags)
+
+class Boolean(Tkinter.Frame, _BaseWidget):
+    translate = ( "label", )
+    def __init__(self, master, dom):
+        Tkinter.Frame.__init__(self, master)
+        self.readDom(dom)
+        self.button = Tkinter.Checkbutton(self, text=self.curlabel)
+        self.button.pack(side="left")
+        self.variable = Tkinter.BooleanVar()
+        self.button["variable"] = self.variable
+        if os.name == "posix":
+            self.button["selectcolor"] = "green"
+        self.helpbutton = Tkinter.Button(self, text=txt("lhelp", "?"),
+                                         command=self.provide_help)
+        self.helpbutton.pack(side="right")
+
+class String(Tkinter.Frame, _BaseWidget):
+    translate = ( "label", )
+    def __init__(self, master, dom):
+        Tkinter.Frame.__init__(self, master)
+        self.readDom(dom)
+        self.label = Tkinter.Label(self, text=self.curlabel)
+        self.label.pack(side="left")
+        self.variable = Tkinter.StringVar()
+        self.veld = Tkinter.Entry(self, textvariable=self.variable)
+        self.helpbutton = Tkinter.Button(self, text=txt("lhelp", "?"),
+                                         command=self.provide_help)
+        self.helpbutton.pack(side="right")
+        self.veld.pack(side="right", fill="x")
+
+class Ruler(Tkinter.Frame):
+    def __init__(self, master, dom):
+        Tkinter.Frame.__init__(self, master, relief="sunken", height=4,
+                               borderwidth=2)
+    def value_dom(self, document, parent, flags):
+        pass
+    def cleanup(self):
+        self.destroy()
+
+_subwidgets = {
+    "boolean" : Boolean,
+    "group" : Group,
+    "ruler" : Ruler,
+    "string" : String
+}
diff --git a/src/coconf/coxmlfile.py b/src/coconf/coxmlfile.py
new file mode 100644 (file)
index 0000000..f3a0366
--- /dev/null
@@ -0,0 +1,42 @@
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+import string
+from xml.dom.minidom import parse, Document
+
+_id = "$Id: coxmlfile.py,v 1.1 2002-11-19 19:21:18 arjen Exp $"
+
+def emptytext(node):
+    return node.nodeType == node.TEXT_NODE and string.strip(node.data) == ""
+
+# NOTE: the normalise function doesn't work under python 2.0.
+def normalise(xmlnode):
+    "We strip blanks-only text nodes"
+    child = xmlnode.firstChild
+    while child != None:
+        if emptytext(child):
+            remove = child
+            child = child.nextSibling
+            xmlnode.removeChild(remove)
+            remove.unlink()
+        else:
+            if child.hasChildNodes():
+                normalise(child)
+            child = child.nextSibling
+    return xmlnode;
+
+def load_from_file(filename):
+    file = open(filename, "r")
+    dom = parse(file)
+    file.close()
+#   return normalise(dom)
+    return dom
+
+def save_to_file(dom, filename):
+    file = open(filename, "w")
+    dom.writexml(file)
+    file.close()
diff --git a/src/coconf/textbase.py b/src/coconf/textbase.py
new file mode 100644 (file)
index 0000000..82909b0
--- /dev/null
@@ -0,0 +1,22 @@
+#   Copyright (C) 2002, Peter Roozemaal.
+#
+# GnuCoMo/CoConf is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.  See the file COPYING.
+
+"""The textbase module implements the internationalisation interface for the
+   coconf application.
+
+Exported functions:
+    txt(tag, default) - localise a string
+    TODO!
+"""
+
+_id = "$Id: textbase.py,v 1.1 2002-11-19 19:21:18 arjen Exp $"
+
+def txt(tag, default):
+    """Returns the localised string for tag;
+       default if no string can be found in localisation database"""
+    #TODO!
+    return default