mirror of
https://github.com/python/cpython.git
synced 2024-12-01 03:01:36 +01:00
f260e443ac
Updated documentation to use new name. Merged revisions 63077 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r63077 | alexandre.vassalotti | 2008-05-11 15:39:48 -0400 (Sun, 11 May 2008) | 3 lines Added stub for the Queue module to be renamed in 3.0. Use the 3.0 module name to avoid spurious warnings. ........
241 lines
6.9 KiB
Python
Executable File
241 lines
6.9 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 websucker
|
|
import os
|
|
import threading
|
|
import queue
|
|
import time
|
|
|
|
VERBOSE = 2
|
|
|
|
|
|
try:
|
|
class Canceled(Exception):
|
|
"Exception used to cancel run()."
|
|
except (NameError, TypeError):
|
|
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 = url.strip()
|
|
if not url:
|
|
self.top.bell()
|
|
self.message("[Error: No URL entered]")
|
|
return
|
|
self.rooturl = url
|
|
dir = self.dir_entry.get().strip()
|
|
if not dir:
|
|
self.sucker.savedir = None
|
|
else:
|
|
self.sucker.savedir = dir
|
|
self.sucker.rootdir = os.path.dirname(
|
|
websucker.Sucker.savefilename(self.sucker, 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 = text.strip()
|
|
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()
|