diff options
Diffstat (limited to 'Tools/webchecker/wcgui.py')
-rwxr-xr-x | Tools/webchecker/wcgui.py | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/Tools/webchecker/wcgui.py b/Tools/webchecker/wcgui.py new file mode 100755 index 0000000..745ee7f --- /dev/null +++ b/Tools/webchecker/wcgui.py @@ -0,0 +1,329 @@ +#! /usr/bin/env python + +"""GUI interface to webchecker. + +This works as a Grail applet too! E.g. + + <APPLET CODE=wcgui.py NAME=CheckerWindow> + <PARAM NAME=roots VALUE="http://<yourfavoritehost>"> + </APPLET> + +Checkpoints are not (yet?) supported. + +User interface: + +When the 'Go' checkbutton is checked, web pages will be checked, one +at a time in the Tk 'idle' time. The other checkbuttons determine +whether the corresponding output panel is shown. There are six +panels: + +Log -- raw output from the checker (-v, -q affect this) +To check -- local links discovered but not yet checked +Off site -- links discovered that point off site +Checked -- local links that have been checked +Bad links -- links that failed upon checking +Details -- details about one URL; double click on a URL in any of + the aboce list panels (not in Log) will show that URL + +XXX There ought to be a list of pages known to contain at least one +bad link. + +Use your window manager's Close command to quit. + +Command line options: + +-m bytes -- skip HTML pages larger than this size (default %(MAXPAGE)d) +-n -- reports only, no checking (use with -R) +-q -- quiet operation (also suppresses external links report) +-v -- verbose operation; repeating -v will increase verbosity +-x -- check external links (during report phase) + +Command line arguments: + +rooturl -- URL to start checking + (default %(DEFROOT)s) + +XXX The command line options should all be GUI accessible. + +XXX The roots should be a list and there should be a GUI way to add a +root. + +XXX The alphabetizing of the lists makes the display very jumpy. + +XXX The multipanel user interface is bogus. + +""" + +# ' Emacs bait + + +import sys +import getopt +import string +from Tkinter import * +import tktools +import webchecker +import random + + +def main(): + checkext = 0 + try: + opts, args = getopt.getopt(sys.argv[1:], 'm:qvx') + except getopt.error, msg: + sys.stdout = sys.stderr + print msg + print __doc__%vars(webchecker) + sys.exit(2) + for o, a in opts: + if o == '-m': + webchecker.maxpage = string.atoi(a) + if o == '-q': + webchecker.verbose = 0 + if o == '-v': + webchecker.verbose = webchecker.verbose + 1 + if o == '-x': + checkext = 1 + root = Tk(className='Webchecker') + root.protocol("WM_DELETE_WINDOW", root.quit) + c = CheckerWindow(root, checkext) + for arg in args or [webchecker.DEFROOT]: + c.addroot(arg) + root.mainloop() + + +class CheckerWindow(webchecker.Checker): + + def __init__(self, parent, checkext=0, roots=None): + self.__parent = parent + self.__checkext = checkext + self.__controls = Frame(parent) + self.__controls.pack(side=TOP, fill=X) + self.__govar = IntVar() + self.__go = Checkbutton(self.__controls, text="GO", + variable=self.__govar, + command=self.go) + self.__go.pack(side=LEFT) + self.__status = Label(parent, text="Status: initial", anchor=W) + self.__status.pack(side=TOP, fill=X) + self.__checking = Label(parent, text="Checking: none", anchor=W) + self.__checking.pack(side=TOP, fill=X) + self.__mp = mp = MultiPanel(parent) + sys.stdout = self.__log = LogPanel(mp, "Log") + self.__todo = ListPanel(mp, "To check", self.showinfo) + self.__ext = ListPanel(mp, "Off site", self.showinfo) + self.__done = ListPanel(mp, "Checked", self.showinfo) + self.__bad = ListPanel(mp, "Bad links", self.showinfo) + self.__details = LogPanel(mp, "Details") + self.__extodo = [] + webchecker.Checker.__init__(self) + if roots: + roots = string.split(roots) + for root in roots: + self.addroot(root) + + def go(self): + if self.__govar.get(): + self.__parent.after_idle(self.dosomething) + else: + self.__checking.config(text="Checking: none") + + def dosomething(self): + if self.todo: + i = random.randint(0, len(self.todo)-1) + url = self.__todo.items[i] + self.__checking.config(text="Checking: "+url) + self.__parent.update() + self.dopage(url) + elif self.__checkext and self.__extodo: + # XXX Should have an indication of these in the todo window... + i = random.randint(0, len(self.__extodo)-1) + url = self.__extodo[i] + del self.__extodo[i] + self.__checking.config(text="Checking: "+url) + self.__parent.update() + self.checkextpage(url) + else: + self.__govar.set(0) + self.go() + + def showinfo(self, url): + d = self.__details + d.clear() + d.write("URL: %s\n" % url) + if self.bad.has_key(url): + d.write("Error: %s\n" % str(self.bad[url])) + if self.done.has_key(url): + d.write("Status: done\n") + o = self.done[url] + elif self.todo.has_key(url): + d.write("Status: todo\n") + o = self.todo[url] + elif self.ext.has_key(url): + d.write("Status: ext\n") + o = self.ext[url] + else: + d.write("Status: unknown (!)\n") + o = [] + if url in self.roots: + d.write("This is a root URL\n") + for source, rawlink in o: + d.write("Origin: %s" % source) + if rawlink != url: + d.write(" (%s)" % rawlink) + d.write("\n") + self.__mp.showpanel("Details") + + def newstatus(self): + self.__status.config(text="Status: "+self.status()[1:-1]) + self.__parent.update() + + def setbad(self, url, msg): + webchecker.Checker.setbad(self, url, msg) + self.__bad.insert(url) + self.newstatus() + + def setgood(self, url): + webchecker.Checker.setgood(self, url) + self.__bad.remove(url) + self.newstatus() + + def newextlink(self, url, origin): + webchecker.Checker.newextlink(self, url, origin) + self.__extodo.append(url) + self.__ext.insert(url) + self.newstatus() + + def newintlink(self, url, origin): + webchecker.Checker.newintlink(self, url, origin) + if self.done.has_key(url): + self.__done.insert(url) + elif self.todo.has_key(url): + self.__todo.insert(url) + self.newstatus() + + def markdone(self, url): + webchecker.Checker.markdone(self, url) + self.__done.insert(url) + self.__todo.remove(url) + self.newstatus() + + +class ListPanel: + + def __init__(self, mp, name, showinfo=None): + self.mp = mp + self.name = name + self.showinfo = showinfo + self.panel = mp.addpanel(name) + self.list, self.frame = tktools.make_list_box( + self.panel, width=60, height=5) + self.list.config(exportselection=0) + if showinfo: + self.list.bind('<Double-Button-1>', self.event) + self.items = [] + + def event(self, dummy): + l = self.list.curselection() + if not l: return + self.showinfo(self.list.get(string.atoi(l[0]))) + + def insert(self, url): + if url not in self.items: + if not self.items: + self.mp.showpanel(self.name) + # (I tried sorting alphabetically, but the display is too jumpy) + i = len(self.items) + self.list.insert(i, url) + self.list.select_clear(0, END) + self.list.select_set(i) + self.list.yview(i) + self.items.insert(i, url) + + def remove(self, url): + try: + i = self.items.index(url) + except (ValueError, IndexError): + pass + else: + self.list.delete(i) + self.list.select_clear(i) + del self.items[i] + if not self.items: + self.mp.hidepanel(self.name) + + +class LogPanel: + + def __init__(self, mp, name): + self.mp = mp + self.name = name + self.panel = mp.addpanel(name) + self.text, self.frame = tktools.make_text_box(self.panel, height=10) + self.text.config(wrap=NONE) + + def clear(self): + self.text.delete("1.0", END) + self.text.yview("1.0") + + def write(self, s): + self.text.insert(END, s) + self.text.yview(END) + self.panel.update() + + +class MultiPanel: + + def __init__(self, parent): + self.parent = parent + self.frame = Frame(self.parent) + self.frame.pack(expand=1, fill=BOTH) + self.topframe = Frame(self.frame, borderwidth=2, relief=RAISED) + self.topframe.pack(fill=X) + self.botframe = Frame(self.frame) + self.botframe.pack(expand=1, fill=BOTH) + self.panelnames = [] + self.panels = {} + + def addpanel(self, name, on=0): + v = StringVar() + if on: + v.set(name) + else: + v.set("") + check = Checkbutton(self.topframe, text=name, + offvalue="", onvalue=name, variable=v, + command=self.checkpanel) + check.pack(side=LEFT) + panel = Frame(self.botframe) + label = Label(panel, text=name, borderwidth=2, relief=RAISED, anchor=W) + label.pack(side=TOP, fill=X) + t = v, check, panel + self.panelnames.append(name) + self.panels[name] = t + if on: + panel.pack(expand=1, fill=BOTH) + return panel + + def showpanel(self, name): + v, check, panel = self.panels[name] + v.set(name) + panel.pack(expand=1, fill=BOTH) + + def hidepanel(self, name): + v, check, panel = self.panels[name] + v.set("") + panel.pack_forget() + + def checkpanel(self): + for name in self.panelnames: + v, check, panel = self.panels[name] + panel.pack_forget() + for name in self.panelnames: + v, check, panel = self.panels[name] + if v.get(): + panel.pack(expand=1, fill=BOTH) + + +if __name__ == '__main__': + main() |