PageRenderTime 52ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/kdsdevs/live-installer
Python | 1924 lines | 1656 code | 145 blank | 123 comment | 110 complexity | 1309701ba8b6163aaf8b5c5446c15f36 MD5 | raw file

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. import math
  16. sys.path.append('/usr/lib/live-installer')
  17. from PIL import Image
  18. import pango
  19. import threading
  20. import xml.dom.minidom
  21. from xml.dom.minidom import parse
  22. import gobject
  23. import time
  24. import webkit
  25. import GeoIP
  26. import urllib
  27. import string
  28. import parted
  29. except Exception, detail:
  30. print detail
  31. from slideshow import Slideshow
  32. gettext.install("live-installer", "/usr/share/linuxmint/locale")
  33. gtk.gdk.threads_init()
  34. INDEX_PARTITION_PATH=0
  35. INDEX_PARTITION_TYPE=1
  36. INDEX_PARTITION_DESCRIPTION=2
  37. INDEX_PARTITION_FORMAT_AS=3
  38. INDEX_PARTITION_MOUNT_AS=4
  39. INDEX_PARTITION_SIZE=5
  40. INDEX_PARTITION_FREE_SPACE=6
  41. INDEX_PARTITION_OBJECT=7
  42. class ProgressDialog:
  43. def __init__(self):
  44. self.glade = '/usr/share/live-installer/interface.glade'
  45. self.dTree = gtk.glade.XML(self.glade, 'progress_window')
  46. self.window = self.dTree.get_widget('progress_window')
  47. self.progressbar = self.dTree.get_widget('progressbar_operation')
  48. self.label = self.dTree.get_widget('label_operation')
  49. self.should_pulse = False
  50. def show(self, label=None, title=None):
  51. def pbar_pulse():
  52. if(not self.should_pulse):
  53. return False
  54. self.progressbar.pulse()
  55. return self.should_pulse
  56. if(label is not None):
  57. self.label.set_markup(label)
  58. if(title is not None):
  59. self.window.set_title(title)
  60. self.should_pulse = True
  61. self.window.show_all()
  62. gobject.timeout_add(100, pbar_pulse)
  63. def hide(self):
  64. self.should_pulse = False
  65. self.window.hide()
  66. ''' Handy. Makes message dialogs easy :D '''
  67. class MessageDialog(object):
  68. def __init__(self, title, message, style, parent=None):
  69. self.title = title
  70. self.message = message
  71. self.style = style
  72. self.parent = parent
  73. ''' Show me on screen '''
  74. def show(self):
  75. dialog = gtk.MessageDialog(self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, self.style, gtk.BUTTONS_OK, self.message)
  76. dialog.set_title(self.title)
  77. dialog.set_position(gtk.WIN_POS_CENTER)
  78. dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
  79. dialog.run()
  80. dialog.destroy()
  81. class QuestionDialog(object):
  82. def __init__(self, title, message, parent=None):
  83. self.title = title
  84. self.message = message
  85. self.parent = parent
  86. ''' Show me on screen '''
  87. def show(self):
  88. dialog = gtk.MessageDialog(self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, self.message)
  89. dialog.set_title(self.title)
  90. dialog.set_position(gtk.WIN_POS_CENTER)
  91. dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
  92. answer = dialog.run()
  93. if answer==gtk.RESPONSE_YES:
  94. return_value = True
  95. else:
  96. return_value = False
  97. dialog.destroy()
  98. return return_value
  99. class WizardPage:
  100. def __init__(self, help_text, icon):
  101. self.help_text = help_text
  102. self.icon = icon
  103. class Timezone:
  104. def __init__(self, name, country_code, coordinates):
  105. self.height = 409 # Height of the map
  106. self.width = 800 # Width of the map
  107. self.name = name
  108. self.country_code = country_code
  109. self.coordinates = coordinates
  110. latlongsplit = coordinates.find('-', 1)
  111. if latlongsplit == -1:
  112. latlongsplit = coordinates.find('+', 1)
  113. if latlongsplit != -1:
  114. self.latitude = coordinates[:latlongsplit]
  115. self.longitude = coordinates[latlongsplit:]
  116. else:
  117. self.latitude = coordinates
  118. self.longitude = '+0'
  119. self.latitude = self.parse_position(self.latitude, 2)
  120. self.longitude = self.parse_position(self.longitude, 3)
  121. (self.x, self.y) = self.getPosition(self.latitude, self.longitude)
  122. def parse_position(self, position, wholedigits):
  123. if position == '' or len(position) < 4 or wholedigits > 9:
  124. return 0.0
  125. wholestr = position[:wholedigits + 1]
  126. fractionstr = position[wholedigits + 1:]
  127. whole = float(wholestr)
  128. fraction = float(fractionstr)
  129. if whole >= 0.0:
  130. return whole + fraction / pow(10.0, len(fractionstr))
  131. else:
  132. return whole - fraction / pow(10.0, len(fractionstr))
  133. # @return pixel coordinate of a latitude and longitude for self
  134. # map uses Miller Projection, but is also clipped
  135. def getPosition(self, la, lo):
  136. # need to add/sub magic numbers because the map doesn't actually go from -180...180, -90...90
  137. # thus the upper corner is not -180, -90 and we have to compensate
  138. # we need a better method of determining the actually range so we can better place citites (shtylman)
  139. xdeg_offset = -6
  140. # the 180 - 35) accounts for the fact that the map does not span the entire -90 to 90
  141. # the map does span the entire 360 though, just offset
  142. x = (self.width * (180.0 + lo) / 360.0) + (self.width * xdeg_offset/ 180.0)
  143. x = x % self.width
  144. #top and bottom clipping latitudes
  145. topLat = 81
  146. bottomLat = -59
  147. #percent of entire possible range
  148. topPer = topLat/180.0
  149. # get the y in rectangular coordinates
  150. y = 1.25 * math.log(math.tan(math.pi/4.0 + 0.4 * math.radians(la)))
  151. # calculate the map range (smaller than full range because the map is clipped on top and bottom
  152. fullRange = 4.6068250867599998
  153. # the amount of the full range devoted to the upper hemisphere
  154. topOffset = fullRange*topPer
  155. mapRange = abs(1.25 * math.log(math.tan(math.pi/4.0 + 0.4 * math.radians(bottomLat))) - topOffset)
  156. # Convert to a percentage of the map range
  157. y = abs(y - topOffset)
  158. y = y / mapRange
  159. # this then becomes the percentage of the height
  160. y = y * self.height
  161. return (int(x), int(y))
  162. class InstallerWindow:
  163. def __init__(self, fullscreen=False):
  164. #Build the Setup object (where we put all our choices)
  165. self.setup = Setup()
  166. self.resource_dir = '/usr/share/live-installer/'
  167. #self.glade = 'interface.glade'
  168. self.glade = os.path.join(self.resource_dir, 'interface.glade')
  169. self.wTree = gtk.glade.XML(self.glade, 'main_window')
  170. # should be set early
  171. self.done = False
  172. self.fail = False
  173. self.paused = False
  174. # here comes the installer engine
  175. self.installer = InstallerEngine()
  176. # the distribution name
  177. DISTRIBUTION_NAME = self.installer.get_distribution_name()
  178. # load the window object
  179. self.window = self.wTree.get_widget("main_window")
  180. if "--debug" in sys.argv:
  181. self.window.set_title((_("%s Installer") % DISTRIBUTION_NAME) + " (debug)")
  182. else:
  183. self.window.set_title(_("%s Installer") % DISTRIBUTION_NAME)
  184. self.window.connect("destroy", self.quit_cb)
  185. # Wizard pages
  186. [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, self.PAGE_CUSTOMWARNING, self.PAGE_CUSTOMPAUSED] = range(11)
  187. self.wizard_pages = range(11)
  188. self.wizard_pages[self.PAGE_LANGUAGE] = WizardPage(_("Language"), "locales.png")
  189. self.wizard_pages[self.PAGE_TIMEZONE] = WizardPage(_("Timezone"), "time.png")
  190. self.wizard_pages[self.PAGE_KEYBOARD] = WizardPage(_("Keyboard layout"), "keyboard.png")
  191. self.wizard_pages[self.PAGE_USER] = WizardPage(_("User info"), "user.png")
  192. self.wizard_pages[self.PAGE_HDD] = WizardPage(_("Hard drive"), "hdd.svg")
  193. self.wizard_pages[self.PAGE_PARTITIONS] = WizardPage(_("Partitioning"), "hdd.svg")
  194. self.wizard_pages[self.PAGE_CUSTOMWARNING] = WizardPage(_("Please make sure you wish to manually manage partitions"), "hdd.svg")
  195. self.wizard_pages[self.PAGE_ADVANCED] = WizardPage(_("Advanced options"), "advanced.png")
  196. self.wizard_pages[self.PAGE_OVERVIEW] = WizardPage(_("Summary"), "summary.png")
  197. self.wizard_pages[self.PAGE_INSTALL] = WizardPage(_("Installing Linux Mint..."), "install.png")
  198. self.wizard_pages[self.PAGE_CUSTOMPAUSED] = WizardPage(_("Installation is Paused: Please finish the custom installation"), "install.png")
  199. # set the button events (wizard_cb)
  200. self.wTree.get_widget("button_next").connect("clicked", self.wizard_cb, False)
  201. self.wTree.get_widget("button_back").connect("clicked", self.wizard_cb, True)
  202. self.wTree.get_widget("button_quit").connect("clicked", self.quit_cb)
  203. ren = gtk.CellRendererPixbuf()
  204. column = gtk.TreeViewColumn("Flags", ren)
  205. column.add_attribute(ren, "pixbuf", 2)
  206. self.wTree.get_widget("treeview_language_list").append_column(column)
  207. ren = gtk.CellRendererText()
  208. column = gtk.TreeViewColumn("Languages", ren)
  209. column.add_attribute(ren, "text", 0)
  210. self.wTree.get_widget("treeview_language_list").append_column(column)
  211. self.wTree.get_widget("treeview_language_list").connect("cursor-changed", self.assign_language)
  212. # build user info page
  213. self.wTree.get_widget("face_select_picture_button").connect( "button-release-event", self.face_select_picture_button_clicked)
  214. self.wTree.get_widget("face_take_picture_button").connect( "button-release-event", self.face_take_picture_button_clicked)
  215. os.system("convert /usr/share/pixmaps/faces/user-generic.png -resize x96 /tmp/live-installer-face.png")
  216. self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
  217. webcam_detected = False
  218. try:
  219. import cv
  220. capture = cv.CaptureFromCAM(-1)
  221. for i in range(10):
  222. img = cv.QueryFrame(capture)
  223. if img != None:
  224. webcam_detected = True
  225. except Exception, detail:
  226. print detail
  227. if webcam_detected:
  228. self.wTree.get_widget("face_take_picture_button").set_tooltip_text(_("Click this button to take a new picture of yourself with the webcam"))
  229. else:
  230. self.wTree.get_widget("face_take_picture_button").set_sensitive(False)
  231. self.wTree.get_widget("face_take_picture_button").set_tooltip_text(_("The installer did not detect any webcam"))
  232. # build the language list
  233. self.build_lang_list()
  234. self.build_timezones()
  235. # disk view
  236. ren = gtk.CellRendererText()
  237. self.column1 = gtk.TreeViewColumn("Hard drive", ren)
  238. self.column1.add_attribute(ren, "text", 0)
  239. self.wTree.get_widget("treeview_hdds").append_column(self.column1)
  240. self.column2 = gtk.TreeViewColumn("Description", ren)
  241. self.column2.add_attribute(ren, "text", 1)
  242. self.wTree.get_widget("treeview_hdds").append_column(self.column2)
  243. self.wTree.get_widget("treeview_hdds").connect("cursor-changed", self.assign_hdd)
  244. self.build_hdds()
  245. #self.build_grub_partitions()
  246. self.wTree.get_widget("radio_hdd").set_group(self.wTree.get_widget("radio_custom"))
  247. self.wTree.get_widget("radio_hdd").connect("toggled", self.hdd_pane_toggled)
  248. self.wTree.get_widget("radio_hdd").set_active(True)
  249. self.wTree.get_widget("button_edit").connect("clicked", self.edit_partitions)
  250. self.wTree.get_widget("button_refresh").connect("clicked", self.refresh_partitions)
  251. self.wTree.get_widget("treeview_disks").connect("row_activated", self.assign_partition)
  252. self.wTree.get_widget("treeview_disks").connect( "button-release-event", self.partitions_popup_menu)
  253. # device
  254. ren = gtk.CellRendererText()
  255. self.column3 = gtk.TreeViewColumn(_("Device"), ren)
  256. self.column3.add_attribute(ren, "markup", INDEX_PARTITION_PATH)
  257. self.wTree.get_widget("treeview_disks").append_column(self.column3)
  258. # Type
  259. ren = gtk.CellRendererText()
  260. self.column4 = gtk.TreeViewColumn(_("Type"), ren)
  261. self.column4.add_attribute(ren, "markup", INDEX_PARTITION_TYPE)
  262. self.wTree.get_widget("treeview_disks").append_column(self.column4)
  263. # description
  264. ren = gtk.CellRendererText()
  265. self.column5 = gtk.TreeViewColumn(_("Operating system"), ren)
  266. self.column5.add_attribute(ren, "markup", INDEX_PARTITION_DESCRIPTION)
  267. self.wTree.get_widget("treeview_disks").append_column(self.column5)
  268. # mount point
  269. ren = gtk.CellRendererText()
  270. self.column6 = gtk.TreeViewColumn(_("Mount point"), ren)
  271. self.column6.add_attribute(ren, "markup", INDEX_PARTITION_MOUNT_AS)
  272. self.wTree.get_widget("treeview_disks").append_column(self.column6)
  273. # format
  274. ren = gtk.CellRendererText()
  275. self.column7 = gtk.TreeViewColumn(_("Format?"), ren)
  276. self.column7.add_attribute(ren, "markup", INDEX_PARTITION_FORMAT_AS)
  277. self.wTree.get_widget("treeview_disks").append_column(self.column7)
  278. # size
  279. ren = gtk.CellRendererText()
  280. self.column8 = gtk.TreeViewColumn(_("Size"), ren)
  281. self.column8.add_attribute(ren, "markup", INDEX_PARTITION_SIZE)
  282. self.wTree.get_widget("treeview_disks").append_column(self.column8)
  283. # Used space
  284. ren = gtk.CellRendererText()
  285. self.column9 = gtk.TreeViewColumn(_("Free space"), ren)
  286. self.column9.add_attribute(ren, "markup", INDEX_PARTITION_FREE_SPACE)
  287. self.wTree.get_widget("treeview_disks").append_column(self.column9)
  288. self.wTree.get_widget("entry_your_name").connect("notify::text", self.assign_realname)
  289. self.wTree.get_widget("entry_username").connect("notify::text", self.assign_username)
  290. self.wTree.get_widget("entry_hostname").connect("notify::text", self.assign_hostname)
  291. # events for detecting password mismatch..
  292. self.wTree.get_widget("entry_userpass1").connect("changed", self.assign_password)
  293. self.wTree.get_widget("entry_userpass2").connect("changed", self.assign_password)
  294. # link the checkbutton to the combobox
  295. grub_check = self.wTree.get_widget("checkbutton_grub")
  296. grub_box = self.wTree.get_widget("combobox_grub")
  297. grub_check.connect("clicked", self.assign_grub_install, grub_box)
  298. grub_box.connect("changed", self.assign_grub_device)
  299. # Install Grub by default
  300. grub_check.set_active(True)
  301. grub_box.set_sensitive(True)
  302. # kb models
  303. cell = gtk.CellRendererText()
  304. self.wTree.get_widget("combobox_kb_model").pack_start(cell, True)
  305. self.wTree.get_widget("combobox_kb_model").add_attribute(cell, 'text', 0)
  306. self.wTree.get_widget("combobox_kb_model").connect("changed", self.assign_keyboard_model)
  307. # kb layouts
  308. ren = gtk.CellRendererText()
  309. self.column10 = gtk.TreeViewColumn(_("Layout"), ren)
  310. self.column10.add_attribute(ren, "text", 0)
  311. self.wTree.get_widget("treeview_layouts").append_column(self.column10)
  312. self.wTree.get_widget("treeview_layouts").connect("cursor-changed", self.assign_keyboard_layout)
  313. ren = gtk.CellRendererText()
  314. self.column11 = gtk.TreeViewColumn(_("Variant"), ren)
  315. self.column11.add_attribute(ren, "text", 0)
  316. self.wTree.get_widget("treeview_variants").append_column(self.column11)
  317. self.wTree.get_widget("treeview_variants").connect("cursor-changed", self.assign_keyboard_variant)
  318. self.build_kb_lists()
  319. # 'about to install' aka overview
  320. ren = gtk.CellRendererText()
  321. self.column12 = gtk.TreeViewColumn(_("Overview"), ren)
  322. self.column12.add_attribute(ren, "markup", 0)
  323. self.wTree.get_widget("treeview_overview").append_column(self.column12)
  324. # install page
  325. self.wTree.get_widget("label_install_progress").set_markup("<i>%s</i>" % _("Calculating file indexes..."))
  326. #i18n
  327. self.i18n()
  328. # build partition list
  329. self.should_pulse = False
  330. # make sure we're on the right page (no pun.)
  331. self.activate_page(0)
  332. # this is a hack atm to steal the menubar's background color
  333. self.wTree.get_widget("menubar").realize()
  334. style = self.wTree.get_widget("menubar").style.copy()
  335. self.wTree.get_widget("menubar").hide()
  336. # apply to the header
  337. self.title_box = self.wTree.get_widget("title_eventbox")
  338. bgColor = gtk.gdk.color_parse('#585858')
  339. self.title_box.modify_bg(gtk.STATE_NORMAL, bgColor)
  340. fgColor = gtk.gdk.color_parse('#FFFFFF')
  341. self.help_label = self.wTree.get_widget("help_label")
  342. self.help_label.modify_fg(gtk.STATE_NORMAL, fgColor)
  343. if(fullscreen):
  344. # dedicated installer mode thingum
  345. self.window.maximize()
  346. self.window.fullscreen()
  347. #''' Launch the Slideshow '''
  348. #if ("_" in self.setup.language):
  349. # locale_code = self.setup.language.split("_")[0]
  350. #else:
  351. # locale_code = self.setup.language
  352. #slideshow_path = "/usr/share/live-installer-slideshow/slides/index.html"
  353. #if os.path.exists(slideshow_path):
  354. # browser = webkit.WebView()
  355. # s = browser.get_settings()
  356. # s.set_property('enable-file-access-from-file-uris', True)
  357. # s.set_property('enable-default-context-menu', False)
  358. # browser.open("file://" + slideshow_path + "#?locale=" + locale_code)
  359. # self.wTree.get_widget("vbox_install").add(browser)
  360. # self.wTree.get_widget("vbox_install").show_all()
  361. # Initiate the slide show
  362. self.slideshow_path = "/usr/share/live-installer/slideshow"
  363. if os.path.exists(self.slideshow_path):
  364. self.slideshow_browser = webkit.WebView()
  365. s = self.slideshow_browser.get_settings()
  366. s.set_property('enable-file-access-from-file-uris', True)
  367. s.set_property('enable-default-context-menu', False)
  368. self.slideshow_browser.open("file://" + os.path.join(self.slideshow_path, 'template.html'))
  369. self.wTree.get_widget("vbox_install").add(self.slideshow_browser)
  370. self.wTree.get_widget("vbox_install").show_all()
  371. self.browser = webkit.WebView()
  372. s = self.browser.get_settings()
  373. s.set_property('enable-file-access-from-file-uris', True)
  374. s.set_property('enable-default-context-menu', False)
  375. self.wTree.get_widget("scrolled_partitions").add(self.browser)
  376. self.window.show_all()
  377. # fix text wrap
  378. self.fix_text_wrap()
  379. def face_select_picture_button_clicked(self, widget, event):
  380. image = gtk.Image()
  381. preview = gtk.ScrolledWindow()
  382. preview.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  383. preview.set_size_request(150, 150)
  384. preview.add_with_viewport(image)
  385. image.show()
  386. preview.show()
  387. chooser = gtk.FileChooserDialog(title=None, parent=self.window,
  388. action=gtk.FILE_CHOOSER_ACTION_OPEN,
  389. buttons=(gtk.STOCK_CANCEL,
  390. gtk.RESPONSE_CANCEL,
  391. gtk.STOCK_OPEN,
  392. gtk.RESPONSE_OK),
  393. backend=None)
  394. chooser.set_default_response(gtk.RESPONSE_OK)
  395. chooser.set_current_folder("/usr/share/pixmaps/faces")
  396. if os.path.exists("/home/mint"):
  397. chooser.add_shortcut_folder("/home/mint")
  398. filter = gtk.FileFilter()
  399. filter.set_name(_('Images'))
  400. filter.add_mime_type('image/png')
  401. filter.add_mime_type('image/jpeg')
  402. filter.add_mime_type('image/gif')
  403. filter.add_mime_type('bitmap/bmp')
  404. chooser.add_filter(filter)
  405. chooser.set_preview_widget(preview)
  406. chooser.connect("update-preview", self.update_preview_cb, preview)
  407. response = chooser.run()
  408. if response == gtk.RESPONSE_OK:
  409. filename = chooser.get_filename()
  410. os.system("convert %s -resize x96 /tmp/live-installer-face.png" % filename)
  411. self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
  412. chooser.destroy()
  413. def update_preview_cb(self, file_chooser, preview):
  414. filename = file_chooser.get_preview_filename()
  415. try:
  416. if filename:
  417. pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
  418. preview.child.child.set_from_pixbuf(pixbuf)
  419. have_preview = True
  420. else:
  421. have_preview = False
  422. except Exception, e:
  423. #print e
  424. have_preview = False
  425. file_chooser.set_preview_widget_active(have_preview)
  426. return
  427. def face_take_picture_button_clicked(self, widget, event):
  428. try:
  429. import cv
  430. capture = cv.CaptureFromCAM(-1)
  431. for i in range(10):
  432. img = cv.QueryFrame(capture)
  433. if img != None:
  434. cv.SaveImage("/tmp/live-installer-webcam.png", img)
  435. os.system("convert /tmp/live-installer-webcam.png -resize x96 /tmp/live-installer-face.png")
  436. self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
  437. except Exception, detail:
  438. print detail
  439. def fix_text_wrap(self):
  440. while gtk.events_pending():
  441. gtk.main_iteration_do(False)
  442. # this looks bad on resize, but to handle it on resize gracefully requires quite a bit of code (to keep from lagging)
  443. width = self.window.get_size()[0] - 75
  444. # custom install warning
  445. self.wTree.get_widget("label_custom_install_directions_1").set_size_request(width, -1)
  446. self.wTree.get_widget("label_custom_install_directions_1").set_size_request(width, -1)
  447. self.wTree.get_widget("label_custom_install_directions_2").set_size_request(width, -1)
  448. self.wTree.get_widget("label_custom_install_directions_3").set_size_request(width, -1)
  449. self.wTree.get_widget("label_custom_install_directions_4").set_size_request(width, -1)
  450. self.wTree.get_widget("label_custom_install_directions_5").set_size_request(width, -1)
  451. self.wTree.get_widget("label_custom_install_directions_6").set_size_request(width, -1)
  452. # custom install installation paused directions
  453. self.wTree.get_widget("label_custom_install_paused_1").set_size_request(width, -1)
  454. self.wTree.get_widget("label_custom_install_paused_2").set_size_request(width, -1)
  455. self.wTree.get_widget("label_custom_install_paused_3").set_size_request(width, -1)
  456. self.wTree.get_widget("label_custom_install_paused_4").set_size_request(width, -1)
  457. self.wTree.get_widget("label_custom_install_paused_5").set_size_request(width, -1)
  458. def i18n(self):
  459. # about you
  460. self.wTree.get_widget("label_your_name").set_markup("<b>%s</b>" % _("Your full name"))
  461. self.wTree.get_widget("label_your_name_help").set_markup("<span fgcolor='#3C3C3C'><sub><i>%s</i></sub></span>" % _("This will be shown in the About Me application"))
  462. self.wTree.get_widget("label_username").set_markup("<b>%s</b>" % _("Your username"))
  463. self.wTree.get_widget("label_username_help").set_markup("<span fgcolor='#3C3C3C'><sub><i>%s</i></sub></span>" % _("This is the name you will use to login to your computer"))
  464. self.wTree.get_widget("label_choose_pass").set_markup("<b>%s</b>" % _("Your password"))
  465. self.wTree.get_widget("label_pass_help").set_markup("<span fgcolor='#3C3C3C'><sub><i>%s</i></sub></span>" % _("Please enter your password twice to ensure it is correct"))
  466. self.wTree.get_widget("label_hostname").set_markup("<b>%s</b>" % _("Hostname"))
  467. self.wTree.get_widget("label_hostname_help").set_markup("<span fgcolor='#3C3C3C'><sub><i>%s</i></sub></span>" % _("This hostname will be the computers name on the network"))
  468. self.wTree.get_widget("face_label").set_markup("<b>%s</b>" % _("Your picture"))
  469. self.wTree.get_widget("face_description").set_markup("<span fgcolor='#3C3C3C'><sub><i>%s</i></sub></span>" % _("This picture represents your user account. It is used in the login screen and a few other places."))
  470. self.wTree.get_widget("face_take_picture_button").set_label(_("Take a photo"))
  471. self.wTree.get_widget("face_select_picture_button").set_label(_("Select a picture"))
  472. self.wTree.get_widget("face_select_picture_button").set_tooltip_text(_("Click this button to choose a picture for your account"))
  473. # timezones
  474. self.wTree.get_widget("label_timezones").set_label(_("Selected timezone:"))
  475. # grub
  476. self.wTree.get_widget("label_grub").set_markup("<b>%s</b>" % _("Bootloader"))
  477. self.wTree.get_widget("checkbutton_grub").set_label(_("Install GRUB"))
  478. self.wTree.get_widget("label_grub_help").set_label(_("GRUB is a bootloader used to load the Linux kernel"))
  479. # keyboard page
  480. self.wTree.get_widget("label_test_kb").set_label(_("Use this box to test your keyboard layout"))
  481. self.wTree.get_widget("label_kb_model").set_label(_("Model"))
  482. # custom install warning
  483. self.wTree.get_widget("label_custom_install_directions_1").set_label(_("You have selected to manage your partitions manually, this feature is for ADVANCED USERS ONLY."))
  484. self.wTree.get_widget("label_custom_install_directions_2").set_label(_("Before continuing, please mount your target filesystem(s) at /target."))
  485. self.wTree.get_widget("label_custom_install_directions_3").set_label(_("Do NOT mount virtual devices such as /dev, /proc, /sys, etc on /target/."))
  486. self.wTree.get_widget("label_custom_install_directions_4").set_label(_("During the install, you will be given time to chroot into /target and install any pacakges that will be needed to boot your new system."))
  487. self.wTree.get_widget("label_custom_install_directions_5").set_label(_("During the install, you will be required to write your own /etc/fstab."))
  488. self.wTree.get_widget("label_custom_install_directions_6").set_label(_("If you arent sure what any of this means, please go back and deselect manual partition management."))
  489. # custom install installation paused directions
  490. self.wTree.get_widget("label_custom_install_paused_1").set_label(_("Please do the following and then click Forward to finish Installation:"))
  491. self.wTree.get_widget("label_custom_install_paused_2").set_label(_("Create /target/etc/fstab for the filesystems as they will be mounted in your new system, matching those currently mounted at /target (without using the /target prefix in the mount paths themselves)."))
  492. self.wTree.get_widget("label_custom_install_paused_3").set_label(_("Install any packages that may be needed for first boot (mdadm, cryptsetup, dmraid, etc) by calling \"sudo chroot /target\" followed by the relevant apt-get/aptitude installations."))
  493. self.wTree.get_widget("label_custom_install_paused_4").set_label(_("Note that in order for update-initramfs to work properly in some cases (such as dm-crypt), you may need to have drives currently mounted using the same block device name as they appear in /target/etc/fstab."))
  494. self.wTree.get_widget("label_custom_install_paused_5").set_label(_("Double-check that your /target/etc/fstab is correct, matches what your new system will have at first boot, and matches what is currently mounted at /target."))
  495. # hdd page
  496. self.wTree.get_widget("label_radio_hdd").set_label(_("Install Linux Mint on the selected drive:"))
  497. self.wTree.get_widget("label_radio_custom").set_label(_("Manually mount partitions (ADVANCED USERS ONLY)."))
  498. #Columns
  499. self.column1.set_title(_("Hard drive"))
  500. self.column2.set_title(_("Description"))
  501. self.column3.set_title(_("Device"))
  502. self.column4.set_title(_("Type"))
  503. self.column5.set_title(_("Operating system"))
  504. self.column6.set_title(_("Mount point"))
  505. self.column7.set_title(_("Format?"))
  506. self.column8.set_title(_("Size"))
  507. self.column9.set_title(_("Free space"))
  508. self.column10.set_title(_("Layout"))
  509. self.column11.set_title(_("Variant"))
  510. self.column12.set_title(_("Overview"))
  511. #Partitions
  512. self.wTree.get_widget("label_edit_partitions").set_label(_("Edit partitions"))
  513. def assign_realname(self, entry, prop):
  514. self.setup.real_name = entry.props.text
  515. text = entry.props.text.strip().lower()
  516. if " " in entry.props.text:
  517. elements = text.split()
  518. text = elements[0]
  519. self.setup.username = text
  520. self.wTree.get_widget("entry_username").set_text(text)
  521. self.setup.print_setup()
  522. def assign_username(self, entry, prop):
  523. self.setup.username = entry.props.text
  524. self.setup.print_setup()
  525. def assign_hostname(self, entry, prop):
  526. self.setup.hostname = entry.props.text
  527. self.setup.print_setup()
  528. def quit_cb(self, widget, data=None):
  529. ''' ask whether we should quit. because touchpads do happen '''
  530. gtk.main_quit()
  531. def assign_partition(self, widget, data=None, data2=None):
  532. ''' assign the partition ... '''
  533. model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
  534. if iter is not None:
  535. row = model[iter]
  536. partition = row[INDEX_PARTITION_OBJECT]
  537. if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1:
  538. dlg = PartitionDialog(row[INDEX_PARTITION_PATH], row[INDEX_PARTITION_MOUNT_AS], row[INDEX_PARTITION_FORMAT_AS], row[INDEX_PARTITION_TYPE])
  539. (mount_as, format_as) = dlg.show()
  540. self.assign_mount_point(partition, mount_as, format_as)
  541. def partitions_popup_menu( self, widget, event ):
  542. if event.button == 3:
  543. model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
  544. if iter is not None:
  545. partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
  546. partition_type = model.get_value(iter, INDEX_PARTITION_TYPE)
  547. if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1 and "swap" not in partition_type:
  548. menu = gtk.Menu()
  549. menuItem = gtk.MenuItem(_("Edit"))
  550. menuItem.connect( "activate", self.assign_partition, partition)
  551. menu.append(menuItem)
  552. menuItem = gtk.SeparatorMenuItem()
  553. menu.append(menuItem)
  554. menuItem = gtk.MenuItem(_("Assign to /"))
  555. menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/", "ext4")
  556. menu.append(menuItem)
  557. menuItem = gtk.MenuItem(_("Assign to /home"))
  558. menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/home", "")
  559. menu.append(menuItem)
  560. menu.show_all()
  561. menu.popup( None, None, None, event.button, event.time )
  562. def assign_mount_point_context_menu_wrapper(self, menu, partition, mount_point, filesystem):
  563. self.assign_mount_point(partition, mount_point, filesystem)
  564. def assign_mount_point(self, partition, mount_point, filesystem):
  565. #Assign it in the treeview
  566. model = self.wTree.get_widget("treeview_disks").get_model()
  567. iter = model.get_iter_first()
  568. while iter is not None:
  569. iter_partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
  570. if iter_partition == partition:
  571. model.set_value(iter, INDEX_PARTITION_MOUNT_AS, mount_point)
  572. model.set_value(iter, INDEX_PARTITION_FORMAT_AS, filesystem)
  573. else:
  574. mountpoint = model.get_value(iter, INDEX_PARTITION_MOUNT_AS)
  575. if mountpoint == mount_point:
  576. model.set_value(iter, INDEX_PARTITION_MOUNT_AS, "")
  577. model.set_value(iter, INDEX_PARTITION_FORMAT_AS, "")
  578. iter = model.iter_next(iter)
  579. #Assign it in our setup
  580. for apartition in self.setup.partitions:
  581. if (apartition.partition.path == partition.partition.path):
  582. apartition.mount_as = mount_point
  583. apartition.format_as = filesystem
  584. else:
  585. if apartition.mount_as == mount_point:
  586. apartition.mount_as = None
  587. apartition.format_as = None
  588. self.setup.print_setup()
  589. def refresh_partitions(self, widget, data=None):
  590. ''' refresh the partitions ... '''
  591. self.build_partitions()
  592. def edit_partitions(self, widget, data=None):
  593. ''' edit the partitions ... '''
  594. os.popen("gparted &")
  595. def build_lang_list(self):
  596. #Try to find out where we're located...
  597. cur_country_code = None
  598. try:
  599. whatismyip = 'http://debian.linuxmint.com/installer/show_my_ip.php'
  600. ip = urllib.urlopen(whatismyip).readlines()[0]
  601. gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
  602. cur_country_code = gi.country_code_by_addr(ip)
  603. except:
  604. pass #best effort, we get here if we're not connected to the Internet
  605. #Plan B... find out what locale we're in (i.e. USA on the live session)
  606. cur_lang = os.environ['LANG']
  607. if("." in cur_lang):
  608. cur_lang = cur_lang.split(".")[0]
  609. model = gtk.ListStore(str,str,gtk.gdk.Pixbuf)
  610. model.set_sort_column_id(0, gtk.SORT_ASCENDING)
  611. #Load countries into memory
  612. countries = {}
  613. file = open(os.path.join(self.resource_dir, 'countries'), "r")
  614. for line in file:
  615. line = line.strip()
  616. split = line.split("=")
  617. if len(split) == 2:
  618. countries[split[0]] = split[1]
  619. file.close()
  620. #Load languages into memory
  621. languages = {}
  622. file = open(os.path.join(self.resource_dir, 'languages'), "r")
  623. for line in file:
  624. line = line.strip()
  625. split = line.split("=")
  626. if len(split) == 2:
  627. languages[split[0]] = split[1]
  628. file.close()
  629. path = os.path.join(self.resource_dir, 'locales')
  630. locales = open(path, "r")
  631. cur_index = -1 # find the locale :P
  632. set_index = None
  633. for line in locales:
  634. cur_index += 1
  635. if "UTF-8" in line:
  636. locale_code = line.replace("UTF-8", "")
  637. locale_code = locale_code.replace(".", "")
  638. locale_code = locale_code.strip()
  639. if "_" in locale_code:
  640. split = locale_code.split("_")
  641. if len(split) == 2:
  642. language_code = split[0]
  643. if language_code in languages:
  644. language = languages[language_code]
  645. else:
  646. language = language_code
  647. country_code = split[1].lower()
  648. if country_code in countries:
  649. country = countries[country_code]
  650. else:
  651. country = country_code
  652. language_label = "%s (%s)" % (language, country)
  653. #language_label = "%s - %s" % (country, language)
  654. iter = model.append()
  655. model.set_value(iter, 0, language_label)
  656. model.set_value(iter, 1, locale_code)
  657. flag_path = self.resource_dir + '/flags/16/' + country_code + '.png'
  658. if os.path.exists(flag_path):
  659. model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
  660. else:
  661. flag_path = self.resource_dir + '/flags/16/generic.png'
  662. model.set_value(iter, 2, gtk.gdk.pixbuf_new_from_file(flag_path))
  663. # If it's matching our country code, that's our language right there..
  664. if ((cur_country_code is not None) and (cur_country_code.lower() == country_code)):
  665. if (set_index is None):
  666. set_index = iter
  667. else:
  668. # If we find more than one language for a particular country, one of them being English, go for English by default.
  669. if (language_code == "en"):
  670. set_index = iter
  671. # Guesswork... handy for countries which have their own language (fr_FR, de_DE, es_ES.. etc. )
  672. elif (country_code == language_code):
  673. set_index = iter
  674. # as a plan B... use the locale (USA)
  675. if((set_index is None) and (locale_code == cur_lang)):
  676. set_index = iter
  677. #print "Set via locale: " + cur_lang
  678. treeview = self.wTree.get_widget("treeview_language_list")
  679. treeview.set_model(model)
  680. if(set_index is not None):
  681. column = treeview.get_column(0)
  682. path = model.get_path(set_index)
  683. treeview.set_cursor(path, focus_column=column)
  684. treeview.scroll_to_cell(path, column=column)
  685. treeview.set_search_column(0)
  686. def build_timezones(self):
  687. self.combo_timezones = self.wTree.get_widget("combo_timezones")
  688. self.combo_timezones.connect('changed', self.timezone_combo_selected)
  689. self.timezone_colors = {}
  690. self.timezone_colors["2b0000"] = "-11.0"
  691. self.timezone_colors["550000"] = "-10.0"
  692. self.timezone_colors["66ff00"] = "-9.5"
  693. self.timezone_colors["800000"] = "-9.0"
  694. self.timezone_colors["aa0000"] = "-8.0"
  695. self.timezone_colors["d40000"] = "-7.0"
  696. self.timezone_colors["ff0001"] = "-6.0"
  697. self.timezone_colors["66ff00"] = "-5.5"
  698. self.timezone_colors["ff2a2a"] = "-5.0"
  699. self.timezone_colors["c0ff00"] = "-4.5"
  700. self.timezone_colors["ff5555"] = "-4.0"
  701. self.timezone_colors["00ff00"] = "-3.5"
  702. self.timezone_colors["ff8080"] = "-3.0"
  703. self.timezone_colors["ffaaaa"] = "-2.0"
  704. self.timezone_colors["ffd5d5"] = "-1.0"
  705. self.timezone_colors["2b1100"] = "0.0"
  706. self.timezone_colors["552200"] = "1.0"
  707. self.timezone_colors["803300"] = "2.0"
  708. self.timezone_colors["aa4400"] = "3.0"
  709. self.timezone_colors["00ff66"] = "3.5"
  710. self.timezone_colors["d45500"] = "4.0"
  711. self.timezone_colors["00ccff"] = "4.5"
  712. self.timezone_colors["ff6600"] = "5.0"
  713. self.timezone_colors["0066ff"] = "5.5"
  714. self.timezone_colors["00ffcc"] = "5.75"
  715. self.timezone_colors["ff7f2a"] = "6.0"
  716. self.timezone_colors["cc00ff"] = "6.5"
  717. self.timezone_colors["ff9955"] = "7.0"
  718. self.timezone_colors["ffb380"] = "8.0"
  719. self.timezone_colors["ffccaa"] = "9.0"
  720. self.timezone_colors["a90345"] = "9.5"
  721. self.timezone_colors["ffe6d5"] = "10.0"
  722. self.timezone_colors["d10255"] = "10.5"
  723. self.timezone_colors["d4aa00"] = "11.0"
  724. self.timezone_colors["fc0266"] = "11.5"
  725. self.timezone_colors["ffcc00"] = "12.0"
  726. self.timezone_colors["fd2c80"] = "12.75"
  727. self.timezone_colors["fc5598"] = "13.0"
  728. #Add some timezones for cities which are located on borders (for which the color doesn't match the color of the rest of the timezone)
  729. self.timezone_colors["6771a9"] = "5.5" # Calcutta, India
  730. self.timezone_colors["ff7b7b"] = "-3.0" # Buenos Aires, Argentina
  731. self.timezone_colors["ff7f7f"] = "-3.0" # Rio Gallegos, Argentina
  732. self.timezone_colors["d45c27"] = "11.0" # Lord Howe, Australia
  733. self.timezone_colors["b71f54"] = "10.5" # Adelaide, Australia
  734. self.timezone_colors["d29130"] = "-4.0" # Aruba
  735. self.timezone_colors["ee5f00"] = "4.0" # Baku, Azerbaidjan
  736. self.timezone_colors["6a2a00"] = "2.0" # Sofia, Bulgaria
  737. self.timezone_colors["3c1800"] = "" # Porto Novo
  738. self.timezone_colors["3c1800"] = "1.0" # Benin
  739. self.timezone_colors["ff9898"] = "-3.0" # Maceio, Brazil
  740. self.timezone_colors["ff3f3f"] = "-4.0" # Rio Branco, Brazil
  741. self.timezone_colors["ff802c"] = "6.0" # Thimphu, Bhutan
  742. self.timezone_colors["ff0000"] = "-6.0" # Belize
  743. self.timezone_colors["11f709"] = "-3.5" # St Johns, Canada
  744. self.timezone_colors["e56347"] = "-4.0" # Curacao
  745. self.timezone_colors["cd5200"] = "4.0" # Tbilisi, Georgia
  746. self.timezone_colors["2f1300"] = "0.0" # Guernsey. UK
  747. self.timezone_colors["cea7a3"] = "0.0" # Danmarkshavn, Greenland
  748. self.timezone_colors["ff2b2b"] = "-4.0" # Thule, Greenland
  749. self.timezone_colors["79594e"] = "0.0" # Banjul, Gambia
  750. self.timezone_colors["c7a19d"] = "0.0" # Conakry, Guinea
  751. self.timezone_colors["5b3e31"] = "0.0" # Bissau, Guinea-Bissau
  752. self.timezone_colors["3f2314"] = "0.0" # Monrovia, Liberia
  753. self.timezone_colors["d515db"] = "6.5" # Rangoon, Myanmar
  754. self.timezone_colors["fd0000"] = "-7.0" # Bahia_Banderas, Mexico
  755. self.timezone_colors["ffb37f"] = "8.0" # Kuching, Malaysia
  756. self.timezone_colors["ff0066"] = "11.5" # Norfolk
  757. self.timezone_colors["351500"] = "1.0" # Lagos, Nigeria
  758. self.timezone_colors["ff8935"] = "12.75" # Chatham, New Zealand
  759. self.timezone_colors["913a00"] = "2.0" # Kigali, Rwanda
  760. self.timezone_colors["ffb17d"] = "8.0" # Singapore
  761. self.timezone_colors["ddb6b3"] = "0.0" # Freetown, Sierra Leone
  762. self.timezone_colors["ffb482"] = "9.0" # Dili, East Timor
  763. self.timezone_colors["ff5599"] = "13.0" # Tongatapu, Tonga
  764. self.timezone_colors["ff2020"] = "-5.0" # Monticello, USA
  765. self.timezone_colors["ff2525"] = "-5.0" # Marengo, USA
  766. self.timezone_colors["9d0000"] = "-9.0" # Metlakatla, Alaska/USA
  767. self.timezones = []
  768. model = gtk.ListStore(str, object)
  769. model.set_sort_column_id(0, gtk.SORT_ASCENDING)
  770. timezones = open("/usr/share/zoneinfo/zone.tab", "r")
  771. for line in timezones:
  772. if not line.strip().startswith("#"):
  773. content = line.strip().split("\t")
  774. if len(content) >= 2:
  775. country_code = content[0]
  776. coordinates = content[1]
  777. timezone = content[2]
  778. tz = Timezone(timezone, country_code, coordinates)
  779. self.timezones.append(tz)
  780. iter = model.append()
  781. model.set_value(iter, 0, timezone)
  782. model.set_value(iter, 1, tz)
  783. # Uncomment the code below to check that each timezone has a corresponding color code (the code is here for debugging only)
  784. #print "Timezone: %s, X: %s, Y: %s" % (tz.name, tz.x, tz.y)
  785. #if (tz.x <= 800 and tz.y <= 409):
  786. # im = Image.open('/usr/share/live-installer/timezone/cc.png')
  787. # rgb_im = im.convert('RGB')
  788. # hexcolor = '%02x%02x%02x' % rgb_im.getpixel((tz.x, tz.y))
  789. # print " Color: #%s" % (hexcolor)
  790. # image = "/usr/share/live-installer/timezone/timezone_%s.png" % self.timezone_colors[hexcolor]
  791. # print "Image: %s" % image
  792. cell = gtk.CellRendererText()
  793. self.combo_timezones.pack_start(cell, True)
  794. self.combo_timezones.add_attribute(cell, 'text', 0)
  795. self.combo_timezones.set_model(model)
  796. self.timezone_map = self.wTree.get_widget("image_timezones")
  797. timezone_event = self.wTree.get_widget("event_timezones")
  798. self.timezone_map.set_from_file("/usr/share/live-installer/timezone/bg.png")
  799. timezone_event.connect("button-release-event", self.timezone_map_clicked)
  800. def timezone_combo_selected(self, combobox):
  801. model = combobox.get_model()
  802. index = combobox.get_active()
  803. if index:
  804. timezone = model[index][1]
  805. self.timezone_select(timezone)
  806. def timezone_map_clicked(self, widget, event):
  807. x = event.x
  808. y = event.y
  809. print "Coords: %s %s" % (x, y)
  810. min_distance = 1000 # Looking for min, starting with a large number
  811. closest_timezone = None
  812. for timezone in self.timezones:
  813. distance = abs(x - timezone.x) + abs(y - timezone.y)
  814. if distance < min_distance:
  815. min_distance = distance
  816. closest_timezone = timezone
  817. print "Closest timezone %s" % closest_timezone.name
  818. self.timezone_select(closest_timezone)
  819. model = self.combo_timezones.get_model()
  820. iter = model.get_iter_first()
  821. while iter is not None:
  822. if closest_timezone.name == model.get_value(iter, 1).name:
  823. self.combo_timezones.set_active_iter(iter)
  824. break
  825. iter = model.iter_next(iter)
  826. def timezone_select(self, timezone):
  827. im = Image.open('/usr/share/live-installer/timezone/cc.png')
  828. rgb_im = im.convert('RGB')
  829. hexcolor = '%02x%02x%02x' % rgb_im.getpixel((timezone.x, timezone.y))
  830. print "Color: #%s" % (hexcolor)
  831. overlay_path = "/usr/share/live-installer/timezone/timezone_%s.png" % self.timezone_colors[hexcolor]
  832. print "Image: %s" % overlay_path
  833. # Superpose the picture of the timezone on the map
  834. background = Image.open("/usr/share/live-installer/timezone/bg.png")
  835. dot = Image.open("/usr/share/live-installer/timezone/dot.png")
  836. overlay = Image.open(overlay_path)
  837. background = background.convert("RGBA")
  838. overlay = overlay.convert("RGBA")
  839. dot = dot.convert("RGBA")
  840. background.paste(overlay, (0,0), overlay)
  841. background.paste(dot, (timezone.x-3, timezone.y-3), dot)
  842. background.save("/tmp/live-installer-map.png","PNG")
  843. self.timezone_map.set_from_file("/tmp/live-installer-map.png")
  844. # Save the selection
  845. self.setup.timezone = timezone.name
  846. self.setup.timezone_code = timezone.name
  847. def build_hdds(self):
  848. self.setup.disks = []
  849. model = gtk.ListStore(str, str)
  850. inxi = subprocess.Popen("inxi -c0 -D", shell=True, stdout=subprocess.PIPE)
  851. for line in inxi.stdout:
  852. line = line.rstrip("\r\n")
  853. if(line.startswith("Disks:")):
  854. line = line.replace("Disks:", "")
  855. sections = line.split(":")
  856. for section in sections:
  857. section = section.strip()
  858. if("/dev/" in section):
  859. elements = section.split()
  860. for element in elements:
  861. if "/dev/" in element:
  862. self.setup.disks.append(element)
  863. description = section.replace(element, "").strip()
  864. iter = model.append([element, description]);
  865. self.wTree.get_widget("treeview_hdds").set_model(model)
  866. if(len(self.setup.disks) > 0):
  867. # select the first HDD
  868. treeview = self.wTree.get_widget("treeview_hdds")
  869. column = treeview.get_column(0)
  870. path = model.get_path(model.get_iter_first())
  871. treeview.set_cursor(path, focus_column=column)
  872. treeview.scroll_to_cell(path, column=column)
  873. self.setup.target_disk = model.get_value(model.get_iter_first(), 0)
  874. def build_grub_partitions(self):
  875. grub_model = gtk.ListStore(str)
  876. # Add disks

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