mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#! /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
 | 
						|
import threading
 | 
						|
import Queue
 | 
						|
import time		
 | 
						|
 | 
						|
VERBOSE = 2
 | 
						|
 | 
						|
 | 
						|
try:
 | 
						|
	class Canceled(Exception):
 | 
						|
		"Exception used to cancel run()."
 | 
						|
except:
 | 
						|
	Canceled = __name__ + ".Canceled"
 | 
						|
 | 
						|
 | 
						|
class SuckerThread(websucker.Sucker):
 | 
						|
 | 
						|
	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
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class App:
 | 
						|
 | 
						|
	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()
 | 
						|
		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:
 | 
						|
			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
 | 
						|
			text = string.strip(text)
 | 
						|
			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()
 | 
						|
 | 
						|
 | 
						|
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()
 | 
						|
	
 | 
						|
	def exit(self):
 | 
						|
		for app in self.applist:
 | 
						|
			app.cancel()
 | 
						|
			app.message("[exiting...]")
 | 
						|
		self.done = 1
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
	AppArray().mainloop()
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main()
 |