#!/usr/bin/python

#TODO, when quitting kill off the forever process by communicating with it....will require it to become a class

#import subprocess
#import os
import sys
import signal
import gtk
import gtk.glade
import gobject
import pwd
import string
import studentcontrolpanel.ltcm as ltcm
from studentcontrolpanel.vnc import VNC
import studentcontrolpanel.tcmplugins as tcmplugins
import thread
import time

class ControlPanel:
    oldlist = ""
    user = []
    myip = "127.0.0.1"

    def __init__(self):
        """
        Draw the main window and fill the list/treestores
        """        


	self.disconnected_vnc = gtk.gdk.pixbuf_new_from_file("/usr/share/student-control-panel/disconnected.png")
	self.vnc={}
	self.ufilter = None
        self.filtering = False
        self.wTree=gtk.glade.XML ("/usr/share/student-control-panel/student-control-panel.glade")
        self.win = self.wTree.get_widget("window")

	if not ltcm.check_uid():
            self.win.set_sensitive(False)
            dialog = gtk.MessageDialog(self.win,
                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
					gtk.MESSAGE_ERROR, gtk.BUTTONS_CANCEL, None)
            dialog.set_markup('<big><b>This tool needs administrative system access</b>\nPlease run it with sudo or gksudo</big>')
            resp = dialog.run()
            if resp:
				sys.exit(1)

	self.testing = ltcm.backend()
	self.command = self.wTree.get_widget("command")
	self.message = self.wTree.get_widget("message")
	self.addgroup = self.wTree.get_widget("addgroup")
	self.vnc_offset = 0
        self.win.connect("destroy", lambda w: gtk.main_quit())
#        for a in range(4):
#		self.wTree.get_widget("vnc" + str(a)).set_from_pixbuf(self.disconnected_vnc)
        # check if we have root rights exit if not 


	self.cur_user = ''

	#Here we can quickly set the remote business
        self.remote = None
	if self.remote:
		self.testing.open_forever_socket(self.remote)            
        #self.vnc = self.wTree.get_widget("vncbutton")
        #self.vnc.set_sensitive(False)
	#self.vnc.connect("clicked", lambda w: self.vnc_conn(treeselection))
        
        self.execute = self.wTree.get_widget("exec")
        self.execute.connect("clicked", lambda w: self.start_app(treeselection))

	self.command_ok = self.wTree.get_widget('command_ok')
	self.command_cancel = self.wTree.get_widget('command_cancel')

	self.command_ok.connect("clicked", lambda w: self.comm_ok(treeselection))
	self.command_cancel.connect("clicked", lambda w: self.comm_cancel())
        
	self.command.connect("delete_event", self.comm_cancel)

	self.addgroup_ok = self.wTree.get_widget('addgroup_ok')
	self.addgroup_cancel = self.wTree.get_widget('addgroup_cancel')

	self.addgroup_ok.connect("clicked", lambda w: self.addgroup_ok_f(treeselection))
	self.addgroup_cancel.connect("clicked", lambda w: self.addgroup_cancel_f())
        
	self.addgroup.connect("delete_event", self.addgroup_cancel_f)

        self.smess = self.wTree.get_widget("mess")
        self.smess.connect("clicked", lambda w: self.send_mess(treeselection))

	self.message_ok = self.wTree.get_widget('message_ok')
	self.message_cancel = self.wTree.get_widget('message_cancel')

	self.message_ok.connect("clicked", lambda w: self.mess_ok(treeselection))
	self.message_cancel.connect("clicked", lambda w: self.mess_cancel())
        
	self.message.connect("delete_event", self.mess_cancel)

	self.message.hide_all()

	self.share = self.wTree.get_widget("share")
	self.share.connect("clicked", lambda w: self.make_share(treeselection))

	self.control = self.wTree.get_widget("control")
	self.control.connect("clicked", lambda w: self.make_control(treeselection))

	self.remote_conn = self.wTree.get_widget("remote")
	self.remote_conn.connect("clicked", self.remote_call)

	self.blank = self.wTree.get_widget("blank")
	self.blank.connect("clicked", lambda w: self.make_blank(treeselection))

	self.unblank = self.wTree.get_widget("unblank")
	self.unblank.connect("clicked", lambda w: self.make_unblank(treeselection))

	self.vncprev = self.wTree.get_widget("vncprev")
	self.vncprev.connect("clicked", self.butvncnext)

	self.vncnext = self.wTree.get_widget("vncnext")
	self.vncnext.connect("clicked", self.butvncnext)

	self.vncrefresh = self.wTree.get_widget("vncrefresh")
	self.vncrefresh.connect("clicked", self.butvncnext)
        
        self.logout = self.wTree.get_widget("logout")
        
        self.userlist = self.wTree.get_widget("studenttree")
        self.userlist.set_property('headers_visible', False)
        self.userlist.set_property('rules_hint', True)
        treeselection = self.userlist.get_selection()
        treeselection.set_mode(gtk.SELECTION_MULTIPLE)
	
	self.notebook = self.wTree.get_widget('notebook1')
	self.notebook.connect("switch_page", self.check_tab)

        self.logout.connect("clicked", lambda w: self.logout_user(treeselection))
        #self.vnc.connect("clicked", lambda w: self.vnc_conn(treeselection))
        treeselection.connect("changed", lambda w: self.populate_procs(treeselection, False))
        
        self.liststore = gtk.ListStore(str, str, 'gboolean')
        
        self.userlist.set_model(self.liststore)
        
        text = gtk.CellRendererText()
        pix = gtk.CellRendererPixbuf()
	lock = gtk.CellRendererText()
        
        column = gtk.TreeViewColumn("Students")
        
        column.pack_start(pix, False)
        column.pack_start(text, False)
        
        column.set_attributes(text, markup=1)
        
        self.userlist.append_column(column)
        
        pbuf = gtk.gdk.pixbuf_new_from_file('/usr/share/student-control-panel/nobody.png')
        pix.set_property('pixbuf', pbuf)
        
        self.init_proclist()

	self.kill = self.wTree.get_widget("kill")
	procselection = self.proctree.get_selection()
        #procselection.set_mode(gtk.SELECTION_MULTIPLE)
        self.kill.connect("clicked", lambda w: self.kill_proc(procselection))

	self.gdata = self.testing.readconfig(self.remote)
	self.init_combo()
        gobject.timeout_add(500, lambda: self.populate_list(self.liststore))
	gobject.timeout_add(500, lambda: self.refresh_procs())
        
        self.win.show_all()

	self.userlist.connect("button_press_event", lambda w, y: self.on_treeview_button_press_event(w, y))

        self.menu_items = '''<ui>
    <popup name="Context">
      <menuitem action="Start Application"/>
      <menuitem action="Send Message"/>
      <menuitem action="Lockdown"/>
        <menu action="Plugins">
        </menu>
        <menu action="Groups">
          <menu action="Add to Group">
	  </menu>
          <menu action="Remove from Group">
	  </menu>
          <menuitem action="New Group..."/>
          <menu action="Delete Group">
          </menu>
        </menu>
      <menuitem action="Disconnect"/>
    </popup>
    </ui>'''

        self.actiongroup = gtk.ActionGroup('UIManagerExample')
        self.actiongroup.add_actions([
				('Disconnect', None, '_Disconnect', None,
				'Disconnect', lambda x: self.logout_user(self.userlist.get_selection())),
				('Lockdown', None, '_Lockdown', None,
				'Lockdown', self.lockdown),
				('Start Application', None, '_Start Application', None,
				'Start Application', lambda x: self.start_app(self.userlist.get_selection())),
				('Send Message', None, 'Send _Message', None,
				'Send Message', lambda x: self.send_mess(self.userlist.get_selection())),
				('Plugins', None, '_Plugins'),
				('Groups', None, '_Groups'),
				('Add to Group', None, 'Add to _Group'),
				('Remove from Group', None, 'Remove from _Group'),
				('New Group...', None, 'New _Group...', None,
				'New Group', lambda x: self.new_group(self.userlist.get_selection())),
				('Delete Group', None, 'Delete _Group')
				])
        self.uimanager=gtk.UIManager()
        self.uimanager.insert_action_group(self.actiongroup, 0)
        self.uimanager.add_ui_from_string(self.menu_items)
        self.menubar = self.uimanager.get_widget('/Context')
	self.plugin_list = tcmplugins.register_plugins()
	self.plugin_gui_register()
	self.refresh_menus()


    def start_vnc(self):
	#self.vnc=[]
	self.vnc_t_id=[]
	self.vnc_thread={}
	for a in range(0,4):
		self.wTree.get_widget("vnc_lab"+str(a)).set_text("Unavailable")

	users = self.testing.poll_userlist(self.remote)
	for a in range(0, min(len(users), 4)):
		self.wTree.get_widget("vnc_lab"+str(a)).set_markup("<b>" + users[self.vnc_offset + a][2] + '</b>\n' + users[self.vnc_offset + a][1])
		#self.new_vnc(users, 5900, "vncvnc", a)
		self.vnc_thread[(a)] = thread.start_new_thread(self.new_vnc,(users, 5900, "vncvnc", a))
		gobject.timeout_add(1000, self.start_polling, users, a)
	return

    def start_polling(self, users, a):
	try:
		self.vnc[(a)]
	except KeyError:
		#gobject.timeout_add(1000, self.set_mark, a, "<b>" + users[a][2] + '</b>\n' + users[a][1] + "<span foreground=\"red\"><b>" + '\nUnavailable' + "</b></span>")
		gobject.timeout_add(1000, self.vnc_unavailable, a, users)
		return

	if self.vnc[(a)].vncViewer.is_connected():
		self.vnc[(a)].get_new_image(self.wTree.get_widget("vnc" + str(a)))
		self.vnc_t_id = gobject.timeout_add(5000, self.get_image, a, users[self.vnc_offset + a][1])
		#self.vnc_t_id = gobject.timeout_add(5000, lambda: self.vnc[a].get_new_image(self.wTree.get_widget("vnc" + str(a))))
	else:
		gobject.timeout_add(3000, self.set_mark, a, "<b>" + users[self.vnc_offset + a][2] + '</b>\n' + users[self.vnc_offset + a][1] + "<small><span foreground=\"red\">\n<b>Unavailable</b>\n</span> (Install x11vnc on the client)</small>")
	return

    def vnc_unavailable(self, a, users):
	self.set_mark( a, "<b>" + users[self.vnc_offset + a][2] + '</b>\n' + users[self.vnc_offset + a][1] + "<span foreground=\"red\"><b>" + '\nUnavailable' + "</b></span>")
	self.wTree.get_widget("vnc" + str(a)).set_from_pixbuf(self.disconnected_vnc)
	self.vnc[(a)]=""

    def new_vnc(self, users, port, passw, a):
	self.vnc[(a)] = VNC(self.wTree, users[self.vnc_offset + a][2], port, passw)
	return

    def get_image(self, a, user):
	if not self.vnc[(a)].vncViewer.is_connected():
		self.wTree.get_widget("vnc_lab"+str(a)).set_markup(user + "<span foreground=\"red\"><b>" + '\nUnavailable' + "</b></span>")
		return False
	else:
		self.vnc[(a)].get_new_image(self.wTree.get_widget("vnc" + str(a)))
		return True

    def set_mark(self, a, text):
	self.wTree.get_widget("vnc_lab"+str(a)).set_markup(text)

    def init_combo(self):
	self.conv_combo = self.wTree.get_widget("combobox1")
	self.conv_tree = gtk.ListStore(str)
	self.conv_combo.set_model(self.conv_tree)
	cell = gtk.CellRendererText()
	self.conv_combo.pack_start(cell, True)
	self.conv_combo.add_attribute(cell, "text", 0)
	self.conv_tree.append(["All users"])
	self.conv_combo.set_active(0)
	self.refresh_combo()
	self.conv_combo.connect("changed", self.updatefilter)
	self.populate_list(self.liststore)

    def updatefilter(self, widget):
	if self.conv_combo.get_active() == 0:
		self.ufilter = None
		self.filtering = False
	else:
		key = self.gdata.keys()[self.conv_combo.get_active()-1]
		self.ufilter = self.gdata[(key)]
		self.filtering = True
	self.populate_list(self.liststore)

    def refresh_combo(self):
	self.conv_tree = gtk.ListStore(str)
	self.conv_tree.append(["All users"])
	for key in self.gdata.keys():
		self.conv_tree.append([key])
	self.conv_combo.set_model(self.conv_tree)
	self.conv_combo.set_active(0)

    def refresh_menus(self):
	self.gdata_ui = {}
	self.gdata_ac = {}
	for key in self.gdata.keys():
		self.gdata_ui[(key+"delgrp")] = self.uimanager.new_merge_id()
		self.uimanager.add_ui(self.gdata_ui[(key+"delgrp")],'/Context/Groups/Delete Group', key, key, 'menuitem',False)
		self.gdata_ac[(key+"delgrp")] = gtk.Action(key, key, key, None)
		self.actiongroup.add_action(self.gdata_ac[(key+"delgrp")])
		self.uimanager.get_widget('/Context/Groups/Delete Group/'+key).connect("activate", self.delete_group, key)

		self.gdata_ui[(key+"add2grp")] = self.uimanager.new_merge_id()
		self.uimanager.add_ui(self.gdata_ui[(key+"add2grp")],'/Context/Groups/Add to Group', key, key, 'menuitem',False)
		self.gdata_ac[(key+"add2grp")] = gtk.Action(key, key, key, None)
		self.actiongroup.add_action(self.gdata_ac[(key+"add2grp")])
		self.uimanager.get_widget('/Context/Groups/Add to Group/'+key).connect("activate", self.add_user_to_group, key)

		self.gdata_ui[(key+"rm4grp")] = self.uimanager.new_merge_id()
		self.uimanager.add_ui(self.gdata_ui[(key+"rm4grp")],'/Context/Groups/Remove from Group', key, key, 'menuitem',False)
		self.gdata_ac[(key+"rm4grp")] = gtk.Action(key, key, key, None)
		self.actiongroup.add_action(self.gdata_ac[(key+"rm4grp")])
		self.uimanager.get_widget('/Context/Groups/Remove from Group/'+key).connect("activate", self.remove_user_from_group, key)

    def get_user_list(self, selection):
	paths = []
	users = []
	list, paths = selection.get_selected_rows()[0], selection.get_selected_rows()[1:]
	for row in paths[0]:
             users.append(list[row[0]][1].split('\n')[0].lstrip('<b>').rstrip('</b>'))
	return users

    def remote_call(self, widget):
	remote_button = self.wTree.get_widget("remote")
	if self.remote:
		self.remote = None
		remote_button.set_stock_id("gtk-connect")
	else:
		self.remote = "127.0.0.1"
		remote_button.set_stock_id("gtk-disconnect")

    def plugin_wrapper(self, widget, module, clname):
	tmpcl=getattr(module, clname)
	tmpcl(self.get_user_list(self.userlist.get_selection()))

    def plugin_gui_register(self):
	for plugin in self.plugin_list:	
		self.uimanager.add_ui(self.uimanager.new_merge_id(),'/Context/Plugins', plugin[0], plugin[0], 'menuitem',False)
		self.actiongroup.add_action(gtk.Action(plugin[0], plugin[0], plugin[0], None))
		self.uimanager.get_widget('/Context/Plugins/'+plugin[0]).connect("activate", self.plugin_wrapper, plugin[2], plugin[1])

    def on_treeview_button_press_event(self, treeview, event):
      if len(self.get_user_list(self.userlist.get_selection())) != 1:
	      self.uimanager.get_widget('/Context/Groups/Remove from Group').set_sensitive(False)
	      self.uimanager.get_widget('/Context/Groups/Add to Group').set_sensitive(False)
	      self.uimanager.get_widget('/Context/Lockdown').set_sensitive(False)
      else:
	      self.uimanager.get_widget('/Context/Groups/Remove from Group').set_sensitive(True)
	      self.uimanager.get_widget('/Context/Groups/Add to Group').set_sensitive(True)
	      self.uimanager.get_widget('/Context/Lockdown').set_sensitive(True)
      if event.button == 3:
          x = int(event.x)
          y = int(event.y)
          time = event.time
          pthinfo = treeview.get_path_at_pos(x, y)
          if pthinfo is not None:
              path, col, cellx, celly = pthinfo
              treeview.grab_focus()
              self.menubar.popup( None, None, None, event.button, time)
          return 1

    def lockdown(self, widget):
	user = self.get_user_list(self.userlist.get_selection())[0]
	self.testing.lockdown_user(user, self.remote)

    def check_tab(self, notebook, page, pagenum):
	if pagenum == 0:
		self.disconnect_vnc()	
	if pagenum == 1:
		gobject.timeout_add(5, self.start_vnc)

    def disconnect_vnc(self):
	for a in range(0, 4):
		if self.vnc.has_key(a):
			if self.vnc[(a)]!= "":
				if self.vnc[(a)].vncViewer.is_connected():
					self.vnc[(a)].vncViewer.disconnect_from_host()			

    def populate_list(self, liststore):
        """
        Get the list of running LTSP sessions and 
        (re)populate the gui if the contents changed
        """
        newlist = self.testing.poll_userlist(self.ufilter, self.filtering, self.remote)
    
        if not newlist == self.oldlist:
           liststore.clear()
           for entry in newlist:
               liststore.append([entry[0], '<b>'+entry[1]+'</b>\n'+entry[-1], True])
           self.oldlist = newlist
	self.vnc_buttons()
        return True

    def vnc_buttons(self):
	if self.vnc_offset == 0:
		self.vncprev.set_sensitive(False)
	else:
		self.vncprev.set_sensitive(True)
	if self.vnc_offset + 4 >=  len(self.testing.poll_userlist()):
		self.vncnext.set_sensitive(False)
	else:
		self.vncnext.set_sensitive(True)


    def refresh_procs(self):
	if self.cur_user != '':
	  procselection = self.proctree.get_selection()
	  flag = procselection.count_selected_rows()
          list,paths = procselection.get_selected_rows()[0], procselection.get_selected_rows()[1:]
	  if self.userlist.get_selection().count_selected_rows():
              list = self.testing.poll_proclist(self.cur_user, self.remote)
              self.fill_proclist(self.cur_user, list)
	      if flag:
	         procselection.select_path(paths[0][0])
	return True
    
    def populate_procs(self, selection, flag):
        """
        Get list of runnig processes for user and populate 
        the proctree in the gui if contents changed
        """
        list,paths = selection.get_selected_rows()[0], selection.get_selected_rows()[1:]
    
        userlabel = self.wTree.get_widget("userlabel")
        sys_entry = self.wTree.get_widget("system")
    
        if selection.count_selected_rows():
            user,host = list[paths[0][0]][1].split('\n')
            stripped_user = user.lstrip('<b>').rstrip('</b>')
	    self.cur_user = stripped_user
    
            userlabel.set_markup('<span font_desc="Sans Italic 18" weight="bold">'+user+'</span>')
            sys_entry.set_markup('<span font_desc="Sans Italic 10">'+host+'</span>')
            list = self.testing.poll_proclist(stripped_user, self.remote)
            self.fill_proclist(stripped_user, list)
        #return flag
	return True

    def clear_procs(self):
        userlabel = self.wTree.get_widget("userlabel")
        sys_entry = self.wTree.get_widget("system")
	userlabel.set_markup('<span font_desc="Sans Italic 18" weight="bold">...</span>')
	sys_entry.set_markup('<span font_desc="Sans Italic 10">...</span>')
	self.procstore.clear()

    def init_proclist(self):
        """
        initialize the proctree
        """
        self.proctree = self.wTree.get_widget("proctree")
        self.proctree.set_property('rules_hint', True)
        self.procstore = gtk.ListStore(str, str, str, str)
        self.proctree.set_model(self.procstore)
        
        ppix = gtk.CellRendererPixbuf()
        
        self.proctree.columns = [None]*4
        self.proctree.columns[0] = gtk.TreeViewColumn('Command')
        self.proctree.columns[1] = gtk.TreeViewColumn('CPU')
        self.proctree.columns[2] = gtk.TreeViewColumn('MEM')
        self.proctree.columns[3] = gtk.TreeViewColumn('Status')
        
        self.proctree.columns[0].pack_start(ppix, False)
        self.proctree.columns[0].set_min_width(300)
        
        for n in range(4):
               self.proctree.append_column(self.proctree.columns[n])
               self.proctree.columns[n].cell = gtk.CellRendererText()
               self.proctree.columns[n].pack_start(self.proctree.columns[n].cell, True)
               self.proctree.columns[n].set_attributes(self.proctree.columns[n].cell, text=n)

    def fill_proclist(self, user, list):
        self.procstore.clear()
        for entry in list:
			self.procstore.append([entry[1], entry[2], entry[3], entry[4]])

    def kill_proc(self, selection):
	"""
	Reads the process to be killed from the list and executes the kill command
	"""
        list,paths = selection.get_selected_rows()[0], selection.get_selected_rows()[1:]
	dialog = gtk.MessageDialog(self.win,
				gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
				gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, None)
        dialog.set_markup('<big><b>This will end the selected process any may cause data loss.</b>\nAre you sure you want to do this ?</big>')
		
        self.win.set_sensitive(False)
        dialog.connect("destroy", lambda w: self.win.set_sensitive(True))

        resp = dialog.run()
        if resp:
            if resp == gtk.RESPONSE_OK:
		self.testing.kill_process(list[paths[0][0]][0], self.cur_user, self.remote)
		self.populate_procs(self.userlist.get_selection(), False)
            dialog.destroy()
            
    def start_app(self, selection):
	if selection.count_selected_rows():
		self.command.show_all()
		self.win.set_sensitive(False)
	else:
	   dialog = gtk.MessageDialog(self.win,
				gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
				gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK, None)
           dialog.set_markup('<big><b>You must select a user first</b></big>')
		
           self.win.set_sensitive(False)
           dialog.connect("destroy", lambda w: self.win.set_sensitive(True))

           resp = dialog.run()
           if resp:
              if resp == gtk.RESPONSE_OK:
	   	dialog.destroy()

    def select_user_dialog(self):
	   dialog = gtk.MessageDialog(self.win,
				gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
				gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK, None)
           dialog.set_markup('<big><b>You must select a user first</b></big>')
		
           self.win.set_sensitive(False)
           dialog.connect("destroy", lambda w: self.win.set_sensitive(True))

           resp = dialog.run()
           if resp:
              if resp == gtk.RESPONSE_OK:
	   	dialog.destroy()

    def comm_ok(self,selection):
	command_entry = self.wTree.get_widget("command_entry")
	self.testing.start_process(self.get_user_list(self.userlist.get_selection()), command_entry.get_text(), self.remote)
	self.populate_procs(self.userlist.get_selection(), False)
	self.command.hide_all()
	self.win.set_sensitive(True)

    def comm_cancel(self, widget=None, event=None):
	self.command.hide_all()
	self.win.set_sensitive(True)
	return True

    def make_blank(self, selection):
	self.testing.lock(self.get_user_list(self.userlist.get_selection()), self.remote)

    def make_unblank(self, selection):
	self.testing.unlock(self.get_user_list(self.userlist.get_selection()), self.remote)

    def make_control(self, selection):
	if selection.count_selected_rows():
		self.testing.control(self.get_user_list(self.userlist.get_selection()), ip, self.remote)
	else:
		self.select_user_dialog()

    def make_share(self, selection):
	if selection.count_selected_rows():
		self.testing.share(self.get_user_list(self.userlist.get_selection()), self.myip, self.remote)
	else:
		self.select_user_dialog()
            
    def send_mess(self, selection):
	if selection.count_selected_rows():
		self.message.show_all()
		self.win.set_sensitive(False)
	else:
	   dialog = gtk.MessageDialog(self.win,
				gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
				gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK, None)
           dialog.set_markup('<big><b>You must select a user first</b></big>')
		
           self.win.set_sensitive(False)
           dialog.connect("destroy", lambda w: self.win.set_sensitive(True))

           resp = dialog.run()
           if resp:
              if resp == gtk.RESPONSE_OK:
	   	dialog.destroy()

    def mess_ok(self,selection):
	self.testing.send_message(self.get_user_list(self.userlist.get_selection()), self.wTree.get_widget("message_entry").get_text())
	self.populate_procs(self.userlist.get_selection(), False)
	self.message.hide_all()
	self.win.set_sensitive(True)

    def mess_cancel(self, widget=None, event=None):
	self.message.hide_all()
	self.win.set_sensitive(True)
	return True

    def new_group(self, selection):
	self.win.set_sensitive(False)
	if selection.count_selected_rows():
		self.wTree.get_widget("importuser").set_sensitive(True)
	else:
		self.wTree.get_widget("importuser").set_sensitive(False)		
	self.addgroup.show_all()

    def addgroup_ok_f(self, selection):
	group = self.wTree.get_widget("entry1").get_text()
	self.gdata[(group)] = []
	if self.wTree.get_widget("importuser").get_active():
		users = self.get_user_list(self.userlist.get_selection())
		for user in users:
			self.gdata[(group)].append(user)
	self.refresh_combo()
	self.refresh_menus()
	self.testing.writeconfig(self.gdata, self.remote)
	#self.testing.send_message(self.get_user_list(self.userlist.get_selection()), self.wTree.get_widget("message_entry").get_text())
	#self.populate_procs(self.userlist.get_selection(), False)
	self.addgroup.hide_all()
	self.win.set_sensitive(True)

    def addgroup_cancel_f(self, widget=None, event=None):
	self.addgroup.hide_all()
	self.win.set_sensitive(True)
	return True

    def delete_group(self, widget, group):
	self.uimanager.remove_ui(self.gdata_ui[(group+"delgrp")])
	self.actiongroup.remove_action(self.gdata_ac[(group+"delgrp")])
	self.uimanager.remove_ui(self.gdata_ui[(group+"add2grp")])
	self.actiongroup.remove_action(self.gdata_ac[(group+"add2grp")])
	self.uimanager.remove_ui(self.gdata_ui[(group+"rm4grp")])
	self.actiongroup.remove_action(self.gdata_ac[(group+"rm4grp")])
	self.gdata.pop(group)
	self.testing.writeconfig(self.gdata, self.remote)
	self.refresh_combo()

    def add_user_to_group(self, widget, group):
	users = self.get_user_list(self.userlist.get_selection())
	for user in users:
		if self.gdata[(group)].count(user) == 0:
			self.gdata[(group)].append(user)
	self.testing.writeconfig(self.gdata, self.remote)

    def remove_user_from_group(self, widget, group):
	users = self.get_user_list(self.userlist.get_selection())
	for user in users:
		self.gdata[(group)].remove(user)
	self.testing.writeconfig(self.gdata, self.remote)

    def butvncnext(self, widget):
	if widget.get_name() == "vncprev":
		if not self.vnc_offset - 4 < 0:
			self.vnc_offset = self.vnc_offset - 4
			self.disconnect_vnc()
			self.start_vnc()
	if widget.get_name() == "vncrefresh":
		self.disconnect_vnc()
		self.start_vnc()
	if widget.get_name() == "vncnext":
		if not self.vnc_offset + 4 > len(self.testing.poll_userlist()):
			self.vnc_offset = self.vnc_offset + 4
			self.disconnect_vnc()
			self.start_vnc()
	self.vnc_buttons()

    def logout_user(self, selection):
	"""
	    Get the selected rows, show a warning dialog and kill the 
	    matching sshd process for each row if ok was clicked
	"""    
        dialog = gtk.MessageDialog(self.win,
				gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
				gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, None)
        dialog.set_markup('<big><b>This will disconnect all selected Students</b>\nAre you sure you want to do this ?</big>')
		
        self.win.set_sensitive(False)
        dialog.connect("destroy", lambda w: self.win.set_sensitive(True))
	
        resp = dialog.run()
        if resp:
            if resp == gtk.RESPONSE_OK:
                paths = []
                list,paths = selection.get_selected_rows()[0], selection.get_selected_rows()[1:]
                for row in paths[0]:
		    self.testing.logout_pid(int(list[row[0]][0]), self.remote)
		#Following line may be able to be back indented
		    self.clear_procs()
		self.cur_user = ''
            dialog.destroy()
	

    def vnc_conn(self, selection):
        """
        Open a VNC connection to the selected host on the list for 
        multiple selected hosts take the first from the list
        """
        list,paths = selection.get_selected_rows()[0], selection.get_selected_rows()[1:]
        err = ''
        if selection.count_selected_rows():
            host = list[paths[0][0]][1].split('\n')[1]
        
            #if not host.startswith('localhost'): # ... to avoid eternal feedback loop
            self.win.set_sensitive(False)

            #Create and show a dialog to get the -shared paramater for vnc

            dialog = gtk.MessageDialog(self.win,
                    gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                    gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK, None)
            vbox = gtk.VBox()
            frame = gtk.Frame()
            radio1 = gtk.RadioButton(None, 'Take over Keyboard and Mouse', '-shared')
            radio2 = gtk.RadioButton(radio1, 'Spymode only', '-viewonly')
        
            vbox.pack_start(radio1, False, True, 2)
            vbox.pack_start(radio2, False, True, 2)
            frame.set_property('border_width', 10)
            frame.add(vbox)
        
            dialog.set_markup('<big><b>Select Connection Method</b></big>\nSelect method to connect to the desktop\non '+host)
        
            dialog.vbox.pack_start(frame, False, False, 0)
        
            dialog.connect("destroy", lambda w: self.win.set_sensitive(True))
            dialog.show_all()
        
            pipe_read, pipe_write = os.pipe()
            resp = dialog.run()
            if resp:
                dialog.destroy()
                switch = '-viewonly'
                if radio1.get_active():
                    switch = '-shared'
        
                command = ['/usr/bin/vncviewer', switch, host+':0']
                vnc = subprocess.Popen(command, stderr=subprocess.PIPE).pid
                while gtk.events_pending():
                    gtk.main_iteration(True)
                pid = vnc.pid
                pid = os.fork()
        
                if pid == 0:

                    #Fork vncviewer

                    sys.stdin.close()
                    command = ['vncviewer', switch, host+':0']
                    sys.stdout.flush()
            
                    print "vnc command line:", command
            
                    os.execvp('vncviewer', command)
            
                    self.win.set_sensitive(False)
                    dialog = gtk.MessageDialog(self.win,
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                        gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, None)
                    dialog.set_markup('<big><b>Connection Failed</b>\nCould not connect to desktop on '+host+'\nmake sure remote desktop sharing is enabled on this host.</big>')
                    dialog.connect("destroy", lambda w: self.win.set_sensitive(True))
            
                    resp = dialog.run()
                if resp:
                    dialog.destroy()
                print os.waitpid(pid, 0)
                gobject.timeout_add(2500, lambda: self.testing.check_proc(pid), self.remote)
                #fh = os.fdopen(pipe_read)
	


    def main(self):
		gtk.gdk.threads_init()
		gtk.main()

if __name__ == "__main__":
    base = ControlPanel()
    base.main()
