#!/usr/bin/env python
#    Giplet - GNOME Panel Applet to display an IP Address
#    Copyright (C) 2006  Erik Larson
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#
import sys
import pygtk
pygtk.require('2.0')
import gtk
import gnomeapplet
import gnome.ui
import socket
import fcntl
import struct
import urllib
import re
import gobject
import giplet_globals as gipglobals
import gipletprefs
import string
from HTMLParser import HTMLParser

def get_ip_address(ifname):
    try:
      s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      newipaddress = socket.inet_ntoa(fcntl.ioctl(
        s.fileno(), 
        0x8915, 
        struct.pack('256s', ifname[:15])
      )[20:24])
    except:
        newipaddress = '???.???.???.???'
    return newipaddress

class ProcessHTML(HTMLParser):
  my_ip_address = ""
  
  def handle_data(self, data):
    ip_address = re.compile("\d+\.\d+\.\d+\.\d+").search(data)
    if ip_address:
      self.my_ip_address = ip_address.group()

def get_external_ip_address( website ):
    try:
      webaddy = website.lower()      
      if ( not webaddy.startswith('http') ):
        webaddy = 'http://' + webaddy
      sock = urllib.urlopen( webaddy )
      pagina = sock.read()
      sock.close()  
      process = ProcessHTML()
      process.feed( pagina )  
      newipaddress = process.my_ip_address
    except:
      newipaddress = '???.???.???.???'
    return newipaddress

class GipletAppletWin:
    # Constructor
    def __init__(self, applet, iid):
        self.applet = applet
        
        #instance variables
        self.tooltip_text = "IP Address"
        
        self.propxml="""
        <popup name="button3">
        <menuitem name="Item 1" verb="Props" label="_Preferences..." pixtype="stock" pixname="gtk-properties"/>
        <menuitem name="Item 2" verb="About" label="_About..." pixtype="stock" pixname="gnome-stock-about"/>
        </popup>        
        """
         
        self.verbs = [ ( "Props", self.properties ), ("About", self.about) ]
        
        gnome.init(gipglobals.name, gipglobals.version)
        
        #Read in preferences
        self.prefs = gipletprefs.GipPrefs()
        self.prefs.readFromFile()
                
        #create the applet and the widgets
        self.label = gtk.Label('???.???.???.???')
        self.applet.add(self.label)
        
        #initialize the timer source
        self.timer_source = None
        
        #update the display
        self.update()
        
        #hook up events
        self.applet.connect("button-press-event", self.button_press)
        self.applet.connect("change_background", self.applet_change_background)              
        
    def cleanup(self, event):
        del self.applet
        
    # On Timeout
    def timeout(self):
        self.update()
        
    # About box
    def about(self, event, data=None):
      about = gtk.AboutDialog()
      about.set_name('Giplet')
      about.set_version(gipglobals.version)
      about.set_comments("A GNOME panel applet for displaying a computer's ip address")
      about.set_license(gipglobals.license)
      about.set_authors(['Erik Larson - Lead Developer', 
                        'Conrad Knauer - Ubuntu Packaging'])
      about.show()
      
    def update(self):
        if (self.prefs.isFromWeb):
            self.label.set_text(get_external_ip_address(self.prefs.website))            
        else:
            self.label.set_text(get_ip_address(self.prefs.interface))
        if (self.prefs.isTimer and self.prefs.interval > 0):
            if (not self.timer_source == None):
                gobject.source_remove(self.timer_source)
            self.timer_source = gobject.timeout_add(60 * 1000 * self.prefs.interval, self.timeout)
      
    #Preferences
    def properties(self, event, data=None):
        prefsDlg = gipletprefs.GipPrefsDlg(self.prefs)
        prefsDlg.run()       
        self.prefs.writeToFile() 
        self.update()
      
    def applet_change_background(self, applet, type, color, pixmap):
      # get reset style
      self.applet.set_style(None)
      rc_style = gtk.RcStyle()
      self.applet.modify_style(rc_style)      
      if (int(type) == 0):      
        return
      elif (int(type) == 1):
        applet.modify_bg(gtk.STATE_NORMAL, color)        
        return
      elif (int(type) == 2):
        style = applet.style
        style.bg_pixmap[gtk.STATE_NORMAL] = pixmap
        applet.set_style(style)
        return
        
    def button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
          self.create_menu()
    
    def create_menu(self):
        self.applet.setup_menu(self.propxml, self.verbs, None)
        
def giplet_factory(applet, iid):
  GipletAppletWin(applet, iid)
  applet.show_all()
  return gtk.TRUE
  
#run it in a gtk window            
if len(sys.argv) > 1 and sys.argv[1] == 'run-in-window':
  main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  main_window.set_title("Giplet Applet")
  main_window.connect("destroy", gtk.main_quit)
  app = gnomeapplet.Applet()
  giplet_factory(app, None)
  app.reparent(main_window)
  main_window.show_all()
  gtk.main()
  sys.exit()
  
gnomeapplet.bonobo_factory("OAFIID:GNOME_GipletApplet_Factory",
                          gnomeapplet.Applet.__gtype__,
                          "Giplet IP Viewer", "0", giplet_factory)
                          
