blob: 96aed0a6b28923fa1d7a43724554fc02b295ffa3 [file] [log] [blame]
Guido van Rossum06981c31997-01-31 18:58:12 +00001#! /usr/bin/env python
2
3"""GUI interface to webchecker.
4
5This works as a Grail applet too! E.g.
6
Guido van Rossum4f6ecda1997-02-01 05:17:29 +00007 <APPLET CODE=wcgui.py NAME=CheckerWindow></APPLET>
Guido van Rossum06981c31997-01-31 18:58:12 +00008
Guido van Rossumaf310c11997-02-02 23:30:32 +00009Checkpoints are not (yet??? ever???) supported.
Guido van Rossum06981c31997-01-31 18:58:12 +000010
11User interface:
12
Tim Peters182b5ac2004-07-18 06:16:08 +000013Enter a root to check in the text entry box. To enter more than one root,
Guido van Rossumaf310c11997-02-02 23:30:32 +000014enter them one at a time and press <Return> for each one.
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000015
Tim Peters182b5ac2004-07-18 06:16:08 +000016Command buttons Start, Stop and "Check one" govern the checking process in
17the obvious way. Start and "Check one" also enter the root from the text
Guido van Rossumaf310c11997-02-02 23:30:32 +000018entry box if one is present. There's also a check box (enabled by default)
19to decide whether actually to follow external links (since this can slow
20the checking down considerably). Finally there's a Quit button.
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000021
Tim Peters182b5ac2004-07-18 06:16:08 +000022A series of checkbuttons determines whether the corresponding output panel
23is shown. List panels are also automatically shown or hidden when their
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000024status changes between empty to non-empty. There are six panels:
Guido van Rossum06981c31997-01-31 18:58:12 +000025
26Log -- raw output from the checker (-v, -q affect this)
Guido van Rossumaf310c11997-02-02 23:30:32 +000027To check -- links discovered but not yet checked
28Checked -- links that have been checked
Guido van Rossum06981c31997-01-31 18:58:12 +000029Bad links -- links that failed upon checking
Guido van Rossumaf310c11997-02-02 23:30:32 +000030Errors -- pages containing at least one bad link
Guido van Rossum06981c31997-01-31 18:58:12 +000031Details -- details about one URL; double click on a URL in any of
Guido van Rossumaf310c11997-02-02 23:30:32 +000032 the above list panels (not in Log) will show details
33 for that URL
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000034
Guido van Rossum06981c31997-01-31 18:58:12 +000035Use your window manager's Close command to quit.
36
37Command line options:
38
39-m bytes -- skip HTML pages larger than this size (default %(MAXPAGE)d)
Guido van Rossum06981c31997-01-31 18:58:12 +000040-q -- quiet operation (also suppresses external links report)
41-v -- verbose operation; repeating -v will increase verbosity
Guido van Rossuma8946401999-11-17 15:03:52 +000042-t root -- specify root dir which should be treated as internal (can repeat)
43-a -- don't check name anchors
Guido van Rossum06981c31997-01-31 18:58:12 +000044
45Command line arguments:
46
47rooturl -- URL to start checking
48 (default %(DEFROOT)s)
49
Guido van Rossumaf310c11997-02-02 23:30:32 +000050XXX The command line options (-m, -q, -v) should be GUI accessible.
Guido van Rossum06981c31997-01-31 18:58:12 +000051
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000052XXX The roots should be visible as a list (?).
Guido van Rossum06981c31997-01-31 18:58:12 +000053
Guido van Rossumaf310c11997-02-02 23:30:32 +000054XXX The multipanel user interface is clumsy.
Guido van Rossum06981c31997-01-31 18:58:12 +000055
56"""
57
58# ' Emacs bait
59
60
61import sys
62import getopt
Guido van Rossum06981c31997-01-31 18:58:12 +000063from Tkinter import *
64import tktools
Guido van Rossum497a1981999-11-17 15:40:48 +000065import webchecker
Guido van Rossum06981c31997-01-31 18:58:12 +000066import random
67
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000068# Override some for a weaker platform
69if sys.platform == 'mac':
70 webchecker.DEFROOT = "http://grail.cnri.reston.va.us/"
71 webchecker.MAXPAGE = 50000
72 webchecker.verbose = 4
Guido van Rossum06981c31997-01-31 18:58:12 +000073
74def main():
Guido van Rossum06981c31997-01-31 18:58:12 +000075 try:
Guido van Rossuma8946401999-11-17 15:03:52 +000076 opts, args = getopt.getopt(sys.argv[1:], 't:m:qva')
Guido van Rossum06981c31997-01-31 18:58:12 +000077 except getopt.error, msg:
Guido van Rossum986abac1998-04-06 14:29:28 +000078 sys.stdout = sys.stderr
79 print msg
80 print __doc__%vars(webchecker)
81 sys.exit(2)
Guido van Rossuma8946401999-11-17 15:03:52 +000082 webchecker.verbose = webchecker.VERBOSE
83 webchecker.nonames = webchecker.NONAMES
84 webchecker.maxpage = webchecker.MAXPAGE
85 extra_roots = []
Guido van Rossum06981c31997-01-31 18:58:12 +000086 for o, a in opts:
Guido van Rossum986abac1998-04-06 14:29:28 +000087 if o == '-m':
Walter Dörwaldaaab30e2002-09-11 20:36:02 +000088 webchecker.maxpage = int(a)
Guido van Rossum986abac1998-04-06 14:29:28 +000089 if o == '-q':
90 webchecker.verbose = 0
91 if o == '-v':
92 webchecker.verbose = webchecker.verbose + 1
Guido van Rossuma8946401999-11-17 15:03:52 +000093 if o == '-t':
94 extra_roots.append(a)
95 if o == '-a':
96 webchecker.nonames = not webchecker.nonames
Guido van Rossum06981c31997-01-31 18:58:12 +000097 root = Tk(className='Webchecker')
98 root.protocol("WM_DELETE_WINDOW", root.quit)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000099 c = CheckerWindow(root)
Guido van Rossuma8946401999-11-17 15:03:52 +0000100 c.setflags(verbose=webchecker.verbose, maxpage=webchecker.maxpage,
101 nonames=webchecker.nonames)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000102 if args:
Guido van Rossum986abac1998-04-06 14:29:28 +0000103 for arg in args[:-1]:
104 c.addroot(arg)
105 c.suggestroot(args[-1])
Guido van Rossuma8946401999-11-17 15:03:52 +0000106 # Usually conditioned on whether external links
107 # will be checked, but since that's not a command
108 # line option, just toss them in.
109 for url_root in extra_roots:
110 # Make sure it's terminated by a slash,
111 # so that addroot doesn't discard the last
112 # directory component.
113 if url_root[-1] != "/":
114 url_root = url_root + "/"
115 c.addroot(url_root, add_to_do = 0)
Guido van Rossum06981c31997-01-31 18:58:12 +0000116 root.mainloop()
117
118
119class CheckerWindow(webchecker.Checker):
120
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000121 def __init__(self, parent, root=webchecker.DEFROOT):
Guido van Rossum986abac1998-04-06 14:29:28 +0000122 self.__parent = parent
Guido van Rossumaf310c11997-02-02 23:30:32 +0000123
Guido van Rossum986abac1998-04-06 14:29:28 +0000124 self.__topcontrols = Frame(parent)
125 self.__topcontrols.pack(side=TOP, fill=X)
126 self.__label = Label(self.__topcontrols, text="Root URL:")
127 self.__label.pack(side=LEFT)
128 self.__rootentry = Entry(self.__topcontrols, width=60)
129 self.__rootentry.pack(side=LEFT)
130 self.__rootentry.bind('<Return>', self.enterroot)
131 self.__rootentry.focus_set()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000132
Guido van Rossum986abac1998-04-06 14:29:28 +0000133 self.__controls = Frame(parent)
134 self.__controls.pack(side=TOP, fill=X)
135 self.__running = 0
136 self.__start = Button(self.__controls, text="Run", command=self.start)
137 self.__start.pack(side=LEFT)
138 self.__stop = Button(self.__controls, text="Stop", command=self.stop,
139 state=DISABLED)
140 self.__stop.pack(side=LEFT)
141 self.__step = Button(self.__controls, text="Check one",
142 command=self.step)
143 self.__step.pack(side=LEFT)
144 self.__cv = BooleanVar(parent)
145 self.__cv.set(self.checkext)
146 self.__checkext = Checkbutton(self.__controls, variable=self.__cv,
147 command=self.update_checkext,
148 text="Check nonlocal links",)
149 self.__checkext.pack(side=LEFT)
150 self.__reset = Button(self.__controls, text="Start over", command=self.reset)
151 self.__reset.pack(side=LEFT)
152 if __name__ == '__main__': # No Quit button under Grail!
153 self.__quit = Button(self.__controls, text="Quit",
154 command=self.__parent.quit)
155 self.__quit.pack(side=RIGHT)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000156
Guido van Rossum986abac1998-04-06 14:29:28 +0000157 self.__status = Label(parent, text="Status: initial", anchor=W)
158 self.__status.pack(side=TOP, fill=X)
159 self.__checking = Label(parent, text="Idle", anchor=W)
160 self.__checking.pack(side=TOP, fill=X)
161 self.__mp = mp = MultiPanel(parent)
162 sys.stdout = self.__log = LogPanel(mp, "Log")
Guido van Rossuma8946401999-11-17 15:03:52 +0000163 self.__todo = ListPanel(mp, "To check", self, self.showinfo)
164 self.__done = ListPanel(mp, "Checked", self, self.showinfo)
165 self.__bad = ListPanel(mp, "Bad links", self, self.showinfo)
166 self.__errors = ListPanel(mp, "Pages w/ bad links", self, self.showinfo)
Guido van Rossum986abac1998-04-06 14:29:28 +0000167 self.__details = LogPanel(mp, "Details")
Guido van Rossuma8946401999-11-17 15:03:52 +0000168 self.root_seed = None
Guido van Rossum986abac1998-04-06 14:29:28 +0000169 webchecker.Checker.__init__(self)
170 if root:
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000171 root = str(root).strip()
Guido van Rossum986abac1998-04-06 14:29:28 +0000172 if root:
173 self.suggestroot(root)
174 self.newstatus()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000175
Guido van Rossumaf310c11997-02-02 23:30:32 +0000176 def reset(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000177 webchecker.Checker.reset(self)
178 for p in self.__todo, self.__done, self.__bad, self.__errors:
179 p.clear()
Guido van Rossuma8946401999-11-17 15:03:52 +0000180 if self.root_seed:
181 self.suggestroot(self.root_seed)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000182
183 def suggestroot(self, root):
Guido van Rossum986abac1998-04-06 14:29:28 +0000184 self.__rootentry.delete(0, END)
185 self.__rootentry.insert(END, root)
186 self.__rootentry.select_range(0, END)
Guido van Rossuma8946401999-11-17 15:03:52 +0000187 self.root_seed = root
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000188
189 def enterroot(self, event=None):
Guido van Rossum986abac1998-04-06 14:29:28 +0000190 root = self.__rootentry.get()
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000191 root = root.strip()
Guido van Rossum986abac1998-04-06 14:29:28 +0000192 if root:
193 self.__checking.config(text="Adding root "+root)
194 self.__checking.update_idletasks()
195 self.addroot(root)
196 self.__checking.config(text="Idle")
197 try:
198 i = self.__todo.items.index(root)
199 except (ValueError, IndexError):
200 pass
201 else:
202 self.__todo.list.select_clear(0, END)
203 self.__todo.list.select_set(i)
204 self.__todo.list.yview(i)
205 self.__rootentry.delete(0, END)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000206
207 def start(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000208 self.__start.config(state=DISABLED, relief=SUNKEN)
209 self.__stop.config(state=NORMAL)
210 self.__step.config(state=DISABLED)
211 self.enterroot()
212 self.__running = 1
213 self.go()
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000214
215 def stop(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000216 self.__stop.config(state=DISABLED, relief=SUNKEN)
217 self.__running = 0
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000218
219 def step(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000220 self.__start.config(state=DISABLED)
221 self.__step.config(state=DISABLED, relief=SUNKEN)
222 self.enterroot()
223 self.__running = 0
224 self.dosomething()
Guido van Rossum06981c31997-01-31 18:58:12 +0000225
226 def go(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000227 if self.__running:
228 self.__parent.after_idle(self.dosomething)
229 else:
230 self.__checking.config(text="Idle")
231 self.__start.config(state=NORMAL, relief=RAISED)
232 self.__stop.config(state=DISABLED, relief=RAISED)
233 self.__step.config(state=NORMAL, relief=RAISED)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000234
235 __busy = 0
Guido van Rossum06981c31997-01-31 18:58:12 +0000236
237 def dosomething(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000238 if self.__busy: return
239 self.__busy = 1
240 if self.todo:
241 l = self.__todo.selectedindices()
242 if l:
243 i = l[0]
244 else:
245 i = 0
246 self.__todo.list.select_set(i)
247 self.__todo.list.yview(i)
248 url = self.__todo.items[i]
Guido van Rossuma8946401999-11-17 15:03:52 +0000249 self.__checking.config(text="Checking "+self.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000250 self.__parent.update()
251 self.dopage(url)
252 else:
253 self.stop()
254 self.__busy = 0
255 self.go()
Guido van Rossum06981c31997-01-31 18:58:12 +0000256
257 def showinfo(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000258 d = self.__details
259 d.clear()
Guido van Rossuma8946401999-11-17 15:03:52 +0000260 d.put("URL: %s\n" % self.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000261 if self.bad.has_key(url):
262 d.put("Error: %s\n" % str(self.bad[url]))
263 if url in self.roots:
264 d.put("Note: This is a root URL\n")
265 if self.done.has_key(url):
266 d.put("Status: checked\n")
267 o = self.done[url]
268 elif self.todo.has_key(url):
269 d.put("Status: to check\n")
270 o = self.todo[url]
271 else:
272 d.put("Status: unknown (!)\n")
273 o = []
Guido van Rossuma8946401999-11-17 15:03:52 +0000274 if (not url[1]) and self.errors.has_key(url[0]):
Guido van Rossum986abac1998-04-06 14:29:28 +0000275 d.put("Bad links from this page:\n")
Guido van Rossuma8946401999-11-17 15:03:52 +0000276 for triple in self.errors[url[0]]:
Guido van Rossum986abac1998-04-06 14:29:28 +0000277 link, rawlink, msg = triple
Guido van Rossuma8946401999-11-17 15:03:52 +0000278 d.put(" HREF %s" % self.format_url(link))
279 if self.format_url(link) != rawlink: d.put(" (%s)" %rawlink)
Guido van Rossum986abac1998-04-06 14:29:28 +0000280 d.put("\n")
281 d.put(" error %s\n" % str(msg))
282 self.__mp.showpanel("Details")
283 for source, rawlink in o:
284 d.put("Origin: %s" % source)
Guido van Rossuma8946401999-11-17 15:03:52 +0000285 if rawlink != self.format_url(url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000286 d.put(" (%s)" % rawlink)
287 d.put("\n")
288 d.text.yview("1.0")
Guido van Rossum06981c31997-01-31 18:58:12 +0000289
290 def setbad(self, url, msg):
Guido van Rossum986abac1998-04-06 14:29:28 +0000291 webchecker.Checker.setbad(self, url, msg)
292 self.__bad.insert(url)
293 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000294
295 def setgood(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000296 webchecker.Checker.setgood(self, url)
297 self.__bad.remove(url)
298 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000299
Guido van Rossumaf310c11997-02-02 23:30:32 +0000300 def newlink(self, url, origin):
Guido van Rossum986abac1998-04-06 14:29:28 +0000301 webchecker.Checker.newlink(self, url, origin)
302 if self.done.has_key(url):
303 self.__done.insert(url)
304 elif self.todo.has_key(url):
305 self.__todo.insert(url)
306 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000307
308 def markdone(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000309 webchecker.Checker.markdone(self, url)
310 self.__done.insert(url)
311 self.__todo.remove(url)
312 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000313
Guido van Rossumaf310c11997-02-02 23:30:32 +0000314 def seterror(self, url, triple):
Guido van Rossum986abac1998-04-06 14:29:28 +0000315 webchecker.Checker.seterror(self, url, triple)
Guido van Rossuma8946401999-11-17 15:03:52 +0000316 self.__errors.insert((url, ''))
Guido van Rossum986abac1998-04-06 14:29:28 +0000317 self.newstatus()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000318
319 def newstatus(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000320 self.__status.config(text="Status: "+self.status())
321 self.__parent.update()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000322
Guido van Rossum88b02cf1998-03-05 20:12:18 +0000323 def update_checkext(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000324 self.checkext = self.__cv.get()
Guido van Rossum88b02cf1998-03-05 20:12:18 +0000325
Guido van Rossum06981c31997-01-31 18:58:12 +0000326
327class ListPanel:
328
Guido van Rossuma8946401999-11-17 15:03:52 +0000329 def __init__(self, mp, name, checker, showinfo=None):
Guido van Rossum986abac1998-04-06 14:29:28 +0000330 self.mp = mp
331 self.name = name
332 self.showinfo = showinfo
Guido van Rossuma8946401999-11-17 15:03:52 +0000333 self.checker = checker
Guido van Rossum986abac1998-04-06 14:29:28 +0000334 self.panel = mp.addpanel(name)
335 self.list, self.frame = tktools.make_list_box(
336 self.panel, width=60, height=5)
337 self.list.config(exportselection=0)
338 if showinfo:
339 self.list.bind('<Double-Button-1>', self.doubleclick)
340 self.items = []
Guido van Rossum06981c31997-01-31 18:58:12 +0000341
Guido van Rossumaf310c11997-02-02 23:30:32 +0000342 def clear(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000343 self.items = []
344 self.list.delete(0, END)
345 self.mp.hidepanel(self.name)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000346
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000347 def doubleclick(self, event):
Guido van Rossum986abac1998-04-06 14:29:28 +0000348 l = self.selectedindices()
349 if l:
Guido van Rossuma8946401999-11-17 15:03:52 +0000350 self.showinfo(self.items[l[0]])
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000351
352 def selectedindices(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000353 l = self.list.curselection()
354 if not l: return []
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000355 return map(int, l)
Guido van Rossum06981c31997-01-31 18:58:12 +0000356
357 def insert(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000358 if url not in self.items:
359 if not self.items:
360 self.mp.showpanel(self.name)
361 # (I tried sorting alphabetically, but the display is too jumpy)
362 i = len(self.items)
Guido van Rossuma8946401999-11-17 15:03:52 +0000363 self.list.insert(i, self.checker.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000364 self.list.yview(i)
365 self.items.insert(i, url)
Guido van Rossum06981c31997-01-31 18:58:12 +0000366
367 def remove(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000368 try:
369 i = self.items.index(url)
370 except (ValueError, IndexError):
371 pass
372 else:
373 was_selected = i in self.selectedindices()
374 self.list.delete(i)
375 del self.items[i]
376 if not self.items:
377 self.mp.hidepanel(self.name)
378 elif was_selected:
379 if i >= len(self.items):
380 i = len(self.items) - 1
381 self.list.select_set(i)
Guido van Rossum06981c31997-01-31 18:58:12 +0000382
383
384class LogPanel:
385
386 def __init__(self, mp, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000387 self.mp = mp
388 self.name = name
389 self.panel = mp.addpanel(name)
390 self.text, self.frame = tktools.make_text_box(self.panel, height=10)
391 self.text.config(wrap=NONE)
Guido van Rossum06981c31997-01-31 18:58:12 +0000392
393 def clear(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000394 self.text.delete("1.0", END)
395 self.text.yview("1.0")
Guido van Rossum06981c31997-01-31 18:58:12 +0000396
Guido van Rossumaf310c11997-02-02 23:30:32 +0000397 def put(self, s):
Guido van Rossum986abac1998-04-06 14:29:28 +0000398 self.text.insert(END, s)
399 if '\n' in s:
400 self.text.yview(END)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000401
Guido van Rossum06981c31997-01-31 18:58:12 +0000402 def write(self, s):
Guido van Rossum986abac1998-04-06 14:29:28 +0000403 self.text.insert(END, s)
404 if '\n' in s:
405 self.text.yview(END)
406 self.panel.update()
Guido van Rossum06981c31997-01-31 18:58:12 +0000407
408
409class MultiPanel:
410
411 def __init__(self, parent):
Guido van Rossum986abac1998-04-06 14:29:28 +0000412 self.parent = parent
413 self.frame = Frame(self.parent)
414 self.frame.pack(expand=1, fill=BOTH)
415 self.topframe = Frame(self.frame, borderwidth=2, relief=RAISED)
416 self.topframe.pack(fill=X)
417 self.botframe = Frame(self.frame)
418 self.botframe.pack(expand=1, fill=BOTH)
419 self.panelnames = []
420 self.panels = {}
Guido van Rossum06981c31997-01-31 18:58:12 +0000421
422 def addpanel(self, name, on=0):
Guido van Rossum986abac1998-04-06 14:29:28 +0000423 v = StringVar(self.parent)
424 if on:
425 v.set(name)
426 else:
427 v.set("")
428 check = Checkbutton(self.topframe, text=name,
429 offvalue="", onvalue=name, variable=v,
430 command=self.checkpanel)
431 check.pack(side=LEFT)
432 panel = Frame(self.botframe)
433 label = Label(panel, text=name, borderwidth=2, relief=RAISED, anchor=W)
434 label.pack(side=TOP, fill=X)
435 t = v, check, panel
436 self.panelnames.append(name)
437 self.panels[name] = t
438 if on:
439 panel.pack(expand=1, fill=BOTH)
440 return panel
Guido van Rossum06981c31997-01-31 18:58:12 +0000441
442 def showpanel(self, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000443 v, check, panel = self.panels[name]
444 v.set(name)
445 panel.pack(expand=1, fill=BOTH)
Guido van Rossum06981c31997-01-31 18:58:12 +0000446
447 def hidepanel(self, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000448 v, check, panel = self.panels[name]
449 v.set("")
450 panel.pack_forget()
Guido van Rossum06981c31997-01-31 18:58:12 +0000451
452 def checkpanel(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000453 for name in self.panelnames:
454 v, check, panel = self.panels[name]
455 panel.pack_forget()
456 for name in self.panelnames:
457 v, check, panel = self.panels[name]
458 if v.get():
459 panel.pack(expand=1, fill=BOTH)
Guido van Rossum06981c31997-01-31 18:58:12 +0000460
461
462if __name__ == '__main__':
463 main()