| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | #! /usr/bin/env python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """Tkinter-based GUI for websucker.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Easy use: type or paste source URL and destination directory in | 
					
						
							|  |  |  | their respective text boxes, click GO or hit return, and presto. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from Tkinter import * | 
					
						
							|  |  |  | import Tkinter | 
					
						
							|  |  |  | import websucker | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | import threading | 
					
						
							|  |  |  | import Queue | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | VERBOSE = 2 | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     class Canceled(Exception): | 
					
						
							|  |  |  |         "Exception used to cancel run()." | 
					
						
							| 
									
										
										
										
											2001-05-11 19:40:10 +00:00
										 |  |  | except (NameError, TypeError): | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     Canceled = __name__ + ".Canceled" | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | class SuckerThread(websucker.Sucker): | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     stopit = 0 | 
					
						
							|  |  |  |     savedir = None | 
					
						
							|  |  |  |     rootdir = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, msgq): | 
					
						
							|  |  |  |         self.msgq = msgq | 
					
						
							|  |  |  |         websucker.Sucker.__init__(self) | 
					
						
							|  |  |  |         self.setflags(verbose=VERBOSE) | 
					
						
							|  |  |  |         self.urlopener.addheaders = [ | 
					
						
							|  |  |  |             ('User-agent', 'websucker/%s' % websucker.__version__), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def message(self, format, *args): | 
					
						
							|  |  |  |         if args: | 
					
						
							|  |  |  |             format = format%args | 
					
						
							|  |  |  |         ##print format | 
					
						
							|  |  |  |         self.msgq.put(format) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def run1(self, url): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self.reset() | 
					
						
							|  |  |  |                 self.addroot(url) | 
					
						
							|  |  |  |                 self.run() | 
					
						
							|  |  |  |             except Canceled: | 
					
						
							|  |  |  |                 self.message("[canceled]") | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.message("[done]") | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             self.msgq.put(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def savefile(self, text, path): | 
					
						
							|  |  |  |         if self.stopit: | 
					
						
							|  |  |  |             raise Canceled | 
					
						
							|  |  |  |         websucker.Sucker.savefile(self, text, path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getpage(self, url): | 
					
						
							|  |  |  |         if self.stopit: | 
					
						
							|  |  |  |             raise Canceled | 
					
						
							|  |  |  |         return websucker.Sucker.getpage(self, url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def savefilename(self, url): | 
					
						
							|  |  |  |         path = websucker.Sucker.savefilename(self, url) | 
					
						
							|  |  |  |         if self.savedir: | 
					
						
							|  |  |  |             n = len(self.rootdir) | 
					
						
							|  |  |  |             if path[:n] == self.rootdir: | 
					
						
							|  |  |  |                 path = path[n:] | 
					
						
							|  |  |  |                 while path[:1] == os.sep: | 
					
						
							|  |  |  |                     path = path[1:] | 
					
						
							|  |  |  |                 path = os.path.join(self.savedir, path) | 
					
						
							|  |  |  |         return path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def XXXaddrobot(self, *args): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def XXXisallowed(self, *args): | 
					
						
							|  |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class App: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     sucker = None | 
					
						
							|  |  |  |     msgq = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, top): | 
					
						
							|  |  |  |         self.top = top | 
					
						
							|  |  |  |         top.columnconfigure(99, weight=1) | 
					
						
							|  |  |  |         self.url_label = Label(top, text="URL:") | 
					
						
							|  |  |  |         self.url_label.grid(row=0, column=0, sticky='e') | 
					
						
							|  |  |  |         self.url_entry = Entry(top, width=60, exportselection=0) | 
					
						
							|  |  |  |         self.url_entry.grid(row=0, column=1, sticky='we', | 
					
						
							|  |  |  |                     columnspan=99) | 
					
						
							|  |  |  |         self.url_entry.focus_set() | 
					
						
							|  |  |  |         self.url_entry.bind("<Key-Return>", self.go) | 
					
						
							|  |  |  |         self.dir_label = Label(top, text="Directory:") | 
					
						
							|  |  |  |         self.dir_label.grid(row=1, column=0, sticky='e') | 
					
						
							|  |  |  |         self.dir_entry = Entry(top) | 
					
						
							|  |  |  |         self.dir_entry.grid(row=1, column=1, sticky='we', | 
					
						
							|  |  |  |                     columnspan=99) | 
					
						
							|  |  |  |         self.go_button = Button(top, text="Go", command=self.go) | 
					
						
							|  |  |  |         self.go_button.grid(row=2, column=1, sticky='w') | 
					
						
							|  |  |  |         self.cancel_button = Button(top, text="Cancel", | 
					
						
							|  |  |  |                         command=self.cancel, | 
					
						
							|  |  |  |                                     state=DISABLED) | 
					
						
							|  |  |  |         self.cancel_button.grid(row=2, column=2, sticky='w') | 
					
						
							|  |  |  |         self.auto_button = Button(top, text="Paste+Go", | 
					
						
							|  |  |  |                       command=self.auto) | 
					
						
							|  |  |  |         self.auto_button.grid(row=2, column=3, sticky='w') | 
					
						
							|  |  |  |         self.status_label = Label(top, text="[idle]") | 
					
						
							|  |  |  |         self.status_label.grid(row=2, column=4, sticky='w') | 
					
						
							|  |  |  |         self.top.update_idletasks() | 
					
						
							|  |  |  |         self.top.grid_propagate(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def message(self, text, *args): | 
					
						
							|  |  |  |         if args: | 
					
						
							|  |  |  |             text = text % args | 
					
						
							|  |  |  |         self.status_label.config(text=text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def check_msgq(self): | 
					
						
							|  |  |  |         while not self.msgq.empty(): | 
					
						
							|  |  |  |             msg = self.msgq.get() | 
					
						
							|  |  |  |             if msg is None: | 
					
						
							|  |  |  |                 self.go_button.configure(state=NORMAL) | 
					
						
							|  |  |  |                 self.auto_button.configure(state=NORMAL) | 
					
						
							|  |  |  |                 self.cancel_button.configure(state=DISABLED) | 
					
						
							|  |  |  |                 if self.sucker: | 
					
						
							|  |  |  |                     self.sucker.stopit = 0 | 
					
						
							|  |  |  |                 self.top.bell() | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.message(msg) | 
					
						
							|  |  |  |         self.top.after(100, self.check_msgq) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def go(self, event=None): | 
					
						
							|  |  |  |         if not self.msgq: | 
					
						
							|  |  |  |             self.msgq = Queue.Queue(0) | 
					
						
							|  |  |  |             self.check_msgq() | 
					
						
							|  |  |  |         if not self.sucker: | 
					
						
							|  |  |  |             self.sucker = SuckerThread(self.msgq) | 
					
						
							|  |  |  |         if self.sucker.stopit: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self.url_entry.selection_range(0, END) | 
					
						
							|  |  |  |         url = self.url_entry.get() | 
					
						
							| 
									
										
										
										
											2002-09-11 20:36:02 +00:00
										 |  |  |         url = url.strip() | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |         if not url: | 
					
						
							|  |  |  |             self.top.bell() | 
					
						
							|  |  |  |             self.message("[Error: No URL entered]") | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self.rooturl = url | 
					
						
							| 
									
										
										
										
											2002-09-11 20:36:02 +00:00
										 |  |  |         dir = self.dir_entry.get().strip() | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |         if not dir: | 
					
						
							|  |  |  |             self.sucker.savedir = None | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.sucker.savedir = dir | 
					
						
							|  |  |  |             self.sucker.rootdir = os.path.dirname( | 
					
						
							|  |  |  |                 websucker.Sucker.savefilename(self, url)) | 
					
						
							|  |  |  |         self.go_button.configure(state=DISABLED) | 
					
						
							|  |  |  |         self.auto_button.configure(state=DISABLED) | 
					
						
							|  |  |  |         self.cancel_button.configure(state=NORMAL) | 
					
						
							|  |  |  |         self.message( '[running...]') | 
					
						
							|  |  |  |         self.sucker.stopit = 0 | 
					
						
							|  |  |  |         t = threading.Thread(target=self.sucker.run1, args=(url,)) | 
					
						
							|  |  |  |         t.start() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cancel(self): | 
					
						
							|  |  |  |         if self.sucker: | 
					
						
							|  |  |  |             self.sucker.stopit = 1 | 
					
						
							|  |  |  |         self.message("[canceling...]") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def auto(self): | 
					
						
							|  |  |  |         tries = ['PRIMARY', 'CLIPBOARD'] | 
					
						
							|  |  |  |         text = "" | 
					
						
							|  |  |  |         for t in tries: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 text = self.top.selection_get(selection=t) | 
					
						
							|  |  |  |             except TclError: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2002-09-11 20:36:02 +00:00
										 |  |  |             text = text.strip() | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |             if text: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         if not text: | 
					
						
							|  |  |  |             self.top.bell() | 
					
						
							|  |  |  |             self.message("[Error: clipboard is empty]") | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         self.url_entry.delete(0, END) | 
					
						
							|  |  |  |         self.url_entry.insert(0, text) | 
					
						
							|  |  |  |         self.go() | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AppArray: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     def __init__(self, top=None): | 
					
						
							|  |  |  |         if not top: | 
					
						
							|  |  |  |             top = Tk() | 
					
						
							|  |  |  |             top.title("websucker GUI") | 
					
						
							|  |  |  |             top.iconname("wsgui") | 
					
						
							|  |  |  |             top.wm_protocol('WM_DELETE_WINDOW', self.exit) | 
					
						
							|  |  |  |         self.top = top | 
					
						
							|  |  |  |         self.appframe = Frame(self.top) | 
					
						
							|  |  |  |         self.appframe.pack(fill='both') | 
					
						
							|  |  |  |         self.applist = [] | 
					
						
							|  |  |  |         self.exit_button = Button(top, text="Exit", command=self.exit) | 
					
						
							|  |  |  |         self.exit_button.pack(side=RIGHT) | 
					
						
							|  |  |  |         self.new_button = Button(top, text="New", command=self.addsucker) | 
					
						
							|  |  |  |         self.new_button.pack(side=LEFT) | 
					
						
							|  |  |  |         self.addsucker() | 
					
						
							|  |  |  |         ##self.applist[0].url_entry.insert(END, "http://www.python.org/doc/essays/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def addsucker(self): | 
					
						
							|  |  |  |         self.top.geometry("") | 
					
						
							|  |  |  |         frame = Frame(self.appframe, borderwidth=2, relief=GROOVE) | 
					
						
							|  |  |  |         frame.pack(fill='x') | 
					
						
							|  |  |  |         app = App(frame) | 
					
						
							|  |  |  |         self.applist.append(app) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     done = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def mainloop(self): | 
					
						
							|  |  |  |         while not self.done: | 
					
						
							|  |  |  |             time.sleep(0.1) | 
					
						
							|  |  |  |             self.top.update() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def exit(self): | 
					
						
							|  |  |  |         for app in self.applist: | 
					
						
							|  |  |  |             app.cancel() | 
					
						
							|  |  |  |             app.message("[exiting...]") | 
					
						
							|  |  |  |         self.done = 1 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											1999-11-17 15:13:21 +00:00
										 |  |  |     AppArray().mainloop() | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  |     main() |