#!/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

import gettext
gettext.install(gipglobals.GETTEXT_PACKAGE, gipglobals.LOCALE_DIR, unicode=1)

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

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

def get_external_ip(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 )  
            result = process.parsed_ip
    except:
        result = None
    return result

class GipletAppletWin:
    # Constructor
    def __init__(self, applet, iid):
        self.applet = applet
        
        gnome.init(gipglobals.PACKAGE, gipglobals.VERSION)

        # context menu
        self.popupxml = '<popup name="button3">\
<menuitem name="Preference Item" verb="Props" _label="' + _("_Preferences") + '"\
 pixtype="stock" pixname="gtk-properties" />\
<menuitem name="About Item" verb="About" _label="' + _("_About") + '"\
 pixtype="stock" pixname="gtk-about" />\
<menuitem name="Copy Item" verb="Copy" _label="' + _("_Copy IP to Clipboard") + '"\
 pixtype="stock" pixname="gtk-copy" />\
<menuitem name="Refresh Item" verb="Refresh" _label="' + _("_Refresh") + '"\
 pixtype="stock" pixname="gtk-refresh" />\
</popup>'

        #Read preferences
        if (iid == None) :
            path = "/apps/giplet"
        else :
            path = self.applet.get_preferences_key()
        self.prefs = gipletprefs.GipPrefs(path)
        self.prefs.readFromGConf()
        
        #create the applet and the widgets
        self.label = gtk.Label(gipglobals.PACKAGE)
        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()
    
    # Closing the about box   
    def close_about_box(self, w, res):
        if res == gtk.RESPONSE_CANCEL:
            w.hide()
    
    # About box
    def about(self, event, data=None):
        about = gtk.AboutDialog()
        about.set_name(gipglobals.PACKAGE)
        about.set_version(gipglobals.VERSION)
        about.set_comments(
            _("Gnome panel applet for displaying IP address"))
        about.set_copyright(_("Copyright (C) 2006 Erik Larson"))
        about.set_website("http://sourceforge.net/projects/giplet")
        about.set_logo_icon_name("giplet")
        about.set_authors([_("Erik Larson - Initiator"),
                           _("Lyman Li <lymanrb@gmail.com> - Current Maintainer"),
                           _("Yanik - Patcher")
                           ])
        about.set_artists([_("Lyman Li <lymanrb@gmail.com>")])
        about.set_translator_credits (_("translator-credits"))
        about.connect("response", self.close_about_box)
        about.show()

    def refresh(self, event, data=None):
        self.update()
        
    def update(self):
        # self.label.set_text(self.prefs.conf_path)
        self.label.set_text(gipglobals.PACKAGE)
        self.applet.set_tooltip_text(_("No IP detected."))
        if (len(self.prefs.interface) > 0) :
            for face in self.prefs.interface.split() :
                if (face.find('.') == -1) :
                    ip = get_internal_ip(face)
                else :
                    ip = get_external_ip(face)
                if (not ip == None) :
                    self.label.set_text(ip)
                    self.applet.set_tooltip_text(face + ": " + ip)
                    break
            #timer
            if (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.writeToGConf()
        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 copy_ip(self, event, data=None):
        clipboard = gtk.Clipboard(display=gtk.gdk.display_get_default(), selection="CLIPBOARD")
        clipboard.set_text(self.label.get_text())
    
    def button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
            self.create_menu()
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
            self.update()
    
    def create_menu(self):
        self.applet.setup_menu(self.popupxml,
                               [("Props", self.properties),
                                ("About", self.about),
                                ("Copy", self.copy_ip),
                                ("Refresh", self.refresh)],
                               None)
        # self.applet.setup_menu_from_file(gipglobals.RES_DIR,
        #                                  'giplet.xml',
        #                                  'giplet',
        #                                  [('Props', self.properties),
        #                                   ('About', self.about),
        #                                   ('Copy', self.copy_ip),
        #                                   ('Refresh', self.refresh)])
        
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")
    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__,
                           gipglobals.PACKAGE, gipglobals.VERSION, giplet_factory)
