1 from Components.Label import Label
2 from Components.ActionMap import ActionMap
3 from Components.config import config, ConfigSelection, getConfigListEntry, ConfigSubsection, ConfigEnableDisable, ConfigYesNo, ConfigInteger
4 from Components.ConfigList import ConfigListScreen
5 from Components.Console import Console
6 from Components.GUIComponent import GUIComponent
7 from Components.Harddisk import harddiskmanager
8 from Components.MenuList import MenuList
9 from Components.Pixmap import Pixmap, MultiPixmap
10 from Components.Sources.List import List
11 from Components.Sources.StaticText import StaticText
12 from Plugins.Plugin import PluginDescriptor
13 from Screens.MessageBox import MessageBox
14 from Screens.Screen import Screen
15 from Screens.VirtualKeyBoard import VirtualKeyBoard
16 from Tools.BoundFunction import boundFunction
17 from Tools.LoadPixmap import LoadPixmap
18 from Tools.Notifications import AddNotificationWithCallback
19 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
20 from skin import loadSkin
21 from os import system, makedirs, path, listdir, statvfs, popen
26 from Components.Sources.StaticText import StaticText
27 from Components.FileList import FileList
28 from Screens.InputBox import InputBox
29 from Components.Input import Input
30 from Screens.ChoiceBox import ChoiceBox
31 from enigma import eTimer
32 from __init__ import _
34 config.plugins.devicemanager = ConfigSubsection()
35 config.plugins.devicemanager.hotplug_enable = ConfigEnableDisable(default=True)
36 config.plugins.devicemanager.mountcheck_enable = ConfigEnableDisable(default=True)
38 def readFile(filename):
40 data = file.read().strip()
44 def byteConversion(byte):
45 if type(byte) == str and len(byte) == 0:
47 if type(byte) != long:
49 if byte > 1024*1024*1024:
50 int_part = byte/1024/1024/1024
51 dec_part = byte%(1024*1024*1024)/(1024*1024)
52 return "%d.%d GB"%(int_part, dec_part)
54 int_part = byte/1024/1024
55 dec_part = byte%(1024*1024)/1024
56 return "%d.%d MB"%(int_part, dec_part)
58 def checkStrValue(value , empty = ""):
59 if type(value) != str or len(value) == 0:
63 class DeviceManagerConfiguration(Screen, ConfigListScreen):
64 def __init__(self,session):
65 self.session = session
66 Screen.__init__(self,session)
67 self.skinName = "Setup"
68 self.createConfigList()
69 ConfigListScreen.__init__(self, self.list, session = self.session)
70 self["key_red"] = StaticText(_("Cancel"))
71 self["key_green"] = StaticText(_("OK"))
72 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
75 "cancel": self.keyCancel,
76 "red": self.keyCancel,
77 "green": self.keySave,
79 self.onShown.append(self.setWindowTitle)
80 self.old_hotplug_enable = config.plugins.devicemanager.hotplug_enable.value
82 def setWindowTitle(self):
83 self.setTitle(_("DeviceManager configuration"))
85 def createConfigList(self):
87 self.list.append(getConfigListEntry(_("Enable mount check for HDD : "), config.plugins.devicemanager.mountcheck_enable))
88 self.list.append(getConfigListEntry(_("Harddisk standby after : "), config.usage.hdd_standby))
89 self.list.append(getConfigListEntry(_("Mount known devices automatically : "), config.plugins.devicemanager.hotplug_enable))
92 if config.plugins.devicemanager.hotplug_enable.value:
93 if not DeviceManagerhotplugDeviceStart in harddiskmanager.on_partition_list_change:
94 harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
96 if DeviceManagerhotplugDeviceStart in harddiskmanager.on_partition_list_change:
97 harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
99 for x in self["config"].list:
103 class DeviceManager(Screen):
105 <screen position="center,center" size="590,350" title="DeviceManager">
106 <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
107 <ePixmap pixmap="skin_default/buttons/green.png" position="160,0" size="140,40" alphatest="on" />
108 <ePixmap pixmap="skin_default/buttons/yellow.png" position="300,0" size="140,40" alphatest="on" />
109 <ePixmap pixmap="skin_default/buttons/blue.png" position="440,0" size="140,40" alphatest="on" />
110 <widget name="key_red" position="20,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
111 <widget name="key_green" position="160,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
112 <widget name="key_yellow" position="300,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
113 <widget name="key_blue" position="440,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
114 <ePixmap pixmap="skin_default/div-h.png" position="0,48" size="590,2" alphatest="on" />
115 <widget source="menu" render="Listbox" position="0,48" size="590,350" scrollbarMode="showOnDemand">
116 <convert type="TemplatedMultiContent">
119 MultiContentEntryText(pos = (50, 0), size = (510, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 0 is vendor - model
120 MultiContentEntryText(pos = (50, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 is Device
121 MultiContentEntryText(pos = (170, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 is Size
122 MultiContentEntryText(pos = (290, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 3 is Partitions
123 MultiContentEntryText(pos = (410, 32), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 4 is Removable
124 MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (590, 2), png = 5), # png 5 is the div pixmap
127 MultiContentEntryText(pos = (50, 0), size = (500, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 1 is Partition
128 MultiContentEntryText(pos = (50, 32), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 2 is Mounted on
129 MultiContentEntryText(pos = (50, 54), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 3 UUID
130 MultiContentEntryText(pos = (50, 76), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 4 Type
131 MultiContentEntryText(pos = (180, 76), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 5 Size_total
132 MultiContentEntryText(pos = (310, 76), size = (190, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 5), # index 6 Size_free
133 MultiContentEntryPixmapAlphaTest(pos = (0, 96), size = (590, 2), png = 6), # png 6 is the div pixmap
136 MultiContentEntryPixmapAlphaTest(pos = (10, 7), size = (30, 30), png = 0), # index 0: picture
137 MultiContentEntryText(pos = (40, 0), size = (500, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 name
138 MultiContentEntryText(pos = (40, 32), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 path
139 MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (590, 2), png = 5), # index 5 is the div pixmap
142 "fonts": [gFont("Regular", 22),gFont("Regular", 16),gFont("Regular", 28)],
150 def __init__(self, session):
151 Screen.__init__(self, session)
152 self.session = session
153 self.currList = "default"
154 self.currDevice = None
155 self.currPartition = None
156 self.defaultMountPoint = "/media/hdd"
158 self["menu"] = List(self.deviceList)
159 self["key_red"] = Label(_("Close"))
160 self["key_green"] = Label(" ")
161 self["key_yellow"] = Label(" ")
162 self["key_blue"] = Label(" ")
164 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions", "MenuActions" ],
167 "cancel": self.keyCancel,
168 "red": self.keyCancel,
170 "yellow": self.keyYellow,
171 "blue": self.keyBlue,
172 "menu": self.keyMenu,
174 self.DeviceManagerConsole = Console()
176 if not self.selectionChanged in self["menu"].onSelectionChanged:
177 self["menu"].onSelectionChanged.append(self.selectionChanged)
178 self.onLayoutFinish.append(self.showDeviceList)
179 self.onLayoutFinish.append(self.addPartitionListChange)
180 self.onClose.append(self.removePartitionListChange)
181 self.onChangedEntry = []
182 self.blockDevices = {}
184 def addPartitionListChange(self):
185 harddiskmanager.on_partition_list_change.append(self.partitionListChanged)
187 def removePartitionListChange(self):
188 harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)
190 def partitionListChanged(self, action, device):
191 print "[Device manager] hotplug partitionListChanged"
192 if self.currList != "default" and device.device[:3] != self.currDevice["blockdev"]:
194 self.showDeviceList()
197 self.icon_button_green = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_green.png"))
198 self.divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
200 def selectionChanged(self):
201 if self.currList == "partitions":
202 currentPartition = self.getCurrentPartition()
203 if currentPartition is not None:
204 if currentPartition["mountpoint"] != "":
205 self["key_green"].setText(_("Umount"))
207 self["key_green"].setText(_("Mount"))
209 if currentPartition["fstype"] == "":
210 self["key_blue"].setText("")
211 elif currentPartition["fstype"][:3] == "ext":
212 self["key_blue"].setText(_("Check"))
214 self["key_blue"].setText("")
216 def showDeviceList(self):
218 self["key_red"].setText(_("Close"))
219 self["key_green"].setText(_("Ok"))
220 self["key_yellow"].setText(" ")
221 self["key_blue"].setText(_("Initialize"))
223 for device in deviceinfo.getBlockDevices():
225 "%s - %s"%(device["vendor"], device["model"]), # vendor : str, model : str, index 0
226 _("device : %s")%(device["blockdev"]), # str
227 _("Size : %s")%(byteConversion(device["size"])), # str, bytes
228 _("Partitions : %s")%(len(device["partitions"])), # list
229 _("Removable : %s")%(device["removable"] and 'Yes' or 'No'), # bool [True, False]
233 # print "[DeviceManager] deviceEntry : ", deviceEntry
234 self.deviceList.append(deviceEntry)
235 self.currList = "default"
236 self["menu"].style = "default"
237 self["menu"].setList(self.deviceList)
239 def showPartitionList(self):
240 if self.currDevice is None:
243 for partition in self.currDevice["partitions"]:
244 partitionInfo = deviceinfo.getPartitionInfo(partition)
246 _("Partition : /dev/%s")%partition, # index 0
247 _("Mounted on : %s")%checkStrValue(partitionInfo["mountpoint"], _("not mounted")),
248 _("UUID : %s")%checkStrValue(partitionInfo["uuid"], _("unknown")),
249 _("Type : %s")%checkStrValue(partitionInfo["fstype"], _("unknown")),
250 _("Size : %s")%checkStrValue(byteConversion(partitionInfo["size"]), _("unknown")),
251 _("Free : %s")%checkStrValue(byteConversion(partitionInfo["free"]), _("unknown")),
252 self.divpng, # index 6
253 partitionInfo, # index 7
255 # print "[DeviceManager] partitionEntry : ",partitionEntry
256 partitionList.append(partitionEntry)
257 if len(partitionList) != 0:
258 self["key_red"].setText(_("Devices"))
259 self["key_green"].setText(_("Mount"))
260 self["key_yellow"].setText(_("Format"))
261 self["key_blue"].setText(_("Check"))
262 self.currList = "partitions"
263 self["menu"].style = "partitions"
264 self["menu"].setList(partitionList)
265 self.selectionChanged()
267 self.session.open(MessageBox, _("No partition list found on device.\nPlease click BLUE key and do Initialize to use this device."), MessageBox.TYPE_ERROR, timeout = 10)
269 def showMountPointSetup(self):
270 if self.currDevice is None or self.currPartition is None:
272 partition = self.currPartition["partition"]
273 if deviceinfo.isMountable(partition) is False:
274 self.session.open(MessageBox, _("This partition is not mountable.\nYou need to check or format this partition."), MessageBox.TYPE_ERROR, timeout = 10)
276 self["key_red"].setText(_("Partitions"))
277 self["key_green"].setText(_("Ok"))
278 self["key_yellow"].setText("")
279 self["key_blue"].setText("")
280 self.mountPointList = []
281 currentMountPoint = self.currPartition["mountpoint"]
282 if currentMountPoint == "":
283 currentMountPoint = "'not mounted'"
284 defaultMountPoint = self.getDefaultMountPoint()
285 autoMountPoint = self.getAutoMountPoint()
286 defaultMountPointEntry = (self.icon_button_green, _("Set up Default Mount Point"), _("Mount Point : %s ->%s")%(currentMountPoint, defaultMountPoint), "default", defaultMountPoint, self.divpng)
287 autoMountPointEntry = (self.icon_button_green, _("Automatically set up a Mount Point"), _("Mount Point : %s -> %s")%(currentMountPoint, autoMountPoint), "auto", autoMountPoint, self.divpng)
288 manuallyMountPointEntry = (self.icon_button_green, _("User manually Set up a Mount Point"), _("Mount Point : click ok button on here."), "manual", "", self.divpng)
289 if not path.ismount(defaultMountPoint):
290 self.mountPointList.append(defaultMountPointEntry)
291 self.mountPointList.append(autoMountPointEntry)
292 self.mountPointList.append(manuallyMountPointEntry)
293 self.currList = "mountpoint"
294 self["menu"].style = "mountpoint"
295 self["menu"].setList(self.mountPointList)
297 def getCurrentDevice(self):
299 return self["menu"].getCurrent()[6]
303 def getCurrentPartition(self):
305 return self["menu"].getCurrent()[7]
311 if self.currList == "default":
312 self.currDevice = self.getCurrentDevice()
313 if self.currDevice is not None:
314 if len(self.currDevice["partitions"]) == 0:
315 self.session.open(MessageBox, _("No partition list found on device.\nPlease click BLUE key and do Initialize to use this device."), MessageBox.TYPE_ERROR, timeout = 10)
317 self.showPartitionList()
319 self.session.open(MessageBox, _("Device not found."), MessageBox.TYPE_ERROR, timeout = 10)
320 elif self.currList == "partitions":
321 currentPartition = self.getCurrentPartition()
322 if currentPartition is not None:
323 currMountPoint = currentPartition["mountpoint"]
324 currUuid = currentPartition["uuid"]
325 if currMountPoint == "":
326 self.currPartition = currentPartition
327 self.showMountPointSetup()
329 self.doUmount(currMountPoint, self.showPartitionList)
331 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
332 elif self.currList == "mountpoint":
333 # self["menu"].getCurrent() : (green_button, "menu description", "mount point description, "default", mountpoint, self.divpng)
334 currEntry = self["menu"].getCurrent()[3]
335 if currEntry == "default":
336 # print "Setup mountpoint default!"
337 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
338 elif currEntry == "auto":
339 # print "Setup mountpoint automatically!"
340 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
342 # print "Setup mountpoint manually!"
343 self.session.openWithCallback(self.MountpointBrowserCB, MountpointBrowser)
349 if self.DeviceManagerConsole is not None:
350 if len(self.DeviceManagerConsole.appContainers):
351 for name in self.DeviceManagerConsole.appContainers.keys():
352 self.DeviceManagerConsole.kill(name)
353 if self.currList == "partitions":
354 self.currDevice = None
355 self.showDeviceList()
356 elif self.currList == "mountpoint":
357 self.currPartition = None
358 self.showPartitionList()
359 else: # currList = "default"
363 if self.currList == "partitions":
364 self.choiceBoxFstype()
367 if self.currList == "default":
368 device = self.getCurrentDevice()
369 if device is not None:
370 self.session.openWithCallback(self.deviceInitCB, DeviceInit, device["blockdev"], device["size"])
372 self.session.open(MessageBox, _("Device not found."), MessageBox.TYPE_ERROR, timeout = 10)
373 elif self.currList == "partitions":
374 partition = self.getCurrentPartition()
375 if partition is not None:
376 self.session.openWithCallback(self.deviceCheckCB, DeviceCheck, partition)
378 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
381 self.session.open(DeviceManagerConfiguration)
383 def deviceInitCB(self, ret = True):
384 self.showDeviceList()
386 def deviceCheckCB(self, ret = True):
387 self.showPartitionList()
389 def deviceFormatCB(self, ret = True):
390 self.showPartitionList()
392 def choiceBoxFstype(self):
394 menu.append((_("ext2 - recommended for USB flash memory"), "ext2"))
395 menu.append((_("ext3 - recommended for harddisks"), "ext3"))
396 menu.append((_("ext4 - experimental"), "ext4"))
397 menu.append((_("vfat - for USB flash memory"), "vfat"))
398 self.session.openWithCallback(self.choiceBoxFstypeCB, ChoiceBox, title=_("Choice filesystem."), list=menu)
400 def choiceBoxFstypeCB(self, choice):
404 partition = self.getCurrentPartition()
405 if partition is not None:
406 self.session.openWithCallback(self.deviceFormatCB, DeviceFormat, partition, choice[1])
408 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
410 # about mount funcs..
411 def doUmount(self, mountpoint, callback):
412 cmd = "umount %s"%mountpoint
413 print "[DeviceManager] cmd : %s"%cmd
415 if not path.ismount(mountpoint):
416 devicemanagerconfig.updateConfigList()
418 self.session.open(MessageBox, _("Can't umount %s. \nMaybe device or resource busy.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
421 def getDefaultMountPoint(self):
422 return self.defaultMountPoint
424 def getAutoMountPoint(self):
425 mountPoint = "/media/"+self.currDevice["model"]
426 mountPoint = mountPoint.replace(' ','-')
427 if path.ismount(mountPoint):
430 mountPoint_fix = mountPoint+str(partnum)
431 if not path.ismount(mountPoint_fix):
434 mountPoint = mountPoint_fix
437 def doMount(self, partition, mountpoint):
439 # check mountpoint is in partition list.
440 if mountpoint != self.getDefaultMountPoint():
441 for p in harddiskmanager.partitions:
442 if p.mountpoint == mountpoint:
443 self.session.open(MessageBox, _("Can not use this mount point.(%s) \nPlease select another mount point.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
446 device = partition["partition"]
447 filesystem = partition["fstype"]
448 uuid = partition["uuid"]
449 if mountpoint.endswith("/"):
450 mountpoint = retval[:-1]
451 if mountpoint.find(' ') != -1:
452 mountpoint = mountpoint.replace(' ','-')
453 devpath = "/dev/"+device
454 if deviceinfo.isMounted(devpath, mountpoint):
455 print "[DeviceManager] '%s -> %s' is already mounted."%(devpath, mountpoint)
458 # check current device mounted on another mountpoint.
459 mp_list = deviceinfo.checkMountDev(devpath)
461 if mp != mountpoint and path.ismount(mp):
462 deviceinfo.umountByMountpoint(mp)
463 # check another device mounted on configmountpoint
464 devpath_list = deviceinfo.checkMountPoint(mountpoint)
465 for devpath_ in devpath_list:
466 if devpath_ != devpath:
467 self.session.open(MessageBox, _("Mount Failed!\nCurrent path is already mounted by \"%s\"")%devpath_list[0], MessageBox.TYPE_ERROR, timeout = 10)
470 print "[DeviceManagerHotplugDevice] doMount"
471 if not path.exists(mountpoint):
472 os.system("mkdir %s"%mountpoint)
473 if path.exists(mountpoint):
474 if not path.ismount(mountpoint):
475 if filesystem == "ntfs":
476 cmd = "ntfs-3g %s %s"%(devpath, mountpoint)
477 elif filesystem is None:
478 cmd = "mount %s %s"%(devpath, mountpoint)
480 cmd = "mount -t %s %s %s"%(filesystem, devpath, mountpoint)
481 print "[DeviceManager] cmd : %s"%cmd
482 self.DeviceManagerConsole.ePopen(cmd, self.doMountFinished, (devpath, mountpoint) )
484 self.session.open(MessageBox, _("Mount Failed!\n(%s -> %s)")%(device, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
486 def doMountFinished(self, result, retval, extra_args = None):
487 (devpath, mountpoint) = extra_args
489 if not deviceinfo.isMounted(devpath, mountpoint):
490 # print "[DeviceManager] %s doMount failed!"%devpath
491 self.session.open(MessageBox, _("Mount Failed!\n(%s -> %s)")%(devpath, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
494 # make movie directory
495 if mountpoint == "/media/hdd":
496 movieDir = mountpoint + "/movie"
497 if not pathExists(movieDir):
498 print "[DeviceManager] make dir %s"%movieDir
499 os.makedirs(movieDir)
500 self.showPartitionList()
501 # update current mount state ,devicemanager.cfg
502 devicemanagerconfig.updateConfigList()
504 def MountpointBrowserCB(self, retval = None):
505 if retval and retval is not None:
506 mountPoint = retval.strip().replace(' ','')
507 if retval.endswith("/"):
508 mountPoint = retval[:-1]
509 print "Mount point from MountpointBrowser : %s"%mountPoint
510 if not path.exists(mountPoint):
511 self.session.open(MessageBox, _("Mount Point is not writeable.\nPath : %s")%mountPoint, MessageBox.TYPE_ERROR, timeout = 10)
514 self.doMount(self.currPartition, mountPoint)
517 # Initializing Start...
518 class DeviceInit(Screen):
519 skin = """<screen position="0,0" size="0,0"/>"""
520 def __init__(self, session, device, devicesize):
521 Screen.__init__(self, session)
522 self.session = session
523 self.deviceInitConsole = Console()
525 self.devicesize = int(devicesize)
526 self.inputbox_partitions = 1
527 self.inputbox_partitionSizeList = []
528 self.inputbox_partitionSizeTotal = int(self.devicesize/1024/1024)
529 self.msgWaiting = None
530 self.msgWaitingMkfs = None
531 self.devicenumber = 0
532 self.newpartitions = 0
533 self.onLayoutFinish.append(self.timerStart)
534 self.initStartTimer = eTimer()
535 self.initStartTimer.callback.append(self.confirmMessage)
536 self.createFSStartTimer = eTimer()
537 self.createFSStartTimer.callback.append(self.createFilesystemStart)
538 self.exitMessageTimer = eTimer()
539 self.exitMessageTimer.callback.append(self.exitMessage)
543 self.doMkfsTimer = eTimer()
544 self.doMkfsTimer.callback.append(self.doMkfs)
545 self.doInitializeTimer = eTimer()
546 self.doInitializeTimer.callback.append(self.doInitialize)
548 self.partitionType = "MBR"
550 self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
553 def timerStart(self):
554 self.initStartTimer.start(100,True)
556 def confirmMessage(self):
557 message = _("Do you really want to initialize the device?\nAll data on the device will be lost!")
558 self.session.openWithCallback(self.confirmed, MessageBox, message)
560 def confirmed(self, ret):
562 self.InitializeStart()
566 def exit(self, ret = True):
569 def unmountAll(self, device):
570 mounts = file('/proc/mounts').read().split('\n')
574 if not line.startswith("/dev/" + device):
576 cmd += "umount %s ;"% line.split()[0]
577 print "[DeviceManager] %s"%cmd
580 mounts = file('/proc/mounts').read().split('\n')
582 if line.startswith("/dev/" + device):
586 def InitializeStart(self):
587 if self.devicesize >= ( 2.2 * 1000 * 1000 * 1000 * 1000 ): # 2.2TB
588 self.partitionType = "GPT"
590 self.inputbox_partitionSizeRemain = 100
593 self.InputPartitionSize_step1()
595 def InputPartitionSize_step1(self):
596 self.session.openWithCallback(self.InputPartitionSize_step1_CB, InputBox, title=_("How many partitions do you want?(1-%d)" % self.maxPartNum), text="1", maxSize=False, type=Input.NUMBER)
598 def InputPartitionSize_step1_CB(self, ret):
599 if ret is not None and int(ret) in range(1,self.maxPartNum+1): # MBR 1~4, GPT 1~20
600 self.inputbox_partitions = int(ret)
601 self.InputPartitionSize_step2()
603 self.session.openWithCallback(self.exit, MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
605 def InputPartitionSize_step2(self):
606 current_partition = len(self.inputbox_partitionSizeList)+1
607 if self.inputbox_partitionSizeRemain == 0:
608 self.choiceBoxFstype()
609 elif current_partition == self.inputbox_partitions:
610 self.inputbox_partitionSizeList.append(str(self.inputbox_partitionSizeRemain))
611 self.choiceBoxFstype()
613 text = str(int(self.inputbox_partitionSizeRemain/(self.inputbox_partitions-len(self.inputbox_partitionSizeList) )))
614 self.session.openWithCallback(self.InputPartitionSize_step2_CB, InputBox, title=_("Input size of partition %s.(Unit = %s, Max = %d %s)")%(current_partition, self.unit, self.inputbox_partitionSizeRemain, self.unit), text=text, maxSize=False, type=Input.NUMBER)
616 def InputPartitionSize_step2_CB(self, ret):
618 if self.inputbox_partitionSizeRemain < int(ret) or int(ret) == 0:
619 self.InputPartitionSize_step2()
621 self.inputbox_partitionSizeList.append(str(ret))
622 self.inputbox_partitionSizeRemain -= int(ret)
623 self.InputPartitionSize_step2()
625 self.session.openWithCallback(self.exit ,MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
627 def choiceBoxFstype(self):
629 menu.append((_("ext2 - recommended for USB flash memory"), "ext2"))
630 menu.append((_("ext3 - recommended for harddisks"), "ext3"))
631 menu.append((_("ext4 - experimental"), "ext4"))
632 menu.append((_("vfat - for USB flash memory"), "vfat"))
633 self.session.openWithCallback(self.choiceBoxFstypeCB, ChoiceBox, title=_("Choice filesystem."), list=menu)
635 def choiceBoxFstypeCB(self, choice):
639 self.fstype = choice[1]
640 if self.fstype not in ["ext2", "ext3", "ext4", "vfat"]:
643 self.initInitializeConfirm()
645 def initInitializeConfirm(self):
646 # print self.inputbox_partitionSizeList
648 for index in range(len(self.inputbox_partitionSizeList)):
649 print "partition %d : %s %s"%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
650 partitionsInfo += "partition %d : %s %s\n"%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
651 partitionsInfo += "filesystem type : %s"%(self.fstype)
652 self.session.openWithCallback(self.initInitializeConfirmCB, MessageBoxConfirm, _("%s\nStart Device Inititlization?") % partitionsInfo , MessageBox.TYPE_YESNO)
654 def initInitializeConfirmCB(self,ret):
656 self.initInitialize()
660 def initInitialize(self):
661 if not self.unmountAll(self.device):
662 self.session.openWithCallback(self.exit, MessageBox, _("umounting failed!Maybe some files in mount point are open"), MessageBox.TYPE_ERROR, timeout = 10)
664 msg = _("InitInitializing, please wait ...")
665 msg += _("\nDevice : %s")%self.device
666 msg += _("\nSize : %s MB\n")%self.inputbox_partitionSizeTotal
667 for index in range(len(self.inputbox_partitionSizeList)):
668 msg += _("\npartition %d : %s %s")%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
669 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
670 self.doInitializeTimer.start(500,True)
672 def doInitialize(self):
673 def CheckPartedVer():
674 cmd = 'parted --version'
675 lines = os.popen(cmd).readlines()
677 if l.find("parted (GNU parted)") != -1:
678 ver = l.split()[3].strip()
683 print "[CheckPartedVer] check parted version Failed!"
687 partitions = len(self.inputbox_partitionSizeList) # get num of partition
689 if self.partitionType == "MBR":
691 cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS /dev/' + self.device
695 set += ",%s\n"%(self.inputbox_partitionSizeList[p])
699 cmd = 'printf "%s" | sfdisk -f -uM /dev/%s'%(set,self.device)
701 elif self.partitionType == "GPT": # partition type is GPT
703 partedVer = CheckPartedVer()
704 if partedVer >= 2.1: # align option is supported in version 2.1 or later
705 setAlign = "--align optimal"
708 cmd = 'parted %s /dev/%s --script mklabel gpt mkpart disk ext2 0%% 100%%' % (setAlign, self.device)
709 else: # has multiple partitions
711 for p in range(partitions):
714 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )
716 elif p > 0 and partitions > (p + 1):
718 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )+ p_start
720 elif partitions == (p + 1):
727 set += 'mkpart disk%d ext2 %d%% %d%% ' % (p + 1, p_start, p_end)
728 cmd = 'parted %s /dev/%s --script mklabel gpt %s' % (setAlign, self.device, set)
730 errorMsg = "Invalid partitioning type"
731 self.msgWaiting.run_close(False, errorMsg)
733 self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
735 def initInitializeFinished(self, result, retval, extra_args = None):
737 if self.partitionType == "MBR":
738 cmd = "sfdisk -R /dev/%s ; sleep 5" % (self.device)
741 self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
743 errorMsg = "initInitializing device Error at /dev/%s"%self.device
744 self.msgWaiting.run_close(False, errorMsg)
746 def initInitializingRefreshFinished(self, result, retval, extra_args = None):
747 cmd = "/bin/umount /dev/%s*" % (self.device)
748 self.deviceInitConsole.ePopen(cmd, self.initInitializingUmountFinished)
750 def initInitializingUmountFinished(self, result, retval, extra_args = None):
751 partitions = open("/proc/partitions")
752 self.devicenumber = 0
753 self.newpartitions = 0
754 for part in partitions:
755 res = re.sub("\s+", " ", part).strip().split(" ")
756 if res and len(res) == 4 and res[3][:3] == self.device:
757 if len(res[3]) > 3 and res[3][:2] == "sd":
758 self.newpartitions += 1
760 partNum = len(self.inputbox_partitionSizeList) # get num of partition
761 if self.newpartitions != partNum:
762 errorMsg = "Partitioning device Error at /dev/%s"%self.device
763 self.msgWaiting.run_close(False, errorMsg)
765 self.msgWaiting.run_close(True)
766 # self.createFilesystem(self.newpartitions)
768 def createFilesystem(self, newpartitions):
769 self.devicenumber = self.devicenumber + 1
770 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
771 shortdevicename = self.device + str(self.devicenumber)
773 partitions = open("/proc/partitions")
774 for part in partitions:
775 res = re.sub("\s+", " ", part).strip().split(" ")
776 if res and len(res) == 4:
777 if res[3] == shortdevicename:
778 partitionsize = int(res[2])
782 if self.fstype == "ext4":
783 cmd = "/sbin/mkfs.ext4 -F "
784 if partitionsize > 2 * 1024 * 1024: # 2GB
785 cmd += "-T largefile "
786 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 " + fulldevicename
787 elif self.fstype == "ext3":
788 cmd = "/sbin/mkfs.ext3 -F "
789 if partitionsize > 2 * 1024 * 1024:
790 cmd += "-T largefile "
791 cmd += "-m0 " + fulldevicename
792 elif self.fstype == "ext2":
793 cmd = "/sbin/mkfs.ext2 -F "
794 if partitionsize > 2 * 1024 * 1024:
795 cmd += "-T largefile "
796 cmd += "-m0 " + fulldevicename
797 elif self.fstype == "vfat":
798 if partitionsize > 4 * 1024 * 1024 * 1024:
799 cmd = "/usr/sbin/mkfs.vfat -I -S4096 " + fulldevicename
801 cmd = "/usr/sbin/mkfs.vfat -I " + fulldevicename
803 self.createFilesystemFinished(None, -1, (self.device, fulldevicename))
806 msg = _("Create filesystem, please wait ...")
807 msg += _("\nPartition : %s") % (fulldevicename)
808 msg += _("\nFilesystem : %s") % (self.fstype)
809 msg += _("\nDisk Size : %s MB") % (self.inputbox_partitionSizeTotal)
810 msg += _("\nPartition Size : %d %s\n") % (int(self.inputbox_partitionSizeList[self.devicenumber-1]), self.unit)
811 self.msgWaitingMkfs = self.session.openWithCallback(self.msgWaitingMkfsCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
813 self.doMkfsTimer.start(500,True)
816 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
817 self.deviceInitConsole.ePopen(self.mkfs_cmd, self.createFilesystemFinished, (self.device, fulldevicename))
819 def createFilesystemFinished(self, result, retval, extra_args = None):
820 device = extra_args[0]
821 fulldevicename = extra_args[1]
823 self.msgWaitingMkfs.run_close(True)
825 errorMsg = _("Creating filesystem Error")
826 if fulldevicename is not None:
827 errorMsg += _(" at /dev/%s")%fulldevicename
828 self.msgWaitingMkfs.run_close(False, errorMsg)
830 def createFilesystemStart(self):
831 self.createFilesystem(self.newpartitions)
833 def msgWaitingCB(self, ret, msg=""):
835 self.createFSStartTimer.start(100,True)
839 self.exitMessageTimer.start(100,True)
841 def msgWaitingMkfsCB(self, ret, msg=""):
842 if self.devicenumber < self.newpartitions:
843 self.createFSStartTimer.start(100,True)
847 self.msg = _("Device Initialization finished sucessfully!")
848 self.updateDeviceInfo()
849 self.exitMessageTimer.start(100,True)
853 self.exitMessageTimer.start(100,True)
855 def exitMessage(self):
857 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_INFO, timeout = 10)
859 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_ERROR, timeout = 10)
861 def updateDeviceInfo(self):
862 # update devicemanager configs
863 devicemanagerconfig.updateConfigList()
867 # device check start..
868 class DeviceCheck(Screen):
869 skin = """<screen position="0,0" size="0,0"/>"""
870 def __init__(self, session, partition):
871 Screen.__init__(self, session)
872 self.session = session
873 self.deviceCheckConsole = Console()
874 self.partition = partition
875 self.onLayoutFinish.append(self.timerStart)
876 self.checkStartTimer = eTimer()
877 self.checkStartTimer.callback.append(self.confirmMessage)
878 self.umountTimer = eTimer()
879 self.umountTimer.callback.append(self.doUnmount)
881 def timerStart(self):
882 self.checkStartTimer.start(100,True)
884 def confirmMessage(self):
885 fssize = self.partition["size"]
886 if long(fssize) > 1024*1024*1024*16:
887 message = _("Do you really want to check the filesystem?\nThis could take lots of time!")
888 self.session.openWithCallback(self.confirmed, MessageBox, message)
890 self.deviceCheckStart()
892 def confirmed(self, ret):
893 print "confirmed : ",ret
895 self.deviceCheckStart()
899 def deviceCheckStart(self):
900 print "deviceCheckStart "
901 print "partition : ", self.partition
902 device = self.partition["partition"]
903 fstype = self.partition["fstype"]
904 fssize = self.partition["size"]
905 if device is not None and fstype.startswith("ext"):
906 msg = _("Check filesystem, please wait ...")
907 msg += _("\nDevice : /dev/%s")%(device)
908 msg += _("\nFilesystem : %s")%(fstype)
909 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
910 self.umountTimer.start(500,True)
915 device = self.partition["partition"]
916 mountpoint = self.partition["mountpoint"]
917 fstype = self.partition["fstype"]
919 self.doUmountFsck(device, mountpoint, fstype)
921 self.umountFsckFinished("NORESULT", 0, (device, mountpoint, fstype))
923 def doUmountFsck(self, device, mountpoint, fstype):
924 cmd = "umount /dev/%s" % device
925 self.deviceCheckConsole.ePopen(cmd, self.umountFsckFinished, (device, mountpoint, fstype))
927 def umountFsckFinished(self, result, retval, extra_args = None):
928 device = extra_args[0]
929 mountpoint = extra_args[1]
930 fstype = extra_args[2]
932 cmd = "fsck." + fstype + " -f -p /dev/" + device
933 self.deviceCheckConsole.ePopen(cmd, self.fsckFinished, extra_args)
935 errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%device
936 self.msgWaiting.run_close(False,errorMsg)
938 def fsckFinished(self, result, retval, extra_args = None):
939 device = extra_args[0]
940 mountpoint = extra_args[1]
942 text = _("Filesystem check finished sucessfully")
943 self.msgWaiting.run_close(True, text)
945 text = _("Error checking disk. The disk or filesystem may be damaged")
946 self.msgWaiting.run_close(False, text)
948 def msgWaitingCB(self, ret, msg):
950 self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
952 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
954 partition = self.partition["partition"]
955 mountpoint = self.partition["mountpoint"]
956 fstype = self.partition["fstype"]
959 cmd = "ntfs-3g /dev/" + partition + " " + mountpoint
961 cmd = "mount /dev/" + partition + " " + mountpoint
962 self.deviceCheckConsole.ePopen(cmd, self.mountPartitionFinished)
966 def mountPartitionFinished(self, result, retval, extra_args = None):
975 class DeviceFormat(Screen):
976 skin = """<screen position="0,0" size="0,0"/>"""
977 def __init__(self, session, partition, newfstype):
978 Screen.__init__(self, session)
979 self.session = session
980 self.deviceFormatConsole = Console()
981 self.partition = partition
982 self.newfstype = newfstype
983 self.unmountedList = []
984 self.onLayoutFinish.append(self.timerStart)
985 self.formatStartTimer = eTimer()
986 self.formatStartTimer.callback.append(self.DeviceFormatStart)
987 self.setHotplugDisabled = False
988 self.umountTimer = eTimer()
989 self.umountTimer.callback.append(self.doUnmount)
991 def timerStart(self):
992 self.formatStartTimer.start(100,True)
994 def DeviceFormatStart(self):
995 devicemanagerhotplug.setHotplugActive(False)
996 self.setHotplugDisabled = True
997 print "DeviceFormatStart : ", self.partition,
998 print "Filesystem : ",self.newfstype
999 device = self.partition["partition"]
1000 devicepath = "/dev/"+device
1001 fssize = self.partition["size"]
1002 newfstype = self.newfstype
1003 msg = _("Format filesystem, please wait ...")
1004 msg += _("\nDevice : %s")%(devicepath)
1005 msg += _("\nFilesystem : %s")%(newfstype)
1006 msg += _("\nSize : %s")%(byteConversion(fssize))
1007 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox_2.TYPE_INFO, enable_input = False, msgBoxID = None)
1008 self.umountTimer.start(500,True)
1010 def doUnmount(self):
1011 mountpoint = self.partition["mountpoint"]
1012 if mountpoint != "":
1013 self.doumountPartition()
1015 self.umountPartitionFinished("NORESULT", 0)
1017 def doumountPartition(self):
1018 oldfstype = self.partition["fstype"]
1019 newfstype = self.newfstype
1021 if newfstype == oldfstype:
1022 device = self.partition["partition"]
1024 device = self.partition["partition"][:3]
1026 mounts = file('/proc/mounts','r')
1027 for line in mounts.readlines():
1028 if line.startswith("/dev/%s"%device):
1029 cmd += "umount %s;"%line.split()[0]
1030 self.unmountedList.append([line.split()[0], line.split()[1]])
1031 self.deviceFormatConsole.ePopen(cmd, self.umountPartitionFinished)
1033 def umountPartitionFinished(self, result, retval, extra_args = None):
1034 partition = self.partition["partition"]
1035 oldfstype = self.partition["fstype"]
1036 newfstype = self.newfstype
1038 if oldfstype == newfstype:
1039 self.changePartitionIDFinished("NORESULT", 0)
1041 cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
1042 if newfstype[:3] == "ext":
1046 self.deviceFormatConsole.ePopen(cmd, self.changePartitionIDFinished)
1048 errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%partition[:3]
1049 self.msgWaiting.run_close(False,errorMsg)
1051 def changePartitionIDFinished(self, result, retval, extra_args = None):
1052 device = self.partition["partition"][:3]
1053 mountpoint = self.partition["mountpoint"]
1054 oldfstype = self.partition["fstype"]
1055 newfstype = self.newfstype
1057 if oldfstype == newfstype:
1058 self.refreshPartitionFinished("NORESULT", 0)
1060 cmd = "sfdisk -R /dev/%s; sleep 5"%(device)
1061 self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
1063 if result and result.find("Use GNU Parted") > 0:
1064 print "[DeviceManager] /dev/%s use GNU Parted!" % device
1065 self.refreshPartitionFinished("NORESULT", 0)
1067 errorMsg = _("Can not change the partition ID for %s")%device
1068 self.msgWaiting.run_close(False,errorMsg)
1070 def refreshPartitionFinished(self, result, retval, extra_args = None):
1071 print "refreshPartitionFinished!"
1072 partition = self.partition["partition"]
1073 mountpoint = self.partition["mountpoint"]
1074 size = int(self.partition["size"])/1024/1024
1075 oldfstype = self.partition["fstype"]
1076 newfstype = self.newfstype
1078 if newfstype == "ext4":
1079 cmd = "/sbin/mkfs.ext4 -F "
1081 cmd += "-T largefile "
1082 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
1083 elif newfstype == "ext3":
1084 cmd = "/sbin/mkfs.ext3 -F "
1086 cmd += "-T largefile "
1087 cmd += "-m0 /dev/" + partition
1088 elif newfstype == "ext2":
1089 cmd = "/sbin/mkfs.ext2 -F "
1091 cmd += "-T largefile "
1092 cmd += "-m0 /dev/" + partition
1093 elif newfstype == "vfat":
1094 if size > 4 * 1024 * 1024:
1095 cmd = "/usr/sbin/mkfs.vfat -I -S4096 /dev/" + partition
1097 cmd = "/usr/sbin/mkfs.vfat -I /dev/" + partition
1098 self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
1100 errorMsg = _("Can not format device /dev/%s.\nrefresh partition information failed!")%partition
1101 self.msgWaiting.run_close(False,errorMsg)
1103 def mkfsFinished(self, result, retval, extra_args = None):
1104 print "mkfsFinished!"
1105 partition = self.partition["partition"]
1108 if len(self.unmountedList) == 0:
1109 self.doMountFinished("NORESULT",0)
1110 for x in self.unmountedList:
1111 cmd += "mount %s %s;"%(x[0], x[1])
1112 self.deviceFormatConsole.ePopen(cmd, self.doMountFinished)
1114 text = _("Make filesystem Error /dev/%s.\nPlease check your device.")%partition
1115 self.msgWaiting.run_close(False, text)
1117 def doMountFinished(self, result, retval, extra_args = None):
1118 print "doMountFinished!"
1119 text = _("Format finished sucessfully.")
1120 self.msgWaiting.run_close(True, text)
1122 def msgWaitingCB(self, ret, msg):
1124 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
1126 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
1128 def exit(self, ret):
1129 if self.setHotplugDisabled == True:
1130 devicemanagerhotplug.setHotplugActive(True)
1131 self.setHotplugDisabled = False
1138 self.blockDeviceList = []
1140 def getBlockDevices(self):
1141 return self.blockDeviceList
1144 self.blockDeviceList = []
1145 self.getBlockDeviceList()
1147 def getBlockDeviceList(self):
1148 print "get block device Infomations..."
1149 for blockdev in listdir("/sys/block"):
1150 (error, blacklisted, removable, partitions, size, model, vendor) = self.getBlockDeviceInfo(blockdev)
1151 if not blacklisted and not error:
1152 # print "%s : error %s, blacklisted %s, removable %s, partitions %s, size %s"%(blockdev, error, blacklisted, removable, partitions, size)
1154 blockDevice["blockdev"] = blockdev # str
1155 blockDevice["removable"] = removable # bool [True, False]
1156 blockDevice["partitions"] = partitions # list
1157 blockDevice["size"] = size # str
1158 blockDevice["model"] = model # str
1159 blockDevice["vendor"] = vendor # str
1160 self.blockDeviceList.append(blockDevice)
1162 def SortPartList(self, partList):
1163 length = len(partList)-1
1165 while sorted is False:
1167 for idx in range(length):
1168 if int(partList[idx][3:]) > int(partList[idx+1][3:]):
1170 partList[idx] , partList[idx+1] = partList[idx+1], partList[idx]
1172 def getBlockDeviceInfo(self, blockdev):
1173 devpath = "/sys/block/" + blockdev
1182 dev = int(readFile(devpath + "/dev").split(':')[0])
1183 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1185 return error, blacklisted, removable, partitions, size, model, vendor
1186 removable = bool(int(readFile(devpath + "/removable")))
1187 size = str(int(readFile(devpath + "/size").strip())*512)
1188 model = readFile(devpath + "/device/model")
1189 vendor = readFile(devpath + "/device/vendor")
1190 for partition in listdir(devpath):
1191 if partition[:len(blockdev)] != blockdev:
1193 partitions.append(partition)
1194 self.SortPartList(partitions)
1198 return error, blacklisted, removable, partitions, size, model, vendor
1200 def getPartitionInfo(self, partition):
1201 mountPoint = self.getPartitionMountpoint(partition)
1202 (uuid , fsType) = self.getPartitionBlkidInfo(partition)
1203 size_total = self.getPartitionSize(partition)
1205 if mountPoint != "":
1206 size_free = self.getPartitionFree(mountPoint)
1208 partitionInfo["partition"] = partition
1209 partitionInfo["mountpoint"] = mountPoint
1210 partitionInfo["uuid"] = uuid
1211 partitionInfo["fstype"] = fsType
1212 partitionInfo["size"] = size_total
1213 partitionInfo["free"] = size_free
1214 return partitionInfo
1216 def getPartitionMountpoint(self, partition):
1217 mounts = file('/proc/mounts').read().split('\n')
1219 if not x.startswith('/'):
1221 devpath, mountpoint, = x.split()[:2]
1222 if mountpoint.startswith('/autofs'):
1224 if path.basename(devpath) == partition:
1228 def getPartitionBlkidInfo(self, partition):
1229 parttionDev = "/dev/"+str(partition)
1232 cmd = "blkid -c /dev/null "+str(parttionDev)
1234 line = popen(cmd).readline().strip()
1235 if not line.startswith(parttionDev):
1236 return (uuid, partitionType)
1237 # print "Blikd %s : %s"%(parttionDev, line)
1238 if line.find(" UUID=") != -1:
1239 uuid = line.split(" UUID=")[1].split(' ')[0]
1240 if line.find(" TYPE=") != -1:
1241 partitionType = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1243 print "get blkid info error (%s)"%cmd
1244 return (uuid, partitionType)
1246 def getPartitionSize(self, partition):
1247 devpath = "/sys/block/%s/%s"%( str(partition[:3]), str(partition) )
1249 size = readFile(devpath + "/size")
1250 return str(int(size)*512)
1254 def getPartitionFree(self, mountPoint):
1256 stat = statvfs(mountPoint)
1257 size_free = stat.f_bfree*stat.f_bsize
1262 def checkMountPoint(self, check_mountpoint):
1265 mounts = file('/proc/mounts').read().split('\n')
1267 if not x.startswith('/'):
1269 devpath, mountpoint = x.split()[:2]
1270 if mountpoint == check_mountpoint:
1276 def checkMountDev(self, device):
1279 mounts = file('/proc/mounts').read().split('\n')
1281 if not x.startswith('/'):
1283 devpath, mountpoint = x.split()[:2]
1284 if devpath == device:
1285 res.append(mountpoint)
1290 def isMounted(self, devpath, mountpoint):
1292 mounts = file('/proc/mounts').readlines()
1294 if not x.startswith('/'):
1296 _devpath, _mountpoint = x.split()[:2]
1297 if devpath == _devpath and mountpoint == _mountpoint:
1303 def isMounted_anymp(self, devpath):
1305 mounts = open('/proc/mounts', 'r').readlines()
1307 if not x.startswith('/'):
1309 _devPart, _mountpoint = x.split()[:2]
1310 if devPart == _devPart:
1316 # check partition ID in extended or swap.
1317 def checkSwapExtended(self, partition):
1318 partID_Extended = ("5", "0f", "85", "c5", "d5")
1319 partID_swap = ("82", "42")
1320 data = os.popen("fdisk -l /dev/%s |grep %s" % (partition[:-1], partition )).readline().split()
1322 partID = str(data[5])
1324 partID = str(data[4])
1325 # print "partID: " ,partID
1326 # print "checkIDS : ", partID_Extended + partID_swap
1327 if partID in partID_Extended + partID_swap:
1332 def isMountable(self, partition):
1333 if self.checkSwapExtended(partition):
1337 if self.isMounted_anymp('/dev/'+partition):
1340 elif os.access('/autofs/'+partition, 0):
1346 def isFstabAutoMounted(self, uuid, devpath, mountpoint):
1347 # print " >> isFstabMounted, uuid : %s, devpath : %s, mountpoint : %s"%(uuid, devpath, mountpoint)
1348 if mountpoint[-1] == '/':
1349 mountpoint = mountpoint[:-1]
1350 data = file('/etc/fstab').read().split('\n')
1352 if not line.startswith('/'):
1354 dev, mp, ms = line.split()[0:3]
1355 if uuid is not None and dev.startswith('UUID'):
1356 if dev.split('=')[1] == uuid.strip("\"") and mp == mountpoint and ms == 'auto':
1357 # print " >> line : ", line
1359 elif dev == devpath and mp == mountpoint and ms == 'auto':
1360 # print " >> line : ", line
1364 def umountByMountpoint(self, mountpoint):
1365 if mountpoint is None:
1368 if path.ismount(mountpoint):
1369 cmd = "umount " + mountpoint
1370 print "[DeviceManager] ", cmd
1373 print "Umount by mountpoint failed!"
1374 if not path.ismount(mountpoint):
1378 def umountByDevpath(self, devpath):
1379 cmd = "umount " + devpath
1380 print "[DeviceManager] ", cmd
1383 deviceinfo = DeviceInfo()
1385 class MountpointBrowser(Screen):
1387 <screen name="MountpointBrowser" position="center,120" size="670,500" title="Select mountpoint">
1388 <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
1389 <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
1390 <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
1391 <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
1392 <widget source="key_red" render = "Label" position="20,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
1393 <widget source="key_green" render = "Label" position="180,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
1394 <widget source="key_yellow" render = "Label" position="340,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
1395 <widget source="key_blue" render = "Label" position="500,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
1396 <eLabel position="10,50" size="650,1" backgroundColor="#b3b3b9"/>
1397 <widget name="filelist" position="10,60" size="650,440" itemHeight="30" scrollbarMode="showOnDemand"/>
1400 def __init__(self, session):
1401 Screen.__init__(self, session)
1402 self["key_red"] = StaticText(_("Cancel"))
1403 self["key_green"] = StaticText(_("Select"))
1404 self["key_yellow"] = StaticText(_("Create directory"))
1405 self["key_blue"] = StaticText("Delete directory")
1406 directory = "/media/"
1407 inhibitDirs = ["/autofs", "/mnt", "/hdd", "/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
1408 self.filelist = FileList(directory, matchingPattern="", inhibitDirs = inhibitDirs)
1409 self["filelist"] = self.filelist
1411 self["shortcuts"] = ActionMap(["ColorActions"],
1414 "green": self.select,
1415 "yellow": self.createDirectory,
1416 "blue": self.deleteDirectory,
1419 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
1421 "cancel": self.exit,
1426 if self.filelist.canDescent():
1427 self.filelist.descent()
1430 if self["filelist"].getCurrentDirectory() is not None:
1431 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1432 self.filelist.descent()
1433 currDir = self["filelist"].getCurrentDirectory()
1436 self.close(self["filelist"].getFilename())
1438 def createDirectory(self):
1439 self.session.openWithCallback(self.createDirectoryCB, VirtualKeyBoard, title = (_("Input mount point path.")), text = "")
1441 def createDirectoryCB(self, retval = None):
1444 if retval is not None:
1445 newdir = self["filelist"].getCurrentDirectory()+'/'+retval
1446 if not path.exists(newdir):
1447 os.system("mkdir %s"%newdir)
1448 self.filelist.refresh()
1451 self.session.open(MessageBox, _("Create directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1453 def deleteDirectory(self):
1456 if self["filelist"].getCurrentDirectory() is not None:
1457 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1458 delDir = self["filelist"].getFilename()
1459 if path.exists(delDir):
1460 os.system("rmdir '%s'"%delDir)
1461 if path.exists(delDir):
1462 self.session.open(MessageBox, _("Delete directory failed!\nMaybe directory is not empty."), MessageBox.TYPE_ERROR, timeout = 10)
1463 self.filelist.refresh()
1466 self.session.open(MessageBox, _("Delete directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1471 class MessageBoxConfirm(MessageBox):
1473 <screen position="center,center" size="620,10" title="Message">
1474 <widget name="text" position="65,8" size="420,0" font="Regular;20" />
1475 <widget name="ErrorPixmap" pixmap="skin_default/icons/input_error.png" position="5,5" size="53,53" alphatest="blend" />
1476 <widget name="QuestionPixmap" pixmap="skin_default/icons/input_question.png" position="5,5" size="53,53" alphatest="blend" />
1477 <widget name="InfoPixmap" pixmap="skin_default/icons/input_info.png" position="5,5" size="53,53" alphatest="blend" />
1478 <widget name="list" position="100,100" size="380,375" transparent="1" />
1479 <applet type="onLayoutFinish">
1480 # this should be factored out into some helper code, but currently demonstrates applets.
1481 from enigma import eSize, ePoint
1483 orgwidth = self.instance.size().width()
1484 orgheight = self.instance.size().height()
1485 orgpos = self.instance.position()
1486 textsize = self["text"].getSize()
1488 # y size still must be fixed in font stuff...
1489 textsize = (textsize[0] + 50, textsize[1] + 50)
1491 if self.type == self.TYPE_YESNO:
1493 wsizex = textsize[0] + 60
1494 wsizey = textsize[1] + offset
1495 if (280 > wsizex):
1497 wsize = (wsizex, wsizey)
1500 self.instance.resize(eSize(*wsize))
1503 self["text"].instance.resize(eSize(*textsize))
1506 listsize = (wsizex, 50)
1507 self["list"].instance.move(ePoint(0, textsize[1]))
1508 self["list"].instance.resize(eSize(*listsize))
1512 newheight = wsize[1]
1513 self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y() + (orgheight - newheight)/2))
1518 dmconfigfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/DeviceManager/devicemanager.cfg")
1519 class DeviceManagerConfig():
1521 self.configList = []
1523 def getConfigList(self):
1524 return self.configList
1526 def updateConfigList(self):
1528 self.configList = []
1529 file = open("/proc/mounts")
1530 mounts = file.readlines()
1533 if x.startswith("/dev/sd"):
1534 device = x.split()[0].split('/dev/')[1]
1535 mountpoint = x.split()[1]
1536 if mountpoint.startswith('/autofs'):
1538 (uuid, partitionType) = deviceinfo.getPartitionBlkidInfo(device)
1539 if uuid != '' and mountpoint != '':
1540 self.configList.append([uuid, mountpoint])
1543 print "updateConfigList failed!"
1545 def loadConfig(self):
1546 if not fileExists(dmconfigfile):
1547 os.system("touch %s" % dmconfigfile)
1548 self.configList = []
1549 data = file(dmconfigfile).read().split('\n')
1551 if line.find(':') != -1:
1552 (uuid, mountpoint) = line.split(':')
1553 if uuid != '' and mountpoint != '':
1554 self.configList.append([uuid, mountpoint])
1556 def saveConfig(self):
1557 confFile = open(dmconfigfile,'w')
1559 for line in self.configList:
1560 data += "%s:%s\n"%(line[0],line[1]) # uuid, mountpoint
1561 confFile.write(data)
1564 def appendConfig(self, uuid, mountpoint):
1565 for x in self.configList:
1566 if x[0] == uuid or x[1] == mountpoint:
1567 self.configList.remove(x)
1568 self.configList.append([uuid, mountpoint])
1570 def removeConfig(self, value):
1571 for x in self.configList:
1572 if x[0] == value or x[1] == value:
1573 self.configList.remove(x)
1575 devicemanagerconfig = DeviceManagerConfig()
1577 class deviceManagerHotplug:
1579 self.hotplugActive = True
1581 def setHotplugActive(self,value=True):
1583 self.hotplugActive = True
1585 self.hotplugActive = False
1587 def printDebug(self):
1588 for p in harddiskmanager.partitions:
1589 print " # partition : %s %s %s %s %s(mp, des, f_mounted, is_hot, dev)"%(p.mountpoint, p.description, p.force_mounted, p.is_hotplug,p.device)
1591 def doMount(self, uuid, devpath, mountpoint, filesystem):
1592 # check current device mounted on another mountpoint.
1594 mp_list = deviceinfo.checkMountDev(devpath)
1596 if mp != mountpoint and path.ismount(mp):
1597 deviceinfo.umountByMountpoint(mp)
1598 # check another device mounted on configmountpoint
1600 devpath_list = deviceinfo.checkMountPoint(mountpoint)
1601 for devpath_ in devpath_list:
1602 if devpath_ != devpath:
1603 print "[DeviceManager] Mount Failed. (Another device is already mounted)"
1606 # print "[DeviceManager] doMount"
1607 if not path.exists(mountpoint):
1608 os.system("mkdir %s"%mountpoint)
1609 if path.exists(mountpoint):
1610 if not path.ismount(mountpoint):
1611 if filesystem == "ntfs":
1612 cmd = "ntfs-3g %s %s"%(devpath, mountpoint)
1613 elif filesystem is None:
1614 cmd = "mount %s %s"%(devpath, mountpoint)
1616 cmd = "mount -t %s %s %s"%(filesystem, devpath, mountpoint)
1617 print "[DeviceManager] cmd : %s"%cmd
1619 if not deviceinfo.isMounted(devpath, mountpoint):
1620 print "[DeviceManager] %s doMount failed!"%devpath
1623 # Update partition Info, add
1624 self.addPartitionAutofsMountpoint(devpath, mountpoint)
1626 def doUmount(self, device, mountpoint):
1627 devpath = "/dev/"+device
1628 mountpoints = deviceinfo.checkMountDev(devpath)
1629 if len(mountpoints) == 0:
1631 for mp in mountpoints:
1632 cmd = "umount %s"%devpath
1633 print "[DeviceManager] cmd : %s"%cmd
1636 def addHotPlugDevice(self, partition):
1637 device = partition.device
1638 devpath = "/dev/"+device
1640 (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1643 os.system("sleep 1")
1644 (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1646 print "[DeviceManagerHotplug] getBlkidInfo failed!"
1649 devicemanagerconfig.loadConfig()
1650 configList = devicemanagerconfig.getConfigList()
1652 for line in configList:
1653 if uuid == line[0].strip():
1654 mountpoint = line[1].strip()
1656 if mountpoint is None:
1659 if deviceinfo.isMounted(devpath, mountpoint):
1661 # print "[DeviceManagerHotplug] already mounted"
1663 self.doMount(uuid, devpath, mountpoint, filesystem)
1665 def removeHotplugDevice(self, partition):
1666 self.doUmount(partition.device, partition.mountpoint)
1668 def getHotplugAction(self, action, partition):
1669 if not self.hotplugActive or not config.plugins.devicemanager.hotplug_enable.value:
1671 if partition.device is None or not partition.device.startswith("sd"):
1673 print "[DeviceManagerHotplug] action : %s, device : %s"%(action, partition.device)
1676 self.addHotPlugDevice(partition)
1677 elif action == 'remove':
1678 self.removeHotplugDevice(partition)
1680 def addPartitionAutofsMountpoint(self, devpath, mountpoint):
1681 device = path.basename(devpath)
1682 autofsMountpoint = harddiskmanager.getAutofsMountpoint(device)
1683 # check already appended to partition list
1684 for x in harddiskmanager.partitions:
1685 if x.mountpoint == autofsMountpoint or x.mountpoint == mountpoint:
1688 from Components.Harddisk import Partition
1689 physdev = path.realpath('/sys/block/' + device[:3] + '/device')[4:]
1690 description = harddiskmanager.getUserfriendlyDeviceName(device, physdev)
1691 p = Partition(mountpoint = autofsMountpoint, description = description, force_mounted = True, device = device)
1692 harddiskmanager.partitions.append(p)
1693 harddiskmanager.on_partition_list_change("add", p)
1695 def autoMountOnStartup(self):
1696 devicemanagerconfig.loadConfig()
1697 configList = devicemanagerconfig.getConfigList()
1700 data = os.popen("blkid -c /dev/NULL /dev/sd*").readlines()
1702 devpath = uuid = filesystem = ""
1703 devpath = line.split(':')[0]
1704 if line.find(" UUID=") != -1:
1705 uuid = line.split(" UUID=")[1].split(' ')[0]
1706 if line.find(" TYPE=") != -1:
1707 filesystem = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1708 blkiddata.append((devpath, uuid, filesystem))
1710 for c in configList:
1711 uuid_cfg = c[0].strip()
1712 mountpoint_cfg = c[1].strip()
1713 for (devpath, uuid, filesystem) in blkiddata:
1714 if uuid_cfg == uuid:
1716 if deviceinfo.isMounted(devpath, mountpoint_cfg):
1717 # print "[Devicemanager startup] already mounted"
1718 self.addPartitionAutofsMountpoint(devpath, mountpoint_cfg)
1720 # print "[autoMountOnStartup] do mount(%s %s %s)"%(devpath, configmountpoint, filesystem)
1721 self.doMount(uuid, devpath, mountpoint_cfg, filesystem)
1723 def umountOnShutdown(self):
1724 devicemanagerconfig.loadConfig()
1725 configList = devicemanagerconfig.getConfigList()
1728 data = file('/proc/mounts').read().split('\n')
1730 if not x.startswith('/dev/sd'):
1732 devpath, mountpoint = x.split()[:2]
1733 mounts.append((path.basename(devpath), mountpoint))
1735 data = self.getBlkidInfo()
1737 for c in configList:
1738 uuid_cfg = c[0].strip()
1739 mountpoint_cfg = c[1].strip()
1741 if uuid_cfg in data.keys():
1742 device_cfg = data[uuid_cfg]
1743 if device_cfg is None:
1745 for (device, mountpoint) in mounts:
1746 if device_cfg == device:
1747 if not deviceinfo.isFstabAutoMounted(uuid_cfg, "/dev/"+device_cfg, mountpoint_cfg):
1748 self.doUmount(device, mountpoint)
1750 def getBlkidInfo(self):
1752 blkid_data = os.popen("blkid -c /dev/NULL /dev/sd*").read()
1753 for line in blkid_data.split('\n'):
1754 # print "[DeviceManager] getBlkidInfo line : ",line
1756 device = path.basename(line.split(':')[0])
1757 if line.find(" UUID=") != -1:
1758 blkid_uuid = line.split(" UUID=")[1].split(' ')[0]
1759 data[blkid_uuid] = device
1762 devicemanagerhotplug = deviceManagerHotplug()
1764 def DeviceManagerhotplugDeviceStart(action, device):
1765 devicemanagerhotplug.getHotplugAction(action, device)
1767 def callBackforDeviceManager(session, callback_result = False):
1768 if callback_result == True:
1769 session.open(DeviceManager)
1771 def checkMounts(session):
1773 noMountable_dev = ""
1774 for blockdev in listdir("/sys/block"):
1775 devpath = "/sys/block/" + blockdev
1776 dev = int(readFile(devpath + "/dev").split(':')[0])
1777 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1780 noMountable_partitions = []
1781 for partition in listdir(devpath):
1782 if not partition.startswith(blockdev):
1785 if deviceinfo.checkSwapExtended(partition):
1788 partitions.append(partition)
1790 if deviceinfo.isMounted_anymp('/dev/' + partition):
1793 if os.access('/autofs/'+partition, 0) is False:
1794 noMountable_partitions.append(partition)
1796 if len(partitions) == 0 or len(noMountable_partitions) != 0:
1797 if noMountable_dev != "":
1798 noMountable_dev += ' '
1799 noMountable_dev += blockdev
1801 if noMountable_dev != "":
1802 print "Umountable partitions found."
1803 InfoText = _("No mountable devices found.! (%s)\nDo you want to open DeviceManager and do initialize or format this device?\n\n(Open 'Menu->Setup->System -> Harddisk -> DeviceManager'\n and press MENU button to deactivate this check.)")%noMountable_dev
1804 AddNotificationWithCallback(
1805 boundFunction(callBackforDeviceManager, session),
1806 MessageBox, InfoText, timeout = 60, default = False
1809 print "checkMounts failed!"
1811 def sessionstart(reason, **kwargs):
1813 if kwargs.has_key("session") and config.plugins.devicemanager.mountcheck_enable.value == True:
1814 session = kwargs["session"]
1815 checkMounts(session)
1816 if config.plugins.devicemanager.hotplug_enable.value:
1817 harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
1819 if config.plugins.devicemanager.hotplug_enable.value:
1820 harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
1822 def autostart(reason, **kwargs):
1825 # check at first enigma2 start
1826 if not fileExists(dmconfigfile):
1827 print "[DeviceManager] autostart : check devices at first start"
1828 sda_isremovable = False
1830 os.system("touch %s"%dmconfigfile)
1832 sda_data = popen("cat /proc/partitions | grep sda1").read()
1834 sda_UUID = popen("blkid -o value -s UUID /dev/sda1").read().strip('\n')
1835 sda_isremovable = bool(int(readFile("/sys/block/sda/removable")))
1836 print "sda : %s, %s"%(sda_UUID, sda_isremovable)
1839 cfg += '"%s":/media/hdd\n'%sda_UUID
1840 confFile = open(dmconfigfile,'w')
1843 if not path.exists("/media/hdd"):
1844 os.system("mkdir -p /media/hdd")
1846 devicemanagerhotplug.autoMountOnStartup()
1848 print "[DeviceManager] autostart failed!"
1850 devicemanagerhotplug.umountOnShutdown()
1852 def menu(menuid, **kwargs):
1853 if menuid == "system":
1854 return [(_("DeviceManager"), main, "device_manager", 50)]
1857 def main(session, **kwargs):
1858 session.open(DeviceManager)
1860 def Plugins(path, **kwargs):
1862 PluginDescriptor(name = _("DeviceManager"), description = _("manage block devices of your VU+"), where = PluginDescriptor.WHERE_MENU,fnc=menu),
1863 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = True, fnc = sessionstart),
1864 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, needsRestart = True, fnc = autostart)
1867 class MessageBox_2(MessageBox):
1868 def __init__(self, session, text, type = MessageBox.TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None):
1869 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default, enable_input, msgBoxID)
1870 self.skinName = "MessageBox"
1871 self.closeTimer = eTimer()
1872 self.closeTimer.callback.append(self.msg_close)
1873 self.devicemanager_ret = False
1874 self.devicemanager_msg = ""
1876 def msg_close(self):
1877 self.close(self.devicemanager_ret, self.devicemanager_msg)
1879 def run_close(self, ret, msg=""):
1880 self.devicemanager_ret = ret
1881 self.devicemanager_msg = msg
1882 self.closeTimer.start(100,True)
1884 def createSummary(self):
1885 return MessageBox_2_Summary
1887 class MessageBox_2_Summary(Screen):
1889 <screen name="MessageBox_2_Summary" position="0,0" size="256,64" id="1">
1890 <widget source="parent.Text" render="Label" position="0,0" size="256,64" font="Regular;13" halign="center" valign="center" />