Exemple #1
0
 def __init__(self):
     self.setup = Setup()
     self.installer = InstallerEngine(self.setup)
     self.d = Dialog(dialog="dialog", autowidgetsize=True)
     self.page_welcome()
     self.page_language()
     self.page_timezone()
     self.page_keyboard_model()
class InstallerWindow:

	def __init__(self):
		self.resource_dir = '/usr/share/live-installer/'
		#self.glade = 'interface.glade'
		self.glade = os.path.join(self.resource_dir, 'interface.glade')
		self.wTree = gtk.glade.XML(self.glade, 'main_window')

		# should be set early
		self.done = False
		self.fail = False

		# here cometh the installer engine
		self.installer = InstallerEngine()
		# the distribution name
		DISTRIBUTION_NAME = self.installer.get_distribution_name()
		# load the window object
		self.window = self.wTree.get_widget("main_window")
		self.window.set_title(DISTRIBUTION_NAME + " " +  _("Installer"))
		self.window.connect("destroy", self.quit_cb)

		# set the step names
		self.wTree.get_widget("label_step_1").set_markup(_("Select language"))
		self.wTree.get_widget("label_step_2").set_markup(_("Choose partitions"))
		self.wTree.get_widget("label_step_3").set_markup(_("Who are you?"))
		self.wTree.get_widget("label_step_4").set_markup(_("Advanced Options"))
		self.wTree.get_widget("label_step_5").set_markup(_("Keyboard Layout"))
		self.wTree.get_widget("label_step_6").set_markup(_("About to install"))
		self.wTree.get_widget("label_step_7").set_markup(_("Install system"))
		# make first step label bolded.
		label = self.wTree.get_widget("label_step_1")
		text = label.get_label()
		attrs = pango.AttrList()
		nattr = pango.AttrWeight(pango.WEIGHT_BOLD, 0, len(text))
		attrs.insert(nattr)
		label.set_attributes(attrs)
		
		# set the button events (wizard_cb)
		self.wTree.get_widget("button_next").connect("clicked", self.wizard_cb, False)
		self.wTree.get_widget("button_back").connect("clicked", self.wizard_cb, True)
		self.wTree.get_widget("button_quit").connect("clicked", self.quit_cb)
		
		# language view
		self.wTree.get_widget("label_select_language").set_markup(_("Please select the language you wish to use\nfor this installation from the list below"))

		ren = gtk.CellRendererPixbuf()
		column = gtk.TreeViewColumn("Flags", ren)
		column.add_attribute(ren, "pixbuf", 2)
		self.wTree.get_widget("treeview_language_list").append_column(column)

		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn("Languages", ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_language_list").append_column(column)
		
		self.wTree.get_widget("treeview_language_list").connect("cursor-changed", self.cb_change_language)

		# build the language list
		self.build_lang_list()

		# disk view
		self.wTree.get_widget("label_select_partition").set_markup(_("Please edit your filesystem mount points using the options below:\nRemember partitioning <b>may cause data loss!</b>"))
		self.wTree.get_widget("button_edit").connect("clicked", self.edit_partition)
		
		# device
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Device"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# filesystem
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Filesystem"), ren)
		column.add_attribute(ren, "text", 1)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# format
		ren = gtk.CellRendererToggle()
		column = gtk.TreeViewColumn(_("Format"), ren)
		column.add_attribute(ren, "active", 2)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# boot flag
		ren = gtk.CellRendererToggle()
		column = gtk.TreeViewColumn(_("Boot"), ren)
		column.add_attribute(ren, "active", 5)
		self.wTree.get_widget("treeview_disks").append_column(column)		
		# mount point
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Mount Point"), ren)
		column.add_attribute(ren, "text", 3)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# size
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Size"), ren)
		column.add_attribute(ren, "text", 4)
		self.wTree.get_widget("treeview_disks").append_column(column) 
		
		# about you
		self.wTree.get_widget("label_setup_user").set_markup(_("You will now need to enter details for your user account\nThis is the account you will use after the installation has completed."))
		self.wTree.get_widget("label_your_name").set_markup("<b>%s</b>" % _("Your full name"))
		self.wTree.get_widget("label_your_name_help").set_label(_("This will be shown in the About Me application"))
		self.wTree.get_widget("label_username").set_markup("<b>%s</b>" % _("Your username"))
		self.wTree.get_widget("label_username_help").set_label(_("This is the name you will use to login to your computer"))
		self.wTree.get_widget("label_choose_pass").set_markup("<b>%s</b>" % _("Your password"))
		self.wTree.get_widget("label_pass_help").set_label(_("Please enter your password twice to ensure it is correct"))
		self.wTree.get_widget("label_hostname").set_markup("<b>%s</b>" % _("Hostname"))
		self.wTree.get_widget("label_hostname_help").set_label(_("This hostname will be the computers name on the network"))		
		
		# try to set the hostname
		machine = HostMachine()
		model = machine.get_model()
		hostname = ""
		if(model is not None):
			model = model.replace(" ", "").lower()
			hostname = model + "-"
		if(machine.is_laptop()):
			hostname += _("laptop")
		else:
			hostname += _("desktop")
		self.wTree.get_widget("entry_hostname").set_text(hostname)
		
		# events for detecting password mismatch..
		entry1 = self.wTree.get_widget("entry_userpass1")
		entry2 = self.wTree.get_widget("entry_userpass2")
		entry1.connect("changed", self.pass_mismatcher)
		entry2.connect("changed", self.pass_mismatcher)
				
		# advanced page
		self.wTree.get_widget("label_advanced").set_markup(_("On this page you can select advanced options regarding your installation"))
		
		# grub
		self.wTree.get_widget("label_grub").set_markup("<b>%s</b>" % _("Bootloader"))
		self.wTree.get_widget("checkbutton_grub").set_label(_("Install GRUB"))
		self.wTree.get_widget("label_grub_help").set_label(_("GRUB is a bootloader used to load the Linux kernel"))
		
		# link the checkbutton to the combobox
		grub_check = self.wTree.get_widget("checkbutton_grub")
		grub_box = self.wTree.get_widget("combobox_grub")
		grub_check.connect("clicked", lambda x: grub_box.set_sensitive(x.get_active()))
		
		# keyboard page
		self.wTree.get_widget("label_keyboard").set_markup(_("Please choose your keyboard model and keyboard layout using the\noptions below"))
		self.wTree.get_widget("label_test_kb").set_label(_("Use this box to test your keyboard layout"))
		# kb models
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Model"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_models").append_column(column)
		self.wTree.get_widget("treeview_models").connect("cursor-changed", self.cb_change_kb_model)			
		
		# kb layouts
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Layout"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_layouts").append_column(column)
		self.wTree.get_widget("treeview_layouts").connect("cursor-changed", self.cb_change_kb_layout)
		self.build_kb_lists()
		
		# 'about to install' aka overview
		self.wTree.get_widget("label_overview").set_markup(_("Please review your options below before going any further.\nPress the finish button to install %s to your hard drive" % DISTRIBUTION_NAME))
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Overview"), ren)
		column.add_attribute(ren, "markup", 0)
		self.wTree.get_widget("treeview_overview").append_column(column)
		# install page
		self.wTree.get_widget("label_installing").set_markup(_("%s is now being installed on your computer\nThis may take some time so please be patient" % DISTRIBUTION_NAME))
		self.wTree.get_widget("label_install_progress").set_markup("<i>%s</i>" % _("Calculating file indexes..."))
		
		# build partition list
		self.build_disk_list()

		# make everything visible.
		self.window.show()
		self.should_pulse = False

	def quit_cb(self, widget, data=None):
		''' ask whether we should quit. because touchpads do happen '''
		gtk.main_quit()

	def edit_partition(self, widget, data=None):
		''' edit the partition ... '''
		disks = self.wTree.get_widget("treeview_disks")
		model = disks.get_model()
		active = disks.get_selection().get_selected_rows()
		if(len(active) < 1):
			return
		if(len(active[1]) < 1):
			return
		active = active[1][0]
		if(active is None):
			return
		row = model[active]
		stabber = fstab_entry(row[0], row[3], row[1], None)
		stabber.format = row[2]
		dlg = PartitionDialog(stabber)
		stabber = dlg.show()
		if(stabber is None):
			return
		# now set the model as shown..
		row[0] = stabber.device
		row[3] = stabber.mountpoint
		row[1] = stabber.filesystem
		row[2] = stabber.format
		model[active] = row
		
	def build_lang_list(self):

	        #Try to find out where we're located...
	        cur_country_code = None
	        try:
	            whatismyip = 'http://debian.linuxmint.com/installer/show_my_ip.php'
	            ip = urllib.urlopen(whatismyip).readlines()[0]
	            gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
	            cur_country_code = gi.country_code_by_addr(ip)
	        except:
	            pass #best effort, we get here if we're not connected to the Internet            
	
	        #Plan B... find out what locale we're in (i.e. USA on the live session)
	        cur_lang = os.environ['LANG']
	        if("." in cur_lang):
	            cur_lang = cur_lang.split(".")[0]
	
	        model = gtk.ListStore(str,str,gtk.gdk.Pixbuf)
	        model.set_sort_column_id(0, gtk.SORT_ASCENDING)
	
	        #Load countries into memory
	        countries = {}
	        file = open(os.path.join(self.resource_dir, 'countries'), "r")
	        for line in file:
	            line = line.strip()
	            split = line.split("=")
	            if len(split) == 2:
	                countries[split[0]] = split[1]
	        file.close()
	
	        #Load languages into memory
	        languages = {}
	        file = open(os.path.join(self.resource_dir, 'languages'), "r")
	        for line in file:
	            line = line.strip()
	            split = line.split("=")
	            if len(split) == 2:
	                languages[split[0]] = split[1]
	        file.close()
	
	        path = os.path.join(self.resource_dir, 'locales')
	        locales = open(path, "r")
	        cur_index = -1 # find the locale :P
	        set_index = None
	        for line in locales:
	            cur_index += 1
	            if "UTF-8" in line:
	                locale_code = line.replace("UTF-8", "")
	                locale_code = locale_code.replace(".", "")
	                locale_code = locale_code.strip()
	                if "_" in locale_code:
	                    split = locale_code.split("_")
	                    if len(split) == 2:
	                        language_code = split[0]
	                        if language_code in languages:
	                            language = languages[language_code]
	                        else:
	                            language = language_code

	                        country_code = split[1].lower()
	                        if country_code in countries:
	                            country = countries[country_code]
	                        else:
	                            country = country_code
	
	                        language_label = "%s (%s)" % (language, country)
	                        #language_label = "%s - %s" % (country, language)
	
	                        iter = model.append()
	                        model.set_value(iter, 0, language_label)
	                        model.set_value(iter, 1, locale_code)
	                        flag_path = self.resource_dir + '/flags/16/' + country_code + '.png'
	                        if os.path.exists(flag_path):
	                            model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
	                        else:
	                            flag_path = self.resource_dir + '/flags/16/generic.png'
	                            model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
	                        # If it's matching our country code, that's our language right there.. 
	                        if ((cur_country_code is not None) and (cur_country_code.lower() == country_code)):                            
	                            if (set_index is None):
	                                set_index = iter                                
	                            else:
	                                # If we find more than one language for a particular country, one of them being English, go for English by default.
	                                if (language_code == "en"):
	                                    set_index = iter                 
	                                # Guesswork... handy for countries which have their own language (fr_FR, de_DE, es_ES.. etc. )
	                                elif (country_code == language_code):
	                                    set_index = iter
	                                    
	                        # as a plan B... use the locale (USA)
	                        if((set_index is None) and (locale_code == cur_lang)):
	                            set_index = iter
	                            #print "Set via locale: " + cur_lang
	
	        treeview = self.wTree.get_widget("treeview_language_list")
	        treeview.set_model(model)
	        if(set_index is not None):
	            column = treeview.get_column(0)
	            path = model.get_path(set_index)
	            treeview.set_cursor(path, focus_column=column)
	            treeview.scroll_to_cell(path, column=column)
	        treeview.set_search_column(0)
	def build_disk_list(self):
		model = gtk.ListStore(str,str,bool,str,str,bool)
		model2 = gtk.ListStore(str)
		pro = subprocess.Popen("parted -lms", stdout=subprocess.PIPE, shell=True)
		last_name = ""
		for line in pro.stdout:
			line = line.rstrip("\r\n")
			if ":" in line:
				split = line.split(":")
				if(len(split) <= 3):
					continue
				if(line.startswith("/dev")):
					last_name = split[0]
					model2.append([last_name])
					continue
				# device list
				sections = line.split(" ")
				device = "%s%s" % (last_name, split[0])
				filesystem = split[4]
				# hack. love em eh? ...
				if(filesystem.startswith("linux-swap")):
					filesystem = "swap"
				size_ = split[3]
				if(len(split) > 5):
					boot  = split[6]
					if(boot == "boot;"):
						model.append([device, filesystem, False, None, size_, True])
					else:
						model.append([device, filesystem, False, None, size_, False])
				else:
					model.append([device, filesystem, False, None, size_, False])
				print "%s - %s" % (device, filesystem)
		self.wTree.get_widget("treeview_disks").set_model(model)
		self.wTree.get_widget("combobox_grub").set_model(model2)
		self.wTree.get_widget("combobox_grub").set_active(0)
		
	def build_kb_lists(self):
		''' Do some xml kung-fu and load the keyboard stuffs '''
		
		# firstly we'll determine the layouts in use
		p = subprocess.Popen("setxkbmap -print",shell=True,stdout=subprocess.PIPE)
		for line in p.stdout:
			# strip it
			line = line.rstrip("\r\n")
			line = line.replace("{","")
			line = line.replace("}","")
			line = line.replace(";","")
			if("xkb_symbols" in line):
				# decipher the layout in use
				section = line.split("\"")[1] # split by the " mark
				self.keyboard_layout = section.split("+")[1]
			if("xkb_geometry" in line):
				first_bracket = line.index("(") +1
				substr = line[first_bracket:]
				last_bracket = substr.index(")")
				substr = substr[0:last_bracket]
				self.keyboard_geom = substr
		p.poll()
		
		xml_file = '/usr/share/X11/xkb/rules/xorg.xml'
		model_models = gtk.ListStore(str,str)
		model_models.set_sort_column_id(0, gtk.SORT_ASCENDING)
		model_layouts = gtk.ListStore(str,str)
		model_layouts.set_sort_column_id(0, gtk.SORT_ASCENDING)
		dom = parse(xml_file)
		
		# if we find the users keyboard info we can set it in the list
		set_keyboard_model = None
		set_keyboard_layout = None
		
		# grab the root element
		root = dom.getElementsByTagName('xkbConfigRegistry')[0]
		# build the list of models
		root_models = root.getElementsByTagName('modelList')[0]
		for element in root_models.getElementsByTagName('model'):
			conf = element.getElementsByTagName('configItem')[0]
			name = conf.getElementsByTagName('name')[0]
			desc = conf.getElementsByTagName('description')[0]
			#vendor = conf.getElementsByTagName('vendor')[0] # presently unused..
			iter_model = model_models.append([self.getText(desc.childNodes), self.getText(name.childNodes)])
			item = self.getText(name.childNodes)
			if(item == self.keyboard_geom):
				set_keyboard_model = iter_model
		root_layouts = root.getElementsByTagName('layoutList')[0]
		for element in root_layouts.getElementsByTagName('layout'):
			conf = element.getElementsByTagName('configItem')[0]
			name = conf.getElementsByTagName('name')[0]
			desc = conf.getElementsByTagName('description')[0]
			iter_layout = model_layouts.append([self.getText(desc.childNodes), self.getText(name.childNodes)])
			item = self.getText(name.childNodes)
			if(item == self.keyboard_layout):
				set_keyboard_layout = iter_layout
		# now set the model
		self.wTree.get_widget("treeview_models").set_model(model_models)
		self.wTree.get_widget("treeview_layouts").set_model(model_layouts)
		
		if(set_keyboard_layout is not None):
			# show it in the list
			treeview = self.wTree.get_widget("treeview_layouts")
			model = treeview.get_model()
			column = treeview.get_column(0)
			path = model.get_path(set_keyboard_layout)
			treeview.set_cursor(path, focus_column=column)
			treeview.scroll_to_cell(path, column=column)
		if(set_keyboard_model is not None):
			# show it in the list
			treeview = self.wTree.get_widget("treeview_models")
			model = treeview.get_model()
			column = treeview.get_column(0)
			path = model.get_path(set_keyboard_model)
			treeview.set_cursor(path, focus_column=column)
			treeview.scroll_to_cell(path, column=column)
			
	def getText(self, nodelist):
	    rc = []
	    for node in nodelist:
	        if node.nodeType == node.TEXT_NODE:
	            rc.append(node.data)
	    return ''.join(rc)

	def cb_change_language(self, treeview, data=None):
		''' Called whenever someone updates the language '''
		model = treeview.get_model()
		active = treeview.get_selection().get_selected_rows()
		if(len(active) < 1):
			return
		active = active[1][0]
		if(active is None):
			return
		row = model[active]		
		self.locale = row[1]
	
	def cb_change_kb_model(self, treeview, data=None):
		''' Called whenever someone updates the keyboard model '''
		model = treeview.get_model()
		active = treeview.get_selection().get_selected_rows()
		if(len(active) < 1):
			return
		active = active[1][0]
		if(active is None):
			return
		row = model[active]
		os.system("setxkbmap -model %s" % row[1])
		self.keyboard_model = row[1]
		self.keyboard_model_desc = row[0]

	def cb_change_kb_layout(self, treeview, data=None):
		''' Called whenever someone updates the keyboard layout '''
		model = treeview.get_model()
		active = treeview.get_selection().get_selected_rows()
		if(len(active) < 1):
			return
		active = active[1][0]
		if(active is None):
			return
		row = model[active]
		os.system("setxkbmap -layout %s" % row[1])
		self.keyboard_layout = row[1]
		self.keyboard_layout_desc = row[0]

	def pass_mismatcher(self, widget):
		''' Someone typed into the entry '''
		w = self.wTree.get_widget("entry_userpass1")
		w2 = self.wTree.get_widget("entry_userpass2")
		txt1 = w.get_text()
		txt2 = w2.get_text()
		if(txt1 == "" and txt2 == ""):
			self.wTree.get_widget("image_mismatch").hide()
			self.wTree.get_widget("label_mismatch").hide()
		else:
			self.wTree.get_widget("image_mismatch").show()
			self.wTree.get_widget("label_mismatch").show()
		if(txt1 != txt2):
			img = self.wTree.get_widget("image_mismatch")
			img.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON)
			label = self.wTree.get_widget("label_mismatch")
			label.set_label(_("Passwords do not match"))
		else:
			img = self.wTree.get_widget("image_mismatch")
			img.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
			label = self.wTree.get_widget("label_mismatch")
			label.set_label(_("Passwords match"))			
			
	def wizard_cb(self, widget, goback, data=None):
		''' wizard buttons '''
		nb = self.wTree.get_widget("notebook1")
		sel = nb.get_current_page() 
		# check each page for errors
		if(not goback):
			if(sel == 1):
				# partitions page
				model = self.wTree.get_widget("treeview_disks").get_model()
				found_root = False
				# found_swap = False
				for row in model:
					mountpoint = row[3]
					if(mountpoint == "/"):
						found_root = True
				if(not found_root):
					dlg = MessageDialog(_("Installation Tool"), _("Please select a root (/) partition before proceeding"), gtk.MESSAGE_ERROR)
					dlg.show()
					return
			elif(sel == 2):
				# about me page
				username = self.wTree.get_widget("entry_username").get_text()
				if(username == ""):
					MessageDialog(_("Installation Tool"), _("Please provide a username"), gtk.MESSAGE_ERROR).show()
					return
				# username valid?
				for char in username:
					if(char.isupper()):
						MessageDialog(_("Installation Tool"), _("Your username must be lower case"), gtk.MESSAGE_WARNING).show()
						return
					if(char.isspace()):
						MessageDialog(_("Installation Tool"), _("Your username may not contain whitespace"), gtk.MESSAGE_WARNING).show()
						return
				password1 = self.wTree.get_widget("entry_userpass1").get_text()
				if(password1 == ""):
					MessageDialog(_("Installation Tool"), _("Please provide a password for your user account"), gtk.MESSAGE_WARNING).show()
					return
				password2 = self.wTree.get_widget("entry_userpass2").get_text()
				if(password1 != password2):
					MessageDialog(_("Installation Tool"), _("Your passwords do not match"), gtk.MESSAGE_ERROR).show()
					return
			elif(sel == 3):				
				pass
		label = self.wTree.get_widget("label_step_" + str(sel+1))
		text = label.get_label()
		attrs = pango.AttrList()
		nattr = pango.AttrWeight(pango.WEIGHT_NORMAL, 0, len(text))
		attrs.insert(nattr)
		label.set_attributes(attrs)
		label.set_sensitive(False)
		if(goback):
			sel-=1
			if(sel == 0):
				self.wTree.get_widget("button_back").set_sensitive(False)
		else:
			sel+=1
			self.wTree.get_widget("button_back").set_sensitive(True)
			
		label = self.wTree.get_widget("label_step_" + str(sel+1))
		attrs = pango.AttrList()
		text = label.get_label()
		battr = pango.AttrWeight(pango.WEIGHT_BOLD, 0, len(text))
		attrs.insert(battr)
		label.set_attributes(attrs)
		label.set_sensitive(True)
		self.wTree.get_widget("notebook1").set_current_page(sel)

		if(sel == 5):
			self.show_overview()
			self.wTree.get_widget("treeview_overview").expand_all()
		if(sel == 6):
			# do install
			self.wTree.get_widget("button_next").hide()
			self.wTree.get_widget("button_back").hide()
			thr = threading.Thread(name="live-install", group=None, args=(), kwargs={}, target=self.do_install)
			thr.start()
			
	def show_overview(self):
		''' build the summary page '''
		model = gtk.TreeStore(str)
		top = model.append(None)
		model.set(top, 0, "Filesystem operations")
		disks = self.wTree.get_widget("treeview_disks").get_model()
		for item in disks:
			if(item[2]):
				# format it
				iter = model.append(top)
				model.set(iter, 0, "<b>%s</b>" % (_("Format %s (%s) as %s" % (item[0], item[4], item[1]))))
			if(item[3] is not None and item[3] is not ""):
				# mount point
				iter = model.append(top)
				model.set(iter, 0, "<b>%s</b>" % (_("Mount %s as %s" % (item[0], item[3]))))
		install_grub = self.wTree.get_widget("checkbutton_grub").get_active()
		grub_box = self.wTree.get_widget("combobox_grub")
		grub_active = grub_box.get_active()
		grub_model = grub_box.get_model()
		iter = model.append(top)
		if(install_grub):
			model.set(iter, 0, _("Install bootloader to %s" % ("<b>%s</b>" % grub_model[grub_active][0])))
		else:
			model.set(iter, 0, _("Do not install bootloader"))
		# now we show the system info
		top = model.append(None)
		model.set(top, 0, _("User settings"))
		username = self.wTree.get_widget("entry_username").get_text()
		realname = self.wTree.get_widget("entry_your_name").get_text()		
		iter = model.append(top)
		model.set(iter, 0, "Username: <b>%s</b>" % username)
		iter = model.append(top)
		model.set(iter, 0, "Real name: <b>%s</b>" % realname)		
		
		# keyboard cruft
		top = model.append(None)
		model.set(top, 0, _("Keyboard"))
		iter = model.append(top)
		model.set(iter, 0, "Layout: <b>%s</b>" % self.keyboard_layout_desc)
		iter = model.append(top)
		model.set(iter, 0, "Model: <b>%s</b>" % self.keyboard_model_desc)
		
		# system stuff
		# todo; probe
		hostname = self.wTree.get_widget("entry_hostname").get_text()
		language = self.locale
		top = model.append(None)
		model.set(top, 0, _("System settings"))
		iter = model.append(top)
		model.set(iter, 0, "Hostname: <b>%s</b>" % hostname)
		#iter = model.append(top)
		#model.set(iter, 0, "Locale: <b>%s</b>" % locale)
		iter = model.append(top)
		model.set(iter, 0, "Language: <b>%s</b>" % language)
		self.wTree.get_widget("treeview_overview").set_model(model)
		
	def do_install(self):
		''' Actually perform the installation .. '''
		inst = self.installer
		
		# Create fstab
		files = fstab()
		model = self.wTree.get_widget("treeview_disks").get_model()
		for row in model:
			if(row[2] or row[3] is not None): # format or mountpoint specified.
				files.add_mount(device=row[0], mountpoint=row[3], filesystem=row[1], format=row[2])
		inst.fstab = files # need to add set_fstab() to InstallerEngine
		
		# set up the system user
		username = self.wTree.get_widget("entry_username").get_text()
		password = self.wTree.get_widget("entry_userpass1").get_text()
		realname = self.wTree.get_widget("entry_your_name").get_text()
		hostname = self.wTree.get_widget("entry_hostname").get_text()		
		user = SystemUser(username=username, password=password, realname=realname)
		inst.set_main_user(user)
		inst.set_hostname(hostname)
					
		# set language
		inst.set_locale(self.locale)
		
		# set keyboard
		inst.set_keyboard_options(layout=self.keyboard_layout, model=self.keyboard_model)

		# grub?
		do_grub = self.wTree.get_widget("checkbutton_grub").get_active()
		if(do_grub):
			grub_box = self.wTree.get_widget("combobox_grub")
			grub_location = grub_box.get_model()[grub_box.get_active()][0]
			inst.set_install_bootloader(device=grub_location)
		inst.set_progress_hook(self.update_progress)

		# do we dare? ..
		inst.install()
		
		# show a message dialog thingum
		while(not self.done):
			time.sleep(0.1)
		gtk.gdk.threads_enter()
		MessageDialog(_("Installation Tool"), _("Installation is now complete. Please restart your computer to use the new system"), gtk.MESSAGE_INFO).show()
		gtk.gdk.threads_leave()
		# safe??
		gtk.main_quit()
		# you are now..
		sys.exit(0)

	def update_progress(self, fail=False, done=False, pulse=False, total=0,current=0,message=""):
		# TODO: ADD FAIL CHECKS..
		if(pulse):
			gtk.gdk.threads_enter()
			self.wTree.get_widget("label_install_progress").set_label(message)
			gtk.gdk.threads_leave()
			self.do_progress_pulse(message)
			return
		if(done):
			# cool, finished :D
			self.should_pulse = False
			self.done = done
			gtk.gdk.threads_enter()
			self.wTree.get_widget("progressbar").set_fraction(1)
			self.wTree.get_widget("label_install_progress").set_label(message)
			gtk.gdk.threads_leave()
			return
		self.should_pulse = False
		_total = float(total)
		_current = float(current)
		pct = float(_current/_total)
		szPct = int(pct)
		# thread block
		gtk.gdk.threads_enter()
		self.wTree.get_widget("progressbar").set_fraction(pct)
		self.wTree.get_widget("label_install_progress").set_label(message)
		gtk.gdk.threads_leave()
		
		# end thread block
	
	def do_progress_pulse(self, message):
		def pbar_pulse():
			if(not self.should_pulse):
				return False
			self.wTree.get_widget("progressbar").pulse()
			return self.should_pulse
		if(not self.should_pulse):
			self.should_pulse = True
			gobject.timeout_add(100, pbar_pulse)
		else:
			# asssume we're "pulsing" already
			self.should_pulse = True
			gtk.gdk.threads_enter()
			pbar_pulse()
			gtk.gdk.threads_leave()
	def __init__(self):
		self.resource_dir = '/usr/share/live-installer/'
		#self.glade = 'interface.glade'
		self.glade = os.path.join(self.resource_dir, 'interface.glade')
		self.wTree = gtk.glade.XML(self.glade, 'main_window')

		# should be set early
		self.done = False
		self.fail = False

		# here cometh the installer engine
		self.installer = InstallerEngine()
		# the distribution name
		DISTRIBUTION_NAME = self.installer.get_distribution_name()
		# load the window object
		self.window = self.wTree.get_widget("main_window")
		self.window.set_title(DISTRIBUTION_NAME + " " +  _("Installer"))
		self.window.connect("destroy", self.quit_cb)

		# set the step names
		self.wTree.get_widget("label_step_1").set_markup(_("Select language"))
		self.wTree.get_widget("label_step_2").set_markup(_("Choose partitions"))
		self.wTree.get_widget("label_step_3").set_markup(_("Who are you?"))
		self.wTree.get_widget("label_step_4").set_markup(_("Advanced Options"))
		self.wTree.get_widget("label_step_5").set_markup(_("Keyboard Layout"))
		self.wTree.get_widget("label_step_6").set_markup(_("About to install"))
		self.wTree.get_widget("label_step_7").set_markup(_("Install system"))
		# make first step label bolded.
		label = self.wTree.get_widget("label_step_1")
		text = label.get_label()
		attrs = pango.AttrList()
		nattr = pango.AttrWeight(pango.WEIGHT_BOLD, 0, len(text))
		attrs.insert(nattr)
		label.set_attributes(attrs)
		
		# set the button events (wizard_cb)
		self.wTree.get_widget("button_next").connect("clicked", self.wizard_cb, False)
		self.wTree.get_widget("button_back").connect("clicked", self.wizard_cb, True)
		self.wTree.get_widget("button_quit").connect("clicked", self.quit_cb)
		
		# language view
		self.wTree.get_widget("label_select_language").set_markup(_("Please select the language you wish to use\nfor this installation from the list below"))

		ren = gtk.CellRendererPixbuf()
		column = gtk.TreeViewColumn("Flags", ren)
		column.add_attribute(ren, "pixbuf", 2)
		self.wTree.get_widget("treeview_language_list").append_column(column)

		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn("Languages", ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_language_list").append_column(column)
		
		self.wTree.get_widget("treeview_language_list").connect("cursor-changed", self.cb_change_language)

		# build the language list
		self.build_lang_list()

		# disk view
		self.wTree.get_widget("label_select_partition").set_markup(_("Please edit your filesystem mount points using the options below:\nRemember partitioning <b>may cause data loss!</b>"))
		self.wTree.get_widget("button_edit").connect("clicked", self.edit_partition)
		
		# device
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Device"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# filesystem
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Filesystem"), ren)
		column.add_attribute(ren, "text", 1)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# format
		ren = gtk.CellRendererToggle()
		column = gtk.TreeViewColumn(_("Format"), ren)
		column.add_attribute(ren, "active", 2)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# boot flag
		ren = gtk.CellRendererToggle()
		column = gtk.TreeViewColumn(_("Boot"), ren)
		column.add_attribute(ren, "active", 5)
		self.wTree.get_widget("treeview_disks").append_column(column)		
		# mount point
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Mount Point"), ren)
		column.add_attribute(ren, "text", 3)
		self.wTree.get_widget("treeview_disks").append_column(column)
		# size
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Size"), ren)
		column.add_attribute(ren, "text", 4)
		self.wTree.get_widget("treeview_disks").append_column(column) 
		
		# about you
		self.wTree.get_widget("label_setup_user").set_markup(_("You will now need to enter details for your user account\nThis is the account you will use after the installation has completed."))
		self.wTree.get_widget("label_your_name").set_markup("<b>%s</b>" % _("Your full name"))
		self.wTree.get_widget("label_your_name_help").set_label(_("This will be shown in the About Me application"))
		self.wTree.get_widget("label_username").set_markup("<b>%s</b>" % _("Your username"))
		self.wTree.get_widget("label_username_help").set_label(_("This is the name you will use to login to your computer"))
		self.wTree.get_widget("label_choose_pass").set_markup("<b>%s</b>" % _("Your password"))
		self.wTree.get_widget("label_pass_help").set_label(_("Please enter your password twice to ensure it is correct"))
		self.wTree.get_widget("label_hostname").set_markup("<b>%s</b>" % _("Hostname"))
		self.wTree.get_widget("label_hostname_help").set_label(_("This hostname will be the computers name on the network"))		
		
		# try to set the hostname
		machine = HostMachine()
		model = machine.get_model()
		hostname = ""
		if(model is not None):
			model = model.replace(" ", "").lower()
			hostname = model + "-"
		if(machine.is_laptop()):
			hostname += _("laptop")
		else:
			hostname += _("desktop")
		self.wTree.get_widget("entry_hostname").set_text(hostname)
		
		# events for detecting password mismatch..
		entry1 = self.wTree.get_widget("entry_userpass1")
		entry2 = self.wTree.get_widget("entry_userpass2")
		entry1.connect("changed", self.pass_mismatcher)
		entry2.connect("changed", self.pass_mismatcher)
				
		# advanced page
		self.wTree.get_widget("label_advanced").set_markup(_("On this page you can select advanced options regarding your installation"))
		
		# grub
		self.wTree.get_widget("label_grub").set_markup("<b>%s</b>" % _("Bootloader"))
		self.wTree.get_widget("checkbutton_grub").set_label(_("Install GRUB"))
		self.wTree.get_widget("label_grub_help").set_label(_("GRUB is a bootloader used to load the Linux kernel"))
		
		# link the checkbutton to the combobox
		grub_check = self.wTree.get_widget("checkbutton_grub")
		grub_box = self.wTree.get_widget("combobox_grub")
		grub_check.connect("clicked", lambda x: grub_box.set_sensitive(x.get_active()))
		
		# keyboard page
		self.wTree.get_widget("label_keyboard").set_markup(_("Please choose your keyboard model and keyboard layout using the\noptions below"))
		self.wTree.get_widget("label_test_kb").set_label(_("Use this box to test your keyboard layout"))
		# kb models
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Model"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_models").append_column(column)
		self.wTree.get_widget("treeview_models").connect("cursor-changed", self.cb_change_kb_model)			
		
		# kb layouts
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Layout"), ren)
		column.add_attribute(ren, "text", 0)
		self.wTree.get_widget("treeview_layouts").append_column(column)
		self.wTree.get_widget("treeview_layouts").connect("cursor-changed", self.cb_change_kb_layout)
		self.build_kb_lists()
		
		# 'about to install' aka overview
		self.wTree.get_widget("label_overview").set_markup(_("Please review your options below before going any further.\nPress the finish button to install %s to your hard drive" % DISTRIBUTION_NAME))
		ren = gtk.CellRendererText()
		column = gtk.TreeViewColumn(_("Overview"), ren)
		column.add_attribute(ren, "markup", 0)
		self.wTree.get_widget("treeview_overview").append_column(column)
		# install page
		self.wTree.get_widget("label_installing").set_markup(_("%s is now being installed on your computer\nThis may take some time so please be patient" % DISTRIBUTION_NAME))
		self.wTree.get_widget("label_install_progress").set_markup("<i>%s</i>" % _("Calculating file indexes..."))
		
		# build partition list
		self.build_disk_list()

		# make everything visible.
		self.window.show()
		self.should_pulse = False
    def __init__(self, fullscreen=False):
        
        #Disable the screensaver to prevent a segfault situation in GTK2
        os.system("sudo -u mint gsettings set org.cinnamon.desktop.screensaver lock-enabled false 2> /dev/null")
        os.system("sudo -u mint gsettings set org.mate.screensaver lock-enabled false 2> /dev/null")
        
        #Build the Setup object (where we put all our choices)
        self.setup = Setup()
        
        self.resource_dir = '/usr/share/live-installer/'
        #self.glade = 'interface.glade'
        self.glade = os.path.join(self.resource_dir, 'interface.glade')
        self.wTree = gtk.glade.XML(self.glade, 'main_window')

        # should be set early
        self.done = False
        self.fail = False
        self.paused = False

        # here comes the installer engine
        self.installer = InstallerEngine()
        # the distribution name
        DISTRIBUTION_NAME = self.installer.get_distribution_name()
        # load the window object
        self.window = self.wTree.get_widget("main_window")
        if __debug__:
            self.window.set_title((_("%s Installer") % DISTRIBUTION_NAME) + ' (debug)')
        else:
            self.window.set_title((_("%s Installer") % DISTRIBUTION_NAME))
        self.window.connect("destroy", self.quit_cb)

        # Wizard pages
        (self.PAGE_LANGUAGE,
         self.PAGE_PARTITIONS,
         self.PAGE_USER,
         self.PAGE_ADVANCED,
         self.PAGE_KEYBOARD,
         self.PAGE_OVERVIEW,
         self.PAGE_INSTALL,
         self.PAGE_TIMEZONE,
         self.PAGE_CUSTOMWARNING,
         self.PAGE_CUSTOMPAUSED) = range(10)
        self.wizard_pages = range(10)
        self.wizard_pages[self.PAGE_LANGUAGE] = WizardPage(_("Language"), "locales.png")
        self.wizard_pages[self.PAGE_TIMEZONE] = WizardPage(_("Timezone"), "time.png")
        self.wizard_pages[self.PAGE_KEYBOARD] = WizardPage(_("Keyboard layout"), "keyboard.png")
        self.wizard_pages[self.PAGE_USER] = WizardPage(_("User info"), "user.png")
        self.wizard_pages[self.PAGE_PARTITIONS] = WizardPage(_("Partitioning"), "hdd.svg")
        self.wizard_pages[self.PAGE_CUSTOMWARNING] = WizardPage(_("Please make sure you wish to manage partitions manually"), "hdd.svg")
        self.wizard_pages[self.PAGE_ADVANCED] = WizardPage(_("Advanced options"), "advanced.png")
        self.wizard_pages[self.PAGE_OVERVIEW] = WizardPage(_("Summary"), "summary.png")
        self.wizard_pages[self.PAGE_INSTALL] = WizardPage(_("Installing Linux Mint..."), "install.png")
        self.wizard_pages[self.PAGE_CUSTOMPAUSED] = WizardPage(_("Installation is paused: please finish the custom installation"), "install.png")
        
        # set the button events (wizard_cb)
        self.wTree.get_widget("button_next").connect("clicked", self.wizard_cb, False)
        self.wTree.get_widget("button_back").connect("clicked", self.wizard_cb, True)
        self.wTree.get_widget("button_quit").connect("clicked", self.quit_cb)

        col = gtk.TreeViewColumn("", gtk.CellRendererPixbuf(), pixbuf=2)
        self.wTree.get_widget("treeview_language_list").append_column(col)
        ren = gtk.CellRendererText()
        col = gtk.TreeViewColumn(_("Language"), ren, text=0)
        col.set_sort_column_id(0)
        self.wTree.get_widget("treeview_language_list").append_column(col)
        col = gtk.TreeViewColumn(_("Country"), ren, text=1)
        col.set_sort_column_id(1)
        self.wTree.get_widget("treeview_language_list").append_column(col)

        self.wTree.get_widget("treeview_language_list").connect("cursor-changed", self.assign_language)

        # build user info page
        self.wTree.get_widget("face_select_picture_button").connect( "button-release-event", self.face_select_picture_button_clicked)        
        self.wTree.get_widget("face_take_picture_button").connect( "button-release-event", self.face_take_picture_button_clicked)           
        os.system("convert /usr/share/pixmaps/faces/t9penguino_trans.png -resize x96 /tmp/live-installer-face.png")
        self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")   
        
        webcam_detected = 0 == os.system('streamer -o /tmp/live-installer-face07.jpeg')
        if webcam_detected:
            self.wTree.get_widget("face_take_picture_button").set_tooltip_text(_("Click this button to take a new picture of yourself with the webcam."))
        else:
            self.wTree.get_widget("face_take_picture_button").set_sensitive(False)
            self.wTree.get_widget("face_take_picture_button").set_tooltip_text(_("The installer did not detect any webcams."))
        
        # build the language list
        self.build_lang_list()        

        # build timezones
        model = timezones.build_timezones(self)
        self.wTree.get_widget("button_timezones").set_label(_('Select timezone'))
        self.wTree.get_widget("event_timezones").connect('button-release-event', timezones.cb_map_clicked, model)

        # partitions
        self.wTree.get_widget("label_edit_partitions").set_label(_("_Edit partitions"))
        self.wTree.get_widget("label_custommount").set_label(_("_Expert mode"))
        self.wTree.get_widget("button_custommount").connect("clicked", self.show_customwarning)
        self.wTree.get_widget("button_edit").connect("clicked", partitioning.manually_edit_partitions)
        self.wTree.get_widget("button_refresh").connect("clicked", lambda _: partitioning.build_partitions(self))
        self.wTree.get_widget("treeview_disks").get_selection().connect("changed", partitioning.update_html_preview)
        self.wTree.get_widget("treeview_disks").connect("row_activated", partitioning.edit_partition_dialog)
        self.wTree.get_widget("treeview_disks").connect("button-release-event", partitioning.partitions_popup_menu)
        text = gtk.CellRendererText()
        for i in (partitioning.IDX_PART_PATH,
                  partitioning.IDX_PART_TYPE,
                  partitioning.IDX_PART_DESCRIPTION,
                  partitioning.IDX_PART_MOUNT_AS,
                  partitioning.IDX_PART_FORMAT_AS,
                  partitioning.IDX_PART_SIZE,
                  partitioning.IDX_PART_FREE_SPACE):
            col = gtk.TreeViewColumn("", text, markup=i)  # real title is set in i18n()
            self.wTree.get_widget("treeview_disks").append_column(col)

        self.wTree.get_widget("entry_your_name").connect("notify::text", self.assign_realname)        
        self.wTree.get_widget("entry_username").connect("notify::text", self.assign_username)    
        self.wTree.get_widget("entry_hostname").connect("notify::text", self.assign_hostname)    

        # events for detecting password mismatch..        
        self.wTree.get_widget("entry_userpass1").connect("changed", self.assign_password)
        self.wTree.get_widget("entry_userpass2").connect("changed", self.assign_password)

        # link the checkbutton to the combobox
        grub_check = self.wTree.get_widget("checkbutton_grub")
        grub_box = self.wTree.get_widget("combobox_grub")
        grub_check.connect("toggled", self.assign_grub_install, grub_box)
        grub_box.connect("changed", self.assign_grub_device)

        # Install Grub by default
        grub_check.set_active(True)
        grub_box.set_sensitive(True)
        
        # kb models
        cell = gtk.CellRendererText()
        self.wTree.get_widget("combobox_kb_model").pack_start(cell, True)
        self.wTree.get_widget("combobox_kb_model").add_attribute(cell, 'text', 0)        
        self.wTree.get_widget("combobox_kb_model").connect("changed", self.assign_keyboard_model)

        # kb layouts
        ren = gtk.CellRendererText()
        self.column10 = gtk.TreeViewColumn(_("Layout"), ren)
        self.column10.add_attribute(ren, "text", 0)
        self.wTree.get_widget("treeview_layouts").append_column(self.column10)
        self.wTree.get_widget("treeview_layouts").connect("cursor-changed", self.assign_keyboard_layout)
        
        ren = gtk.CellRendererText()
        self.column11 = gtk.TreeViewColumn(_("Variant"), ren)
        self.column11.add_attribute(ren, "text", 0)
        self.wTree.get_widget("treeview_variants").append_column(self.column11)
        self.wTree.get_widget("treeview_variants").connect("cursor-changed", self.assign_keyboard_variant)
        
        self.build_kb_lists()

        # 'about to install' aka overview
        ren = gtk.CellRendererText()
        self.column12 = gtk.TreeViewColumn(_("Overview"), ren)
        self.column12.add_attribute(ren, "markup", 0)
        self.wTree.get_widget("treeview_overview").append_column(self.column12)
        # install page
        self.wTree.get_widget("label_install_progress").set_markup("<i>%s</i>" % _("Calculating file indexes ..."))
    
        #i18n
        self.i18n()

        # build partition list
        self.should_pulse = False

        # make sure we're on the right page (no pun.)
        self.activate_page(0)

        # this is a hack atm to steal the menubar's background color
        self.wTree.get_widget("menubar").realize()
        style = self.wTree.get_widget("menubar").style.copy()
        self.wTree.get_widget("menubar").hide()
        # apply to the header       
        self.title_box = self.wTree.get_widget("title_eventbox")
        self.title_box.set_border_width(6);
        bgColor = gtk.gdk.color_parse('#585858')
        self.title_box.modify_bg(gtk.STATE_NORMAL, bgColor)
        fgColor = gtk.gdk.color_parse('#FFFFFF')
        self.help_label = self.wTree.get_widget("help_label")
        self.help_label.modify_fg(gtk.STATE_NORMAL, fgColor)            
        if(fullscreen):
            # dedicated installer mode thingum
            self.window.maximize()
            self.window.fullscreen()        

        # Configure slideshow webview
        self.slideshow_browser = webkit.WebView()
        s = self.slideshow_browser.get_settings()
        s.set_property('enable-file-access-from-file-uris', True)
        s.set_property('enable-default-context-menu', False)
        self.slideshow_browser.load_string(_('No slideshow template found.'), 'text/html', 'UTF-8', 'file:///')
        self.wTree.get_widget("vbox_install").add(self.slideshow_browser)
        self.wTree.get_widget("vbox_install").show_all()

        # Configure disks webview
        self.partitions_browser = webkit.WebView()
        s = self.partitions_browser.get_settings()
        s.set_property('enable-file-access-from-file-uris', True)
        s.set_property('enable-default-context-menu', False)
        self.partitions_browser.set_transparent(True)
        self.wTree.get_widget("scrolled_partitions").add(self.partitions_browser)
        
        self.window.show_all()

        # fix text wrap
        self.fix_text_wrap()