1 # -*- coding: utf-8 -*-
4 from enigma import eTimer
6 from Screens.Screen import Screen
7 from Screens.MessageBox import MessageBox
9 from Components.Label import Label
10 from Components.Pixmap import MultiPixmap
11 from Components.Sources.StaticText import StaticText
12 from Components.Sources.List import List
13 from Components.ActionMap import ActionMap
14 from Components.MenuList import MenuList
15 from Components.Console import Console
16 from Tools.Directories import pathExists, createDir
17 from Tools.BoundFunction import boundFunction
18 from Tools.LoadPixmap import LoadPixmap
20 from Tools.Directories import resolveFilename, SCOPE_SKIN
21 SkinDefaultPath = resolveFilename(SCOPE_SKIN, "skin_default/icons/")
23 from Components.ConfigList import ConfigListScreen
24 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText, ConfigSelection, NoSave
25 config.plugins.eparted = ConfigSubsection()
28 from os import system as os_system, path as os_path, listdir
30 #from Plugins.Bp.geminimain.gTools import cleanexit
49 #-----------------------------------------------------------------------------
51 def getInt_epart(val):
53 return int(float(val[0:-2]))#Einheit abschneiden
62 for x in result.split('\n'):
64 if x.find("BYT;") >= 0:
67 if addok and len(entry):
72 if addok and len(x) > 1 and x[len(x) - 1] == ';':
75 l.insert(0, LIST_TYPE_PAR)
76 l[PA_START] = getInt_epart(l[PA_START])
77 l[PA_END] = getInt_epart(l[PA_END])
78 l[PA_SIZE] = getInt_epart(l[PA_SIZE])
80 if l[PA_FS].find("linux-swap") == 0:
81 l[PA_FS] = "linux-swap"
83 elif len(l) == 8:#Device
84 if l[0].find("/dev/mtd") < 0:
85 l.insert(0, LIST_TYPE_DEV)
88 print "[eParted] <parse error>"
92 def myExecute(cmd, session, test=False):
94 from time import sleep
100 print "[eParted]", result, cmd
101 if result != 0 and session is not None:
102 session.open(MessageBox, _("Error command '%s'") % cmd, MessageBox.TYPE_ERROR, timeout=8)
107 mounts = open("/proc/mounts")
111 lines = mounts.readlines()
116 for x in getMountP():
117 parts = x.strip().split(" ")
119 realpath = os_path.realpath(parts[0])
124 rereaddevices = False
125 #-------------------------------------------------------------------------------------
127 class Ceparted(Screen):
128 skin = """<screen position="center,center" size="820,320" title="eParted v0.13">
129 <widget name="list" position="10,10" size="800,300" enableWrapAround="1" scrollbarMode="showOnDemand"/>
131 def __init__(self, session):
132 Screen.__init__(self, session)
134 self["actions"] = ActionMap(["OkCancelActions"],
140 self["list"] = MenuList(list=[])
141 self.Console = Console()
147 sel = self["list"].getCurrent()
150 rereaddevices = False
151 self.session.openWithCallback(self.__readDev, Cpart, sel[1])
156 self.Console.ePopen("parted -m -l", self.__FinishedConsole)
159 self.Console.killAll()
163 def __FinishedConsole(self, result, retval, extra_args=None):
164 if retval == 0 and '\n' in result:
166 for x in parseCmd(result):
167 if x[0][LIST_TYPE] == LIST_TYPE_DEV:
168 name = x[0][DEV_NAME]
170 name = x[0][DEV_PATH]
172 tstr += " (%s - %d %s %s)" % (x[0][DEV_SIZE], len(x) - 1, _("partition(s)"), x[0][DEV_PATH])
173 list.append((tstr, (name, x[0][DEV_PATH], x[0][DEV_SIZE])))
174 self["list"].setList(list)
176 #-------------------------------------------------------------------------------------
178 class AddPart(Screen, ConfigListScreen):
179 skin = """<screen name="AddPart" position="center,center" size="820,320" title="add Partition" >
180 <ePixmap pixmap="skin_default/buttons/red.png" position="10,5" size="200,40" alphatest="on" />
181 <ePixmap pixmap="skin_default/buttons/green.png" position="210,5" size="200,40" alphatest="on" />
182 <widget render="Label" source="key_red" position="10,5" size="200,40" zPosition="1" valign="center" halign="center" backgroundColor="#9f1313" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
183 <widget render="Label" source="key_green" position="210,5" size="200,40" zPosition="1" valign="center" halign="center" backgroundColor="#1f771f" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
184 <eLabel position="10,50" size="800,1" backgroundColor="grey" />
185 <widget name="config" position="10,60" size="800,240" enableWrapAround="1" scrollbarMode="showOnDemand" />
188 def __init__(self, session, maxsize, unit, countpart):
189 Screen.__init__(self, session)
190 self.session = session
191 self.setup_title = _("add partition")
195 if pathExists("/sbin/mkfs.ext2"):
197 if pathExists("/sbin/mkfs.ext3"):
199 if pathExists("/sbin/mkfs.ext4"):
202 if pathExists("/sbin/mkfs.xfs"):
204 if pathExists("/sbin/mkswap"):
205 menu.append("linux-swap")
206 if pathExists("/sbin/mkfs.vfat"):
208 if pathExists("/usr/sbin/mkfs.msdos"):
210 config.plugins.eparted.fs = NoSave(ConfigSelection(default=default, choices=menu))
211 config.plugins.eparted.size = NoSave(ConfigInteger(default=maxsize, limits=[1, maxsize]))
214 if countpart < 4:#nur 4 parts möglich bei primary
215 list.append(getConfigListEntry(_("size in %s (max %d %s):") % (unit, maxsize, unit), config.plugins.eparted.size))
216 list.append(getConfigListEntry(_("filesystem:"), config.plugins.eparted.fs))
217 ConfigListScreen.__init__(self, list, session=session)
219 self["key_red"] = StaticText(_("cancel"))
220 self["key_green"] = StaticText(_("ok"))
222 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
224 "red": self.keyCancel,
225 "cancel": self.keyCancel,
226 "green": self.keySave,
227 "save": self.keySave,
235 if config.plugins.eparted.size.value > 0:
236 self.close((config.plugins.eparted.size.value, config.plugins.eparted.fs.value))
238 #-------------------------------------------------------------------------------------
245 skin = """<screen position="center,center" size="820,320" title="eParted">
246 <widget name="PixmapRed" pixmaps="skin_default/buttons/button_off.png,skin_default/buttons/button_red.png" position="10,12" size="25,25" alphatest="on" />
247 <widget name="PixmapGreen" pixmaps="skin_default/buttons/button_off.png,skin_default/buttons/button_green.png" position="290,12" size="25,25" alphatest="on" />
248 <widget name="PixmapBlue" pixmaps="skin_default/buttons/button_off.png,skin_default/buttons/button_blue.png" position="570,12" size="25,25" alphatest="on" />
249 <widget name="LabelRed" position="50,5" size="200,40" valign="center" backgroundColor="background" font="Regular;21" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
250 <widget name="LabelGreen" position="330,5" size="200,40" valign="center" backgroundColor="background" font="Regular;21" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
251 <widget name="LabelBlue" position="610,5" size="200,40" valign="center" backgroundColor="background" font="Regular;21" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
252 <eLabel position="10,50" size="800,1" backgroundColor="grey" />
253 <widget source="list" render="Listbox" position="10,60" size="800,240" enableWrapAround="1" scrollbarMode="showOnDemand">
254 <convert type="TemplatedMultiContent">
256 MultiContentEntryText(pos = (10,2), size = (60, 30), font=0, flags = RT_HALIGN_LEFT, text=0),
257 MultiContentEntryText(pos = (80,2), size = (170, 30), font=0, flags = RT_HALIGN_LEFT, text=1),
258 MultiContentEntryText(pos = (260,2), size = (170, 30), font=0, flags = RT_HALIGN_LEFT, text=2),
259 MultiContentEntryText(pos = (440,2), size = (170, 30), font=0, flags = RT_HALIGN_LEFT, text=3),
260 MultiContentEntryText(pos = (620,2), size = (180, 30), font=0, flags = RT_HALIGN_LEFT, text=4)
262 "fonts": [gFont("Regular", 21)],
269 def __init__(self, session, entry):
270 Screen.__init__(self, session)
272 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
275 "green": self.KeyGreen,
276 "blue": self.KeyBlue,
280 self["list"] = List(list=[])
281 self["list"].onSelectionChanged.append(self.__SetLabels)
282 self["PixmapRed"] = MultiPixmap()
283 self["PixmapGreen"] = MultiPixmap()
284 self["PixmapBlue"] = MultiPixmap()
285 self["LabelRed"] = Label()
286 self["LabelGreen"] = Label()
287 self["LabelBlue"] = Label()
289 self.__devpath = entry[DEV_PATH]
291 self.__old_part_list = []
292 self.__new_part_list = []
294 self.__unit = entry[2][len(entry[2]) - 2:]
296 self.Console = Console()
300 self.Console.killAll()
303 def __getPartInfo(self, val=None):
304 self.Console.ePopen("parted -m %s unit %s print" % (self.__devpath, self.__unit), self.__FinishedConsole)
306 def __Filllist(self):
308 index = self["list"].getIndex()
309 for x in self.__new_part_list:
310 if x[LIST_TYPE] == LIST_TYPE_PAR:
312 p0 = "%s: %s" % (_("Nr"), x[PA_NR])
313 p1 = "%s: %d%s" % (_("Start"), x[PA_START], self.__unit)
314 p2 = "%s: %d%s" % (_("End"), x[PA_END], self.__unit)
315 p3 = "%s: %d%s" % (_("Size"), x[PA_SIZE], self.__unit)
316 p4 = "%s: %s" % (_("Type"), x[PA_FS])
317 list.append((p0, p1, p2, p3, p4, x))
318 self["list"].setList(list)
319 self["list"].setIndex(index)
320 self.__createCommandList()
322 def __SetLabels(self):
323 sel = self["list"].getCurrent()
324 self["LabelGreen"].setText("")
325 self["LabelRed"].setText("")
327 if sel[5][PA_TYPE] & self.PA_TYPE_FREE and len(self.__new_part_list) < 6:
328 self["PixmapGreen"].setPixmapNum(1)
329 self["LabelGreen"].setText(_("add"))
331 self["PixmapGreen"].setPixmapNum(0)
332 if sel[5][PA_TYPE] & self.PA_TYPE_LAST and bool(sel[5][PA_TYPE] & self.PA_TYPE_FREE) == False:
333 self["PixmapRed"].setPixmapNum(1)
334 self["LabelRed"].setText(_("delete"))
336 self["PixmapRed"].setPixmapNum(0)
338 def __addFreePart(self, plist, lastPartEnd):
339 x = [LIST_TYPE_PAR, str(len(plist)), lastPartEnd, self.__fullsize, 0, _("free"), (self.PA_TYPE_FREE | self.PA_TYPE_LAST), ";"]
342 def __FinishedConsole(self, result, retval, extra_args=None):
343 if retval == 0 and '\n' in result:
344 tlist = parseCmd(result)
346 self.__old_part_list = tlist[0][:]
347 self.__new_part_list = tlist[0][:]
351 for x in self.__old_part_list:
352 if x[LIST_TYPE] == LIST_TYPE_DEV:
353 self.__fullsize = getInt_epart(x[DEV_SIZE])
357 name += " (%s)" % x[DEV_SIZE]
360 lastPartEnd = x[PA_END]
361 x[PA_TYPE] = self.PA_TYPE_USE
362 if count == len(self.__old_part_list):#is letzte part
363 x[PA_TYPE] |= self.PA_TYPE_LAST
366 if lastPartEnd < self.__fullsize:#Wenn noch Frei, Part erstellen
367 self.__addFreePart(self.__old_part_list, lastPartEnd)
368 self.__addFreePart(self.__new_part_list, lastPartEnd)
373 if len(self.__comlist):
374 self.session.openWithCallback(self.__getPartInfo, Cpartexe, self.__comlist)
377 sel = self["list"].getCurrent()
378 if sel and sel[1] and sel[5][PA_TYPE] & self.PA_TYPE_LAST and bool(sel[5][PA_TYPE] & self.PA_TYPE_FREE) == False:
380 self.__new_part_list.remove(sel[5])#aktuelle part löschen
381 for x in self.__new_part_list:
382 if x[LIST_TYPE] == LIST_TYPE_PAR:
383 if x[PA_TYPE] & self.PA_TYPE_FREE:#letzte Freie suchen und auch löschen
384 self.__new_part_list.remove(x)
387 x[PA_TYPE] = self.PA_TYPE_USE
390 if len(self.__new_part_list) > 1:#von letzter Part, TYp setzen und Ende ermitteln
391 self.__new_part_list[len(self.__new_part_list) - 1][PA_TYPE] = self.PA_TYPE_USE | self.PA_TYPE_LAST
392 lastPartEnd = self.__new_part_list[len(self.__new_part_list) - 1][PA_END]
394 if lastPartEnd < self.__fullsize:#Wenn noch Frei, Part erstellen
395 self.__addFreePart(self.__new_part_list, lastPartEnd)
396 #for x in self.__new_part_list:
397 # if x[LIST_TYPE]==LIST_TYPE_PAR:
400 print "[eParted] <remove part>"
404 sel = self["list"].getCurrent()
405 if sel and sel[5] and sel[5][PA_TYPE] & self.PA_TYPE_FREE and sel[5][PA_START] < sel[5][PA_END] and len(self.__new_part_list) < 6:
406 self.session.openWithCallback(self.__CallbackAddPart, AddPart, sel[5][PA_END] - sel[5][PA_START], self.__unit, len(self.__new_part_list) - 1)
408 def __CallbackAddPart(self, val=None):
410 for x in self.__new_part_list:
411 if x[LIST_TYPE] == LIST_TYPE_PAR:
412 if x[PA_TYPE] & self.PA_TYPE_FREE:
415 x[PA_END] = x[PA_START] + x[PA_SIZE]
416 x[PA_TYPE] = self.PA_TYPE_USE | self.PA_TYPE_LAST
417 if x[PA_END] < self.__fullsize:#Wenn noch Frei, Part erstellen
418 self.__addFreePart(self.__new_part_list, x[PA_END])
421 x[PA_TYPE] = self.PA_TYPE_USE
424 def __addPart2Comlist(self, list, val, mkpart=True):
429 com = "parted -s -a optimal %s mkpart primary %s %s%s %s%s" % (self.__devpath, fs, val[PA_START], self.__unit, val[PA_END], self.__unit)
430 list.append((com , _("create partition %s") % partnr, None))
433 if val[PA_FS] == "linux-swap":
434 mkfs = "/sbin/mkswap"
435 elif val[PA_FS] == "fat16":
436 mkfs = "/usr/sbin/mkfs.msdos -F 16"
437 elif val[PA_FS] == "fat32":
438 mkfs = "/sbin/mkfs.vfat"
440 mkfs = "/sbin/mkfs." + val[PA_FS]
441 mountdev = self.__devpath + partnr
442 if val[PA_FS] == "xfs":
445 com = "%s %s%s" % (mkfs, self.__devpath, partnr)
446 list.append((com , _("make filesystem '%s' on partition %s (%d %s)") % (val[PA_FS], partnr, val[PA_SIZE], self.__unit), mountdev))
448 def __delPart2Comlist(self, list, val):
450 dev = "%s%s" % (self.__devpath, partnr)
453 if myExecute("umount %s" % mp, self.session):
455 list.insert(0, ("parted -s -a none %s rm %s" % (self.__devpath, partnr), _("delete partition %s") % partnr, None))
457 def __createCommandList(self):
459 #welche parts sollen gelöscht werden
460 for x in range(len(self.__old_part_list)):
461 if self.__old_part_list[x][LIST_TYPE] == LIST_TYPE_PAR:
462 if bool(self.__old_part_list[x][PA_TYPE] & self.PA_TYPE_FREE) == False:
463 if len(self.__new_part_list) > x:
464 if self.__old_part_list[x][PA_SIZE] != self.__new_part_list[x][PA_SIZE]:
465 #print self.__old_part_list[x], self.__new_part_list[x]
466 self.__delPart2Comlist(self.__comlist, self.__old_part_list[x])
468 self.__delPart2Comlist(self.__comlist, self.__old_part_list[x])
470 #welche parts sollen erstellt werden
471 for x in range(len(self.__new_part_list)):
472 if self.__new_part_list[x][LIST_TYPE] == LIST_TYPE_PAR:
473 if bool(self.__new_part_list[x][PA_TYPE] & self.PA_TYPE_FREE) == False:
474 if len(self.__old_part_list) > x and bool(self.__old_part_list[x][PA_TYPE] & self.PA_TYPE_FREE) == False:
475 if self.__new_part_list[x][PA_SIZE] != self.__old_part_list[x][PA_SIZE]:
476 #print self.__new_part_list[x], self.__old_part_list[x]
477 self.__addPart2Comlist(self.__comlist, self.__new_part_list[x])
479 if self.__new_part_list[x][PA_FS] != self.__old_part_list[x][PA_FS]:
480 self.__addPart2Comlist(self.__comlist, self.__new_part_list[x], False)
482 self.__addPart2Comlist(self.__comlist, self.__new_part_list[x])
485 #for x in self.__comlist: print "[eParted] com =",x
486 if len(self.__comlist):
487 self["PixmapBlue"].setPixmapNum(1)
488 self["LabelBlue"].setText(_("execute"))
490 self["PixmapBlue"].setPixmapNum(0)
491 self["LabelBlue"].setText("")
493 class Cpartexe(Screen):
494 skin = """<screen position="center,center" size="820,320" title=" ">
495 <widget name="PixmapButton" pixmaps="skin_default/buttons/button_green.png,skin_default/buttons/button_off.png" position="10,12" size="25,25" alphatest="on" />
496 <widget name="LabelButton" position="50,5" size="200,40" valign="center" backgroundColor="background" font="Regular;21" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
497 <eLabel position="10,50" size="800,1" backgroundColor="grey" />
498 <widget source="list" render="Listbox" position="10,60" size="800,252" enableWrapAround="1" scrollbarMode="showOnDemand">
499 <convert type="TemplatedMultiContent">
501 MultiContentEntryText(pos = (40,0), size = (760,36), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=0),
502 MultiContentEntryPixmapAlphaTest(pos = (2,2), size = (32,32), png=1),
504 "fonts": [gFont("Regular", 21)],
511 def __init__(self, session, comlist):
512 Screen.__init__(self, session)
514 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
517 "green": self.KeyGreen,
521 self.setTitle(_("execute"))
522 self["PixmapButton"] = MultiPixmap()
523 self["LabelButton"] = Label(_("Start") + " ?")
529 list.append((x[1], None, x[0]))
531 self.mountlist.append(x[2])
532 self["list"] = List(list)
534 self.__Stimer = eTimer()
535 self.__Stimer_conn = self.__Stimer.timeout.connect(self.__exeList)
538 def __getPartitionUUID(self, device):
540 if os_path.exists("/dev/disk/by-uuid"):
541 for uuid in listdir("/dev/disk/by-uuid/"):
542 if not os_path.exists("/dev/disk/by-uuid/" + uuid):
544 if os_path.realpath("/dev/disk/by-uuid/" + uuid) == device:
545 return ("/dev/disk/by-uuid/" + uuid, uuid)
547 return (device, device[5:])
549 print "[eParted] <error get UUID>"
552 def __mountDevice(self):
553 for x in self.mountlist:
554 dev = self.__getPartitionUUID(x)
556 if os_path.exists("/media/" + dev[1]) == False:
557 createDir("/media/" + dev[1], True)
558 cmd = "mount %s /media/%s" % (dev[0], dev[1])
563 del self.__Stimer_conn
569 if len(self["list"].list) > self.__state and self.__state > -1:
570 res = myExecute(self["list"].list[self.__state][2], self.session)
573 pic = "selectioncross.png"
575 self["list"].list[self.__state] = (self["list"].list[self.__state][0], LoadPixmap(path=SkinDefaultPath + pic), self["list"].list[self.__state][2], self["list"].list[self.__state][2])
576 self["list"].updateList(self["list"].list)
577 self["list"].setIndex(self.__state)
582 self.__state = len(self["list"].list)#bei fehler ans Ende der liste
583 self["PixmapButton"].setPixmapNum(0)
584 self["LabelButton"].setText(_("quit"))
586 self.__Stimer.start(500, True)
589 self["PixmapButton"].setPixmapNum(0)
590 self["LabelButton"].setText(_("quit"))
593 if self.__state == -1:
597 self["PixmapButton"].setPixmapNum(1)
598 self["LabelButton"].setText(_("Please Wait"))
599 self["list"].setIndex(0)
600 self.__Stimer.start(500, True)
601 elif self.__state == -2: