#!/usr/bin/python
#
# Killswitch Applet -- Manage WWAN, WLAN and Bluetooth Killswitches
#
# Copyright (C) 2009,2010 Holger Macht <holger@homac.de>
#
# This file is released under the WTFPL (http://sam.zoy.org/wtfpl/)
#
 
import pygtk
pygtk.require('2.0')
import gtk
import dbus
import os.path
import killswitch
import ConfigParser

NAME="Killswitch Applet"
VERSION="0.2.3"
TRAY_ICON_PATH="%s/../share/icons/hicolor/scalable/apps/killswitch-applet.svg"
CONFIG_FILE="~/.killswitch.cfg"

def get_local_path():
    p = os.path.dirname(__file__)
    return os.path.abspath(p)


# main _K_ill_S_witch_A_pplet class
class KSA:
    def __init__(self):

        self.k = killswitch.KillswitchManager()

        self.icon = gtk.status_icon_new_from_file(TRAY_ICON_PATH % get_local_path())

        self.icon.connect("popup_menu", self.on_rightclick, None)
        self.icon.connect("activate", self.on_leftclick, None)

        self.menu = gtk.Menu()

        self.switches = {}

        self.k.set_state_changed_cb(self.state_changed_cb)
        self.k.set_killswitch_added_cb(self.device_added_cb)
        self.k.set_killswitch_removed_cb(self.device_removed_cb)

        for ks in self.k.get_killswitches():
            self.create_menu_item(ks)

        if len(self.switches) == 0:
            print "No killswitches found, bailing out..."
            exit(0)

        self.read_and_apply_config()

        self.update_icon_tool_tip()

        sep = gtk.SeparatorMenuItem()
        self.menu.append(sep)
        sep.show()
        
        item = gtk.ImageMenuItem("Enable All")
        img = gtk.Image()
        img.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU)
        item.set_image(img)
        self.menu.append(item)
        item.connect("activate", self.enable_all, None)
        item.show()

        item = gtk.ImageMenuItem("Disable All")
        self.menu.append(item)
        img = gtk.Image()
        img.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
        item.set_image(img)
        item.connect("activate", self.disable_all, None)
        item.show()

        sep = gtk.SeparatorMenuItem()
        self.menu.append(sep)
        sep.show()

        item = gtk.ImageMenuItem("About...")
        self.menu.append(item)
        img = gtk.Image()
        img.set_from_stock(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU)
        item.set_image(img)
        item.connect("activate", self.show_about, None)
        item.show()

        item = gtk.ImageMenuItem("Quit")
        self.menu.append(item)
        img = gtk.Image()
        img.set_from_stock(gtk.STOCK_QUIT, gtk.ICON_SIZE_MENU)
        item.set_image(img)
        item.connect("activate", self.destroy, None)
        item.show()

    def enable_all(self, widget, data=None):
        self.k.enable_all()

    def disable_all(self, widget, data=None):
        self.k.disable_all()

    def on_rightclick(self, widget, button, time, data=None):
        self.menu.popup(None, None, None, button, time, data=None)

    def on_leftclick(self, widget, button):
        self.menu.popup(None, None, None, 0, 0, data=None)
        
    def create_menu_item(self, ks):
        label = "%s (%s)" % (ks.name(), ks.type())
        item = gtk.CheckMenuItem(label)

        self.menu.prepend(item)
        self.switches[ks] = item
        
        state = ks.get_state()
        print "state of %s is %d" % (ks.udi(), state)

        item.set_active(ks.get_state())

        item.connect("toggled", self.toggle, ks)
        item.show()

    def toggle(self, widget, ks):
        state = ks.get_state()
        if state != widget.get_active():
            print "setting state to %s" % (not state)
            ks.set_state(not state)
        self.update_icon_tool_tip()

    def state_changed_cb(self, ks, newval):
        print "udi %s newval %d" % (ks.udi(), newval)
        for item in self.switches:
            if item == ks:
                if newval == 2:
                    self.switches[item].set_sensitive(False)
                else:
                    self.switches[item].set_sensitive(True)
                    self.switches[item].set_active(newval)
        self.update_icon_tool_tip()
        self.write_config()

    def device_added_cb(self, ks):
        print "adding menu item %s with name %s" % (ks.udi(), ks.name())
        self.create_menu_item(ks)
        self.update_icon_tool_tip()

    def device_removed_cb(self, ks):
        for item in self.switches.keys():
            if ks == item:
                print "removing killswitch menu item %s" % ks.udi()
                self.menu.remove(self.switches[ks])
                del self.switches[item]
        self.update_icon_tool_tip()
                
    def destroy(self, widget, data=None):
        gtk.main_quit()

    def show_about(self, widget, data=None):
        about = gtk.AboutDialog()
        about.set_program_name(NAME)
        about.set_version(VERSION)
        about.set_copyright("(c) 2009,2010 Holger Macht <holger@homac.de>")
        about.set_comments("Control kill switches for bluetooth, wireless, etc...")
        about.set_website("http://gitorious.org/python-killswitch/killswitch-applet")
        about.set_logo(gtk.gdk.pixbuf_new_from_file(TRAY_ICON_PATH % get_local_path()))
        about.run()
        about.destroy()

    def update_icon_tool_tip(self):
        # construct the tool tip
        text = "Active kill switches:"
        num = 0

        for item in self.switches.keys():
            if item.get_state() == 0:
                text += "\n - " + item.name()
                num += 1

        if num == 0:
            text += " none"

        self.icon.set_tooltip_text(text)

    def write_config(self):
        config = ConfigParser.RawConfigParser()

        config.add_section('Killswitches')

        for ks in self.switches:
            config.set('Killswitches', ks.name(), ks.get_state())

            with open(os.path.expanduser(CONFIG_FILE), 'wb') as configfile:
                config.write(configfile)

    def read_and_apply_config(self):
        config = ConfigParser.RawConfigParser()

        config.read(os.path.expanduser(CONFIG_FILE))

        if not config.has_section('Killswitches'):
            return

        for ks in self.switches:
            if config.has_option('Killswitches', ks.name()):
                ks.set_state(config.getboolean('Killswitches', ks.name()))

    def main(self):
        gtk.main()

if __name__ == "__main__":
    base = KSA()
    base.main()
