# Copyright (C) 2009-2010 Gloobus Developers
#
#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; either version 2
#of the License, or (at your option) any later version.
#
#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.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import cairo
import gtk
import os
import gobject
import pango

import common

from common import c
from common import _

# ======================= COVERGLOOBUS WINDOW WIDGET ========================= #

class GloobusWindow(gtk.Window):
    def __init__(self):
        gtk.rc_parse(common.ABS_PATH + '/gloobusgtk.rc')
        
        # initilizing propertries
        self._to_resize_id = None
        self._resize_show = False
        self._roundness = 10
        self._opacity = 0.8
        self._gap_top = self._roundness/2 + 16
        self._gap_bottom = self._roundness/2
        self._gap_right = self._roundness/2
        self._gap_left = self._roundness/2

        # initializing window
        gtk.Window.__init__(self)
        self._new_background()
        self.set_decorated(False)
        self.set_app_paintable(True)
        self.set_colormap( self.get_screen().get_rgba_colormap())
        self.set_border_width(0)
        self.set_icon_from_file(common.ICON_PATH)
        self._init_buttons()

        self.set_size_request(50, 50)

        self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
        self.connect('expose_event',       self.expose_event)
        self.connect('configure_event',    self.configure_event)
        self.connect('button_press_event', self.button_press_event)

        width, height = self.get_size()
        self.container = gtk.VBox()
        self.container.set_size_request(width-self._gap_left-self._gap_right,
            height-self._gap_top-self._gap_bottom)

        self.fixed = gtk.Fixed()
        self.fixed.put(self.btn_close,0,0)
        self.fixed.put(self.btn_resize,width,height)
        self.fixed.put(self.container,self._gap_left,self._gap_top)
        self._place_buttons()
        gtk.Window.add(self, self.fixed)

    def _new_background(self, width=None, height=None):
        if not width or not height:
            width, height = self.get_size()
        self._background_width = width
        self._background_height = height
        self._background = cairo.ImageSurface(cairo.FORMAT_ARGB32,
            self._background_width, self._background_height)
        self.draw_background(cairo.Context(self._background),
            self._background_width, self._background_height)

    def _init_buttons(self):
        self.btn_close = None
        self.btn_menu = None
        self.btn_resize = None
        self.menu = None

        close_img = gtk.Image()
        close_img.set_from_file(common.ABS_PATH + '/images/close_button.png')
        self.btn_close = gtk.EventBox()
        self.btn_close.set_visible_window(False)
        self.btn_close.add(close_img)
        self.btn_close.set_size_request(16, 16)
        self.btn_close.connect("button-press-event", lambda w,e: self.destroy())

        resize_img = gtk.Image()
        resize_img.set_from_file(common.ABS_PATH + '/images/resize_button.png')
        self.btn_resize = gtk.EventBox()
        self.btn_resize.set_visible_window(False)
        self.btn_resize.add(resize_img)
        self.btn_resize.set_size_request(16, 16)
        self.btn_resize.connect("button-press-event",
            lambda w,e: self.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST,
                e.button, int(e.x_root), int(e.y_root), e.get_time()))

    def _place_buttons(self):
        width, height = self.get_size()
        self.fixed.move(self.btn_close, width-(self._gap_left+16),
            self._gap_top-16)
        if self._resize_show:
         self.fixed.move(self.btn_resize, width-(self._gap_left+16),
            height-self._gap_bottom)

    # =============================== EVENTS ================================ #
    
    def expose_event(self, widget, event):
        cr = self.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y,
            event.area.width, event.area.height)
        cr.clip()
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)
        cr.set_source_surface(self._background)
        cr.paint()
        cr.reset_clip()
        return False

    def configure_event(self, widget, event):
        if self._background_width != event.width or self._background_height != event.height:
            self._new_background(event.width, event.height)
            self._place_buttons()
            self.container.set_size_request(event.width-self._gap_left-self._gap_right,
                event.height-self._gap_top-self._gap_bottom)
            self.queue_draw()
        return False

    def button_press_event(self,widget,event):
        if event.button == 1:
            self.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time)
        #elif event.button == 2:
            #pass
        #elif event.button == 3:
            #if self.menu:
                #self.menu.popup(None,None,None,event.button,event.get_time())
    
    def draw_background(self, cr, w, h):
        r = self._roundness
        x = 0
        y = 0
    
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.move_to    ( x+r,y )                       # Move to A
        cr.line_to    ( x+w-r,y )                        # Straight line to B
        cr.curve_to   ( x+w-r,y,x+w,y,x+w,y+r )        # Curve to C
        cr.line_to    ( x+w,y+h-r )                    # Move to D
        cr.curve_to   ( x+w,y+h-r,x+w,y+h,x+w-r,y+h )    # Curve to E
        cr.line_to    ( x+r,y+h )                      # Line to F
        cr.curve_to   ( x+r,y+h,x,y+h,x,y+h-r )       # Curve to G
        cr.line_to    ( x,y+r )                          # Line to H
        cr.curve_to   ( x,y+r,x,y,x+r,y)              # Curve to G
        cr.fill_preserve()
        
        cr.set_operator(cairo.OPERATOR_OVER)
        cr.set_source_rgba (0, 0, 0, self._opacity)
        cr.fill()

    # ============================ PUBLIC METHODS =========================== #

    def add(self, widget):
        self.container.add(widget)

    def menu_add(self, item):
        if not self.menu:
            self.menu 	= gtk.Menu()
            menu_img = gtk.Image()
            menu_img.set_from_file(common.ABS_PATH + '/images/menu_button.png')
            self.btn_menu = gtk.EventBox()
            self.btn_menu.set_visible_window(False)
            self.btn_menu.add(menu_img)
            self.btn_menu.set_size_request(16, 16)
            self.btn_menu.connect_object("event", self.btn_menu_press, self.menu)
            self.fixed.put(self.btn_menu, 4, 4)
        self.menu.append(item)
        item.show()

    def btn_menu_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.menu.popup(None,None,None,event.button,event.get_time())
            return True
        else:
            return False

    def resize_show(self, show):
        if self._resize_show != show:
            if show:
                self._gap_bottom = self._gap_bottom + 16
                width, height = self.get_size()
                if not self.btn_resize:
                    
                    self.fixed.put(self.btn_resize, width-20, height-self._gap_bottom)
                else:
                    self.btn_resize.show()
                    self.fixed.move(self.btn_resize, width-20, height-self._gap_bottom)
            else:
                self._gap_bottom = self._gap_bottom - 16
                self.btn_resize.hide()
            self._resize_show = show

    def show_all(self):
        gtk.Window.show_all(self)
        if not self._resize_show:
            self.btn_resize.hide()

    def set_size_request(self, width, height):
        gtk.Window.set_size_request(self,
            width + self._gap_left + self._gap_right,
            height + self._gap_top + self._gap_bottom)

    def resize(self, width, height):
        gtk.Window.resize(self,
            width + self._gap_left + self._gap_right,
            height + self._gap_top + self._gap_bottom)

    def smooth_resize(self, w, h):
        print 'resize', w, 'x', h
        width, height = self.get_size()
        print 'resize from', width, 'x', height
        if w > width:
            self._to_resize_way_w = 1
        else:
            self._to_resize_way_w = -1
        self._to_resize_width = self._to_resize_way_w*(w - width)
        print self._to_resize_width
        if h > height:
            self._to_resize_way_h = 1
        else:
            self._to_resize_way_h = -1
        self._to_resize_height = self._to_resize_way_h*(h - height)
        print self._to_resize_height
        self._to_resize_step_w = self._to_resize_width/10
        print self._to_resize_step_w
        self._to_resize_step_h = self._to_resize_height/10
        print self._to_resize_step_h
        if self._to_resize_id:
            gobject.source_remove(self._to_resize_id)
        self._to_resize_id = gobject.timeout_add(25, self._smooth_resize)

    def _smooth_resize(self):
        width, height = self.get_size()
        if self._to_resize_width <= self._to_resize_step_w or self._to_resize_height <= self._to_resize_step_h:
            self.resize(width + self._to_resize_way_w*self._to_resize_width,
                height + self._to_resize_way_h*self._to_resize_height)
            self._to_resize_id = None
            return False
        else:
            self.resize(width + self._to_resize_way_w*self._to_resize_step_w,
                height + self._to_resize_way_h*self._to_resize_step_h)
            self._to_resize_width = self._to_resize_width - self._to_resize_step_w
            self._to_resize_height = self._to_resize_height - self._to_resize_step_h
            return True

# ======================= COVERGLOOBUS COVER WINDOW ========================== #

class CoverWindow(GloobusWindow):
    def __init__(self, track):
        GloobusWindow.__init__(self)
        if not os.path.exists(track.cover):
            common.c.warning('ShowCover: cover file not found')
            self.destroy()
            return

        self.set_title(track.album)
        self.set_icon_from_file(common.ICON_PATH)

        self.connect('button_press_event', self.clicked)
        self.add_events	(gtk.gdk.KEY_PRESS_MASK )
        self.connect('key-press-event', self.keypressed)
        self.set_position(gtk.WIN_POS_CENTER)

        self.cover = gtk.gdk.pixbuf_new_from_file(track.cover)
        self.calc_cover_size()
        w = self.cover.get_width()
        h = self.cover.get_height()
        self.set_size_request(w,h)

        image = gtk.Image()
        image.set_from_pixbuf(self.cover)

        self.add(image)
        self.show_all()

    def calc_cover_size(self):
        width = gtk.gdk.screen_width()-110
        height = gtk.gdk.screen_height()-130

        ratio = 0
        w = self.cover.get_width()
        h = self.cover.get_height()
        if w > width:
            ratio = float(w) / float(width)
        if h > height:
            r = float(h) / float(height)
            if r > ratio:
                ratio = r
        if ratio:
            self.cover = self.cover.scale_simple(int(w/ratio), int(h/ratio), gtk.gdk.INTERP_BILINEAR)

    def clicked(self,widget,event):
        if event.button == 1:
            if event.type == gtk.gdk._2BUTTON_PRESS:
                self.destroy()

    def keypressed(self, widget, event):
        if event.keyval == gtk.keysyms.Escape:
            self.destroy()
            
# =============================== LYRIC WINDOW =============================== #

class LyricWindow(GloobusWindow):
    def __init__(self, text='CoverGloobus', url='http://gloobus.net/'):
        GloobusWindow.__init__(self)
        self.text = LyricText(text)
        self.url = url
        self.calc_sizes()

        self.scroll = gtk.ScrolledWindow()
        viewport = gtk.Viewport()
        viewport.add(self.text)
        viewport.set_border_width(0)
        viewport.set_shadow_type(gtk.SHADOW_NONE)
        self.scroll.add(viewport)
        self.scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.scroll.set_shadow_type(gtk.SHADOW_NONE)
        self.scroll.set_size_request(self.width,self.height-25)

        self.button = LyricLabel(_("Go to webpage"))
        self.web = gtk.EventBox()
        self.web.set_visible_window(False)
        self.web.add(self.button)
        self.web.connect('button-press-event', lambda w,e: os.system("gnome-open " + self.url))
        self.web.connect("enter-notify-event", lambda w,e: self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2)))
        self.web.connect("leave-notify-event", lambda w,e: self.window.set_cursor(None))

        self.create_menu()

        #self.add(self.scroll)
        #self.add(self.web)
        self.container.pack_start(self.scroll)
        self.container.pack_end(self.web, False)

        self._widget = False
        self.loader = None
        self._ontop = False
        self.connect('button_press_event', self.clicked)

    def create_menu(self):

        toclipboard = gtk.MenuItem(_("Copy to clipboard"))
        toclipboard.connect('activate', lambda w: gtk.clipboard_get().set_text(self.text.get_text()))
        self.menu_add(toclipboard)

        save = gtk.MenuItem(_("Save to file"))
        save.connect('activate', self.save_to_file)
        self.menu_add(save)

        self.menu_add(gtk.SeparatorMenuItem())
        
        ontop = gtk.CheckMenuItem(_("Always on top"))
        ontop.connect('activate', self.set_ontop)
        self.menu_add(ontop)

        self.menu_add(gtk.SeparatorMenuItem())
        
        close = gtk.MenuItem(_("Close"))
        close.connect('activate', lambda w: self.destroy())
        self.menu_add(close)
        

    def set_widget(self, widget):
        if widget != self._widget:
            self._widget = widget
            if widget:
                self.stick()
                self.set_property("skip-taskbar-hint", True)
                self.set_property("skip-pager-hint", True)
                self.set_keep_below(True)
            else:
                self.unstick()
                self.set_property("skip-taskbar-hint", False)
                self.set_property("skip-pager-hint", False)
                self.set_keep_below(False)

    def set_loader(self, loader):
        if self.loader:
            self.loader.stop()
        self.loader = loader

    def set_waiting(self, wait):
        self.set_text(wait, 'http://gloobus.net/')

    def set_text(self, text, url):
        self.text.set_text(text)
        self.calc_sizes()
        #self.scroll.set_size_request(self.width,self.height-25)
        self.url = url

    def calc_sizes(self):
        tw = self.text.w+20
        th = self.text.h+45
        sw = gtk.gdk.screen_width()-200
        sh = gtk.gdk.screen_height()-200
        if tw < sw:
            self.width = tw
        else:
            self.width = sw

        if th < sh:
            self.height = th
        else:
            self.height = sh
        
        #self.smooth_resize(self.width,self.height)
        self.resize(self.width,self.height)

    def save_to_file(self, widget):
        text = self.text.get_text()
        chooser = gtk.FileChooserDialog('CoverGloobus - Save to ...',self,
            gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
        chooser.set_icon_from_file(common.ICON_PATH)
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            filename = chooser.get_filename()
        else:
            filename = None
        chooser.destroy()
        if filename and os.path.exists(filename):
            md = gtk.Dialog('', self, gtk.DIALOG_DESTROY_WITH_PARENT, 
                (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
            label = gtk.Label(_('A file named "{0}" already exists.  Do you want to replace it?').format(os.path.basename(filename)))
            md.vbox.pack_start(label)
            label.show()
            response = md.run()
            md.destroy()
            if response == gtk.RESPONSE_CANCEL:
                filename = None
        if filename:
            f = open(filename, 'w')
            f.write(text)
            f.close()

    def clicked(self, widget, event):
        if self._widget and not self._ontop:
            self.set_keep_below(True)

    def set_ontop(self, widget):
        self._ontop = widget.get_active()
        self.set_keep_above(self._ontop)
        if not self._ontop:
            self.set_keep_below(True)

# =============================== LYRIC TEXT ================================= #

class LyricText(gtk.DrawingArea):
    def __init__(self, text):
        gtk.DrawingArea.__init__(self)
        self.connect("expose_event", self.expose)
        self.set_text(text)

    def set_text(self, text):
        self.text = text.strip().decode('utf-8')
        self.calc_size()
        self.queue_draw()

    def get_text(self):
        return self.text

    def expose(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)
        cr.set_source_rgba (0, 0, 0, 0.8)
        cr.paint()
        self.draw(cr)
        return False

    def draw(self, cr):
        #cr.select_font_face("Lucida Grande", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
        cr.select_font_face("Liberation Mono", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
        #cr.set_font_size(12)
        cr.set_font_size(14)
        x = 5
        y = 15
        for line in self.text.splitlines():
            # first some text shadow
            cr.move_to(x-1,y)
            cr.set_source_rgba(0.0, 0.0, 0.0,0.9)
            cr.show_text(line)
            # now white text
            cr.move_to(x,y)
            cr.set_source_rgb(1.0, 1.0, 1.0)
            cr.show_text(line)
            y = y + 15

    def calc_size(self):
        lines = len(self.text.splitlines())
        self.h = lines*15+12
        width = 20
        for line in self.text.splitlines():
            size = len(line)
            if size > width:
                width = size
        self.w = width*8+10
        self.set_size_request(self.w, self.h)

# ============================== LYRIC LABEL ================================= #

class LyricLabel(gtk.Label):
    def __init__(self, label):
        gtk.Label.__init__(self)
        self.modify_font(pango.FontDescription("Liberation Mono 12 bold"))
        self.set_markup('<span foreground="white">'+label+'</span>')

# ======================= COVERGLOOBUS CONFIGURATION ========================= #

class CoverGloobusConfig(gtk.Window):
    
    config_names = ['General', 'Window', 'Theme', 'Lyrics', 'MPD']
    
    def __init__(self, parent = None):
        gtk.Window.__init__(self)

        self._parent = parent

        self.config = common.config_load()
        self.themes = common.get_themes()
        self.current_theme = common.Theme(self.config.get("Theme","name"), 
            self.config.get("Theme","path"))
        c.debug('Current theme: ' + self.current_theme.path)

        self.set_title(_('CoverGloobus Configuration'))
        self.set_icon_from_file(common.ICON_PATH)
        
        #self.connect('destroy', gtk.main_quit)
        #self.connect('delete_event', gtk.main_quit)
        self.set_position(gtk.WIN_POS_CENTER)
        
        self.notebook = gtk.Notebook()
        self.notebook.set_border_width(5)
        self.notebook.set_tab_pos(gtk.POS_LEFT)

        self.container = gtk.VBox()

        self.make_pages()
        self.make_buttons()
        
        self.add(self.container)
        self.show_all()

    def make_pages(self):
        self.pages = {}
        for name in self.config_names:
            method = getattr(self, 'make_'+name)
            page = method()
            label = gtk.Label(_(name))
            valign = gtk.Alignment(0, 0, 0, 0)
            valign.add(page)
            valign.set_border_width(10)
            valign.set_size_request(400, 300)
            self.notebook.append_page(valign, label)
            self.pages[name] = page
        self.container.add(self.notebook)

    def make_buttons(self):
        save = gtk.Button(stock=gtk.STOCK_SAVE)
        save.set_size_request(100,25)
        cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
        cancel.set_size_request(100,25)
        save.connect('clicked', self.save_config)
        #cancel.connect("clicked", gtk.main_quit)
        cancel.connect("clicked", self.cancel)
        
        buttons = gtk.HBox()
        buttons.set_border_width(5)
        buttons.set_spacing(10)
        buttons.add(cancel)
        buttons.add(save)
        
        halign = gtk.Alignment(1, 0, 0, 0)
        halign.add(buttons)
        self.container.add(halign)

    def make_General(self):
        box = gtk.VBox()

        #============= SHOW STATUS ICON ================ #
        self.check_status_icon = gtk.CheckButton(label=_("Show Status Icon"), use_underline=False)
        c.debug("Show status icon:" + str(bool(self.config.get("StatusIcon","value"))))
        self.check_status_icon.set_active(self.config.getint("StatusIcon","value"))
        box.add(self.check_status_icon)

        #=============== ENABLE AMAZON ================== #
        self.check_amazon = gtk.CheckButton(label=_("Enable Amazon Covers"), use_underline=False)
        c.debug("Amazon Covers:" + str(self.config.getboolean("AmazonCovers","value")))
        self.check_amazon.set_active(self.config.getboolean("AmazonCovers","value"))
        box.add(self.check_amazon)

        #=============== ENABLE DOCKY ================== #
        self.check_docky = gtk.CheckButton(label=_("Enable Covers on Docky"), use_underline=False)
        c.debug("Docky:" + str(self.config.getboolean("Docky","value")))
        self.check_docky.set_active(self.config.getboolean("Docky","value"))
        box.add(self.check_docky)

        #=================== PLAYER ================== #
        box_player = gtk.HBox()
        label_player = gtk.Label(_("Player:"))
        label_player.set_size_request(150,30)
        self.entry_player = gtk.combo_box_new_text()
        self.entry_player.set_size_request(200,30)
        players = common.get_players()
        current = self.config.get("Player","name")
        for i in range(len(players)):
            self.entry_player.append_text(players[i])
            if players[i] == current:
                self.entry_player.set_active(i)
                c.debug("Active:" + players[i])
        box_player.add(label_player)
        box_player.add(self.entry_player)
        box.add(box_player)
        
        return box

    def make_Window(self):
        table = gtk.Table(10, 2, True)
        table.set_col_spacings(10)

        #================= X START POS ================= #
        self.entry_pos_x = gtk.Entry(5)
        self.entry_pos_x.set_text(self.config.get('StartPosition','x'))
        table.attach(gtk.Label(_("Start Position x:")), 0, 1, 0, 1)
        table.attach(self.entry_pos_x, 1, 2, 0, 1)

        #================= Y START POS ================= #
        self.entry_pos_y = gtk.Entry(5)
        self.entry_pos_y.set_text(self.config.get('StartPosition','y'))
        table.attach(gtk.Label(_("Start Position y:")), 0, 1, 1, 2)
        table.attach(self.entry_pos_y, 1, 2, 1, 2)

        #=============== ALLWAYS ON TOP ================== #
        self.check_ontop = gtk.CheckButton(label=_("Always on top"), use_underline=False)
        c.debug("On Top:" + str(self.config.getboolean("StartPosition","ontop")))
        self.check_ontop.set_active(self.config.getboolean("StartPosition","ontop"))
        table.attach(self.check_ontop, 0, 2, 2, 3)

        #============= STICK TO DESKTOP ================ #
        self.check_stick = gtk.CheckButton(label=_("Stick to Desktop"), use_underline=False)
        c.debug("Stick to desktop:" + str(self.config.getboolean("DesktopStick","value")))
        self.check_stick.set_active(self.config.getboolean("DesktopStick","value"))
        table.attach(self.check_stick, 0, 2, 3, 4)

        #============= SHOW BACKGROUND ================= #
        self.check_background = gtk.CheckButton(label=_("Show Background"), use_underline=False)
        c.debug("Show background:" + str(bool(self.config.get("Background","show"))))
        self.check_background.set_active(self.config.getint("Background","show"))
        table.attach(self.check_background, 0, 2, 4, 5)

        #============== BACKGROUND OPACITY ============== #
        label_opacity = gtk.Label(_("Background opacity:"))
        adjustment = gtk.Adjustment(self.config.getfloat("Background","opacity"), 0.1, 1, 0.1, 0.1)
        self.spin_opacity = gtk.SpinButton(adjustment, 0.1, 1)
        table.attach(label_opacity, 0, 1, 5, 6)
        table.attach(self.spin_opacity, 1, 2, 5, 6)

        return table

    def make_Theme(self):
        box = gtk.VBox()

        box_theme = gtk.HBox()
        label_theme = gtk.Label(_("Theme:"))
        label_theme.set_size_request(125,30)
        self.entry_theme = gtk.combo_box_new_text()
        self.entry_theme.set_size_request(250,30)
        for theme in self.themes:
            self.entry_theme.append_text(theme.name)
            if theme.path == self.current_theme.path:
                self.entry_theme.set_active(self.themes.index(theme))
                c.debug("Active: " + theme.name)
            
        box_theme.add(label_theme)
        box_theme.add(self.entry_theme)

        box_image = gtk.HBox()
        self.image = gtk.Image()
        self.change_theme(self)
        self.entry_theme.connect('changed',self.change_theme)
        align = gtk.Alignment(0.5, 0.5, 0, 0)
        align.set_size_request(375, 250)
        align.add(self.image)
        box_image.add(align)

        box.add(box_theme)
        box.add(box_image)
        
        return box

    def make_Lyrics(self):
        box = gtk.VBox()

        #=================== LYRICS ================== #
        box_lyrics = gtk.HBox()
        label_lyrics = gtk.Label(_("Lyric Engine:"))
        label_lyrics.set_size_request(175,30)
        label_lyrics.set_alignment(0.0, 0.5)
        self.entry_lyrics = gtk.combo_box_new_text()
        self.entry_lyrics.set_size_request(200,30)
        engines = common.get_lyric_engines()
        current = self.config.get("Lyrics","name")
        for i in range(len(engines)):
            self.entry_lyrics.append_text(engines[i])
            if engines[i] == current:
                self.entry_lyrics.set_active(i)
                c.debug("Active:" + engines[i])
        box_lyrics.add(label_lyrics)
        box_lyrics.add(self.entry_lyrics)
        box.add(box_lyrics)
        
        #=================== TABS ================== #
        box_tabs = gtk.HBox()
        label_tabs = gtk.Label(_("Tab Engine:"))
        label_tabs.set_size_request(175,30)
        label_tabs.set_alignment(0.0, 0.5)
        self.entry_tabs = gtk.combo_box_new_text()
        self.entry_tabs.set_size_request(200,30)
        engines = common.get_tab_engines()
        current = self.config.get("Tabs","name")
        for i in range(len(engines)):
            self.entry_tabs.append_text(engines[i])
            if engines[i] == current:
                self.entry_tabs.set_active(i)
                c.debug("Active:" + engines[i])
        box_tabs.add(label_tabs)
        box_tabs.add(self.entry_tabs)
        box.add(box_tabs)

        self.check_lyrics_try_all = gtk.CheckButton(label=_("Try other engines if nothing found"), use_underline=False)
        self.check_lyrics_try_all.set_active(self.config.getboolean("Lyrics","try_all"))
        box.add(self.check_lyrics_try_all)

        #=================== WINDOW TARGET ================== #
        self.lyric_window_targets = [
            ('new'     , 'New window'),
            ('separate', 'Separate windows'),
            ('shared'  , 'Same window')
        ]
        box_window = gtk.HBox()
        label_window = gtk.Label(_("Open lyrics and tabs in:"))
        label_window.set_size_request(175,30)
        label_window.set_alignment(0.0, 0.5)
        self.entry_lyric_window = gtk.combo_box_new_text()
        self.entry_lyric_window.set_size_request(200,30)
        current = self.config.get("Lyrics","window")
        i = 0
        for entry in self.lyric_window_targets:
            self.entry_lyric_window.append_text(entry[1])
            if entry[0] == current:
                self.entry_lyric_window.set_active(i)
            i = i + 1
        box_window.add(label_window)
        box_window.add(self.entry_lyric_window)
        box.add(box_window)

        self.check_lyrics_widget = gtk.CheckButton(label=_("Show lyrics windows as widget"), use_underline=False)
        self.check_lyrics_widget.set_active(self.config.getboolean("Lyrics","widget"))
        box.add(self.check_lyrics_widget)

        self.check_lyrics_refresh = gtk.CheckButton(label=_("Refresh lyrics/tabs when song changes"), use_underline=False)
        self.check_lyrics_refresh.set_active(self.config.getboolean("Lyrics","refresh"))
        box.add(self.check_lyrics_refresh)

        self.check_lyrics_cache = gtk.CheckButton(label=_("Cache lyrics/tabs"), use_underline=False)
        self.check_lyrics_cache.set_active(self.config.getboolean("Lyrics","cache"))
        box.add(self.check_lyrics_cache)
        
        return box

    def make_MPD(self):
        box = gtk.VBox()
        h = 30
        wlabel = 100
        wentry = 250

        box_host = gtk.HBox()
        label_host = gtk.Label(_("Host:"))
        label_host.set_size_request(wlabel,h)
        self.entry_mpd_host = gtk.Entry()
        self.entry_mpd_host.set_size_request(wentry,h)
        self.entry_mpd_host.set_text(self.config.get('MPD','host'))
        box_host.add(label_host)
        box_host.add(self.entry_mpd_host)

        box_port = gtk.HBox()
        label_port = gtk.Label(_("Port:"))
        label_port.set_size_request(wlabel,h)
        self.entry_mpd_port = gtk.Entry()
        self.entry_mpd_port.set_size_request(wentry,h)
        self.entry_mpd_port.set_text(self.config.get('MPD','port'))
        box_port.add(label_port)
        box_port.add(self.entry_mpd_port)

        box_pass = gtk.HBox()
        label_pass = gtk.Label(_("Password:"))
        label_pass.set_size_request(wlabel,h)
        self.entry_mpd_pass = gtk.Entry()
        self.entry_mpd_pass.set_size_request(wentry,h)
        self.entry_mpd_pass.set_text(self.config.get('MPD','password'))
        box_pass.add(label_pass)
        box_pass.add(self.entry_mpd_pass)

        box_path = gtk.HBox()
        label_path = gtk.Label(_("Library:"))
        label_path.set_size_request(wlabel,h)
        self.entry_mpd_path = gtk.Entry()
        self.entry_mpd_path.set_size_request(wentry,h)
        self.entry_mpd_path.set_text(self.config.get('MPD','path'))
        box_path.add(label_path)
        box_path.add(self.entry_mpd_path)

        box.add(box_host)
        box.add(box_port)
        box.add(box_pass)
        box.add(box_path)
        
        return box

    # ====================================================================== #
    def change_theme(self,widget):
        width = 375
        height = 250
        try:
            pic = gtk.gdk.pixbuf_new_from_file(
                self.themes[self.entry_theme.get_active()].path + 
                "/screenshot.png")
        except:
            pic = gtk.gdk.pixbuf_new_from_file(common.ABS_PATH + 
                "/themes/noscreenshot.png")

        resize = False
        ratio = 0
        w = pic.get_width()
        h = pic.get_height()
        if w > width:
            ratio = float(w) / float(width)
        if h > height:
            r = float(h) / float(height)
            if r > ratio:
                ratio = r
        if ratio:
            pic = pic.scale_simple(int(w/ratio), int(h/ratio), gtk.gdk.INTERP_BILINEAR)
        self.image.set_from_pixbuf(pic)

    def save_config(self,button):
        c.info(c.color('brown', _('Saving new configuration')))
        c.debug("x:" + self.entry_pos_x.get_text())
        c.debug("y:" + self.entry_pos_y.get_text())
        c.debug("Theme:" + self.entry_theme.get_active_text())
        c.debug("Player:" + self.entry_player.get_active_text())
        c.debug("Lyrics:" + self.entry_lyrics.get_active_text())
        c.debug("Tabs:" + self.entry_tabs.get_active_text())
        c.debug("Ontop:" + str(int(self.check_ontop.get_active())))
        c.debug("Amazon Covers:" + str(int(self.check_amazon.get_active())))
        c.debug("Docky:" + str(int(self.check_docky.get_active())))
        c.debug("Stick to desktop:" + str(int(self.check_stick.get_active())))
        c.debug("Show status icon:" + str(int(self.check_status_icon.get_active())))
        c.debug("Show background:" + str(int(self.check_background.get_active())))
        c.debug("Background opacity:" + str(self.spin_opacity.get_value()))
        
        self.config.set('StartPosition', 'x', self.entry_pos_x.get_text())
        self.config.set('StartPosition', 'y', self.entry_pos_y.get_text())
        self.config.set('StartPosition', 'ontop', str(int(self.check_ontop.get_active())))
        self.config.set('Theme', 'name', self.themes[self.entry_theme.get_active()].name)
        self.config.set('Theme', 'path', self.themes[self.entry_theme.get_active()].path)
        self.config.set('Player', 'name', self.entry_player.get_active_text())        
        self.config.set('Lyrics', 'name', self.entry_lyrics.get_active_text())
        self.config.set('Tabs', 'name', self.entry_tabs.get_active_text())
        self.config.set('AmazonCovers', 'value', str(int(self.check_amazon.get_active())))
        self.config.set('Docky', 'value', str(int(self.check_docky.get_active())))
        self.config.set('DesktopStick', 'value', str(int(self.check_stick.get_active())))
        self.config.set('StatusIcon', 'value', str(int(self.check_status_icon.get_active())))
        self.config.set('Background', 'show', str(int(self.check_background.get_active())))
        self.config.set('Background', 'opacity', str(self.spin_opacity.get_value()))
        self.config.set('MPD', 'host', self.entry_mpd_host.get_text())
        self.config.set('MPD', 'port', self.entry_mpd_port.get_text())
        self.config.set('MPD', 'password', self.entry_mpd_pass.get_text())
        self.config.set('MPD', 'path', self.entry_mpd_path.get_text())
        self.config.set('Lyrics', 'try_all', str(int(self.check_lyrics_try_all.get_active())))
        self.config.set('Lyrics', 'window', self.lyric_window_targets[self.entry_lyric_window.get_active()][0])
        self.config.set('Lyrics', 'widget', str(int(self.check_lyrics_widget.get_active())))
        self.config.set('Lyrics', 'refresh', str(int(self.check_lyrics_refresh.get_active())))
        self.config.set('Lyrics', 'cache', str(int(self.check_lyrics_cache.get_active())))

        common.config_save(self.config)
        
        #try:
            #if pid:
                #os.kill(int(pid),signal.SIGUSR1)
        #except:
            #pass
        if self._parent:
            self._parent.init()
            self.destroy()
        else:
            gtk.main_quit()

    def cancel(self, widget=None):
        if not self._parent:
            gtk.main_quit()
        else:
            self.destroy()
