Initial revision
[gnucomo.git] / src / coconf / cotk.py
1 #   Copyright (C) 2002, Peter Roozemaal.
2 #
3 # GnuCoMo/CoConf is free software; you may redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2, or (at your option)
6 # any later version.  See the file COPYING.
7
8 # TODO: error handling
9
10 import string
11 import Tkinter
12 import tkFileDialog
13 import tkMessageBox
14 import coxmlfile
15 import cotkwidget
16 import textbase
17 import tkFont
18 from textbase import txt
19
20 _id = "$Id: cotk.py,v 1.1 2002-11-19 19:21:18 arjen Exp $"
21
22 version = "0.0.1 $Date: 2002-11-19 19:21:18 $"
23
24 copy = "Copyright (C) 2002, Peter Roozemaal"
25
26 licence = txt("lice", "CoConf is free software; you may distribute it under the terms of the GNU General Public License")
27
28 ids = ( "CoConf Version "+version, "", copy, licence, "",
29         _id, cotkwidget._id, coxmlfile._id, textbase._id )
30
31 def is_a_form(dom):
32     return dom.documentElement.tagName == "form"
33
34 # toplevel window
35 class Main(Tkinter.Frame):
36     # TODO: translation
37     filetypes_forms = (
38         ( "Cocola forms", ".ccf" ),
39         ( "All files", ".*" )
40     )
41     filetypes_load = (
42         ( "Coconf files", ".ccs" ),
43         ( "Coconf files", ".ccx" ),
44         ( "Coconf files", ".gcm" ),
45         ( "Coconf save files", ".ccs" ),
46         ( "Coconf export files", ".ccx" ),
47         ( "Gnucomo configuration files", ".gcm" ),
48         ( "All files", ".*" )
49     )
50     filetypes_save = (
51         ( "Coconf save files", ".ccs" ),
52         ( "All files", ".*" )
53     )
54     filetypes_exp = (
55         ( "Coconf export files", ".ccx" ),
56         ( "Gnucomo configuration files", ".gcm" ),
57         ( "All files", ".*" )
58     )
59     def __init__(self, master=None):
60         Tkinter.Frame.__init__(self, master)
61         # The following command is important for security; it disables
62         # remote control and spying via the send command.
63         try:
64             self.tk.call(("rename", "send", ""))
65         except Tkinter.TclError:
66             pass
67         self.pack(expand=1, fill="both")
68         self.master.title(txt("ctitle", "Coconf configuration editor"))
69         self.menubar = MenuBar(self)
70         self.menubar.pack(side="top", fill="x")
71         self.status = StatusBar(self)
72         self.status.pack(side="bottom", fill="x")
73         self.main = MainFrame(self)
74         self.main.pack(side="top", fill="both", expand=1)
75         self.filename = ""
76         self.formname = ""
77     def load(self, file):
78         dom = coxmlfile.load_from_file(file)
79         if is_a_form(dom):
80             self.main.new_form(dom)
81             self.status.set_formname(file)
82             self.formname = file
83             self.menubar.helpmenu.entryconfigure(2, state="normal")
84         # TODO: process datafiles
85         dom.unlink()
86     def save(self, file, export):
87         document = coxmlfile.Document()
88         self.main.value_dom(document, export)
89         if not export:
90             document.documentElement.setAttribute("formfile", self.formname)
91         f = open(file, "w")
92         document.writexml(f)
93         f.close()
94         document.unlink()
95     def load_form(self):
96         filename = tkFileDialog.askopenfilename(filetypes=self.filetypes_forms)
97         if filename:
98             self.load(filename)
99     def load_file(self):
100         filename = tkFileDialog.askopenfilename(filetypes=self.filetypes_load)
101         if filename:
102             self.load(filename)
103     def save_file(self):
104         if self.filename:
105             self.save(self.filename, 0)
106         else:
107             self.save_as()
108     def save_copy(self):
109         filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_save,
110                                                    defaultextension=".ccs")
111         if filename:
112             self.save(filename, 0)
113     def save_as(self):
114         filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_save,
115                                                    defaultextension=".ccs")
116         if filename:
117             self.save(filename, 0)
118             self.filename = filename
119     def export(self):
120         filename = tkFileDialog.asksaveasfilename(filetypes=self.filetypes_exp,
121                                                    defaultextension=".ccx")
122         if filename:
123             self.save(filename, 1)
124     def formhelp(self):
125         self.main.form.provide_help()
126     def about(self):
127         cotkwidget.HelpWin("About CoConf", string.join(ids, '\n'))
128     def help(self):
129         tkMessageBox.showerror(title=txt("sorry", "Sorry"),
130                                message=txt("findhelp", "Can't find helpfile."))
131
132 # menu bar
133 class MenuBar(Tkinter.Frame):
134     def __init__(self, master):
135         Tkinter.Frame.__init__(self, master, relief="raised", borderwidth=2)
136
137         self.file = Tkinter.Menubutton(self, text=txt("mfile", "File"))
138         self.file.pack(side="left")
139         self.filemenu = Tkinter.Menu(self.file)
140         self.filemenu.add_command(label=txt("mform", "Form..."),
141                                    command=master.load_form)
142         self.filemenu.add_command(label=txt("mopen", "Open..."),
143                                    command=master.load_file)
144         self.filemenu.add_command(label=txt("msave", "Save"),
145                                    command=master.save_file)
146         self.filemenu.add_command(label=txt("msaveas", "Save as..."),
147                                    command=master.save_as)
148         self.filemenu.add_command(label=txt("msavecopy", "Save copy..."),
149                                    command=master.save_as)
150         self.filemenu.add_command(label=txt("mexport", "Export..."),
151                                    command=master.export)
152         self.filemenu.add_command(label=txt("mquit", "Quit"),
153                                    command=master.quit)
154         self.file["menu"] = self.filemenu
155
156         self.set = Tkinter.Menubutton(self, text=txt("mset", "Settings"),
157                                       state="disabled")
158         self.set.pack(side="left")
159
160         self.help = Tkinter.Menubutton(self, text=txt("mhelp", "Help"))
161         self.help.pack(side="right")
162         self.helpmenu = Tkinter.Menu(self.help)
163         self.helpmenu.add_command(label=txt("mwork", "Working..."),
164                                    command=master.help)
165         self.helpmenu.add_command(label=txt("mform", "Form..."),
166                                    state="disabled", command=master.formhelp)
167         self.helpmenu.add_separator()
168         self.helpmenu.add_command(label=txt("mabout", "About..."),
169                                    command=master.about)
170         self.help["menu"] = self.helpmenu
171
172 # main form window with scrollbars
173 class MainFrame(Tkinter.Frame):
174     def __init__(self, master):
175         Tkinter.Frame.__init__(self, master)
176         self.canvas = Tkinter.Canvas(self, scrollregion=(0, 0, 200, 200))
177         self.canvas.grid(row=0, column=0, sticky="news")
178         self.scrollY = Tkinter.Scrollbar(self, orient=Tkinter.VERTICAL,
179                                          command=self.canvas.yview)
180         self.scrollY.grid(row=0, column=1, sticky="ns")
181         self.canvas["yscrollcommand"] = self.scrollY.set
182         self.scrollX = Tkinter.Scrollbar(self, orient=Tkinter.HORIZONTAL,
183                                          command=self.canvas.xview)
184         self.scrollX.grid(row=1, column=0, sticky="ew")
185         self.canvas["xscrollcommand"] = self.scrollX.set
186         self.grid_columnconfigure(0, weight=1, minsize=0)
187         self.grid_rowconfigure(0, weight=1, minsize=0)
188         self.formid = None
189         self.form = None
190     def new_form(self, dom):
191         if self.formid != None:
192             self.canvas.delete(self.formid)
193         if self.form != None:
194             self.form.cleanup()
195         self.form = cotkwidget.FormWin(self.canvas, dom.documentElement)
196         self.formid = self.canvas.create_window(0, 0, window=self.form,
197                                                 anchor="nw")
198         self.canvas.update();
199         self.canvas["scrollregion"] = self.canvas.bbox("all")
200     def value_dom(self, dom, flags):
201         self.form.value_dom(dom, dom, flags)
202
203 # the status bar
204 class StatusBar(Tkinter.Frame):
205     def __init__(self, master):
206         Tkinter.Frame.__init__(self, master, relief="raised", borderwidth=2)
207         self.lform = Tkinter.Label(self, text=txt("noform", "<no form>"),
208                                    relief="sunken", borderwidth=2)
209         self.lform.pack(side="left")
210         self.lfile = Tkinter.Label(self, text=txt("nofile", "<no file>"),
211                                    relief="sunken", borderwidth=2)
212         self.lfile.pack(side="left")
213         self.modinc = Tkinter.Label(self, text=" ", relief="sunken",
214                                     borderwidth=2)
215         self.modinc.pack(side="left")
216         self.filler = Tkinter.Label(self, relief="sunken", borderwidth=2)
217         self.filler.pack(side="right", fill="x", expand=1)
218     def set_filename(self, name):
219         if name:
220             self.lfile["text"] = name
221         else:
222             self.lfile["text"] = txt("nofile", "<no file>")
223     def set_formname(self, name):
224         if name:
225             self.lform["text"] = name
226         else:
227             self.lform["text"] = txt("noform", "<no form>")
228     def set_modified(self, mod):
229         if mod:
230             self.modinc["text"] = "*"
231         else:
232             self.modinc["text"] = " "