| 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 PartitionButton
|
| 8 |
from gettext import gettext as _
|
| 9 |
|
| 10 |
class PartProperties(gtk.Window):
|
| 11 |
|
| 12 |
def __init__(self, controller, device, idx):
|
| 13 |
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
|
| 14 |
|
| 15 |
self.controller = controller
|
| 16 |
self.device = device
|
| 17 |
self.idx = idx
|
| 18 |
self.part = self.controller.devices[device].get_partition(idx)
|
| 19 |
self.minor = self.part['minor']
|
| 20 |
self.min_size = self.part['min_size']
|
| 21 |
self.max_size = self.part['max_size']
|
| 22 |
self.cur_size = self.part['mb']
|
| 23 |
self.fstype = self.part['type']
|
| 24 |
if self.min_size == -1 or self.max_size == -1:
|
| 25 |
self.min_size = self.cur_size
|
| 26 |
self.max_size = self.cur_size
|
| 27 |
self.sync_slider_to_text = True
|
| 28 |
self.supported_filesystems = self.controller.devices[self.device].get_supported_filesystems()
|
| 29 |
|
| 30 |
self.connect("delete_event", self.delete_event)
|
| 31 |
self.connect("destroy", self.destroy_event)
|
| 32 |
self.set_default_size(400,300)
|
| 33 |
if self.fstype == "free":
|
| 34 |
self.set_title(_("New partition on ") + device)
|
| 35 |
else:
|
| 36 |
self.set_title(_("Properties for ") + self.part['devnode'])
|
| 37 |
|
| 38 |
self.globalbox = gtk.VBox(False, 0)
|
| 39 |
self.globalbox.set_border_width(10)
|
| 40 |
|
| 41 |
self.resize_box = gtk.VBox(False, 0)
|
| 42 |
self.resize_hpaned = gtk.HPaned()
|
| 43 |
# self.resize_hpaned.set_size_request(400, -1)
|
| 44 |
self.resize_hpaned.connect("size-allocate", self.part_resized)
|
| 45 |
self.resize_part_space_frame = gtk.Frame()
|
| 46 |
self.resize_part_space_frame.set_shadow_type(gtk.SHADOW_IN)
|
| 47 |
self.resize_part_space = PartitionButton.Partition(color1=self.controller.colors['linux-swap'], color2=self.controller.colors['free'], division=0, label="")
|
| 48 |
self.resize_part_space.set_sensitive(False)
|
| 49 |
self.resize_part_space_frame.add(self.resize_part_space)
|
| 50 |
if self.type == "free" or self.min_size <= 1:
|
| 51 |
self.resize_hpaned.pack1(self.resize_part_space_frame, resize=True, shrink=True)
|
| 52 |
else:
|
| 53 |
self.resize_hpaned.pack1(self.resize_part_space_frame, resize=True, shrink=False)
|
| 54 |
self.resize_unalloc_space_frame = gtk.Frame()
|
| 55 |
self.resize_unalloc_space_frame.set_shadow_type(gtk.SHADOW_IN)
|
| 56 |
self.resize_unalloc_space = PartitionButton.Partition(color1=self.controller.colors['unalloc'], color2=self.controller.colors['unalloc'], label="")
|
| 57 |
self.resize_unalloc_space.set_sensitive(False)
|
| 58 |
self.resize_unalloc_space_frame.add(self.resize_unalloc_space)
|
| 59 |
self.resize_hpaned.add2(self.resize_unalloc_space_frame)
|
| 60 |
self.resize_hpaned.set_position(0)
|
| 61 |
self.resize_box.pack_start(self.resize_hpaned, expand=False, fill=False, padding=0)
|
| 62 |
self.resize_box.pack_start(gtk.Label(_("You can slide above or enter values below")), expand=False, padding=2)
|
| 63 |
resize_text_box = gtk.HBox(False, 0)
|
| 64 |
resize_text_box.pack_start(gtk.Label(_("New size:")), expand=False, fill=False, padding=0)
|
| 65 |
self.resize_info_part_size = gtk.Entry(max=9)
|
| 66 |
self.resize_info_part_size.set_width_chars(7)
|
| 67 |
self.resize_info_part_size.connect("insert-text", self.validate_keypress)
|
| 68 |
self.resize_info_part_size.connect("focus-out-event", self.update_slider_and_entries, "part-size")
|
| 69 |
resize_text_box.pack_start(self.resize_info_part_size, expand=False, fill=False, padding=6)
|
| 70 |
resize_text_box.pack_start(gtk.Label(_("MB")), expand=False, fill=False, padding=0)
|
| 71 |
resize_text_box.pack_start(gtk.Label(" "), expand=False, fill=False, padding=20)
|
| 72 |
resize_text_box.pack_start(gtk.Label(_("Unalloc. size:")), expand=False, fill=False, padding=6)
|
| 73 |
self.resize_info_unalloc_size = gtk.Entry(max=9)
|
| 74 |
self.resize_info_unalloc_size.set_width_chars(7)
|
| 75 |
self.resize_info_unalloc_size.connect("insert-text", self.validate_keypress)
|
| 76 |
self.resize_info_unalloc_size.connect("focus-out-event", self.update_slider_and_entries, "unalloc-size")
|
| 77 |
resize_text_box.pack_start(self.resize_info_unalloc_size, expand=False, fill=False, padding=0)
|
| 78 |
resize_text_box.pack_start(gtk.Label("MB"), expand=False, fill=False, padding=3)
|
| 79 |
self.resize_box.pack_start(resize_text_box, expand=False, fill=False, padding=10)
|
| 80 |
self.globalbox.pack_start(self.resize_box, expand=False, fill=False, padding=0)
|
| 81 |
|
| 82 |
self.part_info_box = gtk.HBox(False, 0)
|
| 83 |
part_info_table = gtk.Table(6, 2, False)
|
| 84 |
part_info_table.set_col_spacings(10)
|
| 85 |
part_info_table.set_row_spacings(5)
|
| 86 |
info_partition_label = gtk.Label(_("Partition:"))
|
| 87 |
info_partition_label.set_alignment(0.0, 0.5)
|
| 88 |
part_info_table.attach(info_partition_label, 0, 1, 0, 1)
|
| 89 |
self.info_partition = gtk.Label()
|
| 90 |
self.info_partition.set_alignment(0.0, 0.5)
|
| 91 |
part_info_table.attach(self.info_partition, 1, 2, 0, 1)
|
| 92 |
|
| 93 |
info_partition_type = gtk.Label(_("Type:"))
|
| 94 |
info_partition_type.set_alignment(0.0, 0.5)
|
| 95 |
part_info_table.attach(info_partition_type, 0, 1, 1, 2)
|
| 96 |
self.resize_info_part_type = gtk.combo_box_new_text()
|
| 97 |
self.resize_info_part_type.append_text(_("Primary"))
|
| 98 |
self.resize_info_part_type.append_text(_("Logical"))
|
| 99 |
self.resize_info_part_type.set_active(0)
|
| 100 |
part_info_table.attach(self.resize_info_part_type, 1, 2, 1, 2)
|
| 101 |
|
| 102 |
info_partition_fs = gtk.Label(_("Filesystem:"))
|
| 103 |
info_partition_fs.set_alignment(0.0, 0.5)
|
| 104 |
part_info_table.attach(info_partition_fs, 0, 1, 2, 3)
|
| 105 |
self.resize_info_part_filesystem = gtk.combo_box_new_text()
|
| 106 |
# for fs in self.controller.supported_filesystems:
|
| 107 |
for fs in self.supported_filesystems:
|
| 108 |
self.resize_info_part_filesystem.append_text(fs)
|
| 109 |
self.resize_info_part_filesystem.set_active(0)
|
| 110 |
self.resize_info_part_filesystem.connect("changed", self.filesystem_changed)
|
| 111 |
part_info_table.attach(self.resize_info_part_filesystem, 1, 2, 2, 3)
|
| 112 |
|
| 113 |
info_partition_mountpoint = gtk.Label(_("Mount point:"))
|
| 114 |
info_partition_mountpoint.set_alignment(0.0, 0.5)
|
| 115 |
part_info_table.attach(info_partition_mountpoint, 0, 1, 3, 4)
|
| 116 |
self.part_mount_point_entry = gtk.Entry()
|
| 117 |
part_info_table.attach(self.part_mount_point_entry, 1, 2, 3, 4)
|
| 118 |
|
| 119 |
info_partition_mountopts = gtk.Label(_("Mount options:"))
|
| 120 |
info_partition_mountopts.set_alignment(0.0, 0.5)
|
| 121 |
part_info_table.attach(info_partition_mountopts, 0, 1, 4, 5)
|
| 122 |
self.part_mount_opts_entry = gtk.Entry()
|
| 123 |
part_info_table.attach(self.part_mount_opts_entry, 1, 2, 4, 5)
|
| 124 |
|
| 125 |
self.part_info_box.pack_start(part_info_table, expand=False, fill=False, padding=0)
|
| 126 |
self.globalbox.pack_start(self.part_info_box, expand=False, fill=False, padding=10)
|
| 127 |
|
| 128 |
bottom_box = gtk.HBox(True, 0)
|
| 129 |
ok_button = gtk.Button(_(" OK "))
|
| 130 |
ok_button.set_flags(gtk.CAN_DEFAULT)
|
| 131 |
ok_button.set_size_request(60, -1)
|
| 132 |
ok_button.connect("clicked", self.ok_clicked)
|
| 133 |
bottom_box.pack_start(ok_button, expand=False, fill=False, padding=0)
|
| 134 |
cancel_button = gtk.Button(_(" Cancel "))
|
| 135 |
cancel_button.set_size_request(60, -1)
|
| 136 |
cancel_button.connect("clicked", self.cancel_clicked)
|
| 137 |
bottom_box.pack_start(cancel_button, expand=False, fill=False, padding=0)
|
| 138 |
self.globalbox.pack_end(bottom_box, expand=False, fill=False, padding=0)
|
| 139 |
|
| 140 |
self.add(self.globalbox)
|
| 141 |
ok_button.grab_default()
|
| 142 |
self.set_modal(True)
|
| 143 |
self.set_transient_for(self.controller.controller.window)
|
| 144 |
self.make_visible()
|
| 145 |
|
| 146 |
def run(self):
|
| 147 |
hpaned_width = self.resize_hpaned.get_allocation().width - self.resize_hpaned.style_get_property("handle-size")
|
| 148 |
if self.fstype == "free":
|
| 149 |
hpaned_pos = hpaned_width
|
| 150 |
self.resize_hpaned.set_position(hpaned_pos)
|
| 151 |
# print "min_size = %s, max_size = %s, hpaned_width = %s, hpaned_pos = %s" % (str(self.min_size), str(self.max_size), str(hpaned_width), str(hpaned_pos))
|
| 152 |
self.info_partition.set_text(self.device + _(" (unallocated)"))
|
| 153 |
self.resize_part_space.set_division(0)
|
| 154 |
self.resize_part_space.set_colors(self.controller.colors['ext3'], self.controller.colors['ext3'])
|
| 155 |
if self.controller.devices[self.device].get_extended_partition():
|
| 156 |
if self.controller.devices[self.device].get_partition(self.minor).is_logical():
|
| 157 |
self.resize_info_part_type.set_active(1)
|
| 158 |
else:
|
| 159 |
self.resize_info_part_type.set_active(0)
|
| 160 |
self.resize_info_part_type.set_sensitive(False)
|
| 161 |
else:
|
| 162 |
self.resize_info_part_type.set_active(0)
|
| 163 |
self.resize_info_part_type.set_sensitive(True)
|
| 164 |
self.resize_info_part_filesystem.set_active(0)
|
| 165 |
self.resize_info_part_filesystem.set_sensitive(True)
|
| 166 |
else:
|
| 167 |
tmppart = self.controller.devices[self.device].get_partition(self.minor)
|
| 168 |
self.info_partition.set_text(tmppart['devnode'])
|
| 169 |
if self.minor < 5:
|
| 170 |
self.resize_info_part_type.set_active(0)
|
| 171 |
else:
|
| 172 |
self.resize_info_part_type.set_active(1)
|
| 173 |
self.resize_info_part_type.set_sensitive(False)
|
| 174 |
self.resize_info_part_filesystem.set_sensitive(False)
|
| 175 |
# for i, fs in enumerate(self.controller.supported_filesystems):
|
| 176 |
for i, fs in enumerate(self.supported_filesystems):
|
| 177 |
if fs == self.fstype:
|
| 178 |
self.resize_info_part_filesystem.set_active(i)
|
| 179 |
break
|
| 180 |
hpaned_pos = int(hpaned_width * (float(self.cur_size) / self.max_size))
|
| 181 |
self.resize_hpaned.set_position(hpaned_pos)
|
| 182 |
# print "min_size = %s, max_size = %s, hpaned_width = %s, hpaned_pos = %s" % (str(self.min_size), str(self.max_size), str(hpaned_width), str(hpaned_pos))
|
| 183 |
if self.max_size == self.cur_size and self.min_size == self.cur_size:
|
| 184 |
# Non-resizeable
|
| 185 |
self.resize_part_space.set_division(0)
|
| 186 |
self.resize_part_space.set_colors(self.controller.colors[self.fstype], self.controller.colors[self.fstype])
|
| 187 |
self.resize_hpaned.set_sensitive(False)
|
| 188 |
else:
|
| 189 |
# Resizeable
|
| 190 |
division = int(hpaned_pos * (float(self.min_size) / self.cur_size)) - 13
|
| 191 |
self.resize_part_space.set_division(division)
|
| 192 |
if self.min_size <= 1:
|
| 193 |
self.resize_part_space.set_colors(self.controller.colors[self.fstype], self.controller.colors[self.fstype])
|
| 194 |
else:
|
| 195 |
self.resize_part_space.set_colors(self.controller.colors[self.fstype], self.controller.colors["free"])
|
| 196 |
self.resize_hpaned.set_sensitive(True)
|
| 197 |
self.part_mount_point_entry.set_text(tmppart.get_mountpoint())
|
| 198 |
self.part_mount_opts_entry.set_text(tmppart.get_mountopts())
|
| 199 |
|
| 200 |
def make_visible(self):
|
| 201 |
self.show_all()
|
| 202 |
self.present()
|
| 203 |
|
| 204 |
def make_invisible(self):
|
| 205 |
self.hide_all()
|
| 206 |
|
| 207 |
def ok_clicked(self, button):
|
| 208 |
if not int(self.resize_info_part_size.get_text()):
|
| 209 |
msgdlg = gtk.MessageDialog(parent=self.controller.controller.window, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format="You cannot define a 0MB partition.")
|
| 210 |
resp = msgdlg.run()
|
| 211 |
msgdlg.destroy()
|
| 212 |
return
|
| 213 |
if self.supported_filesystems[self.resize_info_part_filesystem.get_active()] == "linux-swap":
|
| 214 |
self.part_mount_point_entry.set_text("")
|
| 215 |
self.part_mount_opts_entry.set_text("")
|
| 216 |
else:
|
| 217 |
if self.part_mount_point_entry.get_text() and not self.part_mount_opts_entry.get_text():
|
| 218 |
# Mount point but no mount options
|
| 219 |
self.part_mount_opts_entry.set_text("defaults")
|
| 220 |
if self.fstype == "free":
|
| 221 |
hpaned_width = self.resize_hpaned.get_allocation().width - self.resize_hpaned.style_get_property("handle-size")
|
| 222 |
hpaned_pos = self.resize_hpaned.get_position()
|
| 223 |
part_space = float(hpaned_width - (hpaned_width - hpaned_pos)) / hpaned_width
|
| 224 |
# part_size = round(self.max_size * part_space)
|
| 225 |
part_size = int(self.resize_info_part_size.get_text())
|
| 226 |
if self.resize_info_part_type.get_active() == 1 and self.controller.devices[self.device].get_extended_partition() == 0: # Logical and no extended partition
|
| 227 |
self.controller.devices[self.device].add_partition(self.idx, self.max_size, "extended")
|
| 228 |
# TODO: determine idx for new unallocated space inside extended partititon
|
| 229 |
fstype = self.supported_filesystems[self.resize_info_part_filesystem.get_active()]
|
| 230 |
newidx = self.controller.devices[self.device].add_partition(self.idx, part_size, fstype)
|
| 231 |
self.controller.draw_part_box()
|
| 232 |
self.controller.part_selected(None, self.device, newidx)
|
| 233 |
else:
|
| 234 |
self.controller.draw_part_box()
|
| 235 |
self.controller.part_selected(None, self.device, self.idx)
|
| 236 |
|
| 237 |
self.destroy()
|
| 238 |
|
| 239 |
def cancel_clicked(self, button):
|
| 240 |
self.destroy()
|
| 241 |
|
| 242 |
def part_resized(self, widget, allocation):
|
| 243 |
if not self.sync_slider_to_text:
|
| 244 |
self.sync_slider_to_text = True
|
| 245 |
return
|
| 246 |
hpaned_width = self.resize_hpaned.get_allocation().width - self.resize_hpaned.style_get_property("handle-size")
|
| 247 |
hpaned_pos = self.resize_hpaned.get_position()
|
| 248 |
part_space = float(hpaned_width - (hpaned_width - hpaned_pos)) / hpaned_width
|
| 249 |
part_size_mb = int(round(part_space * self.max_size))
|
| 250 |
self.resize_info_part_size.set_text(str(part_size_mb))
|
| 251 |
part_unalloc_mb = int(self.max_size - part_size_mb)
|
| 252 |
self.resize_info_unalloc_size.set_text(str(part_unalloc_mb))
|
| 253 |
|
| 254 |
def validate_keypress(self, editable, new_text, new_text_length, position):
|
| 255 |
if new_text == ".": return
|
| 256 |
try:
|
| 257 |
float(new_text)
|
| 258 |
except:
|
| 259 |
editable.stop_emission("insert-text")
|
| 260 |
|
| 261 |
def update_slider_and_entries(self, widget, event, which_one):
|
| 262 |
hpaned_width = self.resize_hpaned.get_allocation().width - self.resize_hpaned.style_get_property("handle-size")
|
| 263 |
hpaned_pos = self.resize_hpaned.get_position()
|
| 264 |
if which_one == "part-size":
|
| 265 |
part_size_mb = int(round(long(self.resize_info_part_size.get_text())))
|
| 266 |
if part_size_mb > self.max_size:
|
| 267 |
part_size_mb = self.max_size
|
| 268 |
elif part_size_mb < self.min_size:
|
| 269 |
part_size_mb = self.min_size
|
| 270 |
self.resize_info_part_size.set_text(str(part_size_mb))
|
| 271 |
part_unalloc_mb = int(self.max_size - part_size_mb)
|
| 272 |
self.resize_info_unalloc_size.set_text(str(part_unalloc_mb))
|
| 273 |
if part_size_mb >= self.min_size and part_size_mb <= self.max_size:
|
| 274 |
hpaned_pos = round((float(part_size_mb) / self.max_size) * hpaned_width)
|
| 275 |
else:
|
| 276 |
part_unalloc_mb = int(round(long(self.resize_info_unalloc_size.get_text())))
|
| 277 |
if part_unalloc_mb > (self.max_size - self.min_size):
|
| 278 |
part_unalloc_mb = self.max_size = self.min_size
|
| 279 |
self.resize_info_unalloc_size.set_text(str(part_unalloc_mb))
|
| 280 |
part_size_mb = int(round(self.max_size - part_unalloc_mb))
|
| 281 |
self.resize_info_part_size.set_text(str(part_size_mb))
|
| 282 |
if (self.max_size - part_unalloc_mb) >= self.min_size:
|
| 283 |
hpaned_pos = hpaned_width - round((float(part_unalloc_mb) / self.max_size) * hpaned_width)
|
| 284 |
self.sync_slider_to_text = False
|
| 285 |
if hpaned_pos <= hpaned_width:
|
| 286 |
self.resize_hpaned.set_position(int(hpaned_pos))
|
| 287 |
else:
|
| 288 |
self.resize_hpaned.set_position(self.resize_hpaned.get_position())
|
| 289 |
|
| 290 |
def filesystem_changed(self, widget, data=None):
|
| 291 |
fs = self.supported_filesystems[self.resize_info_part_filesystem.get_active()]
|
| 292 |
self.resize_part_space.set_colors(self.controller.colors[fs], self.controller.colors[fs])
|
| 293 |
if self.fstype == "free": self.resize_part_space.get_child().expose_event(None, None)
|
| 294 |
if fs == "linux-swap":
|
| 295 |
self.part_mount_point_entry.set_sensitive(False)
|
| 296 |
self.part_mount_opts_entry.set_sensitive(False)
|
| 297 |
else:
|
| 298 |
self.part_mount_point_entry.set_sensitive(True)
|
| 299 |
self.part_mount_opts_entry.set_sensitive(True)
|
| 300 |
|
| 301 |
def delete_event(self, widget, event, data=None):
|
| 302 |
return False
|
| 303 |
|
| 304 |
def destroy_event(self, widget, data=None):
|
| 305 |
return True
|