home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / webclean / !!!python!!! / BeOpen-Python-2.0.exe / WSGUI.PY < prev    next >
Encoding:
Python Source  |  2000-09-28  |  7.1 KB  |  244 lines

  1. #! /usr/bin/env python
  2.  
  3. """Tkinter-based GUI for websucker.
  4.  
  5. Easy use: type or paste source URL and destination directory in
  6. their respective text boxes, click GO or hit return, and presto.
  7. """
  8.  
  9. from Tkinter import *
  10. import Tkinter
  11. import string
  12. import websucker
  13. import sys
  14. import os
  15. import threading
  16. import Queue
  17. import time
  18.  
  19. VERBOSE = 2
  20.  
  21.  
  22. try:
  23.     class Canceled(Exception):
  24.         "Exception used to cancel run()."
  25. except:
  26.     Canceled = __name__ + ".Canceled"
  27.  
  28.  
  29. class SuckerThread(websucker.Sucker):
  30.  
  31.     stopit = 0
  32.     savedir = None
  33.     rootdir = None
  34.  
  35.     def __init__(self, msgq):
  36.         self.msgq = msgq
  37.         websucker.Sucker.__init__(self)
  38.         self.setflags(verbose=VERBOSE)
  39.         self.urlopener.addheaders = [
  40.             ('User-agent', 'websucker/%s' % websucker.__version__),
  41.         ]
  42.  
  43.     def message(self, format, *args):
  44.         if args:
  45.             format = format%args
  46.         ##print format
  47.         self.msgq.put(format)
  48.  
  49.     def run1(self, url):
  50.         try:
  51.             try:
  52.                 self.reset()
  53.                 self.addroot(url)
  54.                 self.run()
  55.             except Canceled:
  56.                 self.message("[canceled]")
  57.             else:
  58.                 self.message("[done]")
  59.         finally:
  60.             self.msgq.put(None)
  61.  
  62.     def savefile(self, text, path):
  63.         if self.stopit:
  64.             raise Canceled
  65.         websucker.Sucker.savefile(self, text, path)
  66.  
  67.     def getpage(self, url):
  68.         if self.stopit:
  69.             raise Canceled
  70.         return websucker.Sucker.getpage(self, url)
  71.  
  72.     def savefilename(self, url):
  73.         path = websucker.Sucker.savefilename(self, url)
  74.         if self.savedir:
  75.             n = len(self.rootdir)
  76.             if path[:n] == self.rootdir:
  77.                 path = path[n:]
  78.                 while path[:1] == os.sep:
  79.                     path = path[1:]
  80.                 path = os.path.join(self.savedir, path)
  81.         return path
  82.  
  83.     def XXXaddrobot(self, *args):
  84.         pass
  85.  
  86.     def XXXisallowed(self, *args):
  87.         return 1
  88.  
  89.  
  90. class App:
  91.  
  92.     sucker = None
  93.     msgq = None
  94.  
  95.     def __init__(self, top):
  96.         self.top = top
  97.         top.columnconfigure(99, weight=1)
  98.         self.url_label = Label(top, text="URL:")
  99.         self.url_label.grid(row=0, column=0, sticky='e')
  100.         self.url_entry = Entry(top, width=60, exportselection=0)
  101.         self.url_entry.grid(row=0, column=1, sticky='we',
  102.                     columnspan=99)
  103.         self.url_entry.focus_set()
  104.         self.url_entry.bind("<Key-Return>", self.go)
  105.         self.dir_label = Label(top, text="Directory:")
  106.         self.dir_label.grid(row=1, column=0, sticky='e')
  107.         self.dir_entry = Entry(top)
  108.         self.dir_entry.grid(row=1, column=1, sticky='we',
  109.                     columnspan=99)
  110.         self.go_button = Button(top, text="Go", command=self.go)
  111.         self.go_button.grid(row=2, column=1, sticky='w')
  112.         self.cancel_button = Button(top, text="Cancel",
  113.                         command=self.cancel,
  114.                                     state=DISABLED)
  115.         self.cancel_button.grid(row=2, column=2, sticky='w')
  116.         self.auto_button = Button(top, text="Paste+Go",
  117.                       command=self.auto)
  118.         self.auto_button.grid(row=2, column=3, sticky='w')
  119.         self.status_label = Label(top, text="[idle]")
  120.         self.status_label.grid(row=2, column=4, sticky='w')
  121.         self.top.update_idletasks()
  122.         self.top.grid_propagate(0)
  123.  
  124.     def message(self, text, *args):
  125.         if args:
  126.             text = text % args
  127.         self.status_label.config(text=text)
  128.  
  129.     def check_msgq(self):
  130.         while not self.msgq.empty():
  131.             msg = self.msgq.get()
  132.             if msg is None:
  133.                 self.go_button.configure(state=NORMAL)
  134.                 self.auto_button.configure(state=NORMAL)
  135.                 self.cancel_button.configure(state=DISABLED)
  136.                 if self.sucker:
  137.                     self.sucker.stopit = 0
  138.                 self.top.bell()
  139.             else:
  140.                 self.message(msg)
  141.         self.top.after(100, self.check_msgq)
  142.  
  143.     def go(self, event=None):
  144.         if not self.msgq:
  145.             self.msgq = Queue.Queue(0)
  146.             self.check_msgq()
  147.         if not self.sucker:
  148.             self.sucker = SuckerThread(self.msgq)
  149.         if self.sucker.stopit:
  150.             return
  151.         self.url_entry.selection_range(0, END)
  152.         url = self.url_entry.get()
  153.         url = string.strip(url)
  154.         if not url:
  155.             self.top.bell()
  156.             self.message("[Error: No URL entered]")
  157.             return
  158.         self.rooturl = url
  159.         dir = string.strip(self.dir_entry.get())
  160.         if not dir:
  161.             self.sucker.savedir = None
  162.         else:
  163.             self.sucker.savedir = dir
  164.             self.sucker.rootdir = os.path.dirname(
  165.                 websucker.Sucker.savefilename(self, url))
  166.         self.go_button.configure(state=DISABLED)
  167.         self.auto_button.configure(state=DISABLED)
  168.         self.cancel_button.configure(state=NORMAL)
  169.         self.message( '[running...]')
  170.         self.sucker.stopit = 0
  171.         t = threading.Thread(target=self.sucker.run1, args=(url,))
  172.         t.start()
  173.  
  174.     def cancel(self):
  175.         if self.sucker:
  176.             self.sucker.stopit = 1
  177.         self.message("[canceling...]")
  178.  
  179.     def auto(self):
  180.         tries = ['PRIMARY', 'CLIPBOARD']
  181.         text = ""
  182.         for t in tries:
  183.             try:
  184.                 text = self.top.selection_get(selection=t)
  185.             except TclError:
  186.                 continue
  187.             text = string.strip(text)
  188.             if text:
  189.                 break
  190.         if not text:
  191.             self.top.bell()
  192.             self.message("[Error: clipboard is empty]")
  193.             return
  194.         self.url_entry.delete(0, END)
  195.         self.url_entry.insert(0, text)
  196.         self.go()
  197.  
  198.  
  199. class AppArray:
  200.  
  201.     def __init__(self, top=None):
  202.         if not top:
  203.             top = Tk()
  204.             top.title("websucker GUI")
  205.             top.iconname("wsgui")
  206.             top.wm_protocol('WM_DELETE_WINDOW', self.exit)
  207.         self.top = top
  208.         self.appframe = Frame(self.top)
  209.         self.appframe.pack(fill='both')
  210.         self.applist = []
  211.         self.exit_button = Button(top, text="Exit", command=self.exit)
  212.         self.exit_button.pack(side=RIGHT)
  213.         self.new_button = Button(top, text="New", command=self.addsucker)
  214.         self.new_button.pack(side=LEFT)
  215.         self.addsucker()
  216.         ##self.applist[0].url_entry.insert(END, "http://www.python.org/doc/essays/")
  217.  
  218.     def addsucker(self):
  219.         self.top.geometry("")
  220.         frame = Frame(self.appframe, borderwidth=2, relief=GROOVE)
  221.         frame.pack(fill='x')
  222.         app = App(frame)
  223.         self.applist.append(app)
  224.  
  225.     done = 0
  226.  
  227.     def mainloop(self):
  228.         while not self.done:
  229.             time.sleep(0.1)
  230.             self.top.update()
  231.  
  232.     def exit(self):
  233.         for app in self.applist:
  234.             app.cancel()
  235.             app.message("[exiting...]")
  236.         self.done = 1
  237.  
  238.  
  239. def main():
  240.     AppArray().mainloop()
  241.  
  242. if __name__ == '__main__':
  243.     main()
  244.