PageRenderTime 55ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/usr/lib/live-installer/frontend/gtk_interface.py

https://github.com/taem/live-installer
Python | 1480 lines | 1298 code | 95 blank | 87 comment | 70 complexity | fab6603d186f99e0a33750414eff2f93 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. #!/usr/bin/env python
  2. import sys
  3. sys.path.append('/usr/lib/live-installer')
  4. from installer import InstallerEngine, Setup, PartitionSetup
  5. try:
  6. import pygtk
  7. pygtk.require("2.0")
  8. import gtk
  9. import gtk.glade
  10. import gettext
  11. import os
  12. import commands
  13. import subprocess
  14. import sys
  15. sys.path.append('/usr/lib/live-installer')
  16. import pango
  17. import threading
  18. import xml.dom.minidom
  19. from xml.dom.minidom import parse
  20. import gobject
  21. import time
  22. import webkit
  23. import GeoIP
  24. import urllib
  25. import string
  26. import parted
  27. except Exception, detail:
  28. print detail
  29. gettext.install("live-installer", "/usr/share/locale")
  30. gtk.gdk.threads_init()
  31. INDEX_PARTITION_PATH=0
  32. INDEX_PARTITION_TYPE=1
  33. INDEX_PARTITION_DESCRIPTION=2
  34. INDEX_PARTITION_FORMAT_AS=3
  35. INDEX_PARTITION_MOUNT_AS=4
  36. INDEX_PARTITION_SIZE=5
  37. INDEX_PARTITION_FREE_SPACE=6
  38. INDEX_PARTITION_OBJECT=7
  39. class ProgressDialog:
  40. def __init__(self):
  41. self.glade = '/usr/share/live-installer/interface.glade'
  42. self.dTree = gtk.glade.XML(self.glade, 'progress_window')
  43. self.window = self.dTree.get_widget('progress_window')
  44. self.progressbar = self.dTree.get_widget('progressbar_operation')
  45. self.label = self.dTree.get_widget('label_operation')
  46. self.should_pulse = False
  47. def show(self, label=None, title=None):
  48. def pbar_pulse():
  49. if(not self.should_pulse):
  50. return False
  51. self.progressbar.pulse()
  52. return self.should_pulse
  53. if(label is not None):
  54. self.label.set_markup(label)
  55. if(title is not None):
  56. self.window.set_title(title)
  57. self.should_pulse = True
  58. self.window.show_all()
  59. gobject.timeout_add(100, pbar_pulse)
  60. def hide(self):
  61. self.should_pulse = False
  62. self.window.hide()
  63. ''' Handy. Makes message dialogs easy :D '''
  64. class MessageDialog(object):
  65. def __init__(self, title, message, style):
  66. self.title = title
  67. self.message = message
  68. self.style = style
  69. ''' Show me on screen '''
  70. def show(self):
  71. dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, self.style, gtk.BUTTONS_OK, self.message)
  72. dialog.set_title(self.title)
  73. dialog.set_position(gtk.WIN_POS_CENTER)
  74. dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
  75. dialog.run()
  76. dialog.destroy()
  77. class QuestionDialog(object):
  78. def __init__(self, title, message):
  79. self.title = title
  80. self.message = message
  81. ''' Show me on screen '''
  82. def show(self):
  83. dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, self.message)
  84. dialog.set_title(self.title)
  85. dialog.set_position(gtk.WIN_POS_CENTER)
  86. dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
  87. answer = dialog.run()
  88. if answer==gtk.RESPONSE_YES:
  89. return_value = True
  90. else:
  91. return_value = False
  92. dialog.destroy()
  93. return return_value
  94. class WizardPage:
  95. def __init__(self, help_text, icon):
  96. self.help_text = help_text
  97. self.icon = icon
  98. class InstallerWindow:
  99. def __init__(self, fullscreen=False):
  100. #Build the Setup object (where we put all our choices)
  101. self.setup = Setup()
  102. self.resource_dir = '/usr/share/live-installer/'
  103. #self.glade = 'interface.glade'
  104. self.glade = os.path.join(self.resource_dir, 'interface.glade')
  105. self.wTree = gtk.glade.XML(self.glade, 'main_window')
  106. # should be set early
  107. self.done = False
  108. self.fail = False
  109. # here comes the installer engine
  110. self.installer = InstallerEngine()
  111. # the distribution name
  112. DISTRIBUTION_NAME = self.installer.get_distribution_name()
  113. # load the window object
  114. self.window = self.wTree.get_widget("main_window")
  115. if "--debug" in sys.argv:
  116. self.window.set_title((_("%s Installer") % DISTRIBUTION_NAME) + " (debug)")
  117. else:
  118. self.window.set_title(_("%s Installer") % DISTRIBUTION_NAME)
  119. self.window.connect("destroy", self.quit_cb)
  120. # Wizard pages
  121. [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_HDD] = range(9)
  122. self.wizard_pages = range(9)
  123. self.wizard_pages[self.PAGE_LANGUAGE] = WizardPage(_("Choose your language"), "locales.png")
  124. self.wizard_pages[self.PAGE_TIMEZONE] = WizardPage(_("Choose your timezone"), "time.png")
  125. self.wizard_pages[self.PAGE_KEYBOARD] = WizardPage(_("Choose your keyboard layout"), "keyboard.png")
  126. self.wizard_pages[self.PAGE_HDD] = WizardPage(_("On which hard drive do you want to install Kazsid?"), "hdd.svg")
  127. self.wizard_pages[self.PAGE_PARTITIONS] = WizardPage(_("Select where you want to install Kazsid"), "hdd.svg")
  128. self.wizard_pages[self.PAGE_USER] = WizardPage(_("Please indicate your name and select a username, a password and a hostname"), "user.png")
  129. self.wizard_pages[self.PAGE_ADVANCED] = WizardPage(_("Please review the following advanced options"), "advanced.png")
  130. self.wizard_pages[self.PAGE_OVERVIEW] = WizardPage(_("Please review this summary and make sure everything is correct"), "summary.png")
  131. self.wizard_pages[self.PAGE_INSTALL] = WizardPage(_("Please wait while Kazsid is being installed on your computer"), "install.png")
  132. # set the button events (wizard_cb)
  133. self.wTree.get_widget("button_next").connect("clicked", self.wizard_cb, False)
  134. self.wTree.get_widget("button_back").connect("clicked", self.wizard_cb, True)
  135. self.wTree.get_widget("button_quit").connect("clicked", self.quit_cb)
  136. ren = gtk.CellRendererPixbuf()
  137. column = gtk.TreeViewColumn("Flags", ren)
  138. column.add_attribute(ren, "pixbuf", 2)
  139. self.wTree.get_widget("treeview_language_list").append_column(column)
  140. ren = gtk.CellRendererText()
  141. column = gtk.TreeViewColumn("Languages", ren)
  142. column.add_attribute(ren, "text", 0)
  143. self.wTree.get_widget("treeview_language_list").append_column(column)
  144. self.wTree.get_widget("treeview_language_list").connect("cursor-changed", self.assign_language)
  145. # build the language list
  146. self.build_lang_list()
  147. ren = gtk.CellRendererText()
  148. column = gtk.TreeViewColumn("Timezones", ren)
  149. column.add_attribute(ren, "text", 0)
  150. self.wTree.get_widget("treeview_timezones").append_column(column)
  151. self.wTree.get_widget("treeview_timezones").connect("cursor-changed", self.assign_timezone)
  152. self.build_timezones()
  153. # disk view
  154. ren = gtk.CellRendererText()
  155. self.column1 = gtk.TreeViewColumn("Hard drive", ren)
  156. self.column1.add_attribute(ren, "text", 0)
  157. self.wTree.get_widget("treeview_hdds").append_column(self.column1)
  158. self.column2 = gtk.TreeViewColumn("Description", ren)
  159. self.column2.add_attribute(ren, "text", 1)
  160. self.wTree.get_widget("treeview_hdds").append_column(self.column2)
  161. self.wTree.get_widget("treeview_hdds").connect("cursor-changed", self.assign_hdd)
  162. self.build_hdds()
  163. #self.build_grub_partitions()
  164. self.wTree.get_widget("button_edit").connect("clicked", self.edit_partitions)
  165. self.wTree.get_widget("label_edit_partitions").set_label(_("Edit partitions"))
  166. self.wTree.get_widget("button_refresh").connect("clicked", self.refresh_partitions)
  167. self.wTree.get_widget("treeview_disks").connect("row_activated", self.assign_partition)
  168. self.wTree.get_widget("treeview_disks").connect( "button-release-event", self.partitions_popup_menu)
  169. # device
  170. ren = gtk.CellRendererText()
  171. self.column3 = gtk.TreeViewColumn(_("Device"), ren)
  172. self.column3.add_attribute(ren, "markup", INDEX_PARTITION_PATH)
  173. self.wTree.get_widget("treeview_disks").append_column(self.column3)
  174. # Type
  175. ren = gtk.CellRendererText()
  176. self.column4 = gtk.TreeViewColumn(_("Type"), ren)
  177. self.column4.add_attribute(ren, "markup", INDEX_PARTITION_TYPE)
  178. self.wTree.get_widget("treeview_disks").append_column(self.column4)
  179. # description
  180. ren = gtk.CellRendererText()
  181. self.column5 = gtk.TreeViewColumn(_("Operating system"), ren)
  182. self.column5.add_attribute(ren, "markup", INDEX_PARTITION_DESCRIPTION)
  183. self.wTree.get_widget("treeview_disks").append_column(self.column5)
  184. # mount point
  185. ren = gtk.CellRendererText()
  186. self.column6 = gtk.TreeViewColumn(_("Mount point"), ren)
  187. self.column6.add_attribute(ren, "markup", INDEX_PARTITION_MOUNT_AS)
  188. self.wTree.get_widget("treeview_disks").append_column(self.column6)
  189. # format
  190. ren = gtk.CellRendererText()
  191. self.column7 = gtk.TreeViewColumn(_("Format?"), ren)
  192. self.column7.add_attribute(ren, "markup", INDEX_PARTITION_FORMAT_AS)
  193. self.wTree.get_widget("treeview_disks").append_column(self.column7)
  194. # size
  195. ren = gtk.CellRendererText()
  196. self.column8 = gtk.TreeViewColumn(_("Size"), ren)
  197. self.column8.add_attribute(ren, "markup", INDEX_PARTITION_SIZE)
  198. self.wTree.get_widget("treeview_disks").append_column(self.column8)
  199. # Used space
  200. ren = gtk.CellRendererText()
  201. self.column9 = gtk.TreeViewColumn(_("Free space"), ren)
  202. self.column9.add_attribute(ren, "markup", INDEX_PARTITION_FREE_SPACE)
  203. self.wTree.get_widget("treeview_disks").append_column(self.column9)
  204. self.wTree.get_widget("entry_your_name").connect("notify::text", self.assign_realname)
  205. self.wTree.get_widget("entry_username").connect("notify::text", self.assign_username)
  206. self.wTree.get_widget("entry_hostname").connect("notify::text", self.assign_hostname)
  207. # events for detecting password mismatch..
  208. self.wTree.get_widget("entry_userpass1").connect("changed", self.assign_password)
  209. self.wTree.get_widget("entry_userpass2").connect("changed", self.assign_password)
  210. # link the checkbutton to the combobox
  211. grub_check = self.wTree.get_widget("checkbutton_grub")
  212. grub_box = self.wTree.get_widget("combobox_grub")
  213. grub_check.connect("clicked", self.assign_grub_install, grub_box)
  214. grub_box.connect("changed", self.assign_grub_device)
  215. # Install Grub by default
  216. grub_check.set_active(True)
  217. grub_box.set_sensitive(True)
  218. # kb models
  219. cell = gtk.CellRendererText()
  220. self.wTree.get_widget("combobox_kb_model").pack_start(cell, True)
  221. self.wTree.get_widget("combobox_kb_model").add_attribute(cell, 'text', 0)
  222. self.wTree.get_widget("combobox_kb_model").connect("changed", self.assign_keyboard_model)
  223. # kb layouts
  224. ren = gtk.CellRendererText()
  225. self.column10 = gtk.TreeViewColumn(_("Layout"), ren)
  226. self.column10.add_attribute(ren, "text", 0)
  227. self.wTree.get_widget("treeview_layouts").append_column(self.column10)
  228. self.wTree.get_widget("treeview_layouts").connect("cursor-changed", self.assign_keyboard_layout)
  229. ren = gtk.CellRendererText()
  230. self.column11 = gtk.TreeViewColumn(_("Variant"), ren)
  231. self.column11.add_attribute(ren, "text", 0)
  232. self.wTree.get_widget("treeview_variants").append_column(self.column11)
  233. self.wTree.get_widget("treeview_variants").connect("cursor-changed", self.assign_keyboard_variant)
  234. #self.build_kb_lists()
  235. # 'about to install' aka overview
  236. ren = gtk.CellRendererText()
  237. self.column12 = gtk.TreeViewColumn(_("Overview"), ren)
  238. self.column12.add_attribute(ren, "markup", 0)
  239. self.wTree.get_widget("treeview_overview").append_column(self.column12)
  240. # install page
  241. self.wTree.get_widget("label_install_progress").set_markup("<i>%s</i>" % _("Calculating file indexes..."))
  242. #i18n
  243. self.i18n()
  244. # build partition list
  245. self.should_pulse = False
  246. # make sure we're on the right page (no pun.)
  247. self.activate_page(0)
  248. # this is a hack atm to steal the menubar's background color
  249. self.wTree.get_widget("menubar").realize()
  250. style = self.wTree.get_widget("menubar").style.copy()
  251. self.wTree.get_widget("menubar").hide()
  252. # apply to the header
  253. self.wTree.get_widget("help_label").realize()
  254. self.wTree.get_widget("help_label").modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_NORMAL])
  255. if(fullscreen):
  256. # dedicated installer mode thingum
  257. self.window.maximize()
  258. self.window.fullscreen()
  259. #''' Launch the Slideshow '''
  260. #if ("_" in self.setup.language):
  261. # locale_code = self.setup.language.split("_")[0]
  262. #else:
  263. # locale_code = self.setup.language
  264. #slideshow_path = "/usr/share/live-installer-slideshow/slides/index.html"
  265. #if os.path.exists(slideshow_path):
  266. # browser = webkit.WebView()
  267. # s = browser.get_settings()
  268. # s.set_property('enable-file-access-from-file-uris', True)
  269. # s.set_property('enable-default-context-menu', False)
  270. # browser.open("file://" + slideshow_path + "#?locale=" + locale_code)
  271. # self.wTree.get_widget("vbox_install").add(browser)
  272. # self.wTree.get_widget("vbox_install").show_all()
  273. self.browser = webkit.WebView()
  274. s = self.browser.get_settings()
  275. s.set_property('enable-file-access-from-file-uris', True)
  276. s.set_property('enable-default-context-menu', False)
  277. self.wTree.get_widget("scrolled_partitions").add(self.browser)
  278. self.window.show_all()
  279. def i18n(self):
  280. # about you
  281. self.wTree.get_widget("label_your_name").set_markup("<b>%s</b>" % _("Your full name"))
  282. self.wTree.get_widget("label_your_name_help").set_label(_("This will be shown in the About Me application"))
  283. self.wTree.get_widget("label_username").set_markup("<b>%s</b>" % _("Your username"))
  284. self.wTree.get_widget("label_username_help").set_label(_("This is the name you will use to login to your computer"))
  285. self.wTree.get_widget("label_choose_pass").set_markup("<b>%s</b>" % _("Your password"))
  286. self.wTree.get_widget("label_pass_help").set_label(_("Please enter your password twice to ensure it is correct"))
  287. self.wTree.get_widget("label_hostname").set_markup("<b>%s</b>" % _("Hostname"))
  288. self.wTree.get_widget("label_hostname_help").set_label(_("This hostname will be the computers name on the network"))
  289. # grub
  290. self.wTree.get_widget("label_grub").set_markup("<b>%s</b>" % _("Bootloader"))
  291. self.wTree.get_widget("checkbutton_grub").set_label(_("Install GRUB"))
  292. self.wTree.get_widget("label_grub_help").set_label(_("GRUB is a bootloader used to load the Linux kernel"))
  293. # keyboard page
  294. self.wTree.get_widget("label_test_kb").set_label(_("Use this box to test your keyboard layout"))
  295. self.wTree.get_widget("label_kb_model").set_label(_("Model"))
  296. #Installation
  297. self.wTree.get_widget("label_install_1").set_label(_("Please wait while the operating system is installed on your computer."))
  298. self.wTree.get_widget("label_install_2").set_label(_("The installation should take approximately 10 minutes."))
  299. self.wTree.get_widget("label_install_3").set_label(_("We hope you enjoy this new release. Thank you for choosing Kazsid."))
  300. #Columns
  301. self.column1.set_title(_("Hard drive"))
  302. self.column2.set_title(_("Description"))
  303. self.column3.set_title(_("Device"))
  304. self.column4.set_title(_("Type"))
  305. self.column5.set_title(_("Operating system"))
  306. self.column6.set_title(_("Mount point"))
  307. self.column7.set_title(_("Format?"))
  308. self.column8.set_title(_("Size"))
  309. self.column9.set_title(_("Free space"))
  310. self.column10.set_title(_("Layout"))
  311. self.column11.set_title(_("Variant"))
  312. self.column12.set_title(_("Overview"))
  313. def assign_realname(self, entry, prop):
  314. self.setup.real_name = entry.props.text
  315. text = entry.props.text.strip().lower()
  316. if " " in entry.props.text:
  317. elements = text.split()
  318. text = elements[0]
  319. self.setup.username = text
  320. self.wTree.get_widget("entry_username").set_text(text)
  321. self.setup.print_setup()
  322. def assign_username(self, entry, prop):
  323. self.setup.username = entry.props.text
  324. self.setup.print_setup()
  325. def assign_hostname(self, entry, prop):
  326. self.setup.hostname = entry.props.text
  327. self.setup.print_setup()
  328. def quit_cb(self, widget, data=None):
  329. ''' ask whether we should quit. because touchpads do happen '''
  330. gtk.main_quit()
  331. def assign_partition(self, widget, data=None, data2=None):
  332. ''' assign the partition ... '''
  333. model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
  334. if iter is not None:
  335. row = model[iter]
  336. partition = row[INDEX_PARTITION_OBJECT]
  337. if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1:
  338. dlg = PartitionDialog(row[INDEX_PARTITION_PATH], row[INDEX_PARTITION_MOUNT_AS], row[INDEX_PARTITION_FORMAT_AS], row[INDEX_PARTITION_TYPE])
  339. (mount_as, format_as) = dlg.show()
  340. self.assign_mount_point(partition, mount_as, format_as)
  341. def partitions_popup_menu( self, widget, event ):
  342. if event.button == 3:
  343. model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
  344. if iter is not None:
  345. partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
  346. partition_type = model.get_value(iter, INDEX_PARTITION_TYPE)
  347. if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1 and "swap" not in partition_type:
  348. menu = gtk.Menu()
  349. menuItem = gtk.MenuItem(_("Edit"))
  350. menuItem.connect( "activate", self.assign_partition, partition)
  351. menu.append(menuItem)
  352. menuItem = gtk.SeparatorMenuItem()
  353. menu.append(menuItem)
  354. menuItem = gtk.MenuItem(_("Assign to /"))
  355. menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/", "ext4")
  356. menu.append(menuItem)
  357. menuItem = gtk.MenuItem(_("Assign to /home"))
  358. menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/home", "")
  359. menu.append(menuItem)
  360. menu.show_all()
  361. menu.popup( None, None, None, event.button, event.time )
  362. def assign_mount_point_context_menu_wrapper(self, menu, partition, mount_point, filesystem):
  363. self.assign_mount_point(partition, mount_point, filesystem)
  364. def assign_mount_point(self, partition, mount_point, filesystem):
  365. #Assign it in the treeview
  366. model = self.wTree.get_widget("treeview_disks").get_model()
  367. iter = model.get_iter_first()
  368. while iter is not None:
  369. iter_partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
  370. if iter_partition == partition:
  371. model.set_value(iter, INDEX_PARTITION_MOUNT_AS, mount_point)
  372. model.set_value(iter, INDEX_PARTITION_FORMAT_AS, filesystem)
  373. else:
  374. mountpoint = model.get_value(iter, INDEX_PARTITION_MOUNT_AS)
  375. if mountpoint == mount_point:
  376. model.set_value(iter, INDEX_PARTITION_MOUNT_AS, "")
  377. model.set_value(iter, INDEX_PARTITION_FORMAT_AS, "")
  378. iter = model.iter_next(iter)
  379. #Assign it in our setup
  380. for apartition in self.setup.partitions:
  381. if (apartition.partition.path == partition.partition.path):
  382. apartition.mount_as = mount_point
  383. apartition.format_as = filesystem
  384. else:
  385. if apartition.mount_as == mount_point:
  386. apartition.mount_as = None
  387. apartition.format_as = None
  388. self.setup.print_setup()
  389. def refresh_partitions(self, widget, data=None):
  390. ''' refresh the partitions ... '''
  391. self.build_partitions()
  392. def edit_partitions(self, widget, data=None):
  393. ''' edit the partitions ... '''
  394. os.popen("gparted &")
  395. def build_lang_list(self):
  396. #Try to find out where we're located...
  397. cur_country_code = None
  398. # try:
  399. # whatismyip = 'http://debian.linuxmint.com/installer/show_my_ip.php'
  400. # ip = urllib.urlopen(whatismyip).readlines()[0]
  401. # gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
  402. # cur_country_code = gi.country_code_by_addr(ip)
  403. # except:
  404. # pass #best effort, we get here if we're not connected to the Internet
  405. #Plan B... find out what locale we're in (i.e. USA on the live session)
  406. cur_lang = os.environ['LANG']
  407. if("." in cur_lang):
  408. cur_lang = cur_lang.split(".")[0]
  409. model = gtk.ListStore(str,str,gtk.gdk.Pixbuf)
  410. model.set_sort_column_id(0, gtk.SORT_ASCENDING)
  411. #Load countries into memory
  412. countries = {}
  413. file = open(os.path.join(self.resource_dir, 'countries'), "r")
  414. for line in file:
  415. line = line.strip()
  416. split = line.split("=")
  417. if len(split) == 2:
  418. countries[split[0]] = split[1]
  419. file.close()
  420. #Load languages into memory
  421. languages = {}
  422. file = open(os.path.join(self.resource_dir, 'languages'), "r")
  423. for line in file:
  424. line = line.strip()
  425. split = line.split("=")
  426. if len(split) == 2:
  427. languages[split[0]] = split[1]
  428. file.close()
  429. path = os.path.join(self.resource_dir, 'locales')
  430. locales = open(path, "r")
  431. cur_index = -1 # find the locale :P
  432. set_index = None
  433. for line in locales:
  434. cur_index += 1
  435. if "UTF-8" in line:
  436. locale_code = line.replace("UTF-8", "")
  437. locale_code = locale_code.replace(".", "")
  438. locale_code = locale_code.strip()
  439. if "_" in locale_code:
  440. split = locale_code.split("_")
  441. if len(split) == 2:
  442. language_code = split[0]
  443. if language_code in languages:
  444. language = languages[language_code]
  445. else:
  446. language = language_code
  447. country_code = split[1].lower()
  448. if country_code in countries:
  449. country = countries[country_code]
  450. else:
  451. country = country_code
  452. language_label = "%s (%s)" % (language, country)
  453. #language_label = "%s - %s" % (country, language)
  454. iter = model.append()
  455. model.set_value(iter, 0, language_label)
  456. model.set_value(iter, 1, locale_code)
  457. flag_path = self.resource_dir + '/flags/16/' + country_code + '.png'
  458. if os.path.exists(flag_path):
  459. model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
  460. else:
  461. flag_path = self.resource_dir + '/flags/16/generic.png'
  462. model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
  463. # If it's matching our country code, that's our language right there..
  464. if ((cur_country_code is not None) and (cur_country_code.lower() == country_code)):
  465. if (set_index is None):
  466. set_index = iter
  467. else:
  468. # If we find more than one language for a particular country, one of them being English, go for English by default.
  469. if (language_code == "en"):
  470. set_index = iter
  471. # Guesswork... handy for countries which have their own language (fr_FR, de_DE, es_ES.. etc. )
  472. elif (country_code == language_code):
  473. set_index = iter
  474. # as a plan B... use the locale (USA)
  475. if((set_index is None) and (locale_code == cur_lang)):
  476. set_index = iter
  477. #print "Set via locale: " + cur_lang
  478. treeview = self.wTree.get_widget("treeview_language_list")
  479. treeview.set_model(model)
  480. if(set_index is not None):
  481. column = treeview.get_column(0)
  482. path = model.get_path(set_index)
  483. treeview.set_cursor(path, focus_column=column)
  484. treeview.scroll_to_cell(path, column=column)
  485. treeview.set_search_column(0)
  486. def build_timezones(self):
  487. model = gtk.ListStore(str, str)
  488. model.set_sort_column_id(0, gtk.SORT_ASCENDING)
  489. path = os.path.join(self.resource_dir, 'timezones')
  490. timezones = open(path, "r")
  491. cur_index = -1 # find the timezone :P
  492. set_index = None
  493. for line in timezones:
  494. cur_index += 1
  495. content = line.strip().split()
  496. if len(content) == 2:
  497. country_code = content[0]
  498. timezone = content[1]
  499. iter = model.append()
  500. model.set_value(iter, 0, timezone)
  501. model.set_value(iter, 1, country_code)
  502. treeview = self.wTree.get_widget("treeview_timezones")
  503. treeview.set_model(model)
  504. treeview.set_search_column(0)
  505. def build_hdds(self):
  506. self.setup.disks = []
  507. model = gtk.ListStore(str, str)
  508. inxi = subprocess.Popen("inxi -c0 -D", shell=True, stdout=subprocess.PIPE)
  509. for line in inxi.stdout:
  510. line = line.rstrip("\r\n")
  511. if(line.startswith("Disks:")):
  512. line = line.replace("Disks:", "")
  513. sections = line.split(":")
  514. for section in sections:
  515. section = section.strip()
  516. if("/dev/" in section):
  517. elements = section.split()
  518. for element in elements:
  519. if "/dev/" in element:
  520. self.setup.disks.append(element)
  521. description = section.replace(element, "").strip()
  522. iter = model.append([element, description]);
  523. self.wTree.get_widget("treeview_hdds").set_model(model)
  524. if(len(self.setup.disks) > 0):
  525. # select the first HDD
  526. treeview = self.wTree.get_widget("treeview_hdds")
  527. column = treeview.get_column(0)
  528. path = model.get_path(model.get_iter_first())
  529. treeview.set_cursor(path, focus_column=column)
  530. treeview.scroll_to_cell(path, column=column)
  531. self.setup.target_disk = model.get_value(model.get_iter_first(), 0)
  532. def build_grub_partitions(self):
  533. grub_model = gtk.ListStore(str)
  534. # Add disks
  535. for disk in self.setup.disks:
  536. grub_model.append([disk])
  537. # Add partitions
  538. partitions = commands.getoutput("fdisk -l | grep ^/dev/").split("\n")
  539. for partition in partitions:
  540. try:
  541. partition = partition.split()[0].strip()
  542. if partition.startswith("/dev/"):
  543. grub_model.append([partition])
  544. except Exception, detail:
  545. print detail
  546. self.wTree.get_widget("combobox_grub").set_model(grub_model)
  547. self.wTree.get_widget("combobox_grub").set_active(0)
  548. def build_partitions(self):
  549. self.window.set_sensitive(False)
  550. # "busy" cursor.
  551. cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
  552. self.window.window.set_cursor(cursor)
  553. os.popen('mkdir -p /tmp/live-installer/tmpmount')
  554. try:
  555. #grub_model = gtk.ListStore(str)
  556. self.setup.partitions = []
  557. html_partitions = ""
  558. model = gtk.ListStore(str,str,str,str,str,str,str, object, bool, str, str, bool)
  559. model2 = gtk.ListStore(str)
  560. swap_found = False
  561. if self.setup.target_disk is not None:
  562. path = self.setup.target_disk # i.e. /dev/sda
  563. #grub_model.append([path])
  564. device = parted.getDevice(path)
  565. try:
  566. disk = parted.Disk(device)
  567. except Exception:
  568. dialog = QuestionDialog(_("Installation Tool"), _("No partition table was found on the hard drive. Do you want the installer to create a set of partitions for you? Note: This will erase any data present on the disk."))
  569. if (dialog.show()):
  570. # Create a default partition set up
  571. disk = parted.freshDisk(device, 'msdos')
  572. disk.commit()
  573. #Swap
  574. regions = disk.getFreeSpaceRegions()
  575. if len(regions) > 0:
  576. region = regions[-1]
  577. ram_size = int(commands.getoutput("cat /proc/meminfo | grep MemTotal | awk {'print $2'}")) # in KiB
  578. post_mbr_gap = parted.sizeToSectors(1, "MiB", device.sectorSize) # Grub2 requires a post-MBR gap
  579. start = post_mbr_gap
  580. num_sectors = parted.sizeToSectors(ram_size, "KiB", device.sectorSize)
  581. num_sectors = int(float(num_sectors) * 1.5) # Swap is 1.5 times bigger than RAM
  582. end = start + num_sectors
  583. cylinder = device.endSectorToCylinder(end)
  584. end = device.endCylinderToSector(cylinder)
  585. geometry = parted.Geometry(device=device, start=start, end=end)
  586. if end < region.length:
  587. partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geometry)
  588. constraint = parted.Constraint(exactGeom=geometry)
  589. disk.addPartition(partition=partition, constraint=constraint)
  590. disk.commit()
  591. os.system("mkswap %s" % partition.path)
  592. #Root
  593. regions = disk.getFreeSpaceRegions()
  594. if len(regions) > 0:
  595. region = regions[-1]
  596. partition = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=region)
  597. constraint = parted.Constraint(exactGeom=region)
  598. disk.addPartition(partition=partition, constraint=constraint)
  599. disk.commit()
  600. os.system("mkfs.ext4 %s" % partition.path)
  601. self.build_partitions()
  602. return
  603. else:
  604. # Do nothing... just get out of here..
  605. raise
  606. partition = disk.getFirstPartition()
  607. last_added_partition = PartitionSetup(partition)
  608. #self.setup.partitions.append(last_added_partition)
  609. partition = partition.nextPartition()
  610. html_partitions = html_partitions + "<table width='100%'><tr>"
  611. while (partition is not None):
  612. if last_added_partition.partition.number == -1 and partition.number == -1:
  613. last_added_partition.add_partition(partition)
  614. else:
  615. last_added_partition = PartitionSetup(partition)
  616. if "swap" in last_added_partition.type:
  617. last_added_partition.type = "swap"
  618. if partition.number != -1 and "swap" not in last_added_partition.type and partition.type != parted.PARTITION_EXTENDED:
  619. #grub_model.append([partition.path])
  620. #Umount temp folder
  621. if ('/tmp/live-installer/tmpmount' in commands.getoutput('mount')):
  622. os.popen('umount /tmp/live-installer/tmpmount')
  623. #Mount partition if not mounted
  624. if (partition.path not in commands.getoutput('mount')):
  625. os.system("mount %s /tmp/live-installer/tmpmount" % partition.path)
  626. #Identify partition's description and used space
  627. if (partition.path in commands.getoutput('mount')):
  628. df_lines = commands.getoutput("df 2>/dev/null | grep %s" % partition.path).split('\n')
  629. for df_line in df_lines:
  630. df_elements = df_line.split()
  631. if df_elements[0] == partition.path:
  632. last_added_partition.used_space = df_elements[4]
  633. mount_point = df_elements[5]
  634. if "%" in last_added_partition.used_space:
  635. used_space_pct = int(last_added_partition.used_space.replace("%", "").strip())
  636. last_added_partition.free_space = int(float(last_added_partition.size) * (float(100) - float(used_space_pct)) / float(100))
  637. if os.path.exists(os.path.join(mount_point, 'etc/lsb-release')):
  638. last_added_partition.description = commands.getoutput("cat " + os.path.join(mount_point, 'etc/lsb-release') + " | grep DISTRIB_DESCRIPTION").replace('DISTRIB_DESCRIPTION', '').replace('=', '').replace('"', '').strip()
  639. if os.path.exists(os.path.join(mount_point, 'etc/issue')):
  640. last_added_partition.description = commands.getoutput("cat " + os.path.join(mount_point, 'etc/issue')).replace('\\n', '').replace('\l', '').strip()
  641. if os.path.exists(os.path.join(mount_point, 'Windows/servicing/Version')):
  642. version = commands.getoutput("ls %s" % os.path.join(mount_point, 'Windows/servicing/Version'))
  643. if version.startswith("6.1"):
  644. last_added_partition.description = "Windows 7"
  645. elif version.startswith("6.0"):
  646. last_added_partition.description = "Windows Vista"
  647. elif version.startswith("5.1") or version.startswith("5.2"):
  648. last_added_partition.description = "Windows XP"
  649. elif version.startswith("5.0"):
  650. last_added_partition.description = "Windows 2000"
  651. elif version.startswith("4.90"):
  652. last_added_partition.description = "Windows Me"
  653. elif version.startswith("4.1"):
  654. last_added_partition.description = "Windows 98"
  655. elif version.startswith("4.0.1381"):
  656. last_added_partition.description = "Windows NT"
  657. elif version.startswith("4.0.950"):
  658. last_added_partition.description = "Windows 95"
  659. elif os.path.exists(os.path.join(mount_point, 'Boot/BCD')):
  660. if os.system("grep -qs \"V.i.s.t.a\" " + os.path.join(mount_point, 'Boot/BCD')) == 0:
  661. last_added_partition.description = "Windows Vista bootloader"
  662. elif os.system("grep -qs \"W.i.n.d.o.w.s. .7\" " + os.path.join(mount_point, 'Boot/BCD')) == 0:
  663. last_added_partition.description = "Windows 7 bootloader"
  664. elif os.system("grep -qs \"W.i.n.d.o.w.s. .R.e.c.o.v.e.r.y. .E.n.v.i.r.o.n.m.e.n.t\" " + os.path.join(mount_point, 'Boot/BCD')) == 0:
  665. last_added_partition.description = "Windows recovery"
  666. elif os.system("grep -qs \"W.i.n.d.o.w.s. .S.e.r.v.e.r. .2.0.0.8\" " + os.path.join(mount_point, 'Boot/BCD')) == 0:
  667. last_added_partition.description = "Windows Server 2008 bootloader"
  668. else:
  669. last_added_partition.description = "Windows bootloader"
  670. elif os.path.exists(os.path.join(mount_point, 'Windows/System32')):
  671. last_added_partition.description = "Windows"
  672. break
  673. else:
  674. print "Failed to mount %s" % partition.path
  675. #Umount temp folder
  676. if ('/tmp/live-installer/tmpmount' in commands.getoutput('mount')):
  677. os.popen('umount /tmp/live-installer/tmpmount')
  678. if last_added_partition.size > 1.0:
  679. if last_added_partition.partition.type == parted.PARTITION_LOGICAL:
  680. display_name = " " + last_added_partition.name
  681. else:
  682. display_name = last_added_partition.name
  683. iter = model.append([display_name, last_added_partition.type, last_added_partition.description, "", "", '%.0f' % round(last_added_partition.size, 0), last_added_partition.free_space, last_added_partition, False, last_added_partition.start, last_added_partition.end, False]);
  684. if last_added_partition.partition.number == -1:
  685. model.set_value(iter, INDEX_PARTITION_TYPE, "<span foreground='#a9a9a9'>%s</span>" % last_added_partition.type)
  686. elif last_added_partition.partition.type == parted.PARTITION_EXTENDED:
  687. model.set_value(iter, INDEX_PARTITION_TYPE, "<span foreground='#a9a9a9'>%s</span>" % _("Extended"))
  688. else:
  689. if last_added_partition.type == "ntfs":
  690. color = "#42e5ac"
  691. elif last_added_partition.type == "fat32":
  692. color = "#18d918"
  693. elif last_added_partition.type == "ext4":
  694. color = "#4b6983"
  695. elif last_added_partition.type == "ext3":
  696. color = "#7590ae"
  697. elif last_added_partition.type in ["linux-swap", "swap"]:
  698. color = "#c1665a"
  699. last_added_partition.mount_as = "swap"
  700. model.set_value(iter, INDEX_PARTITION_MOUNT_AS, "swap")
  701. else:
  702. color = "#a9a9a9"
  703. model.set_value(iter, INDEX_PARTITION_TYPE, "<span foreground='%s'>%s</span>" % (color, last_added_partition.type))
  704. html_partition = "<td class='partition-cell' title='$title' style='border: 3px solid $color;' width='$space%'><div class='partition'>\n <div style='width: $usage; background-color: #f8f8ba; height: 50px'></div>\n <div class='partition-text'>$path</div><div class='partition-os'>$OS</div>\n</div>\n</td>"
  705. deviceSize = float(device.getSize()) * float(0.9) # Hack.. reducing the real size to 90% of what it is, to make sure our partitions fit..
  706. space = int((float(partition.getSize()) / deviceSize) * float(80))
  707. subs = {}
  708. if (space >= 10):
  709. subs['path'] = display_name.replace("/dev/", "")
  710. subs['OS'] = last_added_partition.description
  711. elif (space >= 5):
  712. subs['path'] = display_name.replace("/dev/", "")
  713. subs['OS'] = ""
  714. else:
  715. #Not enough space, don't write the name
  716. subs['path'] = ""
  717. subs['OS'] = ""
  718. subs['color'] = color
  719. if (space == 0):
  720. space = 1
  721. subs['space'] = space
  722. subs['title'] = display_name + "\n" + last_added_partition.description
  723. if "%" in last_added_partition.used_space:
  724. subs['usage'] = last_added_partition.used_space.strip()
  725. html_partition = string.Template(html_partition).safe_substitute(subs)
  726. html_partitions = html_partitions + html_partition
  727. self.setup.partitions.append(last_added_partition)
  728. partition = partition.nextPartition()
  729. html_partitions = html_partitions + "</tr></table>"
  730. #self.wTree.get_widget("combobox_grub").set_model(grub_model)
  731. #self.wTree.get_widget("combobox_grub").set_active(0)
  732. import tempfile
  733. html_header = "<html><head><style>body {background-color:#d6d6d6;} \
  734. .partition{position:relative; width:100%; float: left; background: white;} \
  735. .partition-cell{ position:relative; margin: 2px 5px 2px 0; padding: 1px; float: left; background: white;} \
  736. .partition-text{ position:absolute; top:10; text-align: center; width=100px; left: 0; right: 0; margin: 0 auto; font-size:12px; } \
  737. .partition-os{ position:absolute; top:30; text-align: center; width=100px; left: 0; right: 0; margin: 0 auto; font-size:10px; font-style:italic;color:#555555;} </style></head><body>"
  738. html_footer = "</body></html>"
  739. html = html_header + html_partitions + html_footer
  740. # create temporary file
  741. f = tempfile.NamedTemporaryFile(delete=False)
  742. f.write(html)
  743. f.close()
  744. self.browser.open(f.name)
  745. #browser.load_html_string(html, "file://")
  746. self.wTree.get_widget("scrolled_partitions").show_all()
  747. self.wTree.get_widget("treeview_disks").set_model(model)
  748. except Exception, detail:
  749. print detail
  750. self.window.set_sensitive(True)
  751. self.window.window.set_cursor(None)
  752. def build_kb_lists(self):
  753. ''' Do some xml kung-fu and load the keyboard stuffs '''
  754. # firstly we'll determine the layouts in use
  755. p = subprocess.Popen("setxkbmap -print",shell=True,stdout=subprocess.PIPE)
  756. for line in p.stdout:
  757. # strip it
  758. line = line.rstrip("\r\n")
  759. line = line.replace("{","")
  760. line = line.replace("}","")
  761. line = line.replace(";","")
  762. if("xkb_symbols" in line):
  763. # decipher the layout in use
  764. section = line.split("\"")[1] # split by the " mark
  765. self.setup.keyboard_layout = section.split("+")[1]
  766. if("xkb_geometry" in line):
  767. first_bracket = line.index("(") +1
  768. substr = line[first_bracket:]
  769. last_bracket = substr.index(")")
  770. substr = substr[0:last_bracket]
  771. keyboard_geom = substr
  772. p.poll()
  773. xml_file = '/usr/share/X11/xkb/rules/xorg.xml'
  774. model_models = gtk.ListStore(str,str)
  775. model_models.set_sort_column_id(0, gtk.SORT_ASCENDING)
  776. model_layouts = gtk.ListStore(str,str)
  777. model_layouts.set_sort_column_id(0, gtk.SORT_ASCENDING)
  778. dom = parse(xml_file)
  779. # if we find the users keyboard info we can set it in the list
  780. set_keyboard_model = None
  781. set_keyboard_layout = None
  782. set_keyboard_variant = None
  783. # grab the root element
  784. root = dom.getElementsByTagName('xkbConfigRegistry')[0]
  785. # build the list of models
  786. root_models = root.getElementsByTagName('modelList')[0]
  787. for element in root_models.getElementsByTagName('model'):
  788. conf = element.getElementsByTagName('configItem')[0]
  789. name = conf.getElementsByTagName('name')[0]
  790. desc = conf.getElementsByTagName('description')[0]
  791. #vendor = conf.getElementsByTagName('vendor')[0] # presently unused..
  792. iter_model = model_models.append([self.getText(desc.childNodes), self.getText(name.childNodes)])
  793. item = self.getText(name.childNodes)
  794. if(item == keyboard_geom):
  795. set_keyboard_model = iter_model
  796. root_layouts = root.getElementsByTagName('layoutList')[0]
  797. for element in root_layouts.getElementsByTagName('layout'):
  798. conf = element.getElementsByTagName('configItem')[0]
  799. name = conf.getElementsByTagName('name')[0]
  800. desc = conf.getElementsByTagName('description')[0]
  801. iter_layout = model_layouts.append([self.getText(desc.childNodes), self.getText(name.childNodes)])
  802. item = self.getText(name.childNodes)
  803. if(item == self.setup.keyboard_layout):
  804. set_keyboard_layout = iter_layout
  805. # now set the model
  806. self.wTree.get_widget("combobox_kb_model").set_model(model_models)
  807. self.wTree.get_widget("treeview_layouts").set_model(model_layouts)
  808. if(set_keyboard_layout is not None):
  809. # show it in the list
  810. treeview = self.wTree.get_widget("treeview_layouts")
  811. model = treeview.get_model()
  812. column = treeview.get_column(0)
  813. path = model.get_path(set_keyboard_layout)
  814. treeview.set_cursor(path, focus_column=column)
  815. treeview.scroll_to_cell(path, column=column)
  816. if(set_keyboard_model is not None):
  817. # show it in the combo
  818. combo = self.wTree.get_widget("combobox_kb_model")
  819. model = combo.get_model()
  820. combo.set_active_iter(set_keyboard_model)

Large files files are truncated, but you can click here to view the full file