/usr/lib/live-installer/frontend/gtk_interface.py
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
- #!/usr/bin/env python
- import sys
- sys.path.append('/usr/lib/live-installer')
- from installer import InstallerEngine, Setup, PartitionSetup
- try:
- import pygtk
- pygtk.require("2.0")
- import gtk
- import gtk.glade
- import gettext
- import os
- import commands
- import subprocess
- import sys
- import math
- sys.path.append('/usr/lib/live-installer')
- from PIL import Image
- import pango
- import threading
- import xml.dom.minidom
- from xml.dom.minidom import parse
- import gobject
- import time
- import webkit
- import GeoIP
- import urllib
- import string
- import parted
- except Exception, detail:
- print detail
- from slideshow import Slideshow
- gettext.install("live-installer", "/usr/share/linuxmint/locale")
- gtk.gdk.threads_init()
- INDEX_PARTITION_PATH=0
- INDEX_PARTITION_TYPE=1
- INDEX_PARTITION_DESCRIPTION=2
- INDEX_PARTITION_FORMAT_AS=3
- INDEX_PARTITION_MOUNT_AS=4
- INDEX_PARTITION_SIZE=5
- INDEX_PARTITION_FREE_SPACE=6
- INDEX_PARTITION_OBJECT=7
- class ProgressDialog:
-
- def __init__(self):
- self.glade = '/usr/share/live-installer/interface.glade'
- self.dTree = gtk.glade.XML(self.glade, 'progress_window')
- self.window = self.dTree.get_widget('progress_window')
- self.progressbar = self.dTree.get_widget('progressbar_operation')
- self.label = self.dTree.get_widget('label_operation')
- self.should_pulse = False
-
- def show(self, label=None, title=None):
- def pbar_pulse():
- if(not self.should_pulse):
- return False
- self.progressbar.pulse()
- return self.should_pulse
- if(label is not None):
- self.label.set_markup(label)
- if(title is not None):
- self.window.set_title(title)
- self.should_pulse = True
- self.window.show_all()
- gobject.timeout_add(100, pbar_pulse)
-
- def hide(self):
- self.should_pulse = False
- self.window.hide()
- ''' Handy. Makes message dialogs easy :D '''
- class MessageDialog(object):
- def __init__(self, title, message, style, parent=None):
- self.title = title
- self.message = message
- self.style = style
- self.parent = parent
- ''' Show me on screen '''
- def show(self):
- dialog = gtk.MessageDialog(self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, self.style, gtk.BUTTONS_OK, self.message)
- dialog.set_title(self.title)
- dialog.set_position(gtk.WIN_POS_CENTER)
- dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
- dialog.run()
- dialog.destroy()
-
- class QuestionDialog(object):
- def __init__(self, title, message, parent=None):
- self.title = title
- self.message = message
- self.parent = parent
- ''' Show me on screen '''
- def show(self):
- dialog = gtk.MessageDialog(self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, self.message)
- dialog.set_title(self.title)
- dialog.set_position(gtk.WIN_POS_CENTER)
- dialog.set_icon_from_file("/usr/share/icons/live-installer.png")
- answer = dialog.run()
- if answer==gtk.RESPONSE_YES:
- return_value = True
- else:
- return_value = False
- dialog.destroy()
- return return_value
- class WizardPage:
- def __init__(self, help_text, icon):
- self.help_text = help_text
- self.icon = icon
-
- class Timezone:
- def __init__(self, name, country_code, coordinates):
- self.height = 409 # Height of the map
- self.width = 800 # Width of the map
- self.name = name
- self.country_code = country_code
- self.coordinates = coordinates
- latlongsplit = coordinates.find('-', 1)
- if latlongsplit == -1:
- latlongsplit = coordinates.find('+', 1)
- if latlongsplit != -1:
- self.latitude = coordinates[:latlongsplit]
- self.longitude = coordinates[latlongsplit:]
- else:
- self.latitude = coordinates
- self.longitude = '+0'
-
- self.latitude = self.parse_position(self.latitude, 2)
- self.longitude = self.parse_position(self.longitude, 3)
-
- (self.x, self.y) = self.getPosition(self.latitude, self.longitude)
-
- def parse_position(self, position, wholedigits):
- if position == '' or len(position) < 4 or wholedigits > 9:
- return 0.0
- wholestr = position[:wholedigits + 1]
- fractionstr = position[wholedigits + 1:]
- whole = float(wholestr)
- fraction = float(fractionstr)
- if whole >= 0.0:
- return whole + fraction / pow(10.0, len(fractionstr))
- else:
- return whole - fraction / pow(10.0, len(fractionstr))
-
- # @return pixel coordinate of a latitude and longitude for self
- # map uses Miller Projection, but is also clipped
- def getPosition(self, la, lo):
- # need to add/sub magic numbers because the map doesn't actually go from -180...180, -90...90
- # thus the upper corner is not -180, -90 and we have to compensate
- # we need a better method of determining the actually range so we can better place citites (shtylman)
- xdeg_offset = -6
- # the 180 - 35) accounts for the fact that the map does not span the entire -90 to 90
- # the map does span the entire 360 though, just offset
- x = (self.width * (180.0 + lo) / 360.0) + (self.width * xdeg_offset/ 180.0)
- x = x % self.width
- #top and bottom clipping latitudes
- topLat = 81
- bottomLat = -59
- #percent of entire possible range
- topPer = topLat/180.0
- # get the y in rectangular coordinates
- y = 1.25 * math.log(math.tan(math.pi/4.0 + 0.4 * math.radians(la)))
- # calculate the map range (smaller than full range because the map is clipped on top and bottom
- fullRange = 4.6068250867599998
- # the amount of the full range devoted to the upper hemisphere
- topOffset = fullRange*topPer
- mapRange = abs(1.25 * math.log(math.tan(math.pi/4.0 + 0.4 * math.radians(bottomLat))) - topOffset)
- # Convert to a percentage of the map range
- y = abs(y - topOffset)
- y = y / mapRange
- # this then becomes the percentage of the height
- y = y * self.height
- return (int(x), int(y))
-
- class InstallerWindow:
- def __init__(self, fullscreen=False):
-
- #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" in sys.argv:
- 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_HDD, self.PAGE_CUSTOMWARNING, self.PAGE_CUSTOMPAUSED] = range(11)
- self.wizard_pages = range(11)
- 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_HDD] = WizardPage(_("Hard drive"), "hdd.svg")
- self.wizard_pages[self.PAGE_PARTITIONS] = WizardPage(_("Partitioning"), "hdd.svg")
- self.wizard_pages[self.PAGE_CUSTOMWARNING] = WizardPage(_("Please make sure you wish to manually manage partitions"), "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)
- 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.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/user-generic.png -resize x96 /tmp/live-installer-face.png")
- self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
-
- webcam_detected = False
- try:
- import cv
- capture = cv.CaptureFromCAM(-1)
- for i in range(10):
- img = cv.QueryFrame(capture)
- if img != None:
- webcam_detected = True
- except Exception, detail:
- print detail
- 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 webcam"))
-
- # build the language list
- self.build_lang_list()
- self.build_timezones()
- # disk view
- ren = gtk.CellRendererText()
- self.column1 = gtk.TreeViewColumn("Hard drive", ren)
- self.column1.add_attribute(ren, "text", 0)
- self.wTree.get_widget("treeview_hdds").append_column(self.column1)
- self.column2 = gtk.TreeViewColumn("Description", ren)
- self.column2.add_attribute(ren, "text", 1)
- self.wTree.get_widget("treeview_hdds").append_column(self.column2)
- self.wTree.get_widget("treeview_hdds").connect("cursor-changed", self.assign_hdd)
- self.build_hdds()
- #self.build_grub_partitions()
- self.wTree.get_widget("radio_hdd").set_group(self.wTree.get_widget("radio_custom"))
- self.wTree.get_widget("radio_hdd").connect("toggled", self.hdd_pane_toggled)
- self.wTree.get_widget("radio_hdd").set_active(True)
-
- self.wTree.get_widget("button_edit").connect("clicked", self.edit_partitions)
- self.wTree.get_widget("button_refresh").connect("clicked", self.refresh_partitions)
- self.wTree.get_widget("treeview_disks").connect("row_activated", self.assign_partition)
- self.wTree.get_widget("treeview_disks").connect( "button-release-event", self.partitions_popup_menu)
-
- # device
- ren = gtk.CellRendererText()
- self.column3 = gtk.TreeViewColumn(_("Device"), ren)
- self.column3.add_attribute(ren, "markup", INDEX_PARTITION_PATH)
- self.wTree.get_widget("treeview_disks").append_column(self.column3)
- # Type
- ren = gtk.CellRendererText()
- self.column4 = gtk.TreeViewColumn(_("Type"), ren)
- self.column4.add_attribute(ren, "markup", INDEX_PARTITION_TYPE)
- self.wTree.get_widget("treeview_disks").append_column(self.column4)
- # description
- ren = gtk.CellRendererText()
- self.column5 = gtk.TreeViewColumn(_("Operating system"), ren)
- self.column5.add_attribute(ren, "markup", INDEX_PARTITION_DESCRIPTION)
- self.wTree.get_widget("treeview_disks").append_column(self.column5)
- # mount point
- ren = gtk.CellRendererText()
- self.column6 = gtk.TreeViewColumn(_("Mount point"), ren)
- self.column6.add_attribute(ren, "markup", INDEX_PARTITION_MOUNT_AS)
- self.wTree.get_widget("treeview_disks").append_column(self.column6)
- # format
- ren = gtk.CellRendererText()
- self.column7 = gtk.TreeViewColumn(_("Format?"), ren)
- self.column7.add_attribute(ren, "markup", INDEX_PARTITION_FORMAT_AS)
- self.wTree.get_widget("treeview_disks").append_column(self.column7)
- # size
- ren = gtk.CellRendererText()
- self.column8 = gtk.TreeViewColumn(_("Size"), ren)
- self.column8.add_attribute(ren, "markup", INDEX_PARTITION_SIZE)
- self.wTree.get_widget("treeview_disks").append_column(self.column8)
- # Used space
- ren = gtk.CellRendererText()
- self.column9 = gtk.TreeViewColumn(_("Free space"), ren)
- self.column9.add_attribute(ren, "markup", INDEX_PARTITION_FREE_SPACE)
- self.wTree.get_widget("treeview_disks").append_column(self.column9)
- 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("clicked", 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")
- 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()
-
- #''' Launch the Slideshow '''
- #if ("_" in self.setup.language):
- # locale_code = self.setup.language.split("_")[0]
- #else:
- # locale_code = self.setup.language
-
- #slideshow_path = "/usr/share/live-installer-slideshow/slides/index.html"
- #if os.path.exists(slideshow_path):
- # browser = webkit.WebView()
- # s = browser.get_settings()
- # s.set_property('enable-file-access-from-file-uris', True)
- # s.set_property('enable-default-context-menu', False)
- # browser.open("file://" + slideshow_path + "#?locale=" + locale_code)
- # self.wTree.get_widget("vbox_install").add(browser)
- # self.wTree.get_widget("vbox_install").show_all()
- # Initiate the slide show
- self.slideshow_path = "/usr/share/live-installer/slideshow"
- if os.path.exists(self.slideshow_path):
- 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.open("file://" + os.path.join(self.slideshow_path, 'template.html'))
- self.wTree.get_widget("vbox_install").add(self.slideshow_browser)
- self.wTree.get_widget("vbox_install").show_all()
-
- self.browser = webkit.WebView()
- s = self.browser.get_settings()
- s.set_property('enable-file-access-from-file-uris', True)
- s.set_property('enable-default-context-menu', False)
- self.wTree.get_widget("scrolled_partitions").add(self.browser)
-
- self.window.show_all()
- # fix text wrap
- self.fix_text_wrap()
-
- def face_select_picture_button_clicked(self, widget, event):
- image = gtk.Image()
- preview = gtk.ScrolledWindow()
- preview.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- preview.set_size_request(150, 150)
- preview.add_with_viewport(image)
- image.show()
- preview.show()
- chooser = gtk.FileChooserDialog(title=None, parent=self.window,
- action=gtk.FILE_CHOOSER_ACTION_OPEN,
- buttons=(gtk.STOCK_CANCEL,
- gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN,
- gtk.RESPONSE_OK),
- backend=None)
- chooser.set_default_response(gtk.RESPONSE_OK)
- chooser.set_current_folder("/usr/share/pixmaps/faces")
- if os.path.exists("/home/mint"):
- chooser.add_shortcut_folder("/home/mint")
- filter = gtk.FileFilter()
- filter.set_name(_('Images'))
- filter.add_mime_type('image/png')
- filter.add_mime_type('image/jpeg')
- filter.add_mime_type('image/gif')
- filter.add_mime_type('bitmap/bmp')
- chooser.add_filter(filter)
- chooser.set_preview_widget(preview)
- chooser.connect("update-preview", self.update_preview_cb, preview)
- response = chooser.run()
- if response == gtk.RESPONSE_OK:
- filename = chooser.get_filename()
- os.system("convert %s -resize x96 /tmp/live-installer-face.png" % filename)
- self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
- chooser.destroy()
-
- def update_preview_cb(self, file_chooser, preview):
- filename = file_chooser.get_preview_filename()
- try:
- if filename:
- pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
- preview.child.child.set_from_pixbuf(pixbuf)
- have_preview = True
- else:
- have_preview = False
- except Exception, e:
- #print e
- have_preview = False
- file_chooser.set_preview_widget_active(have_preview)
- return
-
- def face_take_picture_button_clicked(self, widget, event):
- try:
- import cv
- capture = cv.CaptureFromCAM(-1)
- for i in range(10):
- img = cv.QueryFrame(capture)
- if img != None:
- cv.SaveImage("/tmp/live-installer-webcam.png", img)
- os.system("convert /tmp/live-installer-webcam.png -resize x96 /tmp/live-installer-face.png")
- self.wTree.get_widget("face_image").set_from_file("/tmp/live-installer-face.png")
- except Exception, detail:
- print detail
- def fix_text_wrap(self):
- while gtk.events_pending():
- gtk.main_iteration_do(False)
- # this looks bad on resize, but to handle it on resize gracefully requires quite a bit of code (to keep from lagging)
- width = self.window.get_size()[0] - 75
- # custom install warning
- self.wTree.get_widget("label_custom_install_directions_1").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_1").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_2").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_3").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_4").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_5").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_directions_6").set_size_request(width, -1)
- # custom install installation paused directions
- self.wTree.get_widget("label_custom_install_paused_1").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_paused_2").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_paused_3").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_paused_4").set_size_request(width, -1)
- self.wTree.get_widget("label_custom_install_paused_5").set_size_request(width, -1)
-
- def i18n(self):
- # about you
- self.wTree.get_widget("label_your_name").set_markup("<b>%s</b>" % _("Your full name"))
- 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"))
- self.wTree.get_widget("label_username").set_markup("<b>%s</b>" % _("Your username"))
- 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"))
- self.wTree.get_widget("label_choose_pass").set_markup("<b>%s</b>" % _("Your password"))
- 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"))
- self.wTree.get_widget("label_hostname").set_markup("<b>%s</b>" % _("Hostname"))
- 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"))
-
- self.wTree.get_widget("face_label").set_markup("<b>%s</b>" % _("Your picture"))
- 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."))
- self.wTree.get_widget("face_take_picture_button").set_label(_("Take a photo"))
-
- self.wTree.get_widget("face_select_picture_button").set_label(_("Select a picture"))
- self.wTree.get_widget("face_select_picture_button").set_tooltip_text(_("Click this button to choose a picture for your account"))
-
- # timezones
- self.wTree.get_widget("label_timezones").set_label(_("Selected timezone:"))
-
- # 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"))
-
- # keyboard page
- self.wTree.get_widget("label_test_kb").set_label(_("Use this box to test your keyboard layout"))
- self.wTree.get_widget("label_kb_model").set_label(_("Model"))
-
- # custom install warning
- 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."))
- self.wTree.get_widget("label_custom_install_directions_2").set_label(_("Before continuing, please mount your target filesystem(s) at /target."))
- self.wTree.get_widget("label_custom_install_directions_3").set_label(_("Do NOT mount virtual devices such as /dev, /proc, /sys, etc on /target/."))
- 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."))
- self.wTree.get_widget("label_custom_install_directions_5").set_label(_("During the install, you will be required to write your own /etc/fstab."))
- 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."))
- # custom install installation paused directions
- self.wTree.get_widget("label_custom_install_paused_1").set_label(_("Please do the following and then click Forward to finish Installation:"))
- 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)."))
- 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."))
- 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."))
- 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."))
- # hdd page
- self.wTree.get_widget("label_radio_hdd").set_label(_("Install Linux Mint on the selected drive:"))
- self.wTree.get_widget("label_radio_custom").set_label(_("Manually mount partitions (ADVANCED USERS ONLY)."))
-
- #Columns
- self.column1.set_title(_("Hard drive"))
- self.column2.set_title(_("Description"))
- self.column3.set_title(_("Device"))
- self.column4.set_title(_("Type"))
- self.column5.set_title(_("Operating system"))
- self.column6.set_title(_("Mount point"))
- self.column7.set_title(_("Format?"))
- self.column8.set_title(_("Size"))
- self.column9.set_title(_("Free space"))
- self.column10.set_title(_("Layout"))
- self.column11.set_title(_("Variant"))
- self.column12.set_title(_("Overview"))
-
- #Partitions
- self.wTree.get_widget("label_edit_partitions").set_label(_("Edit partitions"))
- def assign_realname(self, entry, prop):
- self.setup.real_name = entry.props.text
- text = entry.props.text.strip().lower()
- if " " in entry.props.text:
- elements = text.split()
- text = elements[0]
- self.setup.username = text
- self.wTree.get_widget("entry_username").set_text(text)
- self.setup.print_setup()
- def assign_username(self, entry, prop):
- self.setup.username = entry.props.text
- self.setup.print_setup()
- def assign_hostname(self, entry, prop):
- self.setup.hostname = entry.props.text
- self.setup.print_setup()
-
- def quit_cb(self, widget, data=None):
- ''' ask whether we should quit. because touchpads do happen '''
- gtk.main_quit()
- def assign_partition(self, widget, data=None, data2=None):
- ''' assign the partition ... '''
- model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
- if iter is not None:
- row = model[iter]
- partition = row[INDEX_PARTITION_OBJECT]
- if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1:
- dlg = PartitionDialog(row[INDEX_PARTITION_PATH], row[INDEX_PARTITION_MOUNT_AS], row[INDEX_PARTITION_FORMAT_AS], row[INDEX_PARTITION_TYPE])
- (mount_as, format_as) = dlg.show()
- self.assign_mount_point(partition, mount_as, format_as)
-
- def partitions_popup_menu( self, widget, event ):
- if event.button == 3:
- model, iter = self.wTree.get_widget("treeview_disks").get_selection().get_selected()
- if iter is not None:
- partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
- partition_type = model.get_value(iter, INDEX_PARTITION_TYPE)
- if not partition.partition.type == parted.PARTITION_EXTENDED and not partition.partition.number == -1 and "swap" not in partition_type:
- menu = gtk.Menu()
- menuItem = gtk.MenuItem(_("Edit"))
- menuItem.connect( "activate", self.assign_partition, partition)
- menu.append(menuItem)
- menuItem = gtk.SeparatorMenuItem()
- menu.append(menuItem)
- menuItem = gtk.MenuItem(_("Assign to /"))
- menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/", "ext4")
- menu.append(menuItem)
- menuItem = gtk.MenuItem(_("Assign to /home"))
- menuItem.connect( "activate", self.assign_mount_point_context_menu_wrapper, partition, "/home", "")
- menu.append(menuItem)
- menu.show_all()
- menu.popup( None, None, None, event.button, event.time )
- def assign_mount_point_context_menu_wrapper(self, menu, partition, mount_point, filesystem):
- self.assign_mount_point(partition, mount_point, filesystem)
- def assign_mount_point(self, partition, mount_point, filesystem):
-
- #Assign it in the treeview
- model = self.wTree.get_widget("treeview_disks").get_model()
- iter = model.get_iter_first()
- while iter is not None:
- iter_partition = model.get_value(iter, INDEX_PARTITION_OBJECT)
- if iter_partition == partition:
- model.set_value(iter, INDEX_PARTITION_MOUNT_AS, mount_point)
- model.set_value(iter, INDEX_PARTITION_FORMAT_AS, filesystem)
- else:
- mountpoint = model.get_value(iter, INDEX_PARTITION_MOUNT_AS)
- if mountpoint == mount_point:
- model.set_value(iter, INDEX_PARTITION_MOUNT_AS, "")
- model.set_value(iter, INDEX_PARTITION_FORMAT_AS, "")
- iter = model.iter_next(iter)
- #Assign it in our setup
- for apartition in self.setup.partitions:
- if (apartition.partition.path == partition.partition.path):
- apartition.mount_as = mount_point
- apartition.format_as = filesystem
- else:
- if apartition.mount_as == mount_point:
- apartition.mount_as = None
- apartition.format_as = None
- self.setup.print_setup()
-
- def refresh_partitions(self, widget, data=None):
- ''' refresh the partitions ... '''
- self.build_partitions()
- def edit_partitions(self, widget, data=None):
- ''' edit the partitions ... '''
- os.popen("gparted &")
- 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_timezones(self):
-
- self.combo_timezones = self.wTree.get_widget("combo_timezones")
- self.combo_timezones.connect('changed', self.timezone_combo_selected)
-
- self.timezone_colors = {}
- self.timezone_colors["2b0000"] = "-11.0"
- self.timezone_colors["550000"] = "-10.0"
- self.timezone_colors["66ff00"] = "-9.5"
- self.timezone_colors["800000"] = "-9.0"
- self.timezone_colors["aa0000"] = "-8.0"
- self.timezone_colors["d40000"] = "-7.0"
- self.timezone_colors["ff0001"] = "-6.0"
- self.timezone_colors["66ff00"] = "-5.5"
- self.timezone_colors["ff2a2a"] = "-5.0"
- self.timezone_colors["c0ff00"] = "-4.5"
- self.timezone_colors["ff5555"] = "-4.0"
- self.timezone_colors["00ff00"] = "-3.5"
- self.timezone_colors["ff8080"] = "-3.0"
- self.timezone_colors["ffaaaa"] = "-2.0"
- self.timezone_colors["ffd5d5"] = "-1.0"
- self.timezone_colors["2b1100"] = "0.0"
- self.timezone_colors["552200"] = "1.0"
- self.timezone_colors["803300"] = "2.0"
- self.timezone_colors["aa4400"] = "3.0"
- self.timezone_colors["00ff66"] = "3.5"
- self.timezone_colors["d45500"] = "4.0"
- self.timezone_colors["00ccff"] = "4.5"
- self.timezone_colors["ff6600"] = "5.0"
- self.timezone_colors["0066ff"] = "5.5"
- self.timezone_colors["00ffcc"] = "5.75"
- self.timezone_colors["ff7f2a"] = "6.0"
- self.timezone_colors["cc00ff"] = "6.5"
- self.timezone_colors["ff9955"] = "7.0"
- self.timezone_colors["ffb380"] = "8.0"
- self.timezone_colors["ffccaa"] = "9.0"
- self.timezone_colors["a90345"] = "9.5"
- self.timezone_colors["ffe6d5"] = "10.0"
- self.timezone_colors["d10255"] = "10.5"
- self.timezone_colors["d4aa00"] = "11.0"
- self.timezone_colors["fc0266"] = "11.5"
- self.timezone_colors["ffcc00"] = "12.0"
- self.timezone_colors["fd2c80"] = "12.75"
- self.timezone_colors["fc5598"] = "13.0"
-
- #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)
- self.timezone_colors["6771a9"] = "5.5" # Calcutta, India
- self.timezone_colors["ff7b7b"] = "-3.0" # Buenos Aires, Argentina
- self.timezone_colors["ff7f7f"] = "-3.0" # Rio Gallegos, Argentina
- self.timezone_colors["d45c27"] = "11.0" # Lord Howe, Australia
- self.timezone_colors["b71f54"] = "10.5" # Adelaide, Australia
- self.timezone_colors["d29130"] = "-4.0" # Aruba
- self.timezone_colors["ee5f00"] = "4.0" # Baku, Azerbaidjan
- self.timezone_colors["6a2a00"] = "2.0" # Sofia, Bulgaria
- self.timezone_colors["3c1800"] = "" # Porto Novo
- self.timezone_colors["3c1800"] = "1.0" # Benin
- self.timezone_colors["ff9898"] = "-3.0" # Maceio, Brazil
- self.timezone_colors["ff3f3f"] = "-4.0" # Rio Branco, Brazil
- self.timezone_colors["ff802c"] = "6.0" # Thimphu, Bhutan
- self.timezone_colors["ff0000"] = "-6.0" # Belize
- self.timezone_colors["11f709"] = "-3.5" # St Johns, Canada
- self.timezone_colors["e56347"] = "-4.0" # Curacao
- self.timezone_colors["cd5200"] = "4.0" # Tbilisi, Georgia
- self.timezone_colors["2f1300"] = "0.0" # Guernsey. UK
- self.timezone_colors["cea7a3"] = "0.0" # Danmarkshavn, Greenland
- self.timezone_colors["ff2b2b"] = "-4.0" # Thule, Greenland
- self.timezone_colors["79594e"] = "0.0" # Banjul, Gambia
- self.timezone_colors["c7a19d"] = "0.0" # Conakry, Guinea
- self.timezone_colors["5b3e31"] = "0.0" # Bissau, Guinea-Bissau
- self.timezone_colors["3f2314"] = "0.0" # Monrovia, Liberia
- self.timezone_colors["d515db"] = "6.5" # Rangoon, Myanmar
- self.timezone_colors["fd0000"] = "-7.0" # Bahia_Banderas, Mexico
- self.timezone_colors["ffb37f"] = "8.0" # Kuching, Malaysia
- self.timezone_colors["ff0066"] = "11.5" # Norfolk
- self.timezone_colors["351500"] = "1.0" # Lagos, Nigeria
- self.timezone_colors["ff8935"] = "12.75" # Chatham, New Zealand
- self.timezone_colors["913a00"] = "2.0" # Kigali, Rwanda
- self.timezone_colors["ffb17d"] = "8.0" # Singapore
- self.timezone_colors["ddb6b3"] = "0.0" # Freetown, Sierra Leone
- self.timezone_colors["ffb482"] = "9.0" # Dili, East Timor
- self.timezone_colors["ff5599"] = "13.0" # Tongatapu, Tonga
- self.timezone_colors["ff2020"] = "-5.0" # Monticello, USA
- self.timezone_colors["ff2525"] = "-5.0" # Marengo, USA
- self.timezone_colors["9d0000"] = "-9.0" # Metlakatla, Alaska/USA
-
- self.timezones = []
- model = gtk.ListStore(str, object)
- model.set_sort_column_id(0, gtk.SORT_ASCENDING)
- timezones = open("/usr/share/zoneinfo/zone.tab", "r")
- for line in timezones:
- if not line.strip().startswith("#"):
- content = line.strip().split("\t")
- if len(content) >= 2:
- country_code = content[0]
- coordinates = content[1]
- timezone = content[2]
- tz = Timezone(timezone, country_code, coordinates)
- self.timezones.append(tz)
- iter = model.append()
- model.set_value(iter, 0, timezone)
- model.set_value(iter, 1, tz)
- # Uncomment the code below to check that each timezone has a corresponding color code (the code is here for debugging only)
- #print "Timezone: %s, X: %s, Y: %s" % (tz.name, tz.x, tz.y)
- #if (tz.x <= 800 and tz.y <= 409):
- # im = Image.open('/usr/share/live-installer/timezone/cc.png')
- # rgb_im = im.convert('RGB')
- # hexcolor = '%02x%02x%02x' % rgb_im.getpixel((tz.x, tz.y))
- # print " Color: #%s" % (hexcolor)
- # image = "/usr/share/live-installer/timezone/timezone_%s.png" % self.timezone_colors[hexcolor]
- # print "Image: %s" % image
-
- cell = gtk.CellRendererText()
- self.combo_timezones.pack_start(cell, True)
- self.combo_timezones.add_attribute(cell, 'text', 0)
-
- self.combo_timezones.set_model(model)
- self.timezone_map = self.wTree.get_widget("image_timezones")
- timezone_event = self.wTree.get_widget("event_timezones")
- self.timezone_map.set_from_file("/usr/share/live-installer/timezone/bg.png")
- timezone_event.connect("button-release-event", self.timezone_map_clicked)
-
- def timezone_combo_selected(self, combobox):
- model = combobox.get_model()
- index = combobox.get_active()
- if index:
- timezone = model[index][1]
- self.timezone_select(timezone)
-
- def timezone_map_clicked(self, widget, event):
- x = event.x
- y = event.y
- print "Coords: %s %s" % (x, y)
-
- min_distance = 1000 # Looking for min, starting with a large number
- closest_timezone = None
- for timezone in self.timezones:
- distance = abs(x - timezone.x) + abs(y - timezone.y)
- if distance < min_distance:
- min_distance = distance
- closest_timezone = timezone
-
- print "Closest timezone %s" % closest_timezone.name
- self.timezone_select(closest_timezone)
-
- model = self.combo_timezones.get_model()
- iter = model.get_iter_first()
- while iter is not None:
- if closest_timezone.name == model.get_value(iter, 1).name:
- self.combo_timezones.set_active_iter(iter)
- break
- iter = model.iter_next(iter)
-
- def timezone_select(self, timezone):
- im = Image.open('/usr/share/live-installer/timezone/cc.png')
- rgb_im = im.convert('RGB')
- hexcolor = '%02x%02x%02x' % rgb_im.getpixel((timezone.x, timezone.y))
- print "Color: #%s" % (hexcolor)
-
- overlay_path = "/usr/share/live-installer/timezone/timezone_%s.png" % self.timezone_colors[hexcolor]
- print "Image: %s" % overlay_path
-
- # Superpose the picture of the timezone on the map
- background = Image.open("/usr/share/live-installer/timezone/bg.png")
- dot = Image.open("/usr/share/live-installer/timezone/dot.png")
- overlay = Image.open(overlay_path)
- background = background.convert("RGBA")
- overlay = overlay.convert("RGBA")
- dot = dot.convert("RGBA")
- background.paste(overlay, (0,0), overlay)
- background.paste(dot, (timezone.x-3, timezone.y-3), dot)
- background.save("/tmp/live-installer-map.png","PNG")
- self.timezone_map.set_from_file("/tmp/live-installer-map.png")
-
- # Save the selection
- self.setup.timezone = timezone.name
- self.setup.timezone_code = timezone.name
-
-
- def build_hdds(self):
- self.setup.disks = []
- model = gtk.ListStore(str, str)
- inxi = subprocess.Popen("inxi -c0 -D", shell=True, stdout=subprocess.PIPE)
- for line in inxi.stdout:
- line = line.rstrip("\r\n")
- if(line.startswith("Disks:")):
- line = line.replace("Disks:", "")
- sections = line.split(":")
- for section in sections:
- section = section.strip()
- if("/dev/" in section):
- elements = section.split()
- for element in elements:
- if "/dev/" in element:
- self.setup.disks.append(element)
- description = section.replace(element, "").strip()
- iter = model.append([element, description]);
-
- self.wTree.get_widget("treeview_hdds").set_model(model)
-
- if(len(self.setup.disks) > 0):
- # select the first HDD
- treeview = self.wTree.get_widget("treeview_hdds")
- column = treeview.get_column(0)
- path = model.get_path(model.get_iter_first())
- treeview.set_cursor(path, focus_column=column)
- treeview.scroll_to_cell(path, column=column)
- self.setup.target_disk = model.get_value(model.get_iter_first(), 0)
-
- def build_grub_partitions(self):
- grub_model = gtk.ListStore(str)
- # Add disks
- …
Large files files are truncated, but you can click here to view the full file