/[gli]/branches/overhaul/src/fe/gtk/Partition.py
Gentoo

Contents of /branches/overhaul/src/fe/gtk/Partition.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1623 - (show annotations) (download) (as text)
Fri Jan 19 10:19:38 2007 UTC (7 years, 10 months ago) by agaffney
File MIME type: text/x-python
File size: 19519 byte(s)
remove Help button
rearrange Stage screen
1 # Copyright 1999-2005 Gentoo Foundation
2 # This source code is distributed under the terms of version 2 of the GNU
3 # General Public License as published by the Free Software Foundation, a copy
4 # of which can be found in the main directory of this project.
5
6 import gtk
7 import GLIScreen
8 import Partitioning
9 from GLIException import *
10 import re
11 import PartitionButton
12 import PartProperties
13 from gettext import gettext as _
14
15 class Panel(GLIScreen.GLIScreen):
16
17 title = _("Partitioning")
18 part_buttons = {}
19 drives = []
20 devices = {}
21 active_device = ""
22 active_device_bytes_in_sector = 0
23 active_part_idx = -1
24 colors = { 'ext2': '#0af2fe', 'ext3': '#0af2fe', 'unalloc': '#a2a2a2', 'unknown': '#ed03e0', 'free': '#ffffff', 'ntfs': '#f20600', 'fat16': '#3d07f9', 'fat32': '#3d07f9', 'reiserfs': '#f0ff00', 'linux-swap': '#12ff09', 'xfs': '#006600', 'jfs': '#ffb400', 'hfs': '#fdb0ff', 'hfs+': '#fdb0ff', 'apple_bootstrap': '#fdb0ff' }
25 supported_filesystems = ["ext2", "ext3", "linux-swap", "xfs", "jfs", "reiserfs", "fat16", "fat32", "ntfs", "hfs", "hfs+"]
26 _helptext = """
27 <b><u>Partitioning</u></b>
28
29 The choices you make on this screen are very important. There are 2 ways to do \
30 your partitioning.
31
32 The first method is the Recommended Layout. If you really have no idea how you \
33 should lay out your partitions, this is probably the best option. You will need \
34 at least 4GB of concurrent disk space to use this option. If you have any \
35 existing partitions, they will be kept intact. Three partitions will be created: \
36 /boot (100MB), swap (calculated based on physical memory, up to 512MB), and \
37 / (remaining concurrent space). The mountpoints and default mount options will
38 be automatically set for you. If you would like to mount any of your previously
39 existing partitions, you will need to edit those manually.
40
41 The second method is the old fashioned one: doing it yourself. The partition
42 edit is fairly straightforward (although, not <i>that</i> straightforward as
43 this help would not need to exist).
44
45 The currently active disk is represented by the bar near the top of the screen.
46 If you have more than one disk present in your system, you can change the
47 active disk by choosing another disk from the drop down box labeled 'Devices'.
48 Along the bottom of the screen, there is a color key for the disk representation
49 above.
50
51 To edit an existing partition, you must first select it by clicking it in the
52 bar above. You will get a brief overview of the partition below the bar. To edit
53 the partition's properties, click the button labeled 'Properties'. To delete it,
54 click the 'Delete' button. You will be asked for confirmation before the
55 partition is removed.
56
57 When you edit a partition's properties, you'll get a popup dialog with a few
58 options. If the installer is able to resize the partition, you will be able to
59 slide the bar at the top or enter a new size in the fields below the slider.
60 You can choose whether or not you want the partition to be formatted. If you
61 to keep the data, you should leave this as No. You can also choose a mountpoint
62 and mount options for the partition. If you don't enter a mountpoint, the
63 partition will not be mounted during the install and will not be added to your
64 /etc/fstab. Click 'OK' to save the changes you have made or 'Cancel' to leave it
65 as it was.
66
67 To create a new partition, select some unallocated space in the bar at the top.
68 The popup dialog that appears is the same one used for editing an existing
69 partition. The difference is that you will be able to select a partition type
70 (primary or logical for x86/amd64) and a filesystem type. If you select logical
71 for the type, an extended partition will be created automatically and take up
72 all of the remaining unallocated space. All partitions created after this will
73 automatically be logical. For a partition for use by Linux, you will want to use
74 ext2, ext3, reiserfs, jfs, or xfs. Ext3 is the recommended type.
75
76 Keep in mind that none of the changes to your partition table and filesystems
77 will be committed until you click the 'Install' button on the last screen of the
78 installer. Also, if your existing partitions are out of disk order, the
79 installer will reorder the partition numbers so that they match the physical
80 disk order.
81 """
82
83 def __init__(self, controller):
84 GLIScreen.GLIScreen.__init__(self, controller, show_title=True)
85
86 vert = gtk.VBox(False, 0)
87 vert.set_border_width(10)
88
89 content_str = _("""
90 On this screen, you will be presented with a list of detected partitionable devices. Selecting
91 a device will show you the current partitions on it (if any) and allow you to add, remove, and
92 resize partitions.""")
93
94 content_label = gtk.Label(content_str)
95 vert.pack_start(content_label, expand=False, fill=False, padding=0) # This was removed for screen space
96 container = gtk.HBox(False, 0)
97 detected_dev_label = gtk.Label(_("Devices:"))
98 container.pack_start(detected_dev_label, expand=False, fill=False, padding=0)
99 self.detected_dev_combo = gtk.combo_box_new_text()
100 self.detected_dev_combo.connect("changed", self.drive_changed)
101 container.pack_start(self.detected_dev_combo, expand=False, fill=False, padding=10)
102 self.part_button_recommended = gtk.Button(_(" Recommended layout "))
103 self.part_button_recommended.connect("clicked", self.part_button_recommended_clicked)
104 container.pack_end(self.part_button_recommended, expand=False, fill=False, padding=0)
105 self.part_button_clear = gtk.Button(_(" Clear partitions "))
106 self.part_button_clear.connect("clicked", self.part_button_clear_clicked)
107 container.pack_end(self.part_button_clear, expand=False, fill=False, padding=10)
108 # self.part_button_dump_info = gtk.Button(_(" Dump to console (debug) "))
109 # self.part_button_dump_info.connect("clicked", self.dump_part_info_to_console)
110 # container.pack_end(self.part_button_dump_info, expand=False, fill=False, padding=0)
111
112 vert.pack_start(container, expand=False, fill=False, padding=10)
113
114 # This builds the container for the "whole disk" display at the top
115 part_table_frame = gtk.Frame()
116 part_table_frame.set_shadow_type(gtk.SHADOW_IN)
117 self.part_table = gtk.Table(1, 1, False)
118 self.part_table.set_size_request(-1, 40)
119 part_table_frame.add(self.part_table)
120 vert.pack_start(part_table_frame, expand=False, fill=False, padding=5)
121
122 # This builds the partition info box
123 self.part_info_box = gtk.HBox(False, 0)
124 part_info_table = gtk.Table(6, 2, False)
125 part_info_table.set_col_spacings(10)
126 info_partition_label = gtk.Label(_("Partition:"))
127 info_partition_label.set_alignment(0.0, 0.5)
128 self.info_partition = gtk.Label()
129 self.info_partition.set_alignment(0.0, 0.5)
130 info_type_label = gtk.Label(_("Type:"))
131 info_type_label.set_alignment(0.0, 0.5)
132 self.info_type = gtk.Label()
133 self.info_type.set_alignment(0.0, 0.5)
134 info_filesystem_label = gtk.Label(_("Filesystem:"))
135 info_filesystem_label.set_alignment(0.0, 0.5)
136 self.info_filesystem = gtk.Label()
137 self.info_filesystem.set_alignment(0.0, 0.5)
138 info_size_label = gtk.Label(_("Size:"))
139 info_size_label.set_alignment(0.0, 0.5)
140 self.info_size = gtk.Label()
141 self.info_size.set_alignment(0.0, 0.5)
142 part_info_table.attach(info_partition_label, 0, 1, 0, 1)
143 part_info_table.attach(self.info_partition, 1, 2, 0, 1)
144 part_info_table.attach(info_type_label, 0, 1, 1, 2)
145 part_info_table.attach(self.info_type, 1, 2, 1, 2)
146 part_info_table.attach(info_filesystem_label, 0, 1, 2, 3)
147 part_info_table.attach(self.info_filesystem, 1, 2, 2, 3)
148 part_info_table.attach(info_size_label, 0, 1, 3, 4)
149 part_info_table.attach(self.info_size, 1, 2, 3, 4)
150 self.part_info_box.pack_start(part_info_table, expand=False, fill=False)
151 vert.pack_start(self.part_info_box, expand=False, fill=False, padding=10)
152
153 # This builds the row of buttons
154 self.part_button_box = gtk.HBox(False, 0)
155 self.part_button_delete = gtk.Button(_(" Delete "))
156 self.part_button_delete.connect("clicked", self.part_button_delete_clicked)
157 self.part_button_box.pack_start(self.part_button_delete, expand=False, fill=False, padding=0)
158 # self.part_button_properties = gtk.Button(_(" Properties "))
159 # self.part_button_properties.connect("clicked", self.part_button_properties_clicked)
160 # self.part_button_box.pack_start(self.part_button_properties, expand=False, fill=False, padding=10)
161 vert.pack_start(self.part_button_box, expand=False, fill=False, padding=10)
162
163 # This builds the color key at the bottom
164 color_codes = [ { 'label': "Swap", 'color': '#12ff09' },
165 { 'label': "Ext2/3", 'color': '#0af2fe' },
166 { 'label': "Reiserfs", 'color': '#f0ff00' },
167 { 'label': "JFS", 'color': '#ffb400' },
168 { 'label': "XFS", 'color': '#006600' },
169 { 'label': "FAT", 'color': '#3d07f9' },
170 { 'label': "NTFS", 'color': '#f20600' },
171 { 'label': "HFS", 'color': '#fdb0ff' },
172 { 'label': _("Other"), 'color': '#ed03e0' },
173 # { 'label': "Free space", 'color': '#ffffff' },
174 { 'label': _("Unallocated"), 'color': '#a2a2a2' }
175 ]
176 color_codes_box = gtk.HBox(False, 0)
177 vert.pack_end(color_codes_box, expand=False, fill=False, padding=2)
178 for color in color_codes:
179 temp_xpm = [ "12 12 2 1",
180 "B c #000000",
181 "C c " + color['color'],
182 "BBBBBBBBBBBB",
183 "BCCCCCCCCCCB",
184 "BCCCCCCCCCCB",
185 "BCCCCCCCCCCB",
186 "BCCCCCCCCCCB",
187 "BCCCCCCCCCCB",
188 "BCCCCCCCCCCB",
189 "BCCCCCCCCCCB",
190 "BCCCCCCCCCCB",
191 "BCCCCCCCCCCB",
192 "BCCCCCCCCCCB",
193 "BBBBBBBBBBBB"
194 ]
195 pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d(self.controller.window.window, None, temp_xpm)
196 tmp_image = gtk.Image()
197 tmp_image.set_from_pixmap(pixmap, mask)
198 tmpbox = gtk.HBox(False, 0)
199 tmpbox.pack_start(tmp_image, expand=False, fill=False, padding=3)
200 tmpbox.pack_start(gtk.Label(color['label']), expand=False, fill=False, padding=3)
201 color_codes_box.pack_start(tmpbox, expand=False, fill=False, padding=6)
202
203 self.add_content(vert)
204
205 def drive_changed(self, combobox, data=None):
206 self.active_device = self.drives[self.detected_dev_combo.get_active()]
207 self.draw_part_box()
208 self.active_device_bytes_in_sector = self.devices[self.active_device].get_geometry()['sector_size']
209 self.info_partition.set_text("")
210 self.info_type.set_text("")
211 self.info_filesystem.set_text("")
212 self.info_size.set_text("")
213 self.part_info_box.hide_all()
214 self.part_button_box.hide_all()
215
216 def part_selected(self, button, dev=None, idx=None):
217 tmppart = self.devices[dev][idx]
218 self.info_partition.set_text(tmppart['devnode'])
219 if tmppart.is_logical():
220 self.info_type.set_text(_("Logical"))
221 elif tmppart.get_type() == "extended":
222 self.info_type.set_text(_("Extended"))
223 else:
224 self.info_type.set_text(_("Primary"))
225 fstype = tmppart.get_type()
226 if fstype == "extended":
227 self.info_filesystem.set_text(_("N/A"))
228 else:
229 self.info_filesystem.set_text(fstype)
230 part_size = int(tmppart['mb'])
231 self.info_size.set_text(str(part_size) + _(" MB"))
232 self.active_part_idx = idx
233 self.part_button_delete.set_sensitive(True)
234 self.part_info_box.show_all()
235 self.part_button_box.show_all()
236
237 def unalloc_selected(self, button, idx=None):
238 tmppart = self.devices[self.active_device][idx]
239 props = PartProperties.PartProperties(self, tmppart)
240 props.run()
241
242 def part_button_delete_clicked(self, button, data=None):
243 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_YES_NO, message_format=_("Are you sure you want to delete ") + self.devices[self.active_device][self.active_part_idx]['devnode'])
244 resp = msgdlg.run()
245 msgdlg.destroy()
246 if resp == gtk.RESPONSE_YES:
247 self.devices[self.active_device].remove_partition(self.active_part_idx)
248 if self.devices[self.active_device]._labelinfo['extended']:
249 ext_idx = self.devices[self.active_device].get_extended_partition()
250 if ext_idx > -1 and not len([x for x in self.devices[self.active_device][ext_idx].get_logicals() if x['type'] != "free"]):
251 self.devices[self.active_device].remove_partition(ext_idx)
252 self.drive_changed(None)
253
254 def part_button_recommended_clicked(self, button):
255 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_YES_NO, message_format=_("This will clear your drive and apply a recommended partition layout. Are you sure you want to do this?"))
256 resp = msgdlg.run()
257 msgdlg.destroy()
258 if resp == gtk.RESPONSE_YES:
259 try:
260 self.devices[self.active_device].do_recommended()
261 except GLIException, error:
262 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=error.get_error_msg())
263 msgdlg.run()
264 msgdlg.destroy()
265 self.draw_part_box()
266
267 def part_button_clear_clicked(self, button):
268 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_YES_NO, message_format=_("Are you sure you wish to clear the partition table for " + self.active_device + "?"))
269 resp = msgdlg.run()
270 msgdlg.destroy()
271 if resp == gtk.RESPONSE_YES:
272 self.devices[self.active_device].clear_partitions()
273 self.drive_changed(self.detected_dev_combo)
274
275 def draw_part_box(self):
276 # partlist = self.devices[self.active_device].get_ordered_partition_list()
277 total_mb = self.devices[self.active_device].get_geometry()['total_mb']
278 for button in self.part_buttons.keys():
279 self.part_table.remove(self.part_buttons[button])
280 self.part_table.resize(1, 100)
281 self.part_buttons = {}
282 last_percent = 0
283 last_log_percent = 0
284 extended_part = 0
285 extended_table = None
286 for idx, tmppart in enumerate(self.devices[self.active_device]):
287 # tmppart = self.devices[self.active_device][part]
288 if tmppart.get_type() == "free":
289 partsize = tmppart.get_mb()
290 percent = (float(partsize) / float(total_mb)) * 100
291 if percent < 1: percent = 1
292 percent = int(percent)
293 # print "minor: " + str(part) + ", mb: " + str(partsize) + ", percent: " + str(percent) + ", last_percent: " + str(last_percent)
294 if tmppart.is_logical():
295 tmpbutton = PartitionButton.Partition(color1=self.colors['unalloc'], color2=self.colors['unalloc'], label="", division=0)
296 tmpbutton.connect("clicked", self.unalloc_selected, idx)
297 extended_table.attach(tmpbutton, last_log_percent, (last_log_percent + percent), 0, 1)
298 last_log_percent = last_log_percent + percent
299 else:
300 self.part_buttons['free_' + str(idx)] = PartitionButton.Partition(color1=self.colors['unalloc'], color2=self.colors['unalloc'], label="", division=0)
301 if self.devices[self.active_device]._labelinfo['extended'] and self.devices[self.active_device].get_partition_idx_from_minor(1) > -1 and self.devices[self.active_device].get_partition_idx_from_minor(2) > -1 and self.devices[self.active_device].get_partition_idx_from_minor(3) > -1 and self.devices[self.active_device].get_partition_idx_from_minor(4) > -1:
302 self.part_buttons['free_' + str(idx)].connect("clicked", self.show_no_more_primary_message)
303 else:
304 self.part_buttons['free_' + str(idx)].connect("clicked", self.unalloc_selected, idx)
305 self.part_table.attach(self.part_buttons['free_' + str(idx)], last_percent, (last_percent + percent), 0, 1)
306 last_percent = last_percent + percent
307 else:
308 partsize = tmppart.get_mb()
309 percent = (float(partsize) / float(total_mb)) * 100
310 if percent < 1: percent = 1
311 percent = int(percent)
312 tmpminor = int(tmppart.get_minor())
313 tmpdevice = self.active_device
314 # print "minor: " + str(tmpminor) + ", mb: " + str(partsize) + ", percent: " + str(percent) + ", last_percent: " + str(last_percent)
315 if tmppart.is_extended():
316 extended_table = gtk.Table(1, percent)
317 extended_table.set_border_width(3)
318 extended_part = tmpminor
319 self.part_buttons[tmpminor] = extended_table
320 self.part_table.attach(self.part_buttons[tmpminor], last_percent, (last_percent + percent), 0, 1)
321 last_percent = last_percent + percent
322 elif tmppart.is_logical():
323 tmpbutton = PartitionButton.Partition(color1=self.colors[tmppart.get_type()], color2=self.colors[tmppart.get_type()], label="", division=0)
324 if percent >= 15:
325 tmpbutton.set_label(tmppart['devnode'])
326 extended_table.attach(tmpbutton, last_log_percent, (last_log_percent + percent), 0, 1)
327 last_log_percent = last_log_percent + percent
328 tmpbutton.connect("clicked", self.part_selected, tmpdevice, idx)
329 else:
330 self.part_buttons[tmpminor] = PartitionButton.Partition(color1=self.colors[tmppart.get_type()], color2=self.colors[tmppart.get_type()], label="", division=0)
331 if percent >= 15:
332 self.part_buttons[tmpminor].set_label(tmppart['devnode'])
333 self.part_buttons[tmpminor].connect("clicked", self.part_selected, tmpdevice, idx)
334 self.part_table.attach(self.part_buttons[tmpminor], last_percent, (last_percent + percent), 0, 1)
335 last_percent = last_percent + percent
336 self.part_table.show_all()
337
338 def show_no_more_primary_message(self, button, data=None):
339 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=_("You cannot create more than 4 primary partitions. If you need more partitions, delete one or more and create logical partitions."))
340 msgdlg.run()
341 msgdlg.destroy()
342
343 def part_button_properties_clicked(self, widget, data=None):
344 tmppart = self.devices[self.active_device][self.active_part_idx]
345 props = PartProperties.PartProperties(self, tmppart)
346 props.run()
347
348 def activate(self):
349 self.controller.SHOW_BUTTON_EXIT = True
350 # self.controller.SHOW_BUTTON_HELP = True
351 self.controller.SHOW_BUTTON_BACK = False
352 self.controller.SHOW_BUTTON_FORWARD = True
353 self.controller.SHOW_BUTTON_FINISH = False
354
355 part_load_error = 0
356 tmp_drives = Partitioning.detect_devices()
357 tmp_drives.sort()
358 for drive in tmp_drives:
359 try:
360 self.devices[drive] = Partitioning.Device(drive, arch="x86")
361 self.detected_dev_combo.append_text(drive)
362 self.drives.append(drive)
363 except:
364 print _("Exception received while loading partitions from device " + drive)
365 if self.devices.has_key(drive): del self.devices[drive]
366 msgdlg = gtk.MessageDialog(parent=self.controller.window, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_OK, message_format="There was an error loading the partition table from device " + drive + ". It will not be displayed.")
367 msgdlg.run()
368 msgdlg.destroy()
369
370 if not self.drives:
371 tmp_drives = self.devices.keys()
372 tmp_drives.sort()
373 self.drives = tmp_drives
374 for drive in self.drives:
375 self.detected_dev_combo.append_text(drive)
376
377 if self.devices:
378 self.active_device = self.drives[0]
379 self.detected_dev_combo.set_active(0)
380 self.drive_changed(None)
381
382 def deactivate(self):
383 return True

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20