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