Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python |
| 2 | |
| 3 | """GUI interface to webchecker. |
| 4 | |
| 5 | This works as a Grail applet too! E.g. |
| 6 | |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 7 | <APPLET CODE=wcgui.py NAME=CheckerWindow></APPLET> |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 8 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 9 | Checkpoints are not (yet??? ever???) supported. |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 10 | |
| 11 | User interface: |
| 12 | |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 13 | Enter a root to check in the text entry box. To enter more than one root, |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 14 | enter them one at a time and press <Return> for each one. |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 15 | |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 16 | Command buttons Start, Stop and "Check one" govern the checking process in |
| 17 | the obvious way. Start and "Check one" also enter the root from the text |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 18 | entry box if one is present. There's also a check box (enabled by default) |
| 19 | to decide whether actually to follow external links (since this can slow |
| 20 | the checking down considerably). Finally there's a Quit button. |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 21 | |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 22 | A series of checkbuttons determines whether the corresponding output panel |
| 23 | is shown. List panels are also automatically shown or hidden when their |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 24 | status changes between empty to non-empty. There are six panels: |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 25 | |
| 26 | Log -- raw output from the checker (-v, -q affect this) |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 27 | To check -- links discovered but not yet checked |
| 28 | Checked -- links that have been checked |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 29 | Bad links -- links that failed upon checking |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 30 | Errors -- pages containing at least one bad link |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 31 | Details -- details about one URL; double click on a URL in any of |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 32 | the above list panels (not in Log) will show details |
| 33 | for that URL |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 34 | |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 35 | Use your window manager's Close command to quit. |
| 36 | |
| 37 | Command line options: |
| 38 | |
| 39 | -m bytes -- skip HTML pages larger than this size (default %(MAXPAGE)d) |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 40 | -q -- quiet operation (also suppresses external links report) |
| 41 | -v -- verbose operation; repeating -v will increase verbosity |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 42 | -t root -- specify root dir which should be treated as internal (can repeat) |
| 43 | -a -- don't check name anchors |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 44 | |
| 45 | Command line arguments: |
| 46 | |
| 47 | rooturl -- URL to start checking |
| 48 | (default %(DEFROOT)s) |
| 49 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 50 | XXX The command line options (-m, -q, -v) should be GUI accessible. |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 51 | |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 52 | XXX The roots should be visible as a list (?). |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 53 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 54 | XXX The multipanel user interface is clumsy. |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 55 | |
| 56 | """ |
| 57 | |
| 58 | # ' Emacs bait |
| 59 | |
| 60 | |
| 61 | import sys |
| 62 | import getopt |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 63 | from Tkinter import * |
| 64 | import tktools |
Guido van Rossum | 497a198 | 1999-11-17 15:40:48 +0000 | [diff] [blame] | 65 | import webchecker |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 66 | |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 67 | # Override some for a weaker platform |
| 68 | if sys.platform == 'mac': |
| 69 | webchecker.DEFROOT = "http://grail.cnri.reston.va.us/" |
| 70 | webchecker.MAXPAGE = 50000 |
| 71 | webchecker.verbose = 4 |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 72 | |
| 73 | def main(): |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 74 | try: |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 75 | opts, args = getopt.getopt(sys.argv[1:], 't:m:qva') |
Guido van Rossum | b940e11 | 2007-01-10 16:19:56 +0000 | [diff] [blame] | 76 | except getopt.error as msg: |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 77 | sys.stdout = sys.stderr |
Collin Winter | 6afaeb7 | 2007-08-03 17:06:41 +0000 | [diff] [blame] | 78 | print(msg) |
| 79 | print(__doc__%vars(webchecker)) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 80 | sys.exit(2) |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 81 | webchecker.verbose = webchecker.VERBOSE |
| 82 | webchecker.nonames = webchecker.NONAMES |
| 83 | webchecker.maxpage = webchecker.MAXPAGE |
| 84 | extra_roots = [] |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 85 | for o, a in opts: |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 86 | if o == '-m': |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 87 | webchecker.maxpage = int(a) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 88 | if o == '-q': |
| 89 | webchecker.verbose = 0 |
| 90 | if o == '-v': |
| 91 | webchecker.verbose = webchecker.verbose + 1 |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 92 | if o == '-t': |
| 93 | extra_roots.append(a) |
| 94 | if o == '-a': |
| 95 | webchecker.nonames = not webchecker.nonames |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 96 | root = Tk(className='Webchecker') |
| 97 | root.protocol("WM_DELETE_WINDOW", root.quit) |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 98 | c = CheckerWindow(root) |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 99 | c.setflags(verbose=webchecker.verbose, maxpage=webchecker.maxpage, |
| 100 | nonames=webchecker.nonames) |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 101 | if args: |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 102 | for arg in args[:-1]: |
| 103 | c.addroot(arg) |
| 104 | c.suggestroot(args[-1]) |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 105 | # 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 115 | root.mainloop() |
| 116 | |
| 117 | |
| 118 | class CheckerWindow(webchecker.Checker): |
| 119 | |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 120 | def __init__(self, parent, root=webchecker.DEFROOT): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 121 | self.__parent = parent |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 122 | |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 123 | 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 Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 131 | |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 132 | 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 Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 155 | |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 156 | 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 Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 162 | 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 Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 166 | self.__details = LogPanel(mp, "Details") |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 167 | self.root_seed = None |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 168 | webchecker.Checker.__init__(self) |
| 169 | if root: |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 170 | root = str(root).strip() |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 171 | if root: |
| 172 | self.suggestroot(root) |
| 173 | self.newstatus() |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 174 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 175 | def reset(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 176 | webchecker.Checker.reset(self) |
| 177 | for p in self.__todo, self.__done, self.__bad, self.__errors: |
| 178 | p.clear() |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 179 | if self.root_seed: |
| 180 | self.suggestroot(self.root_seed) |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 181 | |
| 182 | def suggestroot(self, root): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 183 | self.__rootentry.delete(0, END) |
| 184 | self.__rootentry.insert(END, root) |
| 185 | self.__rootentry.select_range(0, END) |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 186 | self.root_seed = root |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 187 | |
| 188 | def enterroot(self, event=None): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 189 | root = self.__rootentry.get() |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 190 | root = root.strip() |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 191 | 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 Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 205 | |
| 206 | def start(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 207 | 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 Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 213 | |
| 214 | def stop(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 215 | self.__stop.config(state=DISABLED, relief=SUNKEN) |
| 216 | self.__running = 0 |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 217 | |
| 218 | def step(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 219 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 224 | |
| 225 | def go(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 226 | 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 Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 233 | |
| 234 | __busy = 0 |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 235 | |
| 236 | def dosomething(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 237 | 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 Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 248 | self.__checking.config(text="Checking "+self.format_url(url)) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 249 | self.__parent.update() |
| 250 | self.dopage(url) |
| 251 | else: |
| 252 | self.stop() |
| 253 | self.__busy = 0 |
| 254 | self.go() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 255 | |
| 256 | def showinfo(self, url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 257 | d = self.__details |
| 258 | d.clear() |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 259 | d.put("URL: %s\n" % self.format_url(url)) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 260 | 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 Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 273 | if (not url[1]) and self.errors.has_key(url[0]): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 274 | d.put("Bad links from this page:\n") |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 275 | for triple in self.errors[url[0]]: |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 276 | link, rawlink, msg = triple |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 277 | d.put(" HREF %s" % self.format_url(link)) |
| 278 | if self.format_url(link) != rawlink: d.put(" (%s)" %rawlink) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 279 | 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 Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 284 | if rawlink != self.format_url(url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 285 | d.put(" (%s)" % rawlink) |
| 286 | d.put("\n") |
| 287 | d.text.yview("1.0") |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 288 | |
| 289 | def setbad(self, url, msg): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 290 | webchecker.Checker.setbad(self, url, msg) |
| 291 | self.__bad.insert(url) |
| 292 | self.newstatus() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 293 | |
| 294 | def setgood(self, url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 295 | webchecker.Checker.setgood(self, url) |
| 296 | self.__bad.remove(url) |
| 297 | self.newstatus() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 298 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 299 | def newlink(self, url, origin): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 300 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 306 | |
| 307 | def markdone(self, url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 308 | webchecker.Checker.markdone(self, url) |
| 309 | self.__done.insert(url) |
| 310 | self.__todo.remove(url) |
| 311 | self.newstatus() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 312 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 313 | def seterror(self, url, triple): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 314 | webchecker.Checker.seterror(self, url, triple) |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 315 | self.__errors.insert((url, '')) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 316 | self.newstatus() |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 317 | |
| 318 | def newstatus(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 319 | self.__status.config(text="Status: "+self.status()) |
| 320 | self.__parent.update() |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 321 | |
Guido van Rossum | 88b02cf | 1998-03-05 20:12:18 +0000 | [diff] [blame] | 322 | def update_checkext(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 323 | self.checkext = self.__cv.get() |
Guido van Rossum | 88b02cf | 1998-03-05 20:12:18 +0000 | [diff] [blame] | 324 | |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 325 | |
| 326 | class ListPanel: |
| 327 | |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 328 | def __init__(self, mp, name, checker, showinfo=None): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 329 | self.mp = mp |
| 330 | self.name = name |
| 331 | self.showinfo = showinfo |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 332 | self.checker = checker |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 333 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 340 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 341 | def clear(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 342 | self.items = [] |
| 343 | self.list.delete(0, END) |
| 344 | self.mp.hidepanel(self.name) |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 345 | |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 346 | def doubleclick(self, event): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 347 | l = self.selectedindices() |
| 348 | if l: |
Guido van Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 349 | self.showinfo(self.items[l[0]]) |
Guido van Rossum | 4f6ecda | 1997-02-01 05:17:29 +0000 | [diff] [blame] | 350 | |
| 351 | def selectedindices(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 352 | l = self.list.curselection() |
| 353 | if not l: return [] |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 354 | return map(int, l) |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 355 | |
| 356 | def insert(self, url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 357 | 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 Rossum | a894640 | 1999-11-17 15:03:52 +0000 | [diff] [blame] | 362 | self.list.insert(i, self.checker.format_url(url)) |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 363 | self.list.yview(i) |
| 364 | self.items.insert(i, url) |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 365 | |
| 366 | def remove(self, url): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 367 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 381 | |
| 382 | |
| 383 | class LogPanel: |
| 384 | |
| 385 | def __init__(self, mp, name): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 386 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 391 | |
| 392 | def clear(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 393 | self.text.delete("1.0", END) |
| 394 | self.text.yview("1.0") |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 395 | |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 396 | def put(self, s): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 397 | self.text.insert(END, s) |
| 398 | if '\n' in s: |
| 399 | self.text.yview(END) |
Guido van Rossum | af310c1 | 1997-02-02 23:30:32 +0000 | [diff] [blame] | 400 | |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 401 | def write(self, s): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 402 | self.text.insert(END, s) |
| 403 | if '\n' in s: |
| 404 | self.text.yview(END) |
| 405 | self.panel.update() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 406 | |
| 407 | |
| 408 | class MultiPanel: |
| 409 | |
| 410 | def __init__(self, parent): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 411 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 420 | |
| 421 | def addpanel(self, name, on=0): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 422 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 440 | |
| 441 | def showpanel(self, name): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 442 | v, check, panel = self.panels[name] |
| 443 | v.set(name) |
| 444 | panel.pack(expand=1, fill=BOTH) |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 445 | |
| 446 | def hidepanel(self, name): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 447 | v, check, panel = self.panels[name] |
| 448 | v.set("") |
| 449 | panel.pack_forget() |
Guido van Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 450 | |
| 451 | def checkpanel(self): |
Guido van Rossum | 986abac | 1998-04-06 14:29:28 +0000 | [diff] [blame] | 452 | 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 Rossum | 06981c3 | 1997-01-31 18:58:12 +0000 | [diff] [blame] | 459 | |
| 460 | |
| 461 | if __name__ == '__main__': |
| 462 | main() |