#!/usr/bin/python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
# Copyright (C) 2010 Leszek Lesner leszek@zevenos.com
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, 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 warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
### END LICENSE

import sys
import os
import gtk
import xklavier

import gettext
from gettext import gettext as _
gettext.textdomain('lxkeymap')

# optional Launchpad integration
# this shouldn't crash if not found as it is simply used for bug reporting
try:
    import LaunchpadIntegration
    launchpad_available = True
except:
    launchpad_available = False

# Add project root directory (enable symlink, and trunk execution).
PROJECT_ROOT_DIRECTORY = os.path.abspath(
    os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))))

if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'lxkeymap'))
    and PROJECT_ROOT_DIRECTORY not in sys.path):
    sys.path.insert(0, PROJECT_ROOT_DIRECTORY)
    os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses

from lxkeymap import (
    AboutLxkeymapDialog, PreferencesLxkeymapDialog)
from lxkeymap.helpers import get_builder


class LxkeymapWindow(gtk.Window):
    __gtype_name__ = "LxkeymapWindow"

    # To construct a new instance of this method, the following notable
    # methods are called in this order:
    # __new__(cls)
    # __init__(self)
    # finish_initializing(self, builder)
    # __init__(self)
    #
    # For this reason, it's recommended you leave __init__ empty and put
    # your inialization code in finish_intializing

    def __new__(cls):
        """Special static method that's automatically called by Python when
        constructing a new instance of this class.

        Returns a fully instantiated LxkeymapWindow object.
        """
        builder = get_builder('LxkeymapWindow')
        new_object = builder.get_object("lxkeymap_window")
        new_object.finish_initializing(builder)
        return new_object


    def finish_initializing(self, builder):
        """Called while initializing this instance in __new__

        finish_initalizing should be called after parsing the UI definition
        and creating a LxkeymapWindow object with it in order to finish
        initializing the start of the new LxkeymapWindow instance.

        Put your initilization code in here and leave __init__ undefined.
        """
        # Get a reference to the builder and set up the signals.
        self.builder = builder
        self.builder.connect_signals(self)

        global launchpad_available
        if launchpad_available:
            # see https://wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding for more information
            # about LaunchpadIntegration
            helpmenu = self.builder.get_object('helpMenu')
            if helpmenu:
                LaunchpadIntegration.set_sourcepackagename('lxkeymap')
                LaunchpadIntegration.add_items(helpmenu, 0, False, True)
            else:
                launchpad_available = False

        # Uncomment the following code to read in preferences at start up.
        #dlg = PreferencesLxkeymapDialog.PreferencesLxkeymapDialog()
        #self.preferences = dlg.get_preferences()

        self.nodeadkey = builder.get_object("nodeadkeys")

        #List of nodeadkeys variants
        # TODO find a property in each variant ?
        self.nodeadkeys_list = ("nodeadkeys", "oss_nodeadkeys", "latin9_nodeadkeys")

        #Get current layout
        server.get_from_server(engine)
        	
        engine.start_listen(xklavier.XKLL_TRACK_KEYBOARD_STATE)
        state = engine.get_current_state()
        active_group = state['group']

        self.layout_current = server.get_layouts()[active_group]
        try:
            self.variant_current = server.get_variants()[active_group]
        except IndexError:
            self.variant_current = ""
            

        engine.stop_listen(xklavier.XKLL_TRACK_KEYBOARD_STATE)

        # Saved the current layout for restore
        self.layout_saved = self.layout_current
        self.variant_saved = self.variant_current

        self.treestore_layout = gtk.TreeStore(str, str)

        self.country_list = []
        configreg.foreach_country(self.construct_country)

        self.country_list.sort()

        for item in self.country_list:
            self.treestore_layout.append(None, [item[0], item[1]])

        self.treeview_layout = gtk.TreeView(self.treestore_layout)
        self.tvcolumn_layout = gtk.TreeViewColumn('keymap')
        self.treeview_layout.set_headers_visible(False)
        self.treeview_layout.append_column(self.tvcolumn_layout)

        self.cell = gtk.CellRendererText()
        self.tvcolumn_layout.pack_start(self.cell, True)
        self.tvcolumn_layout.add_attribute(self.cell, "text", 0)

        self.treeview_layout.set_search_column(0)

        # Focus to saved layout
        self.model_layout = self.treeview_layout.get_model()
        self.selection_layout = self.treeview_layout.get_selection()
        self.model_layout.foreach(self.return_path, None)
        self.selection_layout.select_path(self.default_path)
        self.treeview_layout.scroll_to_cell(self.default_path, None, False, 0.0, 0.0)

        self.treeview_layout.connect("realize", self.on_country_click)
        self.treeview_layout.connect("cursor-changed", self.on_country_click)

        self.scrolledwindow_layout = builder.get_object("scrolledwindow_layout")

        self.scrolledwindow_layout.add(self.treeview_layout)
        self.treeview_layout.show()

        self.treestore_variant = gtk.TreeStore(str, str)
        self.treeview_variant = gtk.TreeView(self.treestore_variant)
        self.tvcolumn_variant = gtk.TreeViewColumn('variant')
        self.treeview_variant.set_headers_visible(False)
        self.treeview_variant.append_column(self.tvcolumn_variant)
        self.cell_variant = gtk.CellRendererText()
        self.tvcolumn_variant.pack_start(self.cell_variant, True)
        self.tvcolumn_variant.add_attribute(self.cell_variant, "text", 0)

        self.scrolledwindow_variant = builder.get_object("scrolledwindow_variant")

        self.treeview_variant.connect("cursor-changed", self.on_variant_click)

        self.scrolledwindow_variant.add(self.treeview_variant)
        self.treeview_variant.show()

        self.button_apply = builder.get_object("button_apply")
        self.button_apply.connect("clicked", self.on_click_apply)

        self.button_restore = builder.get_object("button_restore")
        self.button_restore.connect("clicked", self.on_click_restore)

        self.status = builder.get_object("statuslbl")
        if not len(self.variant_current) == 0:
            self.status.set_text(_("Current Keymap: %s(%s)") % (self.layout_current, self.variant_current))
        else:
            self.status.set_text(_("Current Keymap: %s") % (self.layout_current))

    def construct_country(self, c_reg, item):
        self.country_list.append((item.get_description(), item.get_name()))

    def return_path (self, model, path, iter, data):
        if model.get_value(iter, 1).lower() == self.layout_saved:
            self.default_path = path

    def generate_variant_list(self):
        self.treeview_variant.hide()
        self.treestore_variant.clear()
        configreg.foreach_country(self.return_layout)
        self.treeview_variant.show()


    def on_country_click(self, data=None):
        model = self.treeview_layout.get_model()
        selection = self.treeview_layout.get_selection()
        (model, iter) = selection.get_selected()

        self.country_selected = model.get_value(iter, 1)
        self.layout_current = model.get_value(iter, 1).lower()
        self.generate_variant_list()


    def return_layout(self, c_reg, item):
        if item.get_name() == self.country_selected:
            c_reg.foreach_country_variant(item.get_name(), self.print_variant)


    def print_variant(self, c_reg, item, subitem):
        if subitem:
            #print ('\t\t %s (%s)' % (subitem.get_description(), subitem.get_name()))
            if self.nodeadkey.get_active() and subitem.get_name() in self.nodeadkeys_list:
                pass
            else:
                self.treestore_variant.append(None, [subitem.get_description(), subitem.get_name()])
        else:
            #print ('\t\t %s (%s)' % (item.get_description(), item.get_name()))
            self.treestore_variant.append(None, [item.get_description(), ""])

    def on_variant_click(self, data=None):
        model = self.treeview_variant.get_model()
        selection = self.treeview_variant.get_selection()
        (model, iter) = selection.get_selected()
        self.variant_current =  model.get_value(iter, 1)

    def save_configuration(self):
        server.set_layouts([self.layout_current])
        server.set_variants([self.variant_current])
        server.activate(engine)
        self.status_update()

    def on_click_apply(self, data=None):
        self.save_configuration()

    def on_click_restore(self, data=None):
        self.layout_current = self.layout_saved
        self.variant_current = self.variant_saved
        self.save_configuration()

    def status_update(self):
        """Update the Statusbar"""
        if not len(self.variant_current) == 0:
            self.status.set_text(_("Current Keymap: %s(%s)") % (self.layout_current, self.variant_current))
        else:
            self.status.set_text(_("Current Keymap: %s") % (self.layout_current))

    def about(self, widget, data=None):
        """Display the about box for lxkeymap."""
        about = AboutLxkeymapDialog.AboutLxkeymapDialog()
        response = about.run()
        about.destroy()

    def preferences(self, widget, data=None):
        """Display the preferences window for lxkeymap."""
        prefs = PreferencesLxkeymapDialog.PreferencesLxkeymapDialog()
        response = prefs.run()
        if response == gtk.RESPONSE_OK:
            # Make any updates based on changed preferences here.
            pass
        prefs.destroy()

    def on_nodeadkeys_toggled(self,widget):
        self.generate_variant_list()

    def on_entry1_activate(self,widget):
        #TODO: if entry == type in here to test delete text. Maybe labelledentry would do better here instead of this.
        if entry1.get_text() == _("Type here to test your keyboard"):
            entry1.set_text("")

    def on_showall_activate(self,widget):
        os.popen("xdg-open /usr/share/X11/xkb/rules/xorg.lst")

    def on_preferences_activate(self,widget):
        prefs = PreferencesLxkeymapDialog.PreferencesLxkeymapDialog()
        response = prefs.run()
        if response == gtk.RESPONSE_OK:
            # Make any updates based on changed preferences here.
            pass
        prefs.destroy()
        self.status_update()

    def quit(self, widget, data=None):
        """Signal handler for closing the LxkeymapWindow."""
        #TODO Make warning if current layout / variant is different than selected.
        self.destroy()

    def on_destroy(self, widget, data=None):
        """Called when the LxkeymapWindow is closed."""
        # Clean up code for saving application state should be added here.
        gtk.main_quit()

if __name__ == "__main__":
    # Support for command line options.
    import logging
    import optparse
    parser = optparse.OptionParser(version="%prog %ver")
    parser.add_option(
        "-v", "--verbose", action="store_true", dest="verbose",
        help=_("Show debug messages"))
    (options, args) = parser.parse_args()

    # Set the logging level to show debug messages.
    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)
        logging.debug('logging enabled')

    #Init xklavier
    display = gtk.gdk.display_get_default()
    engine = xklavier.Engine(display)
    configreg = xklavier.ConfigRegistry(engine)

    configreg.load(False)

    server = xklavier.ConfigRec()
	
    server.get_from_server(engine)

    # Run the application.
    window = LxkeymapWindow()
    window.show()
    gtk.main()
