#!/usr/bin/env python
# Copyright 2005,2006 Michael Rice
# errr@errr-online.com
# vim: noexpandtab:ts=4:sts=4

""" fluxStyle

fluxStyle is a graphical style-manager for the fluxbox
window manager. Orignal version written by Michael Rice.
Many special thanks to Zan a.k.a. Lauri Peltonen for GUI 
Improvements & Bug Stomping. 

Released under GPL v2.

TODO 
- somehow support older styles and not put folders in the list 
  like folders that dont have anything to do with a style.
- fix any bugs that may still be there and unseen..
- add tray icon support (this is started will be done soon)
- convert install script to python. This will allow checking for
  libs so it doesnt have to be done in the main app.
  
"""
import sys
import os
from fluxstyle import findStyles,parseConfig
from os.path import isfile,expanduser,isdir
try:
    import gtk

except:
    #gtk is missing but tkinter is part of standard 
    #python modules so give an error using it about what 
    #the user is missing.
	try:
	    from Tkinter import *
		# set up the window itself
		top = Tk()
		message = Frame(top)
		message.master.title("fluxStlye Error")
		message.pack()
		error = """You do not have pyGTK installed\n
	    please vist http://pygtk.org/ and install\nat least 2.4,
		and for best results get 2.6 or newer."""
			# add the widgets
	    lMessage = Label(message, text = error)
	    lMessage.pack()
	    qButton = Button(message, text = "OK", command = message.quit)
	    qButton.pack()
	    # set the loop running
	    top.mainloop()
	    raise SystemExit
	#no tk for this message so just exit with a message
	except:
	    print "You are missing gtk bindings for python"
		raise SystemExit

from fluxstyle import errorMessage
try:
    import gtk.glade

except:
    #we have gtk so give a gui message as to why this app will not work.
    #maybe we need to offer to open the browser to
    #http://ftp.gnome.org/pub/GNOME/sources/libglade/2.0/ 
    ver = sys.version[:5]
    message = "You need to install libglade2 http://ftp.gnome.org/pub/GNOME/sources"
	message += "/libglade/2.0/ or set your PYTHONPATH correctly. try: export "
	message += "PYTHONPATH=/usr/local/lib/python%s/site-packages/ or export " %(ver)
	message += "PYTHONPATH=/usr/lib/python%s/site-packages/" % (ver)
    errorMessage.infoMessage(message)
    raise SystemExit

if gtk.pygtk_version < (2,3,90):
    #we do have gtk so lets tell them via gui that they need to update pygtk
    #maybe we should add a 'would you like to open a browser to pygtk.org ??
    message = "PyGtk 2.3.90 or later required for this program it is reccomended "
	message += "that you get pygtk 2.6 or newer for best results."
    errorMessage.infoMessage(message)
    raise SystemExit

GLADEFILE="/usr/share/fluxstyle/glade/main.glade"
N_IMAGE="/usr/share/fluxstyle/images/none.jpg"

#GLADEFILE="./images/main.glade"
class StyleChange:
    """Class wrapper for changing styles in fluxbox"""
    location = ""
    def main(self):
        gtk.main()
    
    def __init__(self):
        """The main fluxStyle window will show"""
        global location
        windowname = "window1"
        self.wTree = gtk.glade.XML (GLADEFILE,windowname)
        self.treeview1 = self.wTree.get_widget("treeview1")
        self.view_menu = self.wTree.get_widget("view1_menu")
        self.__fill_view_menu__(self.view_menu)
        
        handler = {"on_apply_style_clicked":self.__apply_style_clicked__,
                   "on_quit_clicked":(gtk.main_quit),
                   "on_add_style_clicked":self.__add_style_clicked__,
                   "on_remove_style_clicked":self.__remove_style_clicked__,
                   "on_quit1_activate":(gtk.main_quit),
                   "on_about1_activate":self.__about1_activate__,
                   "on_window1_destroy":(gtk.main_quit),
                   "on_default1_activate":self.__fill_combolist__}
        
        self.wTree.signal_autoconnect (handler)

        #Preparing the treeview here
        self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
        self.treeview1.set_model(self.liststore)

        renderer = gtk.CellRendererText()
        imagerenderer = gtk.CellRendererPixbuf()
        imagerenderer.set_property('ypad', 10)
        imagerenderer.set_property('xpad', 5)
        column1 = gtk.TreeViewColumn("Preview", imagerenderer, pixbuf=0)
        column1.set_resizable(True)
        column2 = gtk.TreeViewColumn("Name", renderer, text=1)
        column2.set_resizable(True)
        self.treeview1.append_column(column1)
        self.treeview1.append_column(column2)

        #Fill it (Clear + fill)
        self.__fill_combolist__(self.treeview1,loc="default")
        return
    
    # Call backs begin here 
    # fill combo list    
    def __fill_combolist__(self,widget,loc="default"):
        """Fill the combo list with styles test to see if there is a ~/.fluxbox/styles
        if there isnt then make it and move on instead of die."""
        global location
        location = expanduser(loc)
        if location == "default":
            location = expanduser("~/.fluxbox/styles")
            try:
                dir = os.listdir(location)
                dir.sort()
                self.liststore.clear()
                for styles in dir:
				    self.liststore.append((self.__get_preview__(styles), styles,))
            except(OSError):
                dir = expanduser("~/.fluxbox/styles")
                os.makedirs(dir,mode=0700)
                message = "You do not have a default style folder yet I have made it for you. "
				message += "The list will remain empty until you install a style which "
				message += "you can do by clicking the add button."
		        errorMessage.infoMessage(message)
        else:
		    try:
			    dir = os.listdir(location)
				dir.sort()
				self.liststore.clear()
				for styles in dir:
				    self.liststore.append((self.__get_preview__(styles), styles,))
			except(OSError):
			    m = "You have an invalid location in your ~/.fluxStyle.rc file. It is possible "
				m += "that you have a syntax error. Please exit fluxStlye and fix the error in "
				m += "this file and try again."
				errorMessage.infoMessage(m)
    # get the preview image for view
    def __get_preview__(self, stylename):
	    """Get the preview image from: location + /styleName/preview.jpg"""
        global location
        location = expanduser(location)
        image = gtk.Image()
        if os.path.isdir(location + "/" + stylename):
            if isfile(location+"/"+stylename+"/preview.jpg"):
                image.set_from_file(location+"/" +stylename+"/preview.jpg")
            else:
                #image.set_from_file( "/usr/share/fluxstyle-1.0/images/none.jpg")
                image.set_from_file(N_IMAGE)
        return image.get_pixbuf()
    def __fill_view_menu__(self, widget):
        v_menuNam = None
        if parseConfig.check4_config() == 2:
            message = "This looks like the first time you have started fluxStlye "
			message += "a default config has been created for you. You should edit "
			message += "this config to control the location of styles shown in the "
			message += "preview window. The config file is located in ~/.fluxStyle.rc"
            errorMessage.infoMessage(message)
        
        elif parseConfig.check4_config() == 3:
            message = "You do not have the config file \"~/.fluxStyle.rc\" and you do "
			message += "not have write access to the \"~/\" aka $HOME directory. If you "
			message += "find this is not accurate information please report a bug to errr@"
			message += "errr-online.com"
            errorMessage.infoMessage(message)
        elif parseConfig.check4_config() == True:
            ops = parseConfig.parse_file(expanduser("~/.fluxStyle.rc"))
			l = []
            if ops != False:
                count = 1
                view = self.view_menu
                for k,v in ops.iteritems():
                    if k == "STYLES_DIRS":
                        for x in v:
						    l.append(x.strip().split(','))
						for i in l:
						    if len(i) <= 1:
							    name = "_"+str(count)+" %s"%(" Extra Styles")
								menuitem = gtk.MenuItem(name + str(count))
								menuitem.connect("activate", self.__fill_combolist__,i[0])
								view.add(menuitem)
								count += 1
							else:
							    name = "_%s"%(i[0])
								menuitem = gtk.MenuItem(name)
								menuitem.connect("activate",self.__fill_combolist__,i[1])
								view.add(menuitem)
                    view.show_all()            
    # Set style 
    def __apply_style_clicked__(self,widget):
        """Used to apply new styles"""
        global location
        style = self.__get_selected_style__()
        if style:
            findStyles.set_style(style,location)

    # Add style
    def __add_style_clicked__(self,widget):
        """Install a new style, multiple styles can be installed at once."""
        
        dialog = gtk.FileChooserDialog("Choose file to install",
                                        None,gtk.FILE_CHOOSER_ACTION_OPEN,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)
        filter = gtk.FileFilter()
        filter.set_name("Fluxbox Styles")
        filter.add_mime_type("tar/gz")
        filter.add_mime_type("tar/bz2")
        filter.add_pattern("*.tar.gz")
        filter.add_pattern("*.tar.bz2")
        filter.add_pattern("*.tgz")
        dialog.add_filter(filter)
        dialog.set_select_multiple(True)

        response = dialog.run()
        if response == gtk.RESPONSE_OK:
            findStyles.install_style(dialog.get_filenames())
            self.__fill_combolist__(self)
            dialog.destroy()
        if response == gtk.RESPONSE_CANCEL:
            dialog.destroy()
    
    # remove style
    def __remove_style_clicked__(self,widget):
        """Remove selected style, currently only 1 style at a time is supported"""
        global location
        style = self.__get_selected_style__()
        if style == False:
            m = "You must select a style to remove first"
            errorMessage.infoMessage(m)            
        else:
            message = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, \
                gtk.BUTTONS_NONE, "Are you sure you want to delete %s?"%(style))
            message.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
            message.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE)
            response = message.run()
            message.hide()
            if response == gtk.RESPONSE_OK:
                if findStyles.remove_style(style,location) != False:
                    message.destroy()
                    self.__fill_combolist__(self,location)
                else:
                    say = "You do not have access to remove this style please contact "
					say += "your system admin for help removing this style."
                    message = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, \
						gtk.BUTTONS_NONE, say)
                    message.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
                    response = message.run()
                    message.hide()
                if response == gtk.RESPONSE_CLOSE:
                    message.destroy()
            if response == gtk.RESPONSE_CLOSE:
                message.destroy()
    def __get_selected_style__(self):
        """Getting the selected style"""
        selection = self.treeview1.get_selection()
        (model, iter) = selection.get_selected()
        if model and iter:
            return model.get_value(iter, 1)
        else:
            return False
    
    def __about1_activate__(self,widget):
        """Activate the help button with the about dialog, use generic if pygtk < 2.5.9"""
        if gtk.pygtk_version < (2,5,90):
            message = "fluxStyle version 1.0 Updae your pygtk version for more features. Version "
			message += "2.6.0 or newer is reccomended"
            errorMessage.infoMessage(message)
        else:
            windowname2="aboutdialog1"
            self.wTree2=gtk.glade.XML (GLADEFILE,windowname2)
if __name__ == "__main__":
    style = StyleChange()
    style.main()
