| 
									
										
										
										
											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 string | 
					
						
							|  |  |  | import websucker | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | import threading | 
					
						
							|  |  |  | import Queue | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 	class Canceled(Exception): | 
					
						
							|  |  |  | 		"Exception used to cancel run()." | 
					
						
							|  |  |  | except: | 
					
						
							|  |  |  | 	Canceled = __name__ + ".Canceled" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | class SuckerThread(websucker.Sucker): | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 	stopit = 0 | 
					
						
							|  |  |  | 	savedir = None | 
					
						
							|  |  |  | 	rootdir = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def __init__(self, msgq): | 
					
						
							|  |  |  | 		self.msgq = msgq | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		websucker.Sucker.__init__(self) | 
					
						
							|  |  |  | 		self.setflags(verbose=VERBOSE) | 
					
						
							|  |  |  | 		self.urlopener.addheaders = [ | 
					
						
							|  |  |  | 			('User-agent', 'websucker/%s' % websucker.__version__), | 
					
						
							|  |  |  | 		] | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def message(self, format, *args): | 
					
						
							|  |  |  | 		if args: | 
					
						
							|  |  |  | 			format = format%args | 
					
						
							|  |  |  | 		##print format | 
					
						
							|  |  |  | 		self.msgq.put(format) | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class App: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sucker = None | 
					
						
							|  |  |  | 	msgq = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def __init__(self, top): | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		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') | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 		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() | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 		self.url_entry.bind("<Key-Return>", self.go) | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		self.dir_label = Label(top, text="Directory:") | 
					
						
							|  |  |  | 		self.dir_label.grid(row=1, column=0, sticky='e') | 
					
						
							|  |  |  | 		self.dir_entry = Entry(top) | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 		self.dir_entry.grid(row=1, column=1, sticky='we', | 
					
						
							|  |  |  | 				    columnspan=99) | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		self.go_button = Button(top, text="Go", command=self.go) | 
					
						
							|  |  |  | 		self.go_button.grid(row=2, column=1, sticky='w') | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 		self.cancel_button = Button(top, text="Cancel", | 
					
						
							|  |  |  | 					    command=self.cancel, | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		                            state=DISABLED) | 
					
						
							|  |  |  | 		self.cancel_button.grid(row=2, column=2, sticky='w') | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 		self.auto_button = Button(top, text="Paste+Go", | 
					
						
							|  |  |  | 					  command=self.auto) | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		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) | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 	def message(self, text, *args): | 
					
						
							|  |  |  | 		if args: | 
					
						
							|  |  |  | 			text = text % args | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 		self.status_label.config(text=text) | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 	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: | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		self.url_entry.selection_range(0, END) | 
					
						
							|  |  |  | 		url = self.url_entry.get() | 
					
						
							|  |  |  | 		url = string.strip(url) | 
					
						
							|  |  |  | 		if not url: | 
					
						
							|  |  |  | 			self.top.bell() | 
					
						
							|  |  |  | 			self.message("[Error: No URL entered]") | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		self.rooturl = url | 
					
						
							|  |  |  | 		dir = string.strip(self.dir_entry.get()) | 
					
						
							|  |  |  | 		if not dir: | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 			self.sucker.savedir = None | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		else: | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 			self.sucker.savedir = dir | 
					
						
							|  |  |  | 			self.sucker.rootdir = os.path.dirname( | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 				websucker.Sucker.savefilename(self, url)) | 
					
						
							|  |  |  | 		self.go_button.configure(state=DISABLED) | 
					
						
							|  |  |  | 		self.auto_button.configure(state=DISABLED) | 
					
						
							|  |  |  | 		self.cancel_button.configure(state=NORMAL) | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 		self.message( '[running...]') | 
					
						
							|  |  |  | 		self.sucker.stopit = 0 | 
					
						
							|  |  |  | 		t = threading.Thread(target=self.sucker.run1, args=(url,)) | 
					
						
							|  |  |  | 		t.start() | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def cancel(self): | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 		if self.sucker: | 
					
						
							|  |  |  | 			self.sucker.stopit = 1 | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		self.message("[canceling...]") | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def auto(self): | 
					
						
							| 
									
										
										
										
											1998-06-15 14:49:16 +00:00
										 |  |  | 		tries = ['PRIMARY', 'CLIPBOARD'] | 
					
						
							|  |  |  | 		text = "" | 
					
						
							|  |  |  | 		for t in tries: | 
					
						
							|  |  |  | 			try: | 
					
						
							|  |  |  | 				text = self.top.selection_get(selection=t) | 
					
						
							|  |  |  | 			except TclError: | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			text = string.strip(text) | 
					
						
							|  |  |  | 			if text: | 
					
						
							|  |  |  | 				break | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 		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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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() | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | 	def exit(self): | 
					
						
							|  |  |  | 		for app in self.applist: | 
					
						
							|  |  |  | 			app.cancel() | 
					
						
							|  |  |  | 			app.message("[exiting...]") | 
					
						
							|  |  |  | 		self.done = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  | def main(): | 
					
						
							|  |  |  | 	AppArray().mainloop() | 
					
						
							| 
									
										
										
										
											1998-06-15 12:35:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											1998-07-08 03:05:22 +00:00
										 |  |  |     main() |