import os.path
import gobject
import gtk
import gtk.gdk
import bonobo
import gconfsync
import gnome
import gnome.ui
import gettext
import locale
import gnome_osd_conf
import gtkexcepthook
try:
    import dbus
    if getattr(dbus, "version", (0,0,0)) >= (0,41,0):
        import dbus.glib
    HAVE_DBUS = True
except:
    HAVE_DBUS = False

class HIGContainer(gtk.Alignment):
    def __init__(self, title, child):
        gtk.Alignment.__init__(self)
        self.set(xalign=0, yalign=0, xscale=1, yscale=1)
        vbox = gtk.VBox()
        vbox.show()
        self.add(vbox)
        vbox.set_spacing(6)
        label = gtk.Label(); label.show()
        label.set_markup('<span weight="bold">%s</span>' % title)
        label.set_use_underline(True)
        label.set_alignment(0, 0.5)
        vbox.pack_start(label)
        hbox = gtk.HBox(); hbox.show()
        vbox.pack_start(hbox)
        label = gtk.Label('    '); label.show()
        hbox.pack_start(label, False, False)
        hbox.pack_start(child, True, True)
        self.show()
                 

class RadioGroup(gobject.GObject):
    __gsignals__ = {
        'changed': (gobject.SIGNAL_RUN_LAST,
                    None, # return type
                    (object, )) # parameter types
    }

    def __init__(self, items):
        self.__gobject_init__()
        self.radio_map = dict()
        self.items = dict()
        self.__ignore_toggled = False
        radio = None
        for item in items:
            radio = gtk.RadioButton(radio, item[0])
            self.radio_map[radio] = item[1]
            self.items[item[1]] = radio
            radio.show()
            radio.connect("toggled", self.__radio_toggled)

    def __radio_toggled(self, radio):
        if self.__ignore_toggled:
            return
        if radio.get_active():
            value = self.radio_map[radio]
            self.emit("changed", value)

    def get_value(self):
        for radio in self.radio_map:
            if radio.get_active():
                return self.radio_map[radio]

    def set_value(self, value):
        self.__ignore_toggled = True
        radio = self.items[value]
        radio.set_active(True)
        self.__ignore_toggled = False
if gobject.pygtk_version < (2,8):
    gobject.type_register(RadioGroup)

class RadioGroupSync(object):

    ''' Synchronizes a gconf key with a radio group '''

    def __init__(self, group, prefs, key):
        prefs.connect("changed::%s" % key, self.__pref_changed)
        group.connect("changed", self.__gui_changed)
        self.group = group
        self.prefs = prefs
        self.key = key
        group.set_value(prefs[key])

    def __pref_changed(self, prefs, key):
        self.group.set_value(prefs[key])

    def __gui_changed(self, unused_group, value):
        self.prefs[self.key] = value

class FontSync(object):
    def __init__(self, font, prefs, key):
        font.connect("font-set", self.__font_changed)
        prefs.connect("changed::%s" % key, self.__pref_changed)
        font.set_font_name(prefs[key])
        self.prefs = prefs
        self.key = key
        self.font = font
    def __font_changed(self, unused_font, font_name):
        self.prefs[self.key] = font_name
    def __pref_changed(self, prefs, key):
        self.font.set_font_name(prefs[key])

class ToggleSync(object):
    def __init__(self, toggle, prefs, key):
        self.prefs = prefs
        self.key = key
        self.toggle = toggle
        toggle.set_active(prefs[key])
        toggle.connect("toggled", self.__toggled)
        prefs.connect("changed::%s" % key, self.__pref_changed)
        self.__ignore_toggled = False
    def __toggled(self, toggle):
        if self.__ignore_toggled:
            return
        self.prefs[self.key] = toggle.get_active()
    def __pref_changed(self, prefs, key):
        self.__ignore_toggled = True
        self.toggle.set_active(prefs[key])
        self.__ignore_toggled = False

class AlignmentGroupSync(object):
    def __init__(self, group, prefs):
        self.group = group
        self.__pref_changed(prefs, None)
        prefs.connect("changed::osd_halignment", self.__pref_changed)
        prefs.connect("changed::osd_vposition", self.__pref_changed)
        self.prefs = prefs
        group.connect("changed", self.__gui_changed)

    def __pref_changed(self, prefs, unused_name):
        halign = prefs['osd_halignment']
        valign = prefs['osd_vposition']
        self.group.set_value("-".join((valign, halign)))
        
    def __gui_changed(self, unused_group, value):
        valign, halign = value.split('-')
        self.prefs['osd_halignment'] = halign
        self.prefs['osd_vposition'] = valign

def main():
    gettext.install("gnome-osd", os.path.join(gnome_osd_conf.datadir, "locale"))
    locale.setlocale(locale.LC_ALL, '')
    locale.bind_textdomain_codeset('gnome-osd','UTF-8')
    gettext.bind_textdomain_codeset('gnome-osd','UTF-8')
    gnome.program_init("gnome-osd-properties", gnome_osd_conf.VERSION)

    try:
        icon = gtk.gdk.pixbuf_new_from_file(os.path.join(gnome_osd_conf.datadir,
                                                         "pixmaps", "gnome-osd.png"))
        gtk.window_set_default_icon_list(icon)
        del icon
    except gobject.GError:
        print "Icon file not found"


    RESPONSE_TEST, RESPONSE_ABOUT = range(2)
    dialog = gtk.Dialog(title=_("OSD Properties"),
                        buttons=(_("_Test"), RESPONSE_TEST,
                                 gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE,
                                 )
                        )
    about_button = dialog.add_button(gtk.STOCK_ABOUT, RESPONSE_ABOUT)
    dialog.action_area.set_child_secondary(about_button, True)
    dialog.set_property("has-separator", 0)
    dialog.set_border_width(12)
    dialog.set_default_response(RESPONSE_TEST)
    dialog.set_resizable(False)

    def general_preferences():
        prefs = gconfsync.GConfSync("/apps/gnome-osd")
        main_vbox = gtk.VBox(False, 18)
        main_vbox.set_border_width(12)
        main_vbox.show()
        # Font
        hbox = gtk.HBox(False, 6)
        label = gtk.Label(_("OSD _Font: "))
        label.set_use_underline(True)
        label.set_alignment(0, 0.5)
        hbox.pack_start(label, False, True)

        font = gnome.ui.FontPicker()
        font.set_property('mode', gnome.ui.FONT_PICKER_MODE_FONT_INFO)
        hbox.pack_start(font, True, True)
        label.set_mnemonic_widget(font)
        hbox.show_all()
        main_vbox.add(hbox)

        FontSync(font, prefs, 'osd_font')

        hbox = gtk.HBox(False, 6)
        hbox.show()
        main_vbox.add(hbox)

        # Animations
        animations = gtk.CheckButton(_("_Animations"))
        animations.show()
        hbox.add(animations)
        ToggleSync(animations, prefs, "animations")

        # Drop shadow
        drop_shadow = gtk.CheckButton(_("_Drop shadow"))
        drop_shadow.show()
        hbox.add(drop_shadow)
        ToggleSync(drop_shadow, prefs, "drop_shadow")

        # Sound
        sound = gtk.CheckButton(_("_Sound"))
        sound.show()
        hbox.add(sound)
        ToggleSync(sound, prefs, "enable_sound")

        # Hide on hover
        hide = gtk.CheckButton(_("_Hide on mouse hover"))
        hide.show()
        main_vbox.add(hide)
        ToggleSync(hide, prefs, "hide_on_hover")

        # --- Alignment
        group = RadioGroup([
            (_("Top _left"), 'top-left'),
            (_("_Top"), 'top-center'),
            (_("Top _right"), 'top-right'),
            (_("L_eft"), 'center-left'),
            (_("_Center"), 'center-center'),
            (_("Ri_ght"), 'center-right'),
            (_("Bottom l_eft"), 'bottom-left'),
            (_("_Bottom"), 'bottom-center'),
            (_("Bottom r_ight"), 'bottom-right'),
            ])

        table = gtk.Table(3, 3)
        table.show()
        table.set_row_spacings(6)
        table.set_col_spacings(6)

        table.attach(group.items['top-left'], 0, 1, 0, 1)
        table.attach(group.items['top-center'], 1, 2, 0, 1)
        table.attach(group.items['top-right'], 2, 3, 0, 1)
        table.attach(group.items['center-left'], 0, 1, 1, 2)
        table.attach(group.items['center-center'], 1, 2, 1, 2)
        table.attach(group.items['center-right'], 2, 3, 1, 2)
        table.attach(group.items['bottom-left'], 0, 1, 2, 3)
        table.attach(group.items['bottom-center'], 1, 2, 2, 3)
        table.attach(group.items['bottom-right'], 2, 3, 2, 3)


        AlignmentGroupSync(group, prefs)


        # Avoid Panels
        avoid = gtk.CheckButton(_("A_void panels"))
        avoid.show()
        ToggleSync(avoid, prefs, "avoid_panels")

        vbox = gtk.VBox(False, 6)
        vbox.show()
        vbox.add(table)
        vbox.add(avoid)

        container = HIGContainer(_("Alignment"), vbox)
        main_vbox.add(container)
        return main_vbox


    def events_preferences():
        main_vbox = gtk.VBox(False, 18)
        main_vbox.set_border_width(12)
        main_vbox.show()
        tooltips = gtk.Tooltips()

        # Song change
        prefs = gconfsync.GConfSync("/apps/gnome-osd/plugins/song_change")
        check = gtk.CheckButton(_("Notify on _song changes"))
        tooltips.set_tip(check, _("Works with Rhythmbox and Muine"))
        check.show()
        container = HIGContainer(_("Music Player"), check)
        main_vbox.pack_start(container, False, False, 0)
        ToggleSync(check, prefs, "enabled")

        # XChat
        prefs = gconfsync.GConfSync("/apps/gnome-osd/plugins/xchat")
        vbox = gtk.VBox(False, 6)
        vbox.show()
        container = HIGContainer(_("IRC (Chat)"), vbox)
        main_vbox.pack_start(container, False, False, 0)
        
        check = gtk.CheckButton(_("Notify on _IRC messages directed to me"))
        tooltips.set_tip(check, _("Works with XChat (>= 2.6) with D-BUS plugin"))
        check.show()
        vbox.pack_start(check, False, False, 0)
        ToggleSync(check, prefs, "enabled")

        enabled_check = check
        check = gtk.CheckButton(_("Include _message text"))
        enabled_check.connect("toggled",
                              lambda check1, check2: check2.set_sensitive(check1.get_active()),
                              check)
        check.show()
        vbox.pack_start(check, False, False, 0)
        ToggleSync(check, prefs, "full")

        # Evolution
        prefs = gconfsync.GConfSync("/apps/gnome-osd/plugins/email")
        vbox = gtk.VBox(False, 6)
        vbox.show()
        container = HIGContainer(_("EMail"), vbox)
        main_vbox.pack_start(container, False, False, 0)
        
        check = gtk.CheckButton(_("Notify when new _email arrives"))
        tooltips.set_tip(check, _("Works with Evolution with enabled D-BUS plugin"))
        check.show()
        vbox.pack_start(check, False, False, 0)
        ToggleSync(check, prefs, "enabled")
        
        # gaim
        prefs = gconfsync.GConfSync("/apps/gnome-osd/plugins/gaim")
        vbox = gtk.VBox(False, 6)
        vbox.show()
        container = HIGContainer(_("Gaim"), vbox)
        main_vbox.pack_start(container, False, False, 0)
        
        check = gtk.CheckButton(_("Notify buddies actions"))
        tooltips.set_tip(check, _("Notify when a contact logs in or out, writes, or sends a message"))
        check.show()
        vbox.pack_start(check, False, False, 0)
        ToggleSync(check, prefs, "enabled")
        

        return main_vbox
    
    notebook = gtk.Notebook()
    notebook.show()
    dialog.vbox.add(notebook)

    notebook.append_page(general_preferences(), gobject.new(
        gtk.Label, label=_("General"), visible=True))
    notebook.append_page(events_preferences(), gobject.new(
        gtk.Label, label=_("Notifications"), visible=True))


    def dialog_response(dialog, response):
        if response == gtk.RESPONSE_CLOSE:
            dialog.destroy()
        elif response == RESPONSE_TEST:
            osd = bonobo.get_object("OAFIID:GNOME_OSD", "IDL:Bonobo/Application:1.0")
            osd.ref() # AppClient steals one reference
            osd = bonobo.AppClient(osd)
            osd.msg_send("show",
                         [_("This is a %s %s test sent from the preferences dialog")
                          % (gnome_osd_conf.PACKAGE, gnome_osd_conf.VERSION)])
        elif response == RESPONSE_ABOUT:
            about = gobject.new(gtk.AboutDialog, translator_credits=_("translator-credits"),
                                authors=["Gustavo J. A. M. Carneiro"],
                                version=gnome_osd_conf.VERSION, name="GNOME OSD",
                                license=(
"""GNOME OSD 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; either version 2 of the License, or (at your option) any later version.

GNOME OSD 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.

You should have received a copy of the GNU General Public License along with GNOME OSD; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA"""),
                                wrap_license=True,
                                comments=_("An OSD (On Screen Display) message notification system for GNOME.")
                                )
            about.set_transient_for(dialog)
            about.show()

    dialog.connect("response", dialog_response)
    dialog.connect("destroy", lambda *unused_args: gtk.main_quit())

    if HAVE_DBUS:
        ## just in case, activate the event bridge now...
        dbus.SessionBus().start_service_by_name("pt.inescporto.telecom.GnomeOSD.EventBridge")

    dialog.show()
    gtk.main()

if __name__ == '__main__':
    main()
