Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 06981c3

Browse files
committed
Tk interface to webchecker. Not fully featured yet, but usable.
1 parent 0b0b5f0 commit 06981c3

1 file changed

Lines changed: 329 additions & 0 deletions

File tree

Tools/webchecker/wcgui.py

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
#! /usr/bin/env python
2+
3+
"""GUI interface to webchecker.
4+
5+
This works as a Grail applet too! E.g.
6+
7+
<APPLET CODE=wcgui.py NAME=CheckerWindow>
8+
<PARAM NAME=roots VALUE="http://<yourfavoritehost>">
9+
</APPLET>
10+
11+
Checkpoints are not (yet?) supported.
12+
13+
User interface:
14+
15+
When the 'Go' checkbutton is checked, web pages will be checked, one
16+
at a time in the Tk 'idle' time. The other checkbuttons determine
17+
whether the corresponding output panel is shown. There are six
18+
panels:
19+
20+
Log -- raw output from the checker (-v, -q affect this)
21+
To check -- local links discovered but not yet checked
22+
Off site -- links discovered that point off site
23+
Checked -- local links that have been checked
24+
Bad links -- links that failed upon checking
25+
Details -- details about one URL; double click on a URL in any of
26+
the aboce list panels (not in Log) will show that URL
27+
28+
XXX There ought to be a list of pages known to contain at least one
29+
bad link.
30+
31+
Use your window manager's Close command to quit.
32+
33+
Command line options:
34+
35+
-m bytes -- skip HTML pages larger than this size (default %(MAXPAGE)d)
36+
-n -- reports only, no checking (use with -R)
37+
-q -- quiet operation (also suppresses external links report)
38+
-v -- verbose operation; repeating -v will increase verbosity
39+
-x -- check external links (during report phase)
40+
41+
Command line arguments:
42+
43+
rooturl -- URL to start checking
44+
(default %(DEFROOT)s)
45+
46+
XXX The command line options should all be GUI accessible.
47+
48+
XXX The roots should be a list and there should be a GUI way to add a
49+
root.
50+
51+
XXX The alphabetizing of the lists makes the display very jumpy.
52+
53+
XXX The multipanel user interface is bogus.
54+
55+
"""
56+
57+
# ' Emacs bait
58+
59+
60+
import sys
61+
import getopt
62+
import string
63+
from Tkinter import *
64+
import tktools
65+
import webchecker
66+
import random
67+
68+
69+
def main():
70+
checkext = 0
71+
try:
72+
opts, args = getopt.getopt(sys.argv[1:], 'm:qvx')
73+
except getopt.error, msg:
74+
sys.stdout = sys.stderr
75+
print msg
76+
print __doc__%vars(webchecker)
77+
sys.exit(2)
78+
for o, a in opts:
79+
if o == '-m':
80+
webchecker.maxpage = string.atoi(a)
81+
if o == '-q':
82+
webchecker.verbose = 0
83+
if o == '-v':
84+
webchecker.verbose = webchecker.verbose + 1
85+
if o == '-x':
86+
checkext = 1
87+
root = Tk(className='Webchecker')
88+
root.protocol("WM_DELETE_WINDOW", root.quit)
89+
c = CheckerWindow(root, checkext)
90+
for arg in args or [webchecker.DEFROOT]:
91+
c.addroot(arg)
92+
root.mainloop()
93+
94+
95+
class CheckerWindow(webchecker.Checker):
96+
97+
def __init__(self, parent, checkext=0, roots=None):
98+
self.__parent = parent
99+
self.__checkext = checkext
100+
self.__controls = Frame(parent)
101+
self.__controls.pack(side=TOP, fill=X)
102+
self.__govar = IntVar()
103+
self.__go = Checkbutton(self.__controls, text="GO",
104+
variable=self.__govar,
105+
command=self.go)
106+
self.__go.pack(side=LEFT)
107+
self.__status = Label(parent, text="Status: initial", anchor=W)
108+
self.__status.pack(side=TOP, fill=X)
109+
self.__checking = Label(parent, text="Checking: none", anchor=W)
110+
self.__checking.pack(side=TOP, fill=X)
111+
self.__mp = mp = MultiPanel(parent)
112+
sys.stdout = self.__log = LogPanel(mp, "Log")
113+
self.__todo = ListPanel(mp, "To check", self.showinfo)
114+
self.__ext = ListPanel(mp, "Off site", self.showinfo)
115+
self.__done = ListPanel(mp, "Checked", self.showinfo)
116+
self.__bad = ListPanel(mp, "Bad links", self.showinfo)
117+
self.__details = LogPanel(mp, "Details")
118+
self.__extodo = []
119+
webchecker.Checker.__init__(self)
120+
if roots:
121+
roots = string.split(roots)
122+
for root in roots:
123+
self.addroot(root)
124+
125+
def go(self):
126+
if self.__govar.get():
127+
self.__parent.after_idle(self.dosomething)
128+
else:
129+
self.__checking.config(text="Checking: none")
130+
131+
def dosomething(self):
132+
if self.todo:
133+
i = random.randint(0, len(self.todo)-1)
134+
url = self.__todo.items[i]
135+
self.__checking.config(text="Checking: "+url)
136+
self.__parent.update()
137+
self.dopage(url)
138+
elif self.__checkext and self.__extodo:
139+
# XXX Should have an indication of these in the todo window...
140+
i = random.randint(0, len(self.__extodo)-1)
141+
url = self.__extodo[i]
142+
del self.__extodo[i]
143+
self.__checking.config(text="Checking: "+url)
144+
self.__parent.update()
145+
self.checkextpage(url)
146+
else:
147+
self.__govar.set(0)
148+
self.go()
149+
150+
def showinfo(self, url):
151+
d = self.__details
152+
d.clear()
153+
d.write("URL: %s\n" % url)
154+
if self.bad.has_key(url):
155+
d.write("Error: %s\n" % str(self.bad[url]))
156+
if self.done.has_key(url):
157+
d.write("Status: done\n")
158+
o = self.done[url]
159+
elif self.todo.has_key(url):
160+
d.write("Status: todo\n")
161+
o = self.todo[url]
162+
elif self.ext.has_key(url):
163+
d.write("Status: ext\n")
164+
o = self.ext[url]
165+
else:
166+
d.write("Status: unknown (!)\n")
167+
o = []
168+
if url in self.roots:
169+
d.write("This is a root URL\n")
170+
for source, rawlink in o:
171+
d.write("Origin: %s" % source)
172+
if rawlink != url:
173+
d.write(" (%s)" % rawlink)
174+
d.write("\n")
175+
self.__mp.showpanel("Details")
176+
177+
def newstatus(self):
178+
self.__status.config(text="Status: "+self.status()[1:-1])
179+
self.__parent.update()
180+
181+
def setbad(self, url, msg):
182+
webchecker.Checker.setbad(self, url, msg)
183+
self.__bad.insert(url)
184+
self.newstatus()
185+
186+
def setgood(self, url):
187+
webchecker.Checker.setgood(self, url)
188+
self.__bad.remove(url)
189+
self.newstatus()
190+
191+
def newextlink(self, url, origin):
192+
webchecker.Checker.newextlink(self, url, origin)
193+
self.__extodo.append(url)
194+
self.__ext.insert(url)
195+
self.newstatus()
196+
197+
def newintlink(self, url, origin):
198+
webchecker.Checker.newintlink(self, url, origin)
199+
if self.done.has_key(url):
200+
self.__done.insert(url)
201+
elif self.todo.has_key(url):
202+
self.__todo.insert(url)
203+
self.newstatus()
204+
205+
def markdone(self, url):
206+
webchecker.Checker.markdone(self, url)
207+
self.__done.insert(url)
208+
self.__todo.remove(url)
209+
self.newstatus()
210+
211+
212+
class ListPanel:
213+
214+
def __init__(self, mp, name, showinfo=None):
215+
self.mp = mp
216+
self.name = name
217+
self.showinfo = showinfo
218+
self.panel = mp.addpanel(name)
219+
self.list, self.frame = tktools.make_list_box(
220+
self.panel, width=60, height=5)
221+
self.list.config(exportselection=0)
222+
if showinfo:
223+
self.list.bind('<Double-Button-1>', self.event)
224+
self.items = []
225+
226+
def event(self, dummy):
227+
l = self.list.curselection()
228+
if not l: return
229+
self.showinfo(self.list.get(string.atoi(l[0])))
230+
231+
def insert(self, url):
232+
if url not in self.items:
233+
if not self.items:
234+
self.mp.showpanel(self.name)
235+
# (I tried sorting alphabetically, but the display is too jumpy)
236+
i = len(self.items)
237+
self.list.insert(i, url)
238+
self.list.select_clear(0, END)
239+
self.list.select_set(i)
240+
self.list.yview(i)
241+
self.items.insert(i, url)
242+
243+
def remove(self, url):
244+
try:
245+
i = self.items.index(url)
246+
except (ValueError, IndexError):
247+
pass
248+
else:
249+
self.list.delete(i)
250+
self.list.select_clear(i)
251+
del self.items[i]
252+
if not self.items:
253+
self.mp.hidepanel(self.name)
254+
255+
256+
class LogPanel:
257+
258+
def __init__(self, mp, name):
259+
self.mp = mp
260+
self.name = name
261+
self.panel = mp.addpanel(name)
262+
self.text, self.frame = tktools.make_text_box(self.panel, height=10)
263+
self.text.config(wrap=NONE)
264+
265+
def clear(self):
266+
self.text.delete("1.0", END)
267+
self.text.yview("1.0")
268+
269+
def write(self, s):
270+
self.text.insert(END, s)
271+
self.text.yview(END)
272+
self.panel.update()
273+
274+
275+
class MultiPanel:
276+
277+
def __init__(self, parent):
278+
self.parent = parent
279+
self.frame = Frame(self.parent)
280+
self.frame.pack(expand=1, fill=BOTH)
281+
self.topframe = Frame(self.frame, borderwidth=2, relief=RAISED)
282+
self.topframe.pack(fill=X)
283+
self.botframe = Frame(self.frame)
284+
self.botframe.pack(expand=1, fill=BOTH)
285+
self.panelnames = []
286+
self.panels = {}
287+
288+
def addpanel(self, name, on=0):
289+
v = StringVar()
290+
if on:
291+
v.set(name)
292+
else:
293+
v.set("")
294+
check = Checkbutton(self.topframe, text=name,
295+
offvalue="", onvalue=name, variable=v,
296+
command=self.checkpanel)
297+
check.pack(side=LEFT)
298+
panel = Frame(self.botframe)
299+
label = Label(panel, text=name, borderwidth=2, relief=RAISED, anchor=W)
300+
label.pack(side=TOP, fill=X)
301+
t = v, check, panel
302+
self.panelnames.append(name)
303+
self.panels[name] = t
304+
if on:
305+
panel.pack(expand=1, fill=BOTH)
306+
return panel
307+
308+
def showpanel(self, name):
309+
v, check, panel = self.panels[name]
310+
v.set(name)
311+
panel.pack(expand=1, fill=BOTH)
312+
313+
def hidepanel(self, name):
314+
v, check, panel = self.panels[name]
315+
v.set("")
316+
panel.pack_forget()
317+
318+
def checkpanel(self):
319+
for name in self.panelnames:
320+
v, check, panel = self.panels[name]
321+
panel.pack_forget()
322+
for name in self.panelnames:
323+
v, check, panel = self.panels[name]
324+
if v.get():
325+
panel.pack(expand=1, fill=BOTH)
326+
327+
328+
if __name__ == '__main__':
329+
main()

0 commit comments

Comments
 (0)