blob: 835d00834bacaf8b7be2dfbe937448d8751e1ef9 [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 +000066
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000067# Override some for a weaker platform
68if sys.platform == 'mac':
69 webchecker.DEFROOT = "http://grail.cnri.reston.va.us/"
70 webchecker.MAXPAGE = 50000
71 webchecker.verbose = 4
Guido van Rossum06981c31997-01-31 18:58:12 +000072
73def main():
Guido van Rossum06981c31997-01-31 18:58:12 +000074 try:
Guido van Rossuma8946401999-11-17 15:03:52 +000075 opts, args = getopt.getopt(sys.argv[1:], 't:m:qva')
Guido van Rossumb940e112007-01-10 16:19:56 +000076 except getopt.error as msg:
Guido van Rossum986abac1998-04-06 14:29:28 +000077 sys.stdout = sys.stderr
Collin Winter6afaeb72007-08-03 17:06:41 +000078 print(msg)
79 print(__doc__%vars(webchecker))
Guido van Rossum986abac1998-04-06 14:29:28 +000080 sys.exit(2)
Guido van Rossuma8946401999-11-17 15:03:52 +000081 webchecker.verbose = webchecker.VERBOSE
82 webchecker.nonames = webchecker.NONAMES
83 webchecker.maxpage = webchecker.MAXPAGE
84 extra_roots = []
Guido van Rossum06981c31997-01-31 18:58:12 +000085 for o, a in opts:
Guido van Rossum986abac1998-04-06 14:29:28 +000086 if o == '-m':
Walter Dörwaldaaab30e2002-09-11 20:36:02 +000087 webchecker.maxpage = int(a)
Guido van Rossum986abac1998-04-06 14:29:28 +000088 if o == '-q':
89 webchecker.verbose = 0
90 if o == '-v':
91 webchecker.verbose = webchecker.verbose + 1
Guido van Rossuma8946401999-11-17 15:03:52 +000092 if o == '-t':
93 extra_roots.append(a)
94 if o == '-a':
95 webchecker.nonames = not webchecker.nonames
Guido van Rossum06981c31997-01-31 18:58:12 +000096 root = Tk(className='Webchecker')
97 root.protocol("WM_DELETE_WINDOW", root.quit)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +000098 c = CheckerWindow(root)
Guido van Rossuma8946401999-11-17 15:03:52 +000099 c.setflags(verbose=webchecker.verbose, maxpage=webchecker.maxpage,
100 nonames=webchecker.nonames)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000101 if args:
Guido van Rossum986abac1998-04-06 14:29:28 +0000102 for arg in args[:-1]:
103 c.addroot(arg)
104 c.suggestroot(args[-1])
Guido van Rossuma8946401999-11-17 15:03:52 +0000105 # Usually conditioned on whether external links
106 # will be checked, but since that's not a command
107 # line option, just toss them in.
108 for url_root in extra_roots:
109 # Make sure it's terminated by a slash,
110 # so that addroot doesn't discard the last
111 # directory component.
112 if url_root[-1] != "/":
113 url_root = url_root + "/"
114 c.addroot(url_root, add_to_do = 0)
Guido van Rossum06981c31997-01-31 18:58:12 +0000115 root.mainloop()
116
117
118class CheckerWindow(webchecker.Checker):
119
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000120 def __init__(self, parent, root=webchecker.DEFROOT):
Guido van Rossum986abac1998-04-06 14:29:28 +0000121 self.__parent = parent
Guido van Rossumaf310c11997-02-02 23:30:32 +0000122
Guido van Rossum986abac1998-04-06 14:29:28 +0000123 self.__topcontrols = Frame(parent)
124 self.__topcontrols.pack(side=TOP, fill=X)
125 self.__label = Label(self.__topcontrols, text="Root URL:")
126 self.__label.pack(side=LEFT)
127 self.__rootentry = Entry(self.__topcontrols, width=60)
128 self.__rootentry.pack(side=LEFT)
129 self.__rootentry.bind('<Return>', self.enterroot)
130 self.__rootentry.focus_set()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000131
Guido van Rossum986abac1998-04-06 14:29:28 +0000132 self.__controls = Frame(parent)
133 self.__controls.pack(side=TOP, fill=X)
134 self.__running = 0
135 self.__start = Button(self.__controls, text="Run", command=self.start)
136 self.__start.pack(side=LEFT)
137 self.__stop = Button(self.__controls, text="Stop", command=self.stop,
138 state=DISABLED)
139 self.__stop.pack(side=LEFT)
140 self.__step = Button(self.__controls, text="Check one",
141 command=self.step)
142 self.__step.pack(side=LEFT)
143 self.__cv = BooleanVar(parent)
144 self.__cv.set(self.checkext)
145 self.__checkext = Checkbutton(self.__controls, variable=self.__cv,
146 command=self.update_checkext,
147 text="Check nonlocal links",)
148 self.__checkext.pack(side=LEFT)
149 self.__reset = Button(self.__controls, text="Start over", command=self.reset)
150 self.__reset.pack(side=LEFT)
151 if __name__ == '__main__': # No Quit button under Grail!
152 self.__quit = Button(self.__controls, text="Quit",
153 command=self.__parent.quit)
154 self.__quit.pack(side=RIGHT)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000155
Guido van Rossum986abac1998-04-06 14:29:28 +0000156 self.__status = Label(parent, text="Status: initial", anchor=W)
157 self.__status.pack(side=TOP, fill=X)
158 self.__checking = Label(parent, text="Idle", anchor=W)
159 self.__checking.pack(side=TOP, fill=X)
160 self.__mp = mp = MultiPanel(parent)
161 sys.stdout = self.__log = LogPanel(mp, "Log")
Guido van Rossuma8946401999-11-17 15:03:52 +0000162 self.__todo = ListPanel(mp, "To check", self, self.showinfo)
163 self.__done = ListPanel(mp, "Checked", self, self.showinfo)
164 self.__bad = ListPanel(mp, "Bad links", self, self.showinfo)
165 self.__errors = ListPanel(mp, "Pages w/ bad links", self, self.showinfo)
Guido van Rossum986abac1998-04-06 14:29:28 +0000166 self.__details = LogPanel(mp, "Details")
Guido van Rossuma8946401999-11-17 15:03:52 +0000167 self.root_seed = None
Guido van Rossum986abac1998-04-06 14:29:28 +0000168 webchecker.Checker.__init__(self)
169 if root:
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000170 root = str(root).strip()
Guido van Rossum986abac1998-04-06 14:29:28 +0000171 if root:
172 self.suggestroot(root)
173 self.newstatus()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000174
Guido van Rossumaf310c11997-02-02 23:30:32 +0000175 def reset(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000176 webchecker.Checker.reset(self)
177 for p in self.__todo, self.__done, self.__bad, self.__errors:
178 p.clear()
Guido van Rossuma8946401999-11-17 15:03:52 +0000179 if self.root_seed:
180 self.suggestroot(self.root_seed)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000181
182 def suggestroot(self, root):
Guido van Rossum986abac1998-04-06 14:29:28 +0000183 self.__rootentry.delete(0, END)
184 self.__rootentry.insert(END, root)
185 self.__rootentry.select_range(0, END)
Guido van Rossuma8946401999-11-17 15:03:52 +0000186 self.root_seed = root
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000187
188 def enterroot(self, event=None):
Guido van Rossum986abac1998-04-06 14:29:28 +0000189 root = self.__rootentry.get()
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000190 root = root.strip()
Guido van Rossum986abac1998-04-06 14:29:28 +0000191 if root:
192 self.__checking.config(text="Adding root "+root)
193 self.__checking.update_idletasks()
194 self.addroot(root)
195 self.__checking.config(text="Idle")
196 try:
197 i = self.__todo.items.index(root)
198 except (ValueError, IndexError):
199 pass
200 else:
201 self.__todo.list.select_clear(0, END)
202 self.__todo.list.select_set(i)
203 self.__todo.list.yview(i)
204 self.__rootentry.delete(0, END)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000205
206 def start(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000207 self.__start.config(state=DISABLED, relief=SUNKEN)
208 self.__stop.config(state=NORMAL)
209 self.__step.config(state=DISABLED)
210 self.enterroot()
211 self.__running = 1
212 self.go()
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000213
214 def stop(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000215 self.__stop.config(state=DISABLED, relief=SUNKEN)
216 self.__running = 0
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000217
218 def step(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000219 self.__start.config(state=DISABLED)
220 self.__step.config(state=DISABLED, relief=SUNKEN)
221 self.enterroot()
222 self.__running = 0
223 self.dosomething()
Guido van Rossum06981c31997-01-31 18:58:12 +0000224
225 def go(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000226 if self.__running:
227 self.__parent.after_idle(self.dosomething)
228 else:
229 self.__checking.config(text="Idle")
230 self.__start.config(state=NORMAL, relief=RAISED)
231 self.__stop.config(state=DISABLED, relief=RAISED)
232 self.__step.config(state=NORMAL, relief=RAISED)
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000233
234 __busy = 0
Guido van Rossum06981c31997-01-31 18:58:12 +0000235
236 def dosomething(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000237 if self.__busy: return
238 self.__busy = 1
239 if self.todo:
240 l = self.__todo.selectedindices()
241 if l:
242 i = l[0]
243 else:
244 i = 0
245 self.__todo.list.select_set(i)
246 self.__todo.list.yview(i)
247 url = self.__todo.items[i]
Guido van Rossuma8946401999-11-17 15:03:52 +0000248 self.__checking.config(text="Checking "+self.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000249 self.__parent.update()
250 self.dopage(url)
251 else:
252 self.stop()
253 self.__busy = 0
254 self.go()
Guido van Rossum06981c31997-01-31 18:58:12 +0000255
256 def showinfo(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000257 d = self.__details
258 d.clear()
Guido van Rossuma8946401999-11-17 15:03:52 +0000259 d.put("URL: %s\n" % self.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000260 if self.bad.has_key(url):
261 d.put("Error: %s\n" % str(self.bad[url]))
262 if url in self.roots:
263 d.put("Note: This is a root URL\n")
264 if self.done.has_key(url):
265 d.put("Status: checked\n")
266 o = self.done[url]
267 elif self.todo.has_key(url):
268 d.put("Status: to check\n")
269 o = self.todo[url]
270 else:
271 d.put("Status: unknown (!)\n")
272 o = []
Guido van Rossuma8946401999-11-17 15:03:52 +0000273 if (not url[1]) and self.errors.has_key(url[0]):
Guido van Rossum986abac1998-04-06 14:29:28 +0000274 d.put("Bad links from this page:\n")
Guido van Rossuma8946401999-11-17 15:03:52 +0000275 for triple in self.errors[url[0]]:
Guido van Rossum986abac1998-04-06 14:29:28 +0000276 link, rawlink, msg = triple
Guido van Rossuma8946401999-11-17 15:03:52 +0000277 d.put(" HREF %s" % self.format_url(link))
278 if self.format_url(link) != rawlink: d.put(" (%s)" %rawlink)
Guido van Rossum986abac1998-04-06 14:29:28 +0000279 d.put("\n")
280 d.put(" error %s\n" % str(msg))
281 self.__mp.showpanel("Details")
282 for source, rawlink in o:
283 d.put("Origin: %s" % source)
Guido van Rossuma8946401999-11-17 15:03:52 +0000284 if rawlink != self.format_url(url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000285 d.put(" (%s)" % rawlink)
286 d.put("\n")
287 d.text.yview("1.0")
Guido van Rossum06981c31997-01-31 18:58:12 +0000288
289 def setbad(self, url, msg):
Guido van Rossum986abac1998-04-06 14:29:28 +0000290 webchecker.Checker.setbad(self, url, msg)
291 self.__bad.insert(url)
292 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000293
294 def setgood(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000295 webchecker.Checker.setgood(self, url)
296 self.__bad.remove(url)
297 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000298
Guido van Rossumaf310c11997-02-02 23:30:32 +0000299 def newlink(self, url, origin):
Guido van Rossum986abac1998-04-06 14:29:28 +0000300 webchecker.Checker.newlink(self, url, origin)
301 if self.done.has_key(url):
302 self.__done.insert(url)
303 elif self.todo.has_key(url):
304 self.__todo.insert(url)
305 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000306
307 def markdone(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000308 webchecker.Checker.markdone(self, url)
309 self.__done.insert(url)
310 self.__todo.remove(url)
311 self.newstatus()
Guido van Rossum06981c31997-01-31 18:58:12 +0000312
Guido van Rossumaf310c11997-02-02 23:30:32 +0000313 def seterror(self, url, triple):
Guido van Rossum986abac1998-04-06 14:29:28 +0000314 webchecker.Checker.seterror(self, url, triple)
Guido van Rossuma8946401999-11-17 15:03:52 +0000315 self.__errors.insert((url, ''))
Guido van Rossum986abac1998-04-06 14:29:28 +0000316 self.newstatus()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000317
318 def newstatus(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000319 self.__status.config(text="Status: "+self.status())
320 self.__parent.update()
Guido van Rossumaf310c11997-02-02 23:30:32 +0000321
Guido van Rossum88b02cf1998-03-05 20:12:18 +0000322 def update_checkext(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000323 self.checkext = self.__cv.get()
Guido van Rossum88b02cf1998-03-05 20:12:18 +0000324
Guido van Rossum06981c31997-01-31 18:58:12 +0000325
326class ListPanel:
327
Guido van Rossuma8946401999-11-17 15:03:52 +0000328 def __init__(self, mp, name, checker, showinfo=None):
Guido van Rossum986abac1998-04-06 14:29:28 +0000329 self.mp = mp
330 self.name = name
331 self.showinfo = showinfo
Guido van Rossuma8946401999-11-17 15:03:52 +0000332 self.checker = checker
Guido van Rossum986abac1998-04-06 14:29:28 +0000333 self.panel = mp.addpanel(name)
334 self.list, self.frame = tktools.make_list_box(
335 self.panel, width=60, height=5)
336 self.list.config(exportselection=0)
337 if showinfo:
338 self.list.bind('<Double-Button-1>', self.doubleclick)
339 self.items = []
Guido van Rossum06981c31997-01-31 18:58:12 +0000340
Guido van Rossumaf310c11997-02-02 23:30:32 +0000341 def clear(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000342 self.items = []
343 self.list.delete(0, END)
344 self.mp.hidepanel(self.name)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000345
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000346 def doubleclick(self, event):
Guido van Rossum986abac1998-04-06 14:29:28 +0000347 l = self.selectedindices()
348 if l:
Guido van Rossuma8946401999-11-17 15:03:52 +0000349 self.showinfo(self.items[l[0]])
Guido van Rossum4f6ecda1997-02-01 05:17:29 +0000350
351 def selectedindices(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000352 l = self.list.curselection()
353 if not l: return []
Walter Dörwaldaaab30e2002-09-11 20:36:02 +0000354 return map(int, l)
Guido van Rossum06981c31997-01-31 18:58:12 +0000355
356 def insert(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000357 if url not in self.items:
358 if not self.items:
359 self.mp.showpanel(self.name)
360 # (I tried sorting alphabetically, but the display is too jumpy)
361 i = len(self.items)
Guido van Rossuma8946401999-11-17 15:03:52 +0000362 self.list.insert(i, self.checker.format_url(url))
Guido van Rossum986abac1998-04-06 14:29:28 +0000363 self.list.yview(i)
364 self.items.insert(i, url)
Guido van Rossum06981c31997-01-31 18:58:12 +0000365
366 def remove(self, url):
Guido van Rossum986abac1998-04-06 14:29:28 +0000367 try:
368 i = self.items.index(url)
369 except (ValueError, IndexError):
370 pass
371 else:
372 was_selected = i in self.selectedindices()
373 self.list.delete(i)
374 del self.items[i]
375 if not self.items:
376 self.mp.hidepanel(self.name)
377 elif was_selected:
378 if i >= len(self.items):
379 i = len(self.items) - 1
380 self.list.select_set(i)
Guido van Rossum06981c31997-01-31 18:58:12 +0000381
382
383class LogPanel:
384
385 def __init__(self, mp, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000386 self.mp = mp
387 self.name = name
388 self.panel = mp.addpanel(name)
389 self.text, self.frame = tktools.make_text_box(self.panel, height=10)
390 self.text.config(wrap=NONE)
Guido van Rossum06981c31997-01-31 18:58:12 +0000391
392 def clear(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000393 self.text.delete("1.0", END)
394 self.text.yview("1.0")
Guido van Rossum06981c31997-01-31 18:58:12 +0000395
Guido van Rossumaf310c11997-02-02 23:30:32 +0000396 def put(self, s):
Guido van Rossum986abac1998-04-06 14:29:28 +0000397 self.text.insert(END, s)
398 if '\n' in s:
399 self.text.yview(END)
Guido van Rossumaf310c11997-02-02 23:30:32 +0000400
Guido van Rossum06981c31997-01-31 18:58:12 +0000401 def write(self, s):
Guido van Rossum986abac1998-04-06 14:29:28 +0000402 self.text.insert(END, s)
403 if '\n' in s:
404 self.text.yview(END)
405 self.panel.update()
Guido van Rossum06981c31997-01-31 18:58:12 +0000406
407
408class MultiPanel:
409
410 def __init__(self, parent):
Guido van Rossum986abac1998-04-06 14:29:28 +0000411 self.parent = parent
412 self.frame = Frame(self.parent)
413 self.frame.pack(expand=1, fill=BOTH)
414 self.topframe = Frame(self.frame, borderwidth=2, relief=RAISED)
415 self.topframe.pack(fill=X)
416 self.botframe = Frame(self.frame)
417 self.botframe.pack(expand=1, fill=BOTH)
418 self.panelnames = []
419 self.panels = {}
Guido van Rossum06981c31997-01-31 18:58:12 +0000420
421 def addpanel(self, name, on=0):
Guido van Rossum986abac1998-04-06 14:29:28 +0000422 v = StringVar(self.parent)
423 if on:
424 v.set(name)
425 else:
426 v.set("")
427 check = Checkbutton(self.topframe, text=name,
428 offvalue="", onvalue=name, variable=v,
429 command=self.checkpanel)
430 check.pack(side=LEFT)
431 panel = Frame(self.botframe)
432 label = Label(panel, text=name, borderwidth=2, relief=RAISED, anchor=W)
433 label.pack(side=TOP, fill=X)
434 t = v, check, panel
435 self.panelnames.append(name)
436 self.panels[name] = t
437 if on:
438 panel.pack(expand=1, fill=BOTH)
439 return panel
Guido van Rossum06981c31997-01-31 18:58:12 +0000440
441 def showpanel(self, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000442 v, check, panel = self.panels[name]
443 v.set(name)
444 panel.pack(expand=1, fill=BOTH)
Guido van Rossum06981c31997-01-31 18:58:12 +0000445
446 def hidepanel(self, name):
Guido van Rossum986abac1998-04-06 14:29:28 +0000447 v, check, panel = self.panels[name]
448 v.set("")
449 panel.pack_forget()
Guido van Rossum06981c31997-01-31 18:58:12 +0000450
451 def checkpanel(self):
Guido van Rossum986abac1998-04-06 14:29:28 +0000452 for name in self.panelnames:
453 v, check, panel = self.panels[name]
454 panel.pack_forget()
455 for name in self.panelnames:
456 v, check, panel = self.panels[name]
457 if v.get():
458 panel.pack(expand=1, fill=BOTH)
Guido van Rossum06981c31997-01-31 18:58:12 +0000459
460
461if __name__ == '__main__':
462 main()