home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / tkinter / www / www13.py < prev    next >
Text File  |  1996-11-27  |  5KB  |  219 lines

  1. #! /usr/bin/env python
  2.  
  3. # www13.py -- display the contents of a URL in a Text widget
  4. # - set window title
  5. # - make window resizable
  6. # - update display while reading
  7. # - vertical scroll bar
  8. # - rewritten as class
  9. # - editable url entry and reload button
  10. # - error dialog
  11. # - menu bar; added 'master' option to constructor
  12. # - Added HTML parser
  13.  
  14. import sys
  15. import urllib
  16. from Tkinter import *
  17. import Dialog
  18. import tkfmt
  19. import htmllib
  20.  
  21. def main():
  22.     if len(sys.argv) != 2 or sys.argv[1][:1] == '-':
  23.         print "Usage:", sys.argv[0], "url"
  24.         sys.exit(2)
  25.     url = sys.argv[1]
  26.     tk = Tk()
  27.     tk.withdraw()
  28.     viewer = Viewer(tk)
  29.     viewer.load(url)
  30.     viewer.go()
  31.  
  32. class Viewer:
  33.  
  34.     def __init__(self, master = None):
  35.         # Create root window
  36.         if master is None:
  37.             self.root = self.master = Tk()
  38.         else:
  39.             self.master = master
  40.             self.root = Toplevel(self.master)
  41.         self.root.minsize(1, 1)
  42.  
  43.         # Create menu bar
  44.         self.mbar = Frame(self.root,
  45.                   {'relief': 'raised',
  46.                    'border': 2})
  47.         self.mbar.pack({'fill': 'x'})
  48.  
  49.         # Create File menu
  50.         self.filebutton = Menubutton(self.mbar, {'text': 'File'})
  51.         self.filebutton.pack({'side': 'left'})
  52.  
  53.         self.filemenu = Menu(self.filebutton)
  54.         self.filebutton['menu'] = self.filemenu
  55.  
  56.         # Create Edit menu
  57.         self.editbutton = Menubutton(self.mbar, {'text': 'Edit'})
  58.         self.editbutton.pack({'side': 'left'})
  59.  
  60.         self.editmenu = Menu(self.editbutton)
  61.         self.editbutton['menu'] = self.editmenu
  62.  
  63.         # Magic so you can swipe from one button to the next
  64.         self.mbar.tk_menuBar(self.filebutton, self.editbutton)
  65.  
  66.         # Populate File menu
  67.         self.filemenu.add('command', {'label': 'New',
  68.                           'command': self.new_command})
  69.         self.filemenu.add('command', {'label': 'Open...',
  70.                           'command': self.open_command})
  71.         self.filemenu.add('command', {'label': 'Clone',
  72.                           'command': self.clone_command})
  73.         self.filemenu.add('separator')
  74.         self.filemenu.add('command', {'label': 'Close',
  75.                           'command': self.close_command})
  76.         self.filemenu.add('command', {'label': 'Quit',
  77.                           'command': self.quit_command})
  78.  
  79.         # Populate Edit menu
  80.         pass
  81.  
  82.         # Create topframe for the entry and button
  83.         self.topframe = Frame(self.root)
  84.         self.topframe.pack({'fill': 'x'})
  85.  
  86.         # Create a label in front of the entry
  87.         self.urllabel = Label(self.topframe, {'text': 'URL:'})
  88.         self.urllabel.pack({'side': 'left'})
  89.  
  90.         # Create the entry containing the URL
  91.         self.entry = Entry(self.topframe,
  92.                    {'relief': 'sunken', 'border': 2})
  93.         self.entry.pack({'side': 'left', 'fill': 'x', 'expand': 1})
  94.         self.entry.bind('<Return>', self.loadit)
  95.  
  96.         # Create the button
  97.         self.reload = Button(self.topframe,
  98.                      {'text': 'Reload',
  99.                       'command': self.reload})
  100.         self.reload.pack({'side': 'right'})
  101.  
  102.         # Create botframe for the text and scrollbar
  103.         self.botframe = Frame(self.root)
  104.         self.botframe.pack({'fill': 'both', 'expand': 1})
  105.  
  106.         # The Scrollbar *must* be created first
  107.         self.vbar = Scrollbar(self.botframe)
  108.         self.vbar.pack({'fill': 'y', 'side': 'right'})
  109.         self.text = Text(self.botframe)
  110.         self.text.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
  111.  
  112.         # Link Text widget and Scrollbar
  113.         self.text['yscrollcommand'] = (self.vbar, 'set')
  114.         self.vbar['command'] = (self.text, 'yview')
  115.  
  116.         self.url = None
  117.  
  118.     def load(self, url):
  119.         # Load a new URL into the window
  120.         fp, url = self.urlopen(url)
  121.         if not fp:
  122.             return
  123.  
  124.         self.url = url
  125.  
  126.         self.root.title(url)
  127.  
  128.         self.entry.delete('0', 'end')
  129.         self.entry.insert('end', url)
  130.  
  131.         self.text.delete('0.0', 'end')
  132.  
  133.         f = tkfmt.TkFormatter(self.text)
  134.         p = htmllib.FormattingParser(f, htmllib.X11Stylesheet)
  135.  
  136.         while 1:
  137.             line = fp.readline()
  138.             if not line: break
  139.             if line[-2:] == '\r\n': line = line[:-2] + '\n'
  140.             p.feed(line)
  141.             self.root.update_idletasks()
  142.  
  143.         p.close()
  144.  
  145.         fp.close()
  146.  
  147.     def urlopen(self, url):
  148.         # Open a URL --
  149.         # return (fp, url) if successful
  150.         # display dialog and return (None, url) for errors
  151.         try:
  152.             fp = urllib.urlopen(url)
  153.         except IOError, msg:
  154.             import types
  155.             if type(msg) == types.TupleType and len(msg) == 4:
  156.                 if msg[1] == 302:
  157.                     m = msg[3]
  158.                     if m.has_key('location'):
  159.                         url = m['location']
  160.                         return self.urlopen(url)
  161.                     elif m.has_key('uri'):
  162.                         url = m['uri']
  163.                         return self.urlopen(url)
  164.             self.errordialog(IOError, msg)
  165.             fp = None
  166.         return fp, url
  167.  
  168.     def errordialog(self, exc, msg):
  169.         # Display an error dialog -- return when the user clicks OK
  170.         Dialog.Dialog(self.root, {
  171.             'text': str(msg),
  172.             'title': exc,
  173.             'bitmap': 'error',
  174.             'default': 0,
  175.             'strings': ('OK',),
  176.             })
  177.  
  178.     def go(self):
  179.         # Start Tk main loop
  180.         self.root.mainloop()
  181.  
  182.     def reload(self, *args):
  183.         # Callback for Reload button
  184.         if self.url:
  185.             self.load(self.url)
  186.  
  187.     def loadit(self, *args):
  188.         # Callback for <Return> event in entry
  189.         self.load(self.entry.get())
  190.  
  191.     def new_command(self):
  192.         # File/New...
  193.         Viewer(self.master)
  194.  
  195.     def clone_command(self):
  196.         # File/Clone
  197.         v = Viewer(self.master)
  198.         v.load(self.url)
  199.  
  200.     def open_command(self):
  201.         # File/Open...
  202.         print "File/Open...: Not implemented"
  203.  
  204.     def close_command(self):
  205.         # File/Close
  206.         self.destroy()
  207.  
  208.     def quit_command(self):
  209.         # File/Quit
  210.         self.root.quit()
  211.  
  212.     def destroy(self):
  213.         # Destroy this window
  214.         self.root.destroy()
  215.         if self.master is not self.root and not self.master.children:
  216.             self.master.quit()
  217.  
  218. main()
  219.