#!/usr/bin/env python
# Gui for nautilus actions extension


import sys
import os.path
import pwd
import popen2
import string
import commands
import shelve
import glob
import libxml2
import types
import shutil

# Set i18n support :
APP="nautilus-actions"
DIR="/usr/share/locale"
import locale
import gettext

try:
	import pygtk
	#tell pyGTK, if possible, that we want GTKv2
	pygtk.require("2.0")
except:
	#Some distributions come with GTK2, but not pyGTK
	pass
try:
	import gtk
	import gtk.glade
	import pango
	import gobject
except:
	print "You need to install pyGTK or GTKv2 and pyGtkSourceView",
	print "or set your PYTHONPATH correctly."
	print "try: export PYTHONPATH=",
	print "/usr/local/lib/python2.2/site-packages/"
	sys.exit(1)
#now we have both gtk and gtk.glade imported
#Also, we know we are running GTK v2

class Config:
	def __init__ (self, name="", filename=""):
		self.name = name
		self.filename = filename
		self.command = {}
		self.command["path"] = ""
		self.command["parameters"] = ""
		self.menu_item = {}
		self.menu_item["label"] = ""
		self.menu_item["tooltip"] = ""
		self.test = {}
		self.test["basename"] = []
		self.test["isfile"] = True
		self.test["isdir"] = False
		self.test["accept_multiple_file"] = False
		self.test["schemes"] = []
		self.tobedeleted = False
		self.readonly = False
		self.overwritten = False
		self.ow_filename = ""
		self.ow_command = {}
		self.ow_command["path"] = ""
		self.ow_command["parameters"] = ""
		self.ow_menu_item = {}
		self.ow_menu_item["label"] = ""
		self.ow_menu_item["tooltip"] = ""
		self.ow_test = {}
		self.ow_test["basename"] = []
		self.ow_test["isfile"] = True
		self.ow_test["isdir"] = False
		self.ow_test["accept_multiple_file"] = False
		self.ow_test["schemes"] = []
		self.ow_tobedeleted = False
		self.ow_readonly = False


	def mark_as_deleted (self):
		if self.overwritten:
			self.restore_overwritten_config ()
		else:
			self.tobedeleted = True

	def is_deleted (self):
		return self.tobedeleted

	def is_overwritten (self):
		return self.overwritten

	def overwrite_config (self, new_config=None):
		if not self.overwritten:
		#
			self.overwritten = True
			
			# Save overwritten config
			self.ow_filename = self.filename
			self.ow_command = self.command
			self.ow_menu_item = self.menu_item
			self.ow_test = self.test
			self.ow_tobedeleted = self.tobedeleted
			self.ow_readonly = self.readonly

			if new_config == None:
				# reset new one
				self.filename = ""
				del (self.command)
				self.command = {}
				self.command["path"] = ""
				self.command["parameters"] = ""
				del (self.menu_item)
				self.menu_item = {}
				self.menu_item["label"] = ""
				self.menu_item["tooltip"] = ""
				del (self.test)
				self.test = {}
				self.test["basename"] = []
				self.test["isfile"] = True
				self.test["isdir"] = False
				self.test["accept_multiple_file"] = False
				self.test["schemes"] = []
				self.tobedeleted = False
				self.readonly = False
			else:
				del (self.command)
				del (self.menu_item)
				del (self.test)
				self.filename = new_config.filename
				self.command = new_config.command
				self.menu_item = new_config.menu_item
				self.test = new_config.test
				self.tobedeleted = new_config.tobedeleted
				self.readonly = new_config.readonly
		#

	def restore_overwritten_config (self):
		if self.overwritten:
			self.overwritten = False
			
			# Restore overwritten config
			self.filename = self.ow_filename
			self.command = self.ow_command
			self.menu_item = self.ow_menu_item
			self.test = self.ow_test
			self.tobedeleted = self.ow_tobedeleted
			self.readonly = self.ow_readonly

			# Delete overwritten config
			del (self.ow_command)
			del (self.ow_menu_item)
			del (self.ow_test)
		
	def is_readonly (self):
		return self.readonly

	def set_readonly (self, is_readonly):
		self.readonly = bool

	def Bool2Str (self, bool):
		if bool:
			return "TRUE"
		else:
			return "FALSE"
	
	def set_name (self, name):
		self.name = name
	
	def set_filename (self, filename):
		self.filename = filename

	def set_command_path (self, path):
		self.command["path"] = path

	def set_command_parameters (self, parameters):
		self.command["parameters"] = parameters

	def set_menu_item_label (self, label):
		self.menu_item["label"] = label

	def set_menu_item_tooltip (self, tooltip):
		self.menu_item["tooltip"] = tooltip

	def set_test_basename (self, basenames):
		self.test["basename"] =  basenames

	def set_test_basename_str (self, basenames_str):
		del (self.test["basename"])
		self.test["basename"] = []
		basename_list = string.split (basenames_str, ";")
		for basename in basename_list:
			basename = string.strip (basename)
			if len (basename) != 0:
				self.test["basename"].append (basename)

	def append_test_basename (self, basename):
		if not basename in self.test["basename"]:
			self.test["basename"].append (basename)

	def set_test_isfile (self, isfile):
		self.test["isfile"] = isfile

	def set_test_isdir (self, isdir):
		self.test["isdir"] = isdir

	def set_test_accept_multiple_file (self, accept_multiple_file):
		self.test["accept_multiple_file"] = accept_multiple_file

	def set_test_schemes (self, schemes):
		self.test["schemes"] = schemes

	def append_test_schemes (self, scheme):
		if not scheme in self.test["schemes"]:
			self.test["schemes"].append (scheme)

	def remove_test_schemes (self, scheme):
		if scheme in self.test["schemes"]:
			del self.test["schemes"][self.test["schemes"].index (scheme)]

	def get_command_path (self):
		return self.command["path"]

	def get_command_parameters (self):
		return self.command["parameters"]

	def get_menu_item_label (self):
		return self.menu_item["label"]

	def get_menu_item_tooltip (self):
		return self.menu_item["tooltip"]

	def get_test_basename_str (self):
		return string.join (self.test["basename"], " ; ")

	def get_test_basename (self):
		return self.test["basename"]

	def get_test_isfile (self, str=False):
		if str:
			return self.Bool2Str (self.test["isfile"])
		else:
			return self.test["isfile"]

	def get_test_isdir (self, str=False):
		if str:
			return self.Bool2Str (self.test["isdir"])
		else:
			return self.test["isdir"]

	def get_test_accept_multiple_file (self, str=False):
		if str:
			return self.Bool2Str (self.test["accept_multiple_file"])
		else:
			return self.test["accept_multiple_file"]

	def get_test_schemes (self):
		return self.test["schemes"]

	def get_name (self):
		return self.name
	
	def get_filename (self):
		return self.filename

class ConfigParser:
	def __init__ (self):
		self.lang = os.environ["LANG"][:2]
		self.uid = os.getuid ()
		self.home_dir = pwd.getpwuid (self.uid)[5]
		if self.uid == 0:
			self.config_dir = ["/usr/share/nautilus-actions"]
		else:
			current_config_dir = self.home_dir + "/.config/nautilus-actions"
			old_configdir_list = [ self.home_dir + "/.nautilus-actions", self.home_dir + "/.config/.nautilus-actions" ]
			
			if not os.path.exists (current_config_dir):
				os.makedirs (current_config_dir)
				
			for old_configdir in old_configdir_list:
				if os.path.isdir (old_configdir) and old_configdir != current_config_dir:
				#
					for file in glob.glob (old_configdir + "/*.xml"):
						shutil.copy (file, current_config_dir)
						os.remove (file)
					os.rmdir (old_configdir)
				#

			self.config_dir = ["/usr/share/nautilus-actions", current_config_dir]
				

class ConfigReader (ConfigParser):
	def __init__ (self):
		ConfigParser.__init__ (self)
		self.LoadConfigFiles ()

	def LoadConfigFiles (self):
		self.config_list = {}
		for dir in self.config_dir:
			for name in glob.glob (dir + "/*.xml"):
				self.ParseFile (name)

	def isElementOk (self, node, name):
		retv = False
		if not node is None:
			if node.type == "element" and node.name == name:
				retv = True
		return retv

	def getConfigList (self):
		return self.config_list

	def ParseFile (self, filename):
		if os.path.isfile (filename):
		#
			doc = libxml2.parseFile(filename)
			if doc.name == filename:
			#
				root = doc.children
				if self.isElementOk (root, "nautilus-actions-config"):
				#
					version = root.prop ("version")
					node = root.children
					while node != None:
					#
						if self.isElementOk (node, "action"):
						#
							new_config = Config (node.prop ("name"), filename)
							node2 = node.children
							while node2 != None:
							#
								if self.isElementOk (node2, "test"):
								#
									node3 = node2.children
									while node3 != None:
									#
										if self.isElementOk (node3, "basename"):
										#
											basename_list = []
											if version == "0.1":
											#
												basename_list.append (node3.getContent ())
											#
											else:
											#
												node4 = node3.children
												while node4 != None:
												#
													if self.isElementOk (node4, "match"):
													#
														basename_list.append (node4.getContent ())
													#
													node4 = node4.next
												#
											#
											new_config.set_test_basename (basename_list)
													
										#
										elif self.isElementOk (node3, "isfile"):
										#
											new_config.set_test_isfile (False)
											if string.lower (node3.getContent ()) == "true":
												new_config.set_test_isfile (True)
										#
										elif self.isElementOk (node3, "isdir"):
										#
											new_config.set_test_isdir (False)
											if string.lower (node3.getContent ()) == "true":
												new_config.set_test_isdir (True)
										#
										elif self.isElementOk (node3, "accept-multiple-files"):
										#
											new_config.set_test_accept_multiple_file (False)
											if string.lower (node3.getContent ()) == "true":
												new_config.set_test_accept_multiple_file (True)
										#
										elif self.isElementOk (node3, "scheme"):
										#
											node4 = node3.children
											scheme_list = []
											while node4 != None:
											#
												if self.isElementOk (node4, "type"):
												#
													scheme_list.append (string.lower (node4.getContent ()))
												#
												node4 = node4.next
											#
											new_config.set_test_schemes (scheme_list)
										#
										node3 = node3.next
									#
								#	
								elif self.isElementOk (node2, "command"):
								#
									node3 = node2.children
									while node3 != None:
									#
										if self.isElementOk (node3, "path"):
										#
											new_config.set_command_path (node3.getContent ())
										#
										elif self.isElementOk (node3, "parameters"):
										#
											new_config.set_command_parameters (node3.getContent ())
										#
										node3 = node3.next
									#
								#
								elif self.isElementOk (node2, "menu-item"):
								#
									node3 = node2.children
									while node3 != None:
									#
										if self.isElementOk (node3, "label"):
										#
											lang = node3.prop ("lang")
											if lang == self.lang or (lang == None and new_config.get_menu_item_label () == ""):
												new_config.set_menu_item_label (node3.getContent ())
										#
										elif self.isElementOk (node3, "tooltip"):
										#
											lang = node3.prop ("lang")
											if lang == self.lang or (lang == None and new_config.get_menu_item_tooltip () == ""):
												new_config.set_menu_item_tooltip (node3.getContent ())
										#
										node3 = node3.next
									#
								#
								node2 = node2.next
							#
							if filename[0:len (self.home_dir)] != self.home_dir and self.uid != 0:
								new_config.set_readonly (True)
							if not self.config_list.has_key (string.lower (new_config.get_name ())):
								self.config_list[string.lower (new_config.get_name ())] = new_config
							else:
								self.config_list[string.lower (new_config.get_name ())].overwrite_config (new_config)
						#
						node = node.next
					#
				#
			doc.freeDoc()
		#

class ConfigWriter (ConfigParser):
	def __init__ (self):
		ConfigParser.__init__ (self)
		self.config_list = {}

	def setConfigList (self, config_list):
		self.config_list = config_list

	def SortConfigByFilename (self):
		file_dict = {}
		for config_name in self.config_list.keys ():
		#
			filename = self.config_list[config_name].get_filename ()
			if len (filename) == 0:
			#
				filename = "new"
			#
			if file_dict.has_key (filename):
			#
				file_dict[filename].append (self.config_list[config_name])
			#
			else:
			#
				file_dict[filename] = [ self.config_list[config_name] ]
			#
		#
		return file_dict

	def WriteConfig2XmlFile (self, filename, config_list):
			delete_file = True
			for config in config_list:
			#
				# if one is not deleted, delete_file will be set to false forever
				delete_file = delete_file and config.is_deleted ()
			#
			if (not delete_file):
			#
				count = 0;
				doc = libxml2.newDoc ("1.0")
				main_node = libxml2.newNode ("nautilus-actions-config")
				main_node.setProp ("version", "0.2")
				doc.setRootElement (main_node)
				for config in config_list:
				#
					if not config.is_deleted () and not config.is_readonly (): # Skip deleted and readonly config
					#
						count += 1;
						node_action = main_node.newChild (None, "action", None)
						node_action.setProp ("name", config.get_name ())
						
						node_test = node_action.newChild (None, "test", None)
						node_basename = node_test.newChild (None, "basename", None)
						for basename in config.get_test_basename ():
						#
							node_basename.newChild (None, "match", basename)
						#
						node_test.newChild (None, "isfile", config.get_test_isfile (True))
						node_test.newChild (None, "isdir", config.get_test_isdir (True))
						node_test.newChild (None, "accept-multiple-files", config.get_test_accept_multiple_file (True))
						node_scheme = node_test.newChild (None, "scheme", None)
						for scheme in config.get_test_schemes ():
						#
							node_scheme.newChild (None, "type", scheme)
						#
						
						node_command = node_action.newChild (None, "command", None)
						node_command.newChild (None, "path", config.get_command_path ())
						node_command.newChild (None, "parameters", config.get_command_parameters ())
						
						node_menu_item = node_action.newChild (None, "menu-item", None)
						node_menu_item.newChild (None, "label", config.get_menu_item_label ())
						node_menu_item.newChild (None, "tooltip", config.get_menu_item_tooltip ())
					#
				#
				if count > 0: # if not all readonly or deleted
					doc.saveFile (filename)
				doc.freeDoc ()
			#
			else: # delete old file
			#
				if os.path.isfile (filename):
					os.remove (filename)
			#

	def SaveConfigFiles (self):
		file_dict = self.SortConfigByFilename ()
		for filename in file_dict.keys ():
		#
			if filename != "new":
			#
				self.WriteConfig2XmlFile (filename, file_dict[filename])
			#
			else:
			#
				for config in file_dict[filename]:
				#
					self.WriteConfig2XmlFile (self.config_dir[0] + "/config_" + config.get_name () + ".xml", [ config ])
				#
			#
		#


class NACTGui (gtk.glade.XML):
	def __init__ (self, windowname):
		gladefile = "/usr/share/nautilus-actions/nact/nautilus-actions-config.glade"
		gtk.glade.XML.__init__ (self, gladefile, windowname, gettext.textdomain(APP))
		self.widget = self.get_widget (windowname)
	
	def Show (self):
		self.widget.show ()

	def ActionDialogCloseHandler (self, widget, event):
		self.widget.hide ()
		return True

	def ActionCloseHandler (self, widget):
		self.widget.hide ()


class NACTAboutDialog (NACTGui):
	def __init__ (self):
		NACTGui.__init__ (self, "AboutDialog")

		dic = { "ActionDialogClose" : self.ActionDialogCloseHandler, 
				}

		self.signal_autoconnect (dic)
		self.widget.set_version ("0.7")


class NACTLegendDialog (NACTGui):
	def __init__ (self):
		NACTGui.__init__ (self, "DialogLegend")

		dic = { "ActionDialogClose" : self.ActionDialogCloseHandler, 
				  "ActionClose" : self.ActionCloseHandler
				}

		self.signal_autoconnect (dic)


class NACTFileChooserDialog (NACTGui):
	def __init__ (self, entry_path):
		NACTGui.__init__ (self, "FileChooserDialogPath")

		dic = { "ActionFileDialogClose" : self.ActionDialogCloseHandler, 
				  "ActionFileDialogCancel" : self.ActionCloseHandler,
				  "ActionFileChoose" : self.ActionFileChooseHandler
				}

		self.signal_autoconnect (dic)
		self.entry_path = entry_path

	def SetCurrentFile (self, filename):
		self.widget.set_filename (filename)

	def GetCurrentFile (self):
		return self.widget.get_filename ()

	def ActionFileChooseHandler (self, widget):
		self.widget.hide ()
		self.entry_path.set_text (self.GetCurrentFile ())

class NACTConfirmSaveDialog (NACTGui):
	def __init__ (self, save_handler):
		NACTGui.__init__ (self, "DialogConfirmSave")

		dic = { "ActionConfirmDialogCancel" : self.ActionCloseHandler,
				  "ActionConfirmDialogClose" : self.ActionDialogCloseHandler,
				  "ActionConfirmDialogSave" : self.ActionConfirmDialogSaveHandler,
				  "ActionConfirmDialogNoSave": self.ActionConfirmDialogNoSaveHandler
				}

		self.signal_autoconnect (dic)
		self.save_handler = save_handler

	def ActionConfirmDialogSaveHandler (self, widget):
		self.widget.hide ()
		self.save_handler (widget)
		gtk.main_quit ()
	
	def ActionConfirmDialogNoSaveHandler (self, widget):
		self.widget.hide ()
		gtk.main_quit ()

class NACTMainWindow (NACTGui):
	def __init__ (self):
		NACTGui.__init__ (self, "WindowMain")

		self.scheme_list = [["file" , N_("Local files")], 
								  ["sftp" , N_("SSH files")], 
								  ["smb" , N_("Windows files")], 
								  ["ftp" , N_("FTP files")], 
								  ["dav" , N_("Webdav files")] ]
		self.new_config_name = _("New Config")

		
		dic = { "ActionAppQuit" : self.ActionAppQuitHandler, 
				"ActionQuit" : self.ActionQuitHandler,
				"ActionNewConfig" : self.ActionNewConfigHandler,
				"ActionDeleteConfig" : self.ActionDeleteConfigHandler,
				"ActionConfigSelect" : self.ActionConfigSelectHandler,
				"ActionShowLegend" : self.ActionShowLegendHandler,
				"ActionShowROConfig" : self.ActionShowROConfigHandler,
				"ActionBrowse" : self.ActionBrowseHandler,
				"ActionLabelChange" : self.ActionLabelChangeHandler,
				"ActionTooltipChange" : self.ActionTooltipChangeHandler,
				"ActionPathChange" : self.ActionPathChangeHandler,
				"ActionParametersChange" : self.ActionParametersChangeHandler,
				"ActionBasenameChange" : self.ActionBasenameChangeHandler,
				"ActionFileSelect" : self.ActionSelectionTypeSelectHandler,
				"ActionDirSelect" : self.ActionSelectionTypeSelectHandler,
				"ActionBothSelect" : self.ActionSelectionTypeSelectHandler,
				"ActionMultipleToggle" : self.ActionMultipleToggleHandler,
				"ActionReload" : self.ActionReloadHandler,
				"ActionSave" : self.ActionSaveHandler,
				"ActionAbout" : self.ActionAboutHandler,
				}

		self.signal_autoconnect (dic)
		self.AlignLabels ()
		self.show_systemwide = True
		self.config_reader = ConfigReader ()
		self.config_list = self.config_reader.getConfigList ()
		self.config_writer = ConfigWriter ()
		self.CreateConfigListStore ()
		self.CreateSchemeListStore ()
		self.example_text = self.get_widget ("LabelExampleCmd").get_label ()
		self.config_title_text = self.get_widget ("LabelConfigTitle").get_label ()
		self.legenddialog = NACTLegendDialog ()
		self.filedialog = NACTFileChooserDialog (self.get_widget ("EntryPath"))
		self.aboutdialog = NACTAboutDialog ()
		self.confirmsavedialog = NACTConfirmSaveDialog (self.ActionSaveHandler)
		self.uid = os.getuid ()
		if self.uid == 0:
			self.get_widget ("MenuPreferences").hide ()
		self.config_selection_change = False
		self.config_modified = False
		self.ManageWidgetSensitivity ()

	def UpdateConfigList (self):
		model = self.get_widget("TreeViewConfigList").get_model ()
		model.clear ()
		for config_name in self.config_list.keys ():
		#
			config = self.config_list[config_name]
			if not config.is_deleted ():
				if not config.is_readonly ():
				#
					model.prepend([config_name , gtk.STOCK_PREFERENCES, False])
				#
				elif self.show_systemwide:
				#
					model.append([config_name , gtk.STOCK_PREFERENCES, False])
				#
		#

	def AlignLabels (self):
		label_list = self.get_widget_prefix ("LabelAlign")
		sizegrp = gtk.SizeGroup (gtk.SIZE_GROUP_HORIZONTAL)
		for label in label_list:
			sizegrp.add_widget (label)
			

	def CreateConfigListStore (self):
		dist_store = gtk.ListStore (str, str, gobject.TYPE_BOOLEAN)

		treeview = self.get_widget("TreeViewConfigList")
		treeview.set_model (dist_store)

		self.UpdateConfigList ()
		
		column = gtk.TreeViewColumn ()
		column.set_title (_("_Config List"))
		
		icon_renderer = gtk.CellRendererPixbuf ()
		column.pack_start (icon_renderer, False)
		column.add_attribute (icon_renderer, "stock_id", 1)

		text_renderer = gtk.CellRendererText ()
		text_renderer.connect ('edited', self.ActionNewConfigNameEditHandler, dist_store)
		column.pack_end (text_renderer, True)
		column.add_attribute (text_renderer, "text", 0)
		column.add_attribute (text_renderer, "editable", 2)

		treeview.append_column (column)

	def CreateSchemeListStore (self):
		dist_store = gtk.ListStore (gobject.TYPE_BOOLEAN, str, str)
		for scheme in self.scheme_list:
			dist_store.append([False, scheme[0], _(scheme[1])])
		treeview = self.get_widget("TreeViewSelectScheme")
		treeview.set_model (dist_store)

		column = gtk.TreeViewColumn ()
#		column.set_title ("Scheme")

		renderer = gtk.CellRendererToggle()
		renderer.connect ('toggled', self.ActionToggleSchemeHandler, dist_store)

		column.pack_start (renderer, False)
		column.add_attribute (renderer, "active", 0)
		column.set_clickable(True)

		text_renderer = gtk.CellRendererText ()
		column.pack_end (text_renderer, True)
		column.add_attribute (text_renderer, "text", 1)

		column.set_min_width (100)
		treeview.append_column(column)
		
		column = gtk.TreeViewColumn ()
#		column.set_title ("Description")

		text_renderer = gtk.CellRendererText ()
		column.pack_start (text_renderer, False)
		column.add_attribute (text_renderer, "text", 2)
		treeview.append_column(column)

	def ManageWidgetSensitivity (self):
		save1_widget = self.get_widget ("ToolButtonSave")
		save2_widget = self.get_widget ("MenuSave")
		delete1_widget = self.get_widget ("ToolButtonDeleteConfig")
		delete2_widget = self.get_widget ("MenuDeleteConfig")
		readonly1_widget = self.get_widget ("LabelRootWarning")
		readonly2_widget = self.get_widget ("VBoxMenu")
		readonly3_widget = self.get_widget ("VBoxCommand")
		readonly4_widget = self.get_widget ("VBoxTest")
		save1_widget.set_sensitive (False)
		save2_widget.set_sensitive (False)
		delete1_widget.set_sensitive (False)
		delete2_widget.set_sensitive (False)
		readonly1_widget.hide ()
		readonly2_widget.set_sensitive (True)
		readonly3_widget.set_sensitive (True)
		readonly4_widget.set_sensitive (True)
		config_name = self.GetCurrentEditedConfig ()
		if config_name != None and config_name != self.new_config_name:
			config = self.config_list[config_name]
			if config.is_readonly ():
				readonly1_widget.show ()
				readonly2_widget.set_sensitive (False)
				readonly3_widget.set_sensitive (False)
				readonly4_widget.set_sensitive (False)
			else:
				delete1_widget.set_sensitive (True)
				delete2_widget.set_sensitive (True)
		if self.config_modified:
			save1_widget.set_sensitive (True)
			save2_widget.set_sensitive (True)
		
	def CheckSchemeIfInList (self, model, path, iter, scheme_list):
		current_scheme = model.get_value (iter, 1)
		if current_scheme in scheme_list:
		#
			model.set_value (iter, 0, True)
		#
		else:
		#
			model.set_value (iter, 0, False)
		#

	def SetCurrentFilename (self, path):
		self.filedialog.SetCurrentFile (path)
		self.get_widget ("EntryPath").set_text (path)
		
	def FillConfigPanelFromConfigName (self, config_name):
		if config_name != self.new_config_name:
		#
			self.config_selection_change = True
			config = self.config_list[config_name]
			self.get_widget ("LabelConfigTitle").set_label (self.config_title_text % config_name)
			self.get_widget ("EntryLabel").set_text (config.get_menu_item_label ())
			self.get_widget ("EntryTooltip").set_text (config.get_menu_item_tooltip ())

			self.SetCurrentFilename (config.get_command_path ())
			self.get_widget ("EntryParameters").set_text (config.get_command_parameters ())
			self.get_widget ("EntryFilePattern").set_text (config.get_test_basename_str ())

			if config.get_test_isfile () and config.get_test_isdir ():
				self.get_widget ("RadioButtonBoth").set_active (True)
			elif config.get_test_isfile ():
				self.get_widget ("RadioButtonFiles").set_active (True)
			else:
				self.get_widget ("RadioButtonFolders").set_active (True)

			self.get_widget ("CheckButtonMultiple").set_active (config.get_test_accept_multiple_file ())
			self.get_widget ("TreeViewSelectScheme").get_model ().foreach (self.CheckSchemeIfInList, config.get_test_schemes ())
			self.config_selection_change = False
		#
		else:
		#
			self.config_selection_change = True
			self.get_widget ("LabelConfigTitle").set_label (self.config_title_text % config_name)
			self.UpdateCommandExample ()
			self.config_selection_change = False
		#
		
	def GetCurrentEditedConfig (self):
		(model, iter) = self.get_widget ("TreeViewConfigList").get_selection ().get_selected ()
		if iter != None:
			return model.get_value (iter, 0)
		else:
			return None

	def ActionNewConfigNameEditHandler (self, cellrenderer, path, new_text, model):
		treeview = self.get_widget("TreeViewConfigList")
		tmp = ""
		not_trimmed_text = new_text
		for c in new_text: # Trim all characters which are not alphanumeric
			if c in string.letters:
				tmp += c
			elif c in string.digits:
				tmp += c
		new_text = tmp
		if not_trimmed_text != self.new_config_name and len (new_text) > 0:
		#
			is_ok = True
			new_config = None
			if self.config_list.has_key (new_text):
			#
				is_ok = False
				config = self.config_list[new_text]
				if config.is_deleted ():
				#
					is_ok = True
					del (self.config_list[new_text])
				#
				elif config.is_readonly (): # Overwrite system-wide config
				#
					config.overwrite_config ()
					if config.is_overwritten:
						new_config = config
						is_ok = True
				#
			#
				
			if is_ok:
			#
				iter = model.get_iter_from_string (path)
				model.set (iter, 0, new_text)
				model.set (iter, 2, False)
				if new_config == None:
					new_config = Config (new_text)
					self.config_list[new_text] = new_config
				self.UpdateConfigList ()
				iter = model.get_iter_first ()
				found = False
				while iter and not found:
				#
					if model.get_value (iter, 0) == new_text:
					#
						treeview.set_cursor (model.get_path (iter), None, False)
						found = True
					#
					iter = model.iter_next (iter)
				#
				self.config_modified = True
			#
			else:
			#
				treeview.set_cursor_on_cell (path, treeview.get_column (0), None, True)
			#
			self.ManageWidgetSensitivity ()
		#
		else:
		#
			treeview.set_cursor_on_cell (path, treeview.get_column (0), None, True)
		#
	
	def ActionNewConfigHandler (self, widget):
		treeview = self.get_widget ("TreeViewConfigList")
		model = treeview.get_model ()
		iter = model.append([self.new_config_name , gtk.STOCK_PREFERENCES, True])
		treeview.set_cursor_on_cell (model.get_string_from_iter (iter), treeview.get_column (0), None, True)

	def ActionDeleteConfigHandler (self, widget):
		(model, iter) = self.get_widget ("TreeViewConfigList").get_selection ().get_selected ()
		if iter != None:
		#
			config_name = model.get_value (iter, 0)
			self.config_list[config_name].mark_as_deleted ()
			#model.remove (iter)
			self.UpdateConfigList ()
			self.get_widget ("TreeViewConfigList").get_selection ().unselect_all ()
			self.get_widget ("VBoxConfigSelected").hide ()
			self.get_widget ("VBoxNoSelection").show ()
			self.config_modified = True
		#
		self.ManageWidgetSensitivity ()
		

	def ActionConfigSelectHandler (self, treeview):
		(model, iter) = treeview.get_selection ().get_selected ()
		if iter == None:
			self.get_widget ("VBoxConfigSelected").hide ()
			self.get_widget ("VBoxNoSelection").show ()
		else:
			self.FillConfigPanelFromConfigName (model.get_value (iter, 0))
			self.get_widget ("VBoxNoSelection").hide ()
			self.get_widget ("VBoxConfigSelected").show ()
		while gtk.events_pending():
			gtk.main_iteration(False)
		self.ManageWidgetSensitivity ()
			
	
	def ActionShowLegendHandler (self, widget):
		self.legenddialog.Show ()

	def ActionShowROConfigHandler (self, widget):
		self.show_systemwide = widget.get_active ()
		config_name = self.GetCurrentEditedConfig ()
		self.UpdateConfigList ()
		self.get_widget ("TreeViewConfigList").get_selection ().unselect_all ()
		self.get_widget ("VBoxConfigSelected").hide ()
		self.get_widget ("VBoxNoSelection").show ()
		self.ManageWidgetSensitivity ()

	def ActionBrowseHandler (self, widget):
		self.filedialog.Show ()

	def ParseParameters (self, parameters, config_name):
		retv = ""
		if config_name != self.new_config_name:
		#
			ex_path = _("/path/to")
			ex_files = [ _("file1.txt"), _("file2.txt") ]
			ex_dirs = [ _("dir1"), _("dir2")]
			ex_mixed = [_("file1.txt"), _("dir1") ]
			ex_scheme = _("file")
			ex_one = _("file.txt")
			ex_list = [ ex_one ]
			ex_path_list = [ ex_path + "/" + ex_one ]
			config = self.config_list[config_name]
			if config.get_test_accept_multiple_file ():
			#
				if config.get_test_isfile () and config.get_test_isdir ():
				#
					ex_one = ex_files[0]
					ex_list = ex_mixed
				#
				elif config.get_test_isfile ():
				#
					ex_one = ex_files[0]
					ex_list = ex_files
				#
				elif config.get_test_isdir ():
				#
					ex_one = ex_dirs[0]
					ex_list = ex_dirs
				#

				ex_path_list = []
				for value in ex_list:
				#
					ex_path_list.append ( ex_path + "/" + value)
				#
			#
			else:
			#
				if config.get_test_isdir () and not config.get_test_isfile ():
				#
					ex_one = _("dir")
				#
			#
			schemes = config.get_test_schemes ()
			if len (schemes) != 0:
			#
				ex_scheme = schemes[0]
			#
			if ex_scheme == _("file"):
			#
				if len (schemes) > 1:
					ex_scheme = schemes[1]
					ex_host = _("test.example.net")
				else:
					ex_host = ""
			#
			else:
			#
				ex_host = _("test.example.net")
			#

			tmp = parameters
			pos = string.find (tmp, "%")
			retv = tmp[:pos]
			while pos != -1 and len (tmp) >= pos + 2:
			#
				ex_str = ""
				if tmp[pos+1] == 'u':
				#
					ex_str = ex_scheme + "://" + ex_path + ex_one
				#		
				elif tmp[pos+1] == 'd':
				#
					ex_str = ex_path
				#
				elif tmp[pos+1] == 'p':
				#
					ex_str = os.path.dirname (ex_path)
				#
				elif tmp[pos+1] == 'f':
				#
					ex_str = ex_one
				#
				elif tmp[pos+1] == 'm':
				#
					ex_str = string.join (ex_list, " ")
				#
				elif tmp[pos+1] == 'M':
				#
					ex_str = string.join (ex_path_list, " ")
				#
				elif tmp[pos+1] == 's':
				#
					ex_str = ex_scheme
				#
				elif tmp[pos+1] == 'h':
				#
					ex_str = ex_host
				#
				elif tmp[pos+1] == 'U':
				#
					ex_str = "root"
				#
				elif tmp[pos+1] == '%':
				#
					ex_str = "%"
				#
				retv += ex_str
				tmp = tmp[pos+2:]
				pos = string.find (tmp, "%")
				retv += tmp[:pos]
			#
			retv += tmp[pos:]
		#
		return retv

	def UpdateCommandExample (self):
		path = self.get_widget ("EntryPath").get_text ()
		parameters = self.ParseParameters (self.get_widget ("EntryParameters").get_text (), self.GetCurrentEditedConfig ())
		self.get_widget ("LabelExampleCmd").set_label (self.example_text % (path, parameters))

	def ActionPathChangeHandler (self, widget):
		if not self.config_selection_change:
		#
			path = self.get_widget ("EntryPath").get_text ()
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None and self.config_list[config_name].get_command_path () != path :
			#
				self.config_list[config_name].set_command_path (path)
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()
		self.UpdateCommandExample ()

	def ActionParametersChangeHandler (self, widget):
		if not self.config_selection_change:
		#
			parameters = self.get_widget ("EntryParameters").get_text ()
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None:
			#
				self.config_list[config_name].set_command_parameters (parameters)
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()
		self.UpdateCommandExample ()

	def ActionLabelChangeHandler (self, entry):
		if not self.config_selection_change:
		#
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None:
			#
				self.config_list[config_name].set_menu_item_label (entry.get_text ())
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()

	def ActionTooltipChangeHandler (self, entry):
		if not self.config_selection_change:
		#
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None:
			#
				self.config_list[config_name].set_menu_item_tooltip (entry.get_text ())
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()

	def ActionBasenameChangeHandler (self, entry):
		if not self.config_selection_change:
		#
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None:
			#
				self.config_list[config_name].set_test_basename_str (entry.get_text ())
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()

	def ActionSelectionTypeSelectHandler (self, checkbuttton):
		if not self.config_selection_change:
		#
			config_name = self.GetCurrentEditedConfig ()
			file_state = self.get_widget ("RadioButtonFiles").get_active ()
			dir_state = self.get_widget ("RadioButtonFolders").get_active ()
			both_state = self.get_widget ("RadioButtonBoth").get_active ()
			if config_name != None:
			#
				if file_state:
					self.config_list[config_name].set_test_isfile (True)
					self.config_list[config_name].set_test_isdir (False)
				elif dir_state:
					self.config_list[config_name].set_test_isfile (False)
					self.config_list[config_name].set_test_isdir (True)
				elif both_state:	
					self.config_list[config_name].set_test_isfile (True)
					self.config_list[config_name].set_test_isdir (True)
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()
		self.UpdateCommandExample ()

	def ActionMultipleToggleHandler (self, checkbuttton):
		if not self.config_selection_change:
		#
			config_name = self.GetCurrentEditedConfig ()
			if config_name != None:
			#
				self.config_list[config_name].set_test_accept_multiple_file (checkbuttton.get_active ())
				self.config_modified = True
			#
		#
		self.ManageWidgetSensitivity ()
		self.UpdateCommandExample ()

	def ActionToggleSchemeHandler (self, cellrenderer, path, model):
		config_name = self.GetCurrentEditedConfig ()
		iter = model.get_iter (path)
		value = model.get_value (iter, 0)
		scheme = model.get_value (iter, 1)
		model.set_value (iter, 0, not value)
		if value:
			self.config_list[config_name].remove_test_schemes (scheme)
			self.config_modified = True
		else:
			self.config_list[config_name].append_test_schemes (scheme)
			self.config_modified = True
		self.ManageWidgetSensitivity ()
		self.UpdateCommandExample ()

	def ActionReloadHandler (self, widget):
		self.config_reader.LoadConfigFiles ()
		self.config_list = self.config_reader.getConfigList ()
		model = self.get_widget ("TreeViewConfigList").get_model ()
		self.UpdateConfigList ()
		self.get_widget ("TreeViewConfigList").get_selection ().unselect_all ()
		self.get_widget ("VBoxConfigSelected").hide ()
		self.get_widget ("VBoxNoSelection").show ()
		self.config_modified = False
		self.ManageWidgetSensitivity ()
		
	def ActionSaveHandler (self, widget):
		self.config_writer.setConfigList (self.config_list)
		self.config_writer.SaveConfigFiles ()
		self.config_modified = False
		self.ManageWidgetSensitivity ()

	def ActionAboutHandler (self, widget):
		self.aboutdialog.Show ()

	def ActionQuitHandler (self, widget):
		if not self.config_modified:
			gtk.main_quit ()
		else:
			self.confirmsavedialog.Show ()

	def ActionAppQuitHandler (self, widget, event):
		self.ActionQuitHandler (widget)
		return True

## MAIN ##
locale.setlocale(locale.LC_ALL, '')
gtk.glade.bindtextdomain(APP, DIR)
gtk.glade.textdomain(APP)
gettext.install(APP, DIR, unicode=1)
N_ = str
app = NACTMainWindow ()
gtk.main ()

# vim:ts=3:sw=3:tw=1024:ai
