#!/usr/bin/env python
#
# nxrun-gui - GUI for nxrun
#
# For more information about this module, see http://freenx.berlios.de.
#
# Copyright (c) 2005 by Lawrence Roufail <lroufail@nc.rr.com>
#
# By obtaining, using, and/or copying this software and/or its
# associated documentation, you agree that you have read, understood,
# and will comply with the following terms and conditions:
#
# Permission to use, copy, modify, and distribute this software and
# its associated documentation for any purpose and without fee is
# hereby granted, provided that the above copyright notice appears in
# all copies, and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of the
# author not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

r"""nxrun-gui - GUI for nxrun NX client

This module is a self-contained gui for nxrun.  It makes the following assumptions:

*  It is placed in the same directory as nxrun
*  There is a subdirectory ./config with the configuration files
*  Configuration files have the suffix ".conf"

How It Works
-------------

Basically, there are four parts to the script:

1.  Methods for creating the windows
2.  Methods for handling window events
3.  Methods for translating between the windows and the options
4.  Methods for reading and writing the options from the XML file 

1.  Creating the windows
-----------------------------

This is standard python.  The design rules are:

* A new instance of the window is created each time it is invoked
* The data is loaded to the window from the options file after all the widgets are created
* For dialogs, the options are stored when the user presses OK and the dialog is dismissed

Each of these methods is concluded with the following code:

		self.<dialog>_dlg_load()
		self.<dialog>_dlg.show()

This means that the options are loaded from memory into the widgets before the dialog is displayed.


2.  Window events
-----------------------------

These are standard python events.  They handle the enabling and disabling of fields and
responding to button clicks.  Each dialog has an event handler in the following form 

	def <dialog>_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.<dialog>_store()
			self.do_dirty()
		self.<dialog>.destroy()
		
This means that if the user presses ok, the options are stored from the widgets and
a flag is set to indicate that there is dirty data to save. 

3.  Windows and Options
------------------------

As alluded to above, there is a standard pattern for translating between windows
and options (Options will be described in more detail below).

* Each window has its own pair of methods for doing this translation
* The methods are named:
   * <dialog>_dlg_load()
   * <dialog>_dlg_store()

4.  Options and the XML Configuration File
-------------------------------------------

The NXClient configuration file has a standard pattern that looks like the following:

<group name="groupname">
	<option key="keyname" value="value" />
</group>

Because the format is so standard, it can be loaded and parsed in a generic way.

nxrun-gui does this using two methods:
	* load_options() - load options from configuration file
	* save_options() - store options in the configuration file
	
load_options is called when:
	* the configure dialog is invoked
	* a new configuration is created (copied from an existing configuration)

save_options is called when:	
	* a new configuration is created (copied from an existing configuration)
	* the save or ok buttons are clicked on the configure dialog

The Options Structure
-----------------------

Options are stored in a data structure in memory.  The structure is a dictionary:
	* Key - tuple consisting of [group,key]
	* Value - A string representing the value
load_options is very straightforward.  It loops through the groups and options and
fills the dictionary.

store_options() is also straightforward but has a wrinkle.  As it creates the
options, it keeps a dictionary of the group elements it has created.  If the group
does not yet exist, it creates an element for it and adds it to the root before
creating the option element.  If the group exists it creates the option and adds it
to the exisitng group.

The windows interact with the options dictionary using:
	* get_option(group, key) - returns value as string or empty string
	* set_option(group,key,value) - sets the value

Calling nxrun
--------------

The subprocess module is used to call nxrun in the run() method.

To get the right effect, once the process is created, a timer is set up.  Each time
the timer is called, the next status line is read from standard out of nxrun.  When
it is complete, it pauses and then returns to the login dialog.

The progress_timeout(tobj) method contains the status logic.  The tobj is the
process object.

The current implementation passes the username and password on the command line to
nxrun.  Obviously this is not secure because the plaintext password could appear in
ps and in logs.  A better approach would be to use the interactive mode to feed the
password on stdin.


"""


import gtk,os,getpass,sys,subprocess,time,gobject,shutil
from xml.dom import minidom, Node

def progress_timeout(tobj):
	data = tobj.so.readline()
	if data != "":
		tobj.statuslabel.set_text(data)
		gtk.main_iteration(False)		
		return True
	else:
		time.sleep(5)
		tobj.statuswindow.grab_remove()
		tobj.statuswindow.hide()
		tobj.window.show_all()


class nxrungui:
	DEF_PAD = 5
	INDENT = 20
	# Dialog button custom responses
	CONFIG_DLG_RESPONSE_DELETE = 1
	CONFIG_DLG_RESPONSE_SAVE = 2
	NEW_DLG_RESPONSE_CREATE = 1
	NEW_DLG_RESPONSE_RENAME = 2
	# Values for drop-downs - in some cases codes and values are not the same
	SESSION_TYPES = ["Unix", "Windows", "VNC"]
	UNIX_DESKTOPS = ["KDE","GNOME","CDE","Custom"]
	LINK_SPEEDS = ["Modem", "ISDN", "ASDL", "WAN", "LAN"]
	DISPLAY_RES = ["640x480", "800x600","1024x768","Available Area","Fullscreen","Custom"]
	CACHE_VALUES = ["1 MB","2 MB","4 MB","8 MB","16 MB","32 MB"]
	CACHE_CODES = ["1","2","4","8","16","32"]
	DISK_CACHE_VALUES = ["4 MB","8 MB","16 MB","32 MB","64 MB","128 MB"]
	DISK_CACHE_CODES = ["4","8","16","32","64","128"]
	KEYBOARD_VALUES = ["English","Estonian"]
	KEYBOARD_CODES = ["en","ee"]
	# Options and groups dictionaries for working with options
        options = {}
	groups = {}
	# location of cache files - partially implemented
	if os.name == "nt":
		CACHE_PATH = "c:\\.nx\\cache"
	else:
		CACHE_PATH = os.environ['HOME'] + "/.nx/cache/"

	def __init__(self):
		self.timer=0
		self.dirty_flag = False
		self.current_service = ""
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
	        self.window.set_title("NXRUN GUI")
	        self.window.set_border_width(5)
		self.window.set_position(gtk.WIN_POS_CENTER)
	        self.window.set_resizable(False)
	        self.window.connect("delete_event", gtk.main_quit)
	        self.window.connect("destroy", gtk.main_quit)

		MainBox = gtk.VBox(False, self.DEF_PAD)
		self.window.add(MainBox)
		vbox = MainBox

        # Login
                
                hbox = gtk.HBox(False, 5)
                vbox.pack_start(hbox, False, False, 5)
                
                label = gtk.Label("Login:")
                hbox.pack_start(label, False, False, 5)
                self.loginlabel = label
		self.user = gtk.Entry(0)
                self.user.set_size_request(250,22)
                hbox.pack_end(self.user, False, False, 5)
                                 
                hbox = gtk.HBox(False, 5)
                vbox.pack_start(hbox, False, False, 5)

                label = gtk.Label("Password:  ")
                hbox.pack_start(label, False, False, 5)
                self.passw = gtk.Entry(0)
		self.passw.set_visibility(False)
                self.passw.set_size_request(250,22)
                hbox.pack_end(self.passw, False, False, 5)

                hbox = gtk.HBox(False, 5)
                vbox.pack_start(hbox, False, False, 5)
                label = gtk.Label("Service:  ")
                hbox.pack_start(label, False, False, 5)
		self.service_menu = gtk.combo_box_entry_new_text()
		l = os.listdir("./config")
		self.services = []
		for service in l:
			if (service.endswith(".conf")):
				self.services.append(service)
				self.service_menu.append_text(service.rstrip(".conf"))
	        self.service_menu.connect('changed', self.change_service)
	        self.service_menu.child.connect('focus-out-event', self.focus_out_service)
		self.service_menu.set_size_request(250,30)
                hbox.pack_end(self.service_menu, False, False, 5)

	        bbox = gtk.HButtonBox ()
	        vbox.pack_start(bbox, False, False, 0)
	        bbox.set_layout(gtk.BUTTONBOX_END)
	        configure_button = gtk.Button("Configure...")
	        configure_button.connect("clicked", self.configure)
	        bbox.add(configure_button)
	        login_button = gtk.Button("Login")
	        login_button.connect("clicked", self.run)
	        bbox.add(login_button)
	        close_button = gtk.Button("Close")
	        close_button.connect("clicked", gtk.main_quit)
	        bbox.add(close_button)

                self.window.show_all();
		
	# Utility function for loading a combobox
	def load_combo(self, combo, alist):
		for t in alist:
			combo.append_text(t)

	# Utility function for setting the item with the defined value in combobox
	def combo_select(self, combobox, reflist, value):
		try:
			i = reflist.index( value )
			combobox.set_active(i)
		except ValueError:
			i = -1
		return i
			

	# Utility function for returning the path for a config name
	def config_path(self, config):
		return "./config/"+config

	# set the dirty flag and enable the save button
	def do_dirty(self, widget=None):
		if (self.dirty_flag == False):
			self.dirty_flag = True
			self.save_button.set_sensitive(True)
			
	# clear the dirty flag and enable the save button
	def clear_dirty(self):
		if (self.dirty_flag == True):
			self.dirty_flag = False
			self.save_button.set_sensitive(False)


	def change_service(self, combobox):
		if (combobox.get_active() > -1):
			self.current_service = self.services[combobox.get_active()]
		
		return True			

	def focus_out_service(self, comboentry, event):
		# select proper entry if in list.
		index = self.combo_select(self.service_menu, self.services, comboentry.get_text())
		# if this is a new entry, handle it
		if ((index < 0) and ( len(comboentry.get_text()) > 0)):
			index =self.combo_new_entry(self.service_menu, self.services,  comboentry.get_text())
			if (index < 0):
				self.combo_select(self.service_menu, self.services, self.current_service)
			else:
				self.service_menu.set_active(index)
		return False

	def combo_new_entry(self, combobox, reflist, value):
		new_dlg = gtk.Dialog("NX - " + value, self.window,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,("Create", self.NEW_DLG_RESPONSE_CREATE, "Rename",self.NEW_DLG_RESPONSE_RENAME, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
		vb = new_dlg.vbox
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label("You have changed the service name.  What would you like to do?")
                hbox.pack_start(label, False, False, 5)
		label.show()
		resp = new_dlg.run()
		new_dlg.destroy()
		if (resp == self.NEW_DLG_RESPONSE_CREATE):
			# load the active file and save the copy
			if (self.current_service != ""):
				self.load_options()
				self.save_options(value + ".conf")
			reflist.append(value + ".conf")
			combobox.append_text(value)
			self.configure()
			return len(reflist)-1
		elif (resp == self.NEW_DLG_RESPONSE_RENAME):
			os.rename(self.config_path( self.current_service), self.config_path( value + ".conf"))
			index = reflist.index(self.current_service)
			combobox.remove_text(index)
			reflist.remove(self.cuvisrrent_service)
			combobox.insert_text(index, value)
			reflist.insert(index, value + ".conf")
			return index
		return -1

	def configure(self, widget=None):
	# Configuration
		self.config_dlg = gtk.Dialog("NX -" + self.current_service, self.window,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
		self.config_dlg.connect("response", self.config_dlg_do_response)
		MainBox = self.config_dlg.vbox
        # Notebook
        
                self.notebook = gtk.Notebook()
                self.notebook.set_tab_pos(gtk.POS_TOP)
                self.config_dlg.vbox.pack_start(self.notebook, True, True, 5) 
		self.notebook.show()
		
	# General
          
		# General
		self.generalframe = gtk.Frame()
                label = gtk.Label("General")
                self.notebook.append_page(self.generalframe, label)
                generalbox = gtk.VBox(False, 5)
                self.generalframe.add(generalbox)  
		self.generalframe.show()
		generalbox.show()
		# Server
                contentframe = gtk.Frame("Server")
                contentframe.set_border_width(4)
                generalbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label("host:")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.host = gtk.Entry(0)
                self.host.set_size_request(150,22)
	        self.host.connect('changed', self.do_dirty)
                hbox.pack_start(self.host, False, False, 5)
		self.host.show()
		label = gtk.Label("port:")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.port = gtk.Entry(0)
                self.port.set_size_request(65,22)
		self.port.set_max_length(10)
	        self.port.connect('changed', self.do_dirty)
                hbox.pack_start(self.port, False, False, 5)
		self.port.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.remember = gtk.CheckButton("Remember my password")
	        self.remember.connect('toggled', self.do_dirty)
		hbox.pack_start(self.remember, False, False, 5)
		self.remember.show()
		# Desktop
                contentframe = gtk.Frame("Desktop")
                contentframe.set_border_width(4)
                generalbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.session = gtk.combo_box_new_text()
                self.load_combo(self.session, self.SESSION_TYPES)
	        self.session.connect('changed', self.change_config_session)
                hbox.pack_start(self.session, False, False, 5)
		self.session.show()
                self.desktop = gtk.combo_box_new_text()
	        self.desktop.connect('changed', self.change_config_desktop)
                hbox.pack_start(self.desktop, False, False, 5)
		self.desktop.show()
		self.settings_button = gtk.Button("Settings...")
	        self.settings_button.connect("clicked", self.settings)		
                hbox.pack_start(self.settings_button, False, False, 5)
		self.settings_button.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label("Link speed:")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.link_speed = gtk.combo_box_new_text()
                self.load_combo(self.link_speed, self.LINK_SPEEDS)
	        self.link_speed.connect('changed', self.do_dirty)
                hbox.pack_start(self.link_speed, False, False, 5)
		self.link_speed.show()		
		# Display
                contentframe = gtk.Frame("Display")
                contentframe.set_border_width(4)
                generalbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.resolution = gtk.combo_box_new_text()
                self.load_combo(self.resolution, self.DISPLAY_RES)
	        self.resolution.connect('changed', self.change_config_resolution)
                hbox.pack_start(self.resolution, False, False, 5)
		self.resolution.show()		
                label = gtk.Label("W")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.resolution_width = gtk.SpinButton()
		self.resolution_width.set_numeric(True)
		self.resolution_width.set_range(100,9999)
		self.resolution_width.set_increments(1,50)
                self.resolution_width.set_value(800)
	        self.resolution_width.connect('changed', self.do_dirty)
                hbox.pack_start(self.resolution_width, False, False, 5)
		self.resolution_width.show()		
                label = gtk.Label("H")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.resolution_height = gtk.SpinButton()
		self.resolution_height.set_numeric(True)
		self.resolution_height.set_range(100,9999)
		self.resolution_height.set_increments(1,50)
                self.resolution_height.set_value(600)
	        self.resolution_height.connect('changed', self.do_dirty)
                hbox.pack_start(self.resolution_height, False, False, 5)
		self.resolution_height.show()		
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_default = gtk.RadioButton(label='Use default image encoding')
	        self.encoding_default.connect('toggled', self.toggle_config_encoding)
		hbox.pack_start(self.encoding_default, False, False, 5)
		self.encoding_default.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_custom = gtk.RadioButton(self.encoding_default, 'Use custom settings')
                hbox.pack_start(self.encoding_custom, False, False, 5)
		self.encoding_custom.show()
		self.custom_button = gtk.Button("Modify...")
	        self.custom_button.connect("clicked", self.custom)				
                hbox.pack_start(self.custom_button, False, False, 5)
		self.custom_button.show()
		
          # Advanced 
          
                self.advancedframe = gtk.Frame()
                label = gtk.Label("Advanced")
                self.notebook.append_page(self.advancedframe, label)
		self.advancedframe.show()
                advancedbox = gtk.VBox(False, 5)
                self.advancedframe.add(advancedbox)  
                advancedbox.show()
		# Network
                contentframe = gtk.Frame("Network")
                contentframe.set_border_width(4)
                advancedbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.tcp = gtk.CheckButton("Disable no-delay for tcp connections")
	        self.tcp.connect('toggled', self.do_dirty)
		hbox.pack_start(self.tcp, False, False, 5)
		self.tcp.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.zlib = gtk.CheckButton("Disable ZLIB stream compression")
	        self.zlib.connect('toggled', self.do_dirty)
		hbox.pack_start(self.zlib, False, False, 5)
		self.zlib.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.ssl = gtk.CheckButton("Enable SSL encryption of all traffic")
	        self.ssl.connect('toggled', self.do_dirty)
		hbox.pack_start(self.ssl, False, False, 5)
		self.ssl.show()
		# Cache
                contentframe = gtk.Frame("Cache")
                contentframe.set_border_width(4)
                advancedbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label("In memory")
                hbox.pack_start(label, False, False, 5)
		label.show()
                self.cache = gtk.combo_box_new_text()
                self.load_combo(self.cache, self.CACHE_VALUES)
	        self.cache.connect('changed', self.do_dirty)
                hbox.pack_start(self.cache, False, False, 5)
		self.cache.show()		
                label = gtk.Label("On disk")
                self.disk_cache = gtk.combo_box_new_text()
                self.load_combo(self.disk_cache, self.DISK_CACHE_VALUES)
	        self.disk_cache.connect('changed', self.do_dirty)
                hbox.pack_end(self.disk_cache, False, False, 5)
                hbox.pack_end(label, False, False, 5)
		label.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
		self.disk_cache.show()		
		self.cache_button = gtk.Button("Clean all cache files")
	        self.cache_button.connect("clicked", self.clicked_config_cache)
                hbox.pack_end(self.cache_button, False, False, 5)
		self.cache_button.show()
		# Keyboard
                contentframe = gtk.Frame("Keyboard")
                contentframe.set_border_width(4)
                advancedbox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.keyboard_current = gtk.RadioButton(label='Keep current keyboard settings')
	        self.keyboard_current.connect('toggled', self.toggle_config_keyboard)
		hbox.pack_start(self.keyboard_current, False, False, 5)
		self.keyboard_current.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.keyboard_other = gtk.RadioButton(self.keyboard_current, 'Use other layout')
                hbox.pack_start(self.keyboard_other, False, False, 5)
		self.keyboard_other.show()
                self.keyboards = gtk.combo_box_new_text()
                self.load_combo(self.keyboards, self.KEYBOARD_VALUES)
	        self.keyboards.connect('changed', self.do_dirty)
                hbox.pack_start(self.keyboards, False, False, 5)
		self.keyboards.show()		
		
	# Services
          
                self.logframe = gtk.Frame()
                label = gtk.Label("Services")
                self.notebook.append_page(self.logframe, label)
		self.logframe.show()
                logbox = gtk.VBox(False, 5)
                self.logframe.add(logbox)  
		logbox.show()
		
		
	# Buttons

		self.config_dlg.add_button("Delete", self.CONFIG_DLG_RESPONSE_DELETE)
		self.save_button = self.config_dlg.add_button("Save",self.CONFIG_DLG_RESPONSE_SAVE)
		self.save_button.set_state(gtk.STATE_INSENSITIVE)
		self.config_dlg.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
		self.config_dlg.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)	
		self.load_options()
		self.config_dlg_load()
		self.config_dlg.show()

	def change_config_resolution(self, combobox):
		self.do_dirty()
		res = self.DISPLAY_RES[combobox.get_active()]
		if (res == 'Custom'):
			self.resolution_width.set_sensitive(True)
			self.resolution_height.set_sensitive(True)
		else:
			self.resolution_width.set_sensitive(False)
			self.resolution_height.set_sensitive(False)
		
	def change_config_session(self, combobox):
		self.do_dirty()
		ses = ""
		self.desktop.get_model().clear()
		if (combobox.get_active() > -1):
			ses = self.SESSION_TYPES[combobox.get_active()]
		if (ses == 'Unix'):
			self.load_combo(self.desktop, self.UNIX_DESKTOPS)
			self.desktop.set_sensitive(True)
		elif (ses == "Windows"):
			self.desktop.append_text("RDP")
			self.desktop.set_sensitive(False)
		elif (ses == "VNC"):
			self.desktop.append_text("RFB")
			self.desktop.set_sensitive(False)
		self.desktop.set_active(0)
		
	def change_config_desktop(self, combobox):
		self.do_dirty()
		self.settings_button.set_sensitive(True)
		ses = self.SESSION_TYPES[self.session.get_active()]
		if (ses == 'Unix'):
			dt = self.UNIX_DESKTOPS[combobox.get_active()]
		        fl = self.get_option("General", "Virtual desktop");
			if (dt !=  'Custom'):
				self.settings_button.set_sensitive(False)
			if ((dt != 'Custom') or (fl != "false")):
				self.resolution.set_sensitive(True)
				self.change_config_resolution(self.resolution)
			else:
				self.resolution.set_sensitive(False)
				self.resolution_width.set_sensitive(False)
				self.resolution_height.set_sensitive(False)
				
	def toggle_config_encoding(self, radio):
		self.do_dirty()
		self.custom_button.set_sensitive(self.encoding_custom.get_active())		
				
	def clicked_config_cache(self, butn):
		cache_msg_dlg = gtk.MessageDialog(self.config_dlg, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Do you really want to clean all cache files");
		resp = cache_msg_dlg.run()
		if (resp == gtk.RESPONSE_YES):
			shutil.rmtree(self.CACHE_PATH)
			cache_confirm_msg_dlg = gtk.MessageDialog(self.config_dlg, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "All the caches in " + self.CACHE_PATH + " are cleared.");
			cache_confirm_msg_dlg.run()
			cache_confirm_msg_dlg.destroy()
		cache_msg_dlg.destroy()

	def toggle_config_keyboard(self, radio):
		self.do_dirty()
		self.keyboards.set_sensitive(self.keyboard_other.get_active())		


	def config_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_ACCEPT):
			self.config_dlg_store()
			self.save_options()
			self.config_dlg.destroy()
		elif (response_id == self.CONFIG_DLG_RESPONSE_SAVE):
			self.config_dlg_store()
			self.save_options()
			self.clear_dirty()
		elif (response_id == gtk.RESPONSE_REJECT):
			self.config_dlg.destroy()
		elif (response_id == self.CONFIG_DLG_RESPONSE_DELETE):
			os.remove(self.config_path( self.current_service))
			i = self.services.index(self.current_service)
			self.services.remove(self.current_service)
			self.service_menu.remove_text(i)
			self.config_dlg.destroy()
			

	def config_dlg_load(self):
	# Advanced
		if (self.get_option("Advanced", "Disable TCP no-delay") == "true"):
			self.tcp.set_active(True)
		else:
			self.tcp.set_active(False)
		if (self.get_option("Advanced", "Disable ZLIB stream compression") == "true"):
			self.zlib.set_active(True)
		else:
			self.zlib.set_active(False)
		if (self.get_option("Advanced", "Enable SSL encryption") == "true"):
			self.ssl.set_active(True)
		else:
			self.ssl.set_active(False)
		if (self.get_option("Advanced", "Cache size") != ''):
		   cache = self.get_option("Advanced", "Cache size") 
		   i = self.CACHE_CODES.index(cache)
		   if (i > -1):
			self.cache.set_active(i)
		if (self.get_option("Advanced", "Cache size on disk") != ''):
		   cache = self.get_option("Advanced", "Cache size on disk") 
		   i = self.DISK_CACHE_CODES.index(cache)
		   if (i > -1):
			self.disk_cache.set_active(i)
		if (self.get_option("Advanced", "Current keyboard") == "false"):
			self.keyboard_other.set_active(True)
		else:
			self.keyboard_current.set_active(True)
			self.toggle_config_keyboard(self.keyboard_current)
		if (self.get_option("Advanced", "Custom keyboard layout") != ''):
		   layout = self.get_option("Advanced", "Custom keyboard layout") 
		   i = self.KEYBOARD_CODES.index(layout)
		   if (i > -1):
			self.keyboards.set_active(i)
			
	# General
		self.host.set_text(self.get_option("General", "Server host"))
		self.port.set_text(self.get_option("General", "Server port"))
		if (self.get_option("General", "Remember password") == "true"):
			self.remember.set_active(True)
		else:
			self.remember.set_active(False)
		ses = self.get_option("General", "Session")
		dt = self.get_option("General", "Desktop")
		self.combo_select(self.session, self.SESSION_TYPES, ses)
		if (ses == 'Unix'):
			self.combo_select(self.desktop, self.UNIX_DESKTOPS, dt)
		self.combo_select(self.link_speed, self.LINK_SPEEDS, self.get_option("General", "Link speed"))
		self.combo_select(self.resolution, self.DISPLAY_RES, self.get_option("General", "Resolution"))
		if (self.get_option("General","Resolution width") != ''):
			self.resolution_width.set_value(int(self.get_option("General","Resolution width")))
		if (self.get_option("General","Resolution height") != ''):
			self.resolution_height.set_value(int(self.get_option("General","Resolution height")))
		if (self.get_option("General", "Use default image encoding") == "1"):
			self.encoding_custom.set_active(True)
		else:
			self.encoding_default.set_active(True)
			self.toggle_config_encoding(self.encoding_default)
		self.clear_dirty()

	def config_dlg_store(self):
	# Advanced
		if (self.tcp.get_active()):
			cvalue = "true"
		else:
			cvalue = "false"
		self.set_option("Advanced", "Disable TCP no-delay", cvalue)
		if (self.zlib.get_active()):
			cvalue = "true"
		else:
			cvalue = "false"
		self.set_option("Advanced", "Disable ZLIB stream compression", cvalue)
		if (self.ssl.get_active()):
			cvalue = "true"
		else:
			cvalue = "false"
		self.set_option("Advanced", "Enable SSL encryption", cvalue)
		if (self.cache.get_active() > -1):
			self.set_option("Advanced", "Cache size", self.CACHE_CODES[self.cache.get_active()])
		else:
			self.set_option("Advanced", "Cache size", '')
		if (self.disk_cache.get_active() > -1):
			self.set_option("Advanced", "Cache size on disk", self.DISK_CACHE_CODES[self.cache.get_active()])
		else:
			self.set_option("Advanced", "Cache size on disk", '')
		if (self.keyboard_current.get_active() == True):
			self.set_option("Advanced","Current keyboard","true")
		else:
			self.set_option("Advanced","Current keyboard","false")
		if (self.keyboards.get_active() > -1):
			self.set_option("Advanced", "Custom keyboard layout", self.KEYBOARD_CODES[self.keyboards.get_active()])
		else:
			self.set_option("Advanced", "Custom keyboard layout", '')

	# Login
		self.set_option("Login", "User", self.user.get_text())
		self.set_option("Login", "ClearPassword", self.passw.get_text())
	# General
		self.set_option("General", "Server host", self.host.get_text())
		self.set_option("General", "Server port", self.port.get_text())
		
		if (self.remember.get_active()):
			remembervalue = "true"
		else:
			remembervalue = "false"
		self.set_option("General", "Remember password", remembervalue)
		if (self.session.get_active() > -1):
			ses = self.SESSION_TYPES[self.session.get_active()]
			self.set_option("General", "Session", ses)
			if (ses == 'Unix'):
				self.set_option("General", "Desktop", self.UNIX_DESKTOPS[self.desktop.get_active()])
			elif (ses == 'Windows'):
				self.set_option("General", "Desktop", "RDP")
			elif (ses == 'VNC'):
				self.set_option("General", "Desktop", "RFB")
		else:
			self.set_option("General", "Session", '')
			self.set_option("General", "Desktop", '')
		if (self.link_speed.get_active() > -1):
			self.set_option("General", "Link speed", self.LINK_SPEEDS[self.link_speed.get_active()])
		else:
			self.set_option("General", "Link speed", '')
		if (self.resolution.get_active() > -1):
			self.set_option("General", "Resolution", self.DISPLAY_RES[self.resolution.get_active()])
		else:
			self.set_option("General", "Resolution", '')
		self.set_option("General","Resolution width", str(self.resolution_width.get_value_as_int()))	
		self.set_option("General","Resolution height", str(self.resolution_height.get_value_as_int()))	
		if (self.encoding_custom.get_active() == True):
			self.set_option("General","Use default image encoding","1")
		else:
			self.set_option("General","Use default image encoding","0")
	
	def settings(self, widget=None):
		ses = self.SESSION_TYPES[self.session.get_active()]
		if (ses == "Unix"):
			self.settings_unix(widget)
		elif (ses == "VNC"):
			self.settings_vnc(widget)
		elif (ses == "Windows"):
			self.settings_win(widget)
		
	def settings_unix(self, widget=None):
	# Settings
		self.settings_dlg = gtk.Dialog("Custom - Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.settings_dlg.connect("response", self.settings_unix_dlg_do_response)
		MainBox = self.settings_dlg.vbox
                contentframe = gtk.Frame("Application")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.app_console = gtk.RadioButton(label='Run console')
		hbox.pack_start(self.app_console, False, False, 5)
		self.app_console.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.app_default = gtk.RadioButton(self.app_console, 'Run default X client script on server')
                hbox.pack_start(self.app_default, False, False, 5)
	        self.app_default.connect('toggled', self.toggle_settings_unix_app)
		self.app_default.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.app_command = gtk.RadioButton(self.app_console, 'Run the following command')
	        self.app_command.connect('toggled', self.toggle_settings_unix_app)
                hbox.pack_start(self.app_command, False, False, 5)
		self.app_command.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.app_command_value = gtk.Entry(0)
                self.app_command_value.set_size_request(200,22)
                hbox.pack_start(self.app_command_value, False, False, 20)
		self.app_command_value.show()
                contentframe = gtk.Frame("Options")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.options_float = gtk.RadioButton(label='Floating window')
		hbox.pack_start(self.options_float, False, False, 5)
		self.options_float.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.options_taint = gtk.CheckButton("Disable taint of X replies")
		hbox.pack_start(self.options_taint, False, False, 20)
		self.options_taint.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.options_new = gtk.RadioButton(self.options_float, 'New virtual desktop')
                hbox.pack_start(self.options_new, False, False, 5)
	        self.options_new.connect('toggled', self.toggle_settings_unix_options)
		self.options_new.show()

		self.settings_unix_dlg_load()
		self.settings_dlg.show()

	def toggle_settings_unix_app(self, radio):
		self.app_command_value.set_sensitive(self.app_command.get_active())

	def toggle_settings_unix_options(self, radio):
		self.options_taint.set_sensitive(self.options_float.get_active())
		
	def settings_unix_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.settings_unix_dlg_store()
			self.do_dirty()
			self.change_config_desktop(self.desktop)
		self.settings_dlg.destroy()
			
	def settings_unix_dlg_load(self):
		if (self.get_option("General", "Only console") == "true"):
			self.app_console.set_active(True)
		elif (self.get_option("General", "Run default script") == "true"):
			self.app_default.set_active(True)
		else:
			self.app_command.set_active(True)
		self.toggle_settings_unix_app(self.app_console)
		self.app_command_value.set_text(self.get_option("General", "Command line"))
		if (self.get_option("General", "Virtual desktop") == "true"):
			self.options_new.set_active(True)
		if (self.get_option("General", "Use taint") == "true"):
			self.options_taint.set_active(True)
		

	def settings_unix_dlg_store(self):
		if (self.app_console.get_active() == True):
			self.set_option("General","Only console","true")
		else:
			self.set_option("General","Only console","false")
		if (self.app_default.get_active() == True):
			self.set_option("General","Run default script","true")
		else:
			self.set_option("General","Run default script","false")
		self.set_option("General", "Command line", self.app_command_value.get_text())
		if (self.options_new.get_active() == True):
			self.set_option("General","Virtual desktop","true")
		else:
			self.set_option("General","Virtual desktop","false")
		if (self.options_taint.get_active() == True):
			self.set_option("General","Use taint","true")
		else:
			self.set_option("General","Use taint","false")

	def settings_vnc(self, widget=None):
	# Settings
		self.settings_dlg = gtk.Dialog("Custom - Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.settings_dlg.connect("response", self.settings_vnc_dlg_do_response)
		MainBox = self.settings_dlg.vbox
                contentframe = gtk.Frame("Server")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Please specify the name and the display number of the VNC computer connected to the NX server')
		label.set_line_wrap(True)
		hbox.pack_start(label, False, False, 5)
		label.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Host:')
		hbox.pack_start(label, False, False, 5)
		label.show()
                self.vnc_host = gtk.Entry(0)
                self.vnc_host.set_size_request(200,22)
                hbox.pack_start(self.vnc_host, False, False, 5)
		self.vnc_host.show()
                label = gtk.Label(':')
		hbox.pack_start(label, False, False, 5)
		label.show()
                self.vnc_display = gtk.Entry(0)
                self.vnc_display.set_size_request(65,22)
		self.vnc_display.set_max_length(5)
                hbox.pack_start(self.vnc_display, False, False, 5)
		self.vnc_display.show()
                contentframe = gtk.Frame("Authentication")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Please specify a password.  NX will use it to login to the remote VNC server')
		label.set_line_wrap(True)
		hbox.pack_start(label, False, False, 5)
		label.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.vnc_passw = gtk.Entry(0)
		self.vnc_passw.set_visibility(False)
                self.vnc_passw.set_size_request(380,22)
                hbox.pack_start(self.vnc_passw, False, False, 5)
		self.vnc_passw.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.vnc_remember = gtk.CheckButton("Remember my password")
		hbox.pack_start(self.vnc_remember, False, False, 5)
		self.vnc_remember.show()
		
		self.settings_vnc_dlg_load()
		self.settings_dlg.show()

	def settings_vnc_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.settings_vnc_dlg_store()
			self.do_dirty()
		self.settings_dlg.destroy()

	def settings_vnc_dlg_load(self):
		self.vnc_host.set_text(self.get_option("VNC Session", "Server"));
		self.vnc_display.set_text(self.get_option("VNC Session", "Display"));
		if (self.get_option("VNC Session", "Remember") == "true"):
			self.vnc_passw.set_text(self.get_option("VNC Session", "Password"));
			self.vnc_remember.set_active(True)

	def settings_vnc_dlg_store(self):
		self.set_option("VNC Session","Server",self.vnc_host.get_text())
		self.set_option("VNC Session","Display",self.vnc_display.get_text())
		if (self.vnc_remember.get_active() == True):
			self.set_option("VNC Session","Password",self.vnc_passw.get_text())
			self.set_option("VNC Session","Remember","true")			
		else:
			self.set_option("VNC Session","Password","")
			self.set_option("VNC Session","Remember","false")			

	def settings_win(self, widget=None):
	# Settings
		self.settings_dlg = gtk.Dialog("Windows - Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.settings_dlg.connect("response", self.settings_win_dlg_do_response)
		MainBox = self.settings_dlg.vbox
                contentframe = gtk.Frame("Windows Terminal Server")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Please specify the name of the Windows computer connected to the NX server')
		label.set_line_wrap(True)
		hbox.pack_start(label, False, False, 5)
		label.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_host = gtk.Entry(0)
                self.win_host.set_size_request(380,22)
                hbox.pack_start(self.win_host, False, False, 5)
		self.win_host.show()
                contentframe = gtk.Frame("Authentication")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_creds = gtk.RadioButton(label='Use the following credentials')
	        self.win_creds.connect('toggled', self.toggle_settings_win_auth)
		hbox.pack_start(self.win_creds, False, False, 5)
		self.win_creds.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Username:')
		hbox.pack_start(label, False, False, 20)
		label.show()
                self.win_user = gtk.Entry(0)
                self.win_user.set_size_request(200,22)
                hbox.pack_start(self.win_user, False, False, 5)
		self.win_user.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                label = gtk.Label('Password: ')
		hbox.pack_start(label, False, False, 20)
		label.show()
                self.win_passw = gtk.Entry(0)
		self.win_passw.set_visibility(False)
                self.win_passw.set_size_request(200,22)
                hbox.pack_start(self.win_passw, False, False, 5)
		self.win_passw.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_remember = gtk.CheckButton("Remember my password")
		hbox.pack_start(self.win_remember, False, False, 80)
		self.win_remember.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_login = gtk.RadioButton(self.win_creds,'Show the Windows login screen')
	        self.win_login.connect('toggled', self.toggle_settings_win_auth)
		hbox.pack_start(self.win_login, False, False, 5)
		self.win_login.show()
                contentframe = gtk.Frame("Session Type")
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_desktop = gtk.RadioButton(label='Run desktop')
	        self.win_desktop.connect('toggled', self.toggle_settings_win_ses)
		hbox.pack_start(self.win_desktop, False, False, 5)
		self.win_desktop.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_app = gtk.RadioButton(self.win_desktop,'Run application')
	        self.win_login.connect('toggled', self.toggle_settings_win_ses)
		hbox.pack_start(self.win_app, False, False, 5)
		self.win_app.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.win_app_entry = gtk.Entry(0)
                self.win_app_entry.set_size_request(360,22)
                hbox.pack_start(self.win_app_entry, False, False, 20)
		self.win_app_entry.show()
		
		self.settings_win_dlg_load()
		self.settings_dlg.show()

	def toggle_settings_win_auth(self, radio):
		if (self.win_creds.get_active() == True):
			self.win_user.set_sensitive(True)
			self.win_passw.set_sensitive(True)
			self.win_remember.set_sensitive(True)
		else:
			self.win_user.set_sensitive(False)
			self.win_passw.set_sensitive(False)
			self.win_remember.set_sensitive(False)

	def toggle_settings_win_ses(self, radio):
		if (self.win_app.get_active() == True):
			self.win_app_entry.set_sensitive(True)
		else:
			self.win_app_entry.set_sensitive(False)

	def settings_win_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.settings_win_dlg_store()
			self.do_dirty()
		self.settings_dlg.destroy()

	def settings_win_dlg_load(self):
		self.win_host.set_text(self.get_option("Windows Session", "Server"));
		self.win_user.set_text(self.get_option("Windows Session", "User"));
		if (self.get_option("Windows Session", "Remember") == "true"):
			self.win_passw.set_text(self.get_option("Windows Session", "Password"));
			self.win_remember.set_active(True)
		if (self.get_option("Windows Session","Authentication") == "0"):
			self.win_creds.set_active(True)
		else:
			self.win_login.set_active(True)
		self.win_app_entry.set_sensitive(False)
		if (self.get_option("Windows Session","Run application") == "true"):
			self.win_app.set_active(True)
		else:
			self.win_desktop.set_active(True)
		self.win_app_entry.set_text(self.get_option("Windows Session", "Application"));

	def settings_win_dlg_store(self):
		self.set_option("Windows Session","Server",self.win_host.get_text())
		self.set_option("Windows Session","User",self.win_user.get_text())
		if (self.win_creds.get_active() == True):
			self.set_option("Windows Session","Authentication","0")
		else:
			self.set_option("Windows Session","Authentication","1")
		if (self.win_remember.get_active() == True):
			self.set_option("Windows Session","Password",self.win_passw.get_text())
			self.set_option("Windows Session","Remember","true")			
		else:
			self.set_option("Windows Session","Password","")
			self.set_option("Windows Session","Remember","false")
		if (self.win_app.get_active() == True):
			self.set_option("Windows Session","Run application","true")
		else:
			self.set_option("Windows Session","Run application","false")
		self.set_option("Windows Session","Application",self.win_app_entry.get_text())



	def custom(self, widget=None):
		ses = self.SESSION_TYPES[self.session.get_active()]
		if (ses == "Unix"):
			self.custom_unix(widget)
		elif (ses == "VNC"):
			self.custom_vnc(widget)
		elif (ses == "Windows"):
			self.custom_win(widget)
		

	def custom_unix(self, widget=None):
	# Custom
		self.custom_dlg = gtk.Dialog("Unix - Display Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.custom_dlg.connect("response", self.custom_unix_dlg_do_response)
		MainBox = self.custom_dlg.vbox
                contentframe = gtk.Frame("Encoding")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_jpeg = gtk.RadioButton(label='Use JPEG image compression')
	        self.encoding_jpeg.connect('toggled', self.toggle_custom_unix_encoding)
		hbox.pack_start(self.encoding_jpeg, False, False, 5)
		self.encoding_jpeg.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_custom = gtk.CheckButton("Use custom image quality")
	        self.encoding_custom.connect('toggled', self.toggle_custom_unix_encoding)
		hbox.pack_start(self.encoding_custom, False, False, 20)
		self.encoding_custom.show()		
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
		self.adj = gtk.Adjustment(upper=9, step_incr=1)
                self.encoding_custom_scale = gtk.HScale(self.adj)
		self.encoding_custom_scale.set_digits(0)
		hbox.pack_start(self.encoding_custom_scale, True, True, 30)
		self.encoding_custom_scale.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_png = gtk.RadioButton(self.encoding_jpeg, 'Use PNG image compression')
                hbox.pack_start(self.encoding_png, False, False, 5)
	        self.encoding_png.connect('toggled', self.toggle_custom_unix_encoding)
		self.encoding_png.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_plain = gtk.RadioButton(self.encoding_jpeg, 'Use plain X bitmaps')
	        self.encoding_plain.connect('toggled', self.toggle_custom_unix_encoding)
                hbox.pack_start(self.encoding_plain, False, False, 5)
		self.encoding_plain.show()
                contentframe = gtk.Frame("Render")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.render = gtk.CheckButton("Disable render extension")
		hbox.pack_start(self.render, False, False, 5)
		self.render.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()

		self.custom_unix_dlg_load()
		self.custom_dlg.show()

	def toggle_custom_unix_encoding(self, radio):
		if (self.encoding_jpeg.get_active() == True):
			self.encoding_custom.set_sensitive(True)
			if (self.encoding_custom.get_active() == True):
				self.encoding_custom_scale.set_sensitive(True)
			else:
				self.encoding_custom_scale.set_sensitive(False)
		else:
			self.encoding_custom_scale.set_sensitive(False)
			self.encoding_custom.set_sensitive(False)
	
	def custom_unix_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.custom_unix_dlg_store()
			self.do_dirty()
		self.custom_dlg.destroy()

	def custom_unix_dlg_load(self):
		if (self.get_option("General", "Use render") == "false"):
			self.render.set_active(True)
		ict = self.get_option("Images", "Image Compression Type")
		if (ict == "1"):
			self.encoding_jpeg.set_active(True)
			self.encoding_custom.set_active(True)
#			self.encoding_png.set_active(False)
#			self.encoding_plain.set_active(False)
		elif (ict == "2"):
			if (self.get_option("Images","Use PNG Compression") == "true"):
#				self.encoding_jpeg.set_active(False)
				self.encoding_custom.set_active(False)
				self.encoding_png.set_active(True)
#				self.encoding_plain.set_active(False)
			else:
#				self.encoding_jpeg.set_active(False)
				self.encoding_custom.set_active(False)
#				self.encoding_png.set_active(False)
				self.encoding_plain.set_active(True)
		else:
			self.encoding_jpeg.set_active(True)
			self.encoding_custom.set_active(False)
#			self.encoding_png.set_active(False)
#			self.encoding_plain.set_active(False)
			self.encoding_plain.set_active(False)
		if (self.get_option("Images","JPEG Quality") != ''):
			self.encoding_custom_scale.set_value(int(self.get_option("Images","JPEG Quality")))


	def custom_unix_dlg_store(self):
		if (self.render.get_active() == True):
			self.set_option("General","Use render","false")
		else:
			self.set_option("General","Use render","true")
		if (self.encoding_jpeg.get_active() == True):
			if (self.encoding_custom.get_active() == True):
				self.set_option("Images", "Image Compression Type", "1")
				self.set_option("Images", "Use PNG Compression", "false")
			else:
				self.set_option("Images", "Image Compression Type", "0")
				self.set_option("Images", "Use PNG Compression", "false")
		elif (self.encoding_png.get_active() == True):
			self.set_option("Images", "Image Compression Type", "2")
			self.set_option("Images", "Use PNG Compression", "true")
		else:		
			self.set_option("Images", "Image Compression Type", "2")
			self.set_option("Images", "Use PNG Compression", "false")
		self.set_option("Images", "JPEG Quality", str(int(self.encoding_custom_scale.get_value())))

	def custom_vnc(self, widget=None):
	# Custom
		self.custom_dlg = gtk.Dialog("VNC - Display Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.custom_dlg.connect("response", self.custom_vnc_dlg_do_response)
		MainBox = self.custom_dlg.vbox
                contentframe = gtk.Frame("Encoding")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_hextile = gtk.RadioButton(label='Use RFB Hextile encoding')
	        self.encoding_hextile.connect('toggled', self.toggle_custom_vnc_encoding)
		hbox.pack_start(self.encoding_hextile, False, False, 5)
		self.encoding_hextile.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_tight = gtk.RadioButton(self.encoding_hextile, 'Use RFB Tight encoding')
                hbox.pack_start(self.encoding_tight, False, False, 5)
	        self.encoding_tight.connect('toggled', self.toggle_custom_vnc_encoding)
		self.encoding_tight.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_vnc_jpeg = gtk.CheckButton("Enable JPEG encoding")
		hbox.pack_start(self.encoding_vnc_jpeg, False, False, 20)
		self.encoding_vnc_jpeg.show()		
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_vnc_plain = gtk.RadioButton(self.encoding_hextile, 'Use X plain bitmaps')
	        self.encoding_vnc_plain.connect('toggled', self.toggle_custom_vnc_encoding)
                hbox.pack_start(self.encoding_vnc_plain, False, False, 5)
		self.encoding_vnc_plain.show()

		self.custom_vnc_dlg_load()
		self.custom_dlg.show()

	def toggle_custom_vnc_encoding(self, radio):
		if (self.encoding_tight.get_active() == True):
			self.encoding_vnc_jpeg.set_sensitive(True)
		else:
			self.encoding_vnc_jpeg.set_sensitive(False)

	def custom_vnc_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			print "storing custom vnc"
			self.custom_vnc_dlg_store()
			self.do_dirty()
		self.custom_dlg.destroy()


	def custom_vnc_dlg_load(self):
		self.encoding_vnc_jpeg.set_sensitive(False)
		if (self.get_option("Images", "Image JPEG Encoding") == "true"):
			self.encoding_vnc_jpeg.set_active(True)
		ict = self.get_option("Images", "Image Encoding Type")
		if (ict == "1"):
			self.encoding_tight.set_active(True)
		elif (ict == "2"):
			self.encoding_vnc_plain.set_active(True)
		else:
			self.encoding_hextile.set_active(True)
			self.encoding_custom.set_active(False)

	def custom_vnc_dlg_store(self):
		if (self.encoding_vnc_jpeg.get_active() == True):
			self.set_option("Images","Image JPEG Encoding","true")
		else:
			self.set_option("Images","Image JPEG Encoding","false")
		if (self.encoding_tight.get_active() == True):
			self.set_option("Images", "Image Encoding Type", "1")
		elif (self.encoding_vnc_plain.get_active() == True):
			self.set_option("Images", "Image Encoding Type", "2")
		else:		
			self.set_option("Images", "Image Encoding Type", "0")

	def custom_win(self, widget=None):
	# Custom
		self.custom_dlg = gtk.Dialog("Windows - Display Settings", self.config_dlg,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK,gtk.RESPONSE_OK,gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL))
		self.custom_dlg.connect("response", self.custom_win_dlg_do_response)
		MainBox = self.custom_dlg.vbox
                contentframe = gtk.Frame("Encoding")
                contentframe.set_border_width(4)
                MainBox.pack_start(contentframe, False, False, 5)
		contentframe.show()
                vb = gtk.VBox(False, 8)
                vb.set_border_width(6)
                contentframe.add(vb)
		vb.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_rdp = gtk.RadioButton(None, 'Use RDP image encoding')
                hbox.pack_start(self.encoding_rdp, False, False, 5)
	        self.encoding_rdp.connect('toggled', self.toggle_custom_win_encoding)
		self.encoding_rdp.show()
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_win_bitmaps = gtk.CheckButton("Use compressed RDP bitmaps")
		hbox.pack_start(self.encoding_win_bitmaps, False, False, 20)
		self.encoding_win_bitmaps.show()		
                hbox = gtk.HBox(False, 5)
                vb.pack_start(hbox, False, False, 5)
		hbox.show()
                self.encoding_win_plain = gtk.RadioButton(self.encoding_rdp, 'Use X plain bitmaps')
	        self.encoding_win_plain.connect('toggled', self.toggle_custom_win_encoding)
                hbox.pack_start(self.encoding_win_plain, False, False, 5)
		self.encoding_win_plain.show()

		self.custom_win_dlg_load()
		self.custom_dlg.show()

	def toggle_custom_win_encoding(self, radio):
		if (self.encoding_rdp.get_active() == True):
			self.encoding_win_bitmaps.set_sensitive(True)
		else:
			self.encoding_win_bitmaps.set_sensitive(False)

	def custom_win_dlg_do_response(self, dialog, response_id):
		if (response_id == gtk.RESPONSE_OK):
			self.custom_win_dlg_store()
			self.do_dirty()
		self.custom_dlg.destroy()


	def custom_win_dlg_load(self):
		self.encoding_win_bitmaps.set_sensitive(True)
		wic = self.get_option("Images", "Windows Image Compression")
		if (wic == "2"):
			self.encoding_rdp.set_active(True)
			self.encoding_win_bitmaps.set_active(True)
		elif (wic == "1"):
			self.encoding_win_bitmaps.set_active(True)
			self.encoding_win_plain.set_active(True)
		else:
			self.encoding_rdp.set_active(True)
			self.encoding_win_bitmaps.set_active(False)

	def custom_win_dlg_store(self):
		if ((self.encoding_win_bitmaps.get_active() == True) and (self.encoding_rdp.get_active() == True)):
			self.set_option("Images", "Windows Image Compression", "2")
		elif (self.encoding_win_plain.get_active() == True):
			self.set_option("Images", "Windows Image Compression", "1")
		else:		
			self.set_option("Images", "Windows Image Compression", "0")


        def run(self, widget):
	# Status
		self.statuswindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.statuswindow.set_transient_for(self.window)
	        self.statuswindow.set_title("NXRUN GUI Status")
	        self.statuswindow.set_border_width(5)
		self.statuswindow.set_position(gtk.WIN_POS_CENTER)
	        self.statuswindow.set_resizable(False)
		MainBox = gtk.VBox(False, self.DEF_PAD)
		self.statuswindow.add(MainBox)
                hbox = gtk.HBox(False, 5)
                MainBox.pack_start(hbox, False, False, 5)
                self.statuslabel = gtk.Label("Status                                           ")
                hbox.pack_start(self.statuslabel, False, False, 5)
	        bbox = gtk.HButtonBox ()
	        MainBox.pack_start(bbox, False, False, 0)
	        bbox.set_layout(gtk.BUTTONBOX_END)

	        detailsbutton = gtk.Button("details")
		detailsbutton.set_state(gtk.STATE_INSENSITIVE)
		bbox.add(detailsbutton)
	        cancel_button = gtk.Button("Cancel",gtk.STOCK_CANCEL)
	        bbox.add(cancel_button)

	        cancel_button.set_flags(gtk.CAN_DEFAULT)
	        cancel_button.grab_default()
		self.window.hide()
		self.statuswindow.show_all()
		self.statuswindow.grab_add()
		gtk.main_iteration(False)
		cmd = ["./nxrun"]
		if self.current_service != "":
			cmd.append(self.config_path(self.current_service))
		cmd.append("-u")
		cmd.append(self.user.get_text())
		cmd.append("-p")
		cmd.append(self.passw.get_text())
		p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
                self.so = p.stdout
		if (self.timer):
			gobject.source_remove(self.timer)
			self.timer = 0
		self.timer = gobject.timeout_add(100, progress_timeout, self)		
		

	def load_options(self):
		if os.path.isfile(self.config_path( self.current_service)):
			self.options = {}				
			try:
				xmldoc = minidom.parse(self.config_path	(self.current_service))
			except:
				return False
			else:
				tags = xmldoc.getElementsByTagName("group");
				for tag in tags:	
					options = tag.getElementsByTagName("option")
					for option in options:
						self.set_option(tag.getAttribute("name"), option.getAttribute("key"), option.getAttribute("value"))
						
				return True
		else:
			return False

	def save_options(self,service=None):
	# Root
		conf_tree = minidom.Document()
		root_node = conf_tree.createElement("NXClientSettings")
		root_node.setAttribute("application", "nxclient")
		root_node.setAttribute("version", "1.4.0")
		self.groups = {}
	# options
		k = self.options.keys()
		for key in k:
			self.save_groupoption(conf_tree, root_node,key[0], key[1], self.options[key])
	# Save
		if (service == None):
			service = self.current_service
		conf_tree.appendChild(root_node)
		FD = open("./config/" + service, "w")
		FD.write(conf_tree.toprettyxml())
		FD.close()
		

	def save_groupoption(self, tree, root, name, key, value):
		# First check if the group exists
		if self.groups.has_key(name):
			group_node = self.groups[name]
		else:
		# if not create it
			group_node = self.save_group(tree, root, name)
			self.groups[name] = group_node
		# create the option
		self.save_option(tree, group_node, key, value)
		
	def save_group(self, tree, root, name):
		node = tree.createElement("group")
		node.setAttribute("name", name)
		root.appendChild(node)
		return node
		
	
	def save_option(self, tree, node, key, value):
		option_node = tree.createElement("option")
		option_node.setAttribute("key", key)
		option_node.setAttribute("value", value)
		node.appendChild(option_node)

	def get_option(self, group, key):
		if self.options.has_key((group, key)):
			return self.options[(group, key)]
		else:
			return ""
		
	def set_option(self, group, key, value):
		option = group + ":" + key
		self.options[(group,key)] = value
	
		
	def main(self):
		gtk.main()

if __name__ == "__main__":
	nxrungui = nxrungui()
	nxrungui.main()
	
