1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Console import Console
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.MessageBox import MessageBox
5 from Screens.Screen import Screen
6 from Screens.Ipkg import Ipkg
7 from Components.ActionMap import ActionMap, NumberActionMap
8 from Components.Input import Input
9 from Components.Ipkg import IpkgComponent
10 from Components.Label import Label
11 from Components.MenuList import MenuList
12 from Components.Sources.List import List
13 from Components.Slider import Slider
14 from Components.Harddisk import harddiskmanager
15 from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
16 from Components.Console import Console
17 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
18 from Components.SelectionList import SelectionList
19 from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
20 from Tools.LoadPixmap import LoadPixmap
21 from enigma import eTimer, loadPNG, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont
22 from cPickle import dump, load
24 from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
25 from time import time, gmtime, strftime, localtime
26 from stat import ST_MTIME
27 from datetime import date
29 from ImageWizard import ImageWizard
30 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
32 config.plugins.configurationbackup = ConfigSubsection()
33 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
34 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf'])
37 def write_cache(cache_file, cache_data):
39 if not os_path.isdir( os_path.dirname(cache_file) ):
41 mkdir( os_path.dirname(cache_file) )
43 print os_path.dirname(cache_file), 'is a file'
44 fd = open(cache_file, 'w')
45 dump(cache_data, fd, -1)
48 def valid_cache(cache_file, cache_ttl):
49 #See if the cache file exists and is still living
51 mtime = stat(cache_file)[ST_MTIME]
55 if (curr_time - mtime) > cache_ttl:
60 def load_cache(cache_file):
68 class UpdatePluginMenu(Screen):
70 <screen name="UpdatePluginMenu" position="90,130" size="550,330" title="Softwaremanager..." >
71 <ePixmap pixmap="skin_default/border_menu.png" position="10,10" zPosition="1" size="250,300" transparent="1" alphatest="on" />
72 <widget source="menu" render="Listbox" position="20,20" size="230,260" scrollbarMode="showOnDemand">
73 <convert type="TemplatedMultiContent">
75 MultiContentEntryText(pos = (2, 2), size = (230, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
77 "fonts": [gFont("Regular", 20)],
82 <widget source="menu" render="Listbox" position="280,10" size="230,300" scrollbarMode="showNever" selectionDisabled="1">
83 <convert type="TemplatedMultiContent">
85 MultiContentEntryText(pos = (2, 2), size = (230, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 0 is the MenuText,
87 "fonts": [gFont("Regular", 20)],
94 def __init__(self, session, args = 0):
95 Screen.__init__(self, session)
96 self.skin_path = plugin_path
99 self.oktext = _("\nPress OK on your remote control to continue.")
100 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
102 self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext) )
103 self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext))
104 self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext))
105 self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext))
106 if config.usage.setup_level.index >= 2: # expert+
107 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext))
109 self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext))
110 self.list.append(("ipkg-install", _("Install local IPKG"), _("\nScan for local packages and install them." ) + self.oktext))
111 self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext))
112 self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext ))
113 self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext))
114 self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext))
116 self["menu"] = List(self.list)
118 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
125 self.onLayoutFinish.append(self.layoutFinished)
126 self.backuppath = getBackupPath()
127 self.backupfile = getBackupFilename()
128 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
129 self.onShown.append(self.setWindowTitle)
131 def layoutFinished(self):
133 self["menu"].index = idx
135 def setWindowTitle(self):
136 self.setTitle(_("Software manager..."))
139 current = self["menu"].getCurrent()[0]
141 if (current == "software-restore"):
142 self.session.open(ImageWizard)
143 elif (current == "software-update"):
144 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
145 elif (current == "advanced"):
146 self.session.open(UpdatePluginMenu, 1)
147 elif (current == "system-backup"):
148 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
149 elif (current == "system-restore"):
150 if os_path.exists(self.fullbackupfilename):
151 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
153 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO)
155 if (current == "ipkg-manager"):
156 self.session.open(PacketManager, self.skin_path)
157 elif (current == "ipkg-source"):
158 self.session.open(IPKGSource)
159 elif (current == "ipkg-install"):
161 from Plugins.Extensions.MediaScanner.plugin import main
164 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO)
165 elif (current == "backuplocation"):
166 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
168 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
171 if x[1].startswith('/autofs/'):
174 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
175 elif (current == "backupfiles"):
176 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
177 elif (current == "advancedrestore"):
178 self.session.open(RestoreMenu, self.skin_path)
180 def backupfiles_choosen(self, ret):
181 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
183 def backuplocation_choosen(self, option):
184 if option is not None:
185 config.plugins.configurationbackup.backuplocation.value = str(option[1])
186 config.plugins.configurationbackup.backuplocation.save()
187 config.plugins.configurationbackup.save()
189 self.createBackupfolders()
191 def runUpgrade(self, result):
193 self.session.open(UpdatePlugin, self.skin_path)
195 """def runFinished(self):
196 self.session.openWithCallback(self.reboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
198 def reboot(self, result):
204 def createBackupfolders(self):
205 print "Creating backup folder if not already there..."
206 self.backuppath = getBackupPath()
208 if (os_path.exists(self.backuppath) == False):
209 makedirs(self.backuppath)
211 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO)
213 def backupDone(self,retval = None):
215 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO)
217 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO)
219 def startRestore(self, ret = False):
222 self.session.open(RestoreScreen, runRestore = True)
225 class IPKGSource(Screen):
227 <screen position="100,100" size="550,60" title="IPKG source" >
228 <widget name="text" position="0,0" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
231 def __init__(self, session, args = None):
232 Screen.__init__(self, session)
233 self.session = session
235 fp = file('/etc/ipkg/official-feed.conf', 'r')
236 sources = fp.readlines()
239 self["text"] = Input(sources[0], maxSize=False, type=Input.TEXT)
241 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions"],
245 "left": self.keyLeft,
246 "right": self.keyRight,
247 "home": self.keyHome,
249 "deleteForward": self.keyDeleteForward,
250 "deleteBackward": self.keyDeleteBackward,
251 "1": self.keyNumberGlobal,
252 "2": self.keyNumberGlobal,
253 "3": self.keyNumberGlobal,
254 "4": self.keyNumberGlobal,
255 "5": self.keyNumberGlobal,
256 "6": self.keyNumberGlobal,
257 "7": self.keyNumberGlobal,
258 "8": self.keyNumberGlobal,
259 "9": self.keyNumberGlobal,
260 "0": self.keyNumberGlobal
264 fp = file('/etc/ipkg/official-feed.conf', 'w')
265 fp.write(self["text"].getText())
281 def keyDeleteForward(self):
282 self["text"].delete()
284 def keyDeleteBackward(self):
285 self["text"].deleteBackward()
287 def keyNumberGlobal(self, number):
288 print "pressed", number
289 self["text"].number(number)
292 class PacketList(MenuList):
293 def __init__(self, list, enableWrapAround=True):
294 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
295 self.l.setFont(0, gFont("Regular", 22))
296 self.l.setFont(1, gFont("Regular", 14))
297 self.l.setItemHeight(52)
299 class PacketManager(Screen):
301 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
302 <widget name="list" position="5,10" size="520,365" zPosition="1" scrollbarMode="showOnDemand" />
303 <widget name="status" position="30,160" size="530,40" zPosition="4" font="Regular;22" halign="left" transparent="1" />
304 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
305 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
306 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
307 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
310 def __init__(self, session, plugin_path, args = None):
311 Screen.__init__(self, session)
312 self.session = session
313 self.skin_path = plugin_path
315 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
320 "green": self.reload,
324 self["list"] = PacketList(self.list)
325 self.status = Label()
326 self["closetext"] = Label(_("Close"))
327 self["reloadtext"] = Label(_("Reload"))
328 self["status"] = self.status
330 self.list_updating = True
332 self.installed_packetlist = {}
333 self.Console = Console()
336 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
337 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
338 self.oktext = _("\nAfter pressing OK, please wait!")
340 self.ipkg = IpkgComponent()
341 self.ipkg.addCallback(self.ipkgCallback)
342 self.onShown.append(self.setWindowTitle)
343 self.onLayoutFinish.append(self.rebuildList)
344 self.onClose.append(self.cleanup)
348 if self.Console is not None:
352 if (os_path.exists(self.cache_file) == True):
353 remove(self.cache_file)
354 self.list_updating = True
357 def setWindowTitle(self):
358 self.setTitle(_("Packet manager"))
360 def rebuildList(self):
361 self["list"].instance.hide()
362 self.status.setText(_("Package list update"))
365 self.vc = valid_cache(self.cache_file, self.cache_ttl)
366 if self.cache_ttl > 0 and self.vc != 0:
368 self.buildPacketList()
371 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
373 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
375 def go(self, returnValue = None):
376 returnValue = self['list'].l.getCurrentSelection()[0]
378 if returnValue[3] == 'installed':
379 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": returnValue[0] }))
380 if len(self.cmdList):
381 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n" + returnValue[0] + "\n" + self.oktext))
382 elif returnValue[3] == 'upgradeable':
383 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
384 if len(self.cmdList):
385 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n" + returnValue[0] + "\n" + self.oktext))
387 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
388 if len(self.cmdList):
389 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n" + returnValue[0] + "\n" + self.oktext))
391 def runRemove(self, result):
393 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
395 def runRemoveFinished(self):
396 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
398 def RemoveReboot(self, result):
402 entry = self['list'].l.getCurrentSelection()[0]
403 item = self['list'].l.getCurrentSelectionIndex()
404 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installable'])
405 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installable']
406 self['list'].l.setList(self.list)
407 write_cache(self.cache_file, self.cachelist)
411 def runUpgrade(self, result):
413 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
415 def runUpgradeFinished(self):
416 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
418 def UpgradeReboot(self, result):
422 entry = self['list'].l.getCurrentSelection()[0]
423 item = self['list'].l.getCurrentSelectionIndex()
424 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installed'])
425 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installed']
426 self['list'].l.setList(self.list)
427 write_cache(self.cache_file, self.cachelist)
431 def ipkgCallback(self, event, param):
432 if event == IpkgComponent.EVENT_ERROR:
433 self.list_updating = False
434 self.status.setText(_("An error occured!"))
435 elif event == IpkgComponent.EVENT_DONE:
436 if self.list_updating:
437 self.list_updating = False
439 self.Console = Console()
441 self.Console.ePopen(cmd, self.IpkgList_Finished)
442 #print event, "-", param
445 def IpkgList_Finished(self, result, retval, extra_args = None):
448 for x in result.splitlines():
449 split = x.split(' - ')
450 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
452 self.Console = Console()
453 cmd = "ipkg list_installed"
454 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
456 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
458 self.installed_packetlist = {}
459 for x in result.splitlines():
460 split = x.split(' - ')
461 self.installed_packetlist[split[0].strip()] = split[1].strip()
462 self.buildPacketList()
464 def PacketEntryComponent(self,entry):
466 res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
467 res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
468 res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
469 res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
474 def buildPacketList(self):
477 installedpng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
478 upgradeablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
479 installablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
480 divpng = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
482 if self.cache_ttl > 0 and self.vc != 0:
483 print 'Loading packagelist cache from ',self.cache_file
485 self.cachelist = load_cache(self.cache_file)
486 if len(self.cachelist) > 0:
487 for x in self.cachelist:
488 if x[3] == 'installed':
489 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installedpng,divpng]))
490 elif x[3] == 'upgradeable':
491 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],upgradeablepng,divpng]))
493 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installablepng,divpng]))
494 self['list'].l.setList(self.list)
495 self["list"].instance.show()
500 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
501 print 'rebuilding fresh package list'
502 for x in self.packetlist:
504 if self.installed_packetlist.has_key(x[0].strip()):
505 if self.installed_packetlist[x[0].strip()] == x[1].strip():
507 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installedpng,divpng]))
509 status = "upgradeable"
510 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,upgradeablepng,divpng]))
512 status = "installable"
513 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installablepng,divpng]))
514 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
515 write_cache(self.cache_file, self.cachelist)
516 self['list'].l.setList(self.list)
517 self["list"].instance.show()
521 class UpdatePlugin(Screen):
523 <screen position="100,100" size="550,200" title="Software Update..." >
524 <widget name="activityslider" position="0,0" size="550,5" />
525 <widget name="slider" position="0,100" size="550,30" />
526 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
527 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
530 def __init__(self, session, args = None):
531 self.skin = UpdatePlugin.skin
532 Screen.__init__(self, session)
534 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
536 self.slider = Slider(0, 4)
537 self["slider"] = self.slider
538 self.activityslider = Slider(0, 100)
539 self["activityslider"] = self.activityslider
540 self.status = Label(_("Upgrading Dreambox... Please wait"))
541 self["status"] = self.status
542 self.package = Label()
543 self["package"] = self.package
549 self.activityTimer = eTimer()
550 self.activityTimer.callback.append(self.doActivityTimer)
551 self.activityTimer.start(100, False)
553 self.ipkg = IpkgComponent()
554 self.ipkg.addCallback(self.ipkgCallback)
557 self.package.setText(_("Package list update"))
558 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
560 self["actions"] = ActionMap(["WizardActions"],
566 def doActivityTimer(self):
568 if self.activity == 100:
570 self.activityslider.setValue(self.activity)
572 def ipkgCallback(self, event, param):
573 if event == IpkgComponent.EVENT_DOWNLOAD:
574 self.status.setText(_("Downloading"))
575 elif event == IpkgComponent.EVENT_UPGRADE:
576 if self.sliderPackages.has_key(param):
577 self.slider.setValue(self.sliderPackages[param])
578 self.package.setText(param)
579 self.status.setText(_("Upgrading"))
581 elif event == IpkgComponent.EVENT_INSTALL:
582 self.package.setText(param)
583 self.status.setText(_("Installing"))
585 elif event == IpkgComponent.EVENT_CONFIGURING:
586 self.package.setText(param)
587 self.status.setText(_("Configuring"))
588 elif event == IpkgComponent.EVENT_MODIFIED:
589 self.session.openWithCallback(
590 self.modificationCallback,
592 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
594 elif event == IpkgComponent.EVENT_ERROR:
596 elif event == IpkgComponent.EVENT_DONE:
598 self.updating = False
599 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
600 elif self.error == 0:
601 self.slider.setValue(4)
603 self.activityTimer.stop()
604 self.activityslider.setValue(0)
606 self.package.setText("")
607 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
609 self.activityTimer.stop()
610 self.activityslider.setValue(0)
611 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
612 if self.packages == 0:
613 error = _("No packages were upgraded yet. So you can check your network and try again.")
615 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
616 self.status.setText(_("Error") + " - " + error)
617 #print event, "-", param
620 def modificationCallback(self, res):
621 self.ipkg.write(res and "N" or "Y")
624 if not self.ipkg.isRunning():
625 if self.packages != 0 and self.error == 0:
626 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
630 def exitAnswer(self, result):
631 if result is not None and result:
637 class IpkgInstaller(Screen):
639 <screen position="100,100" size="550,400" title="..." >
640 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
641 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
642 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
643 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
644 <widget name="list" position="0,60" size="550,360" />
648 def __init__(self, session, list):
649 self.skin = IpkgInstaller.skin
650 Screen.__init__(self, session)
652 self.list = SelectionList()
653 self["list"] = self.list
654 for listindex in range(len(list)):
655 self.list.addSelection(list[listindex], list[listindex], listindex, True)
657 self["red"] = Label()
658 self["green"] = Label()
659 self["yellow"] = Label()
660 self["blue"] = Label()
662 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
664 "ok": self.list.toggleSelection,
665 "cancel": self.close,
666 "green": self.install
670 list = self.list.getSelectionsList()
673 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
674 self.session.open(Ipkg, cmdList = cmdList)
676 def filescan_open(list, session, **kwargs):
677 filelist = [x.path for x in list]
678 session.open(IpkgInstaller, filelist) # list
680 def filescan(**kwargs):
681 from Components.Scanner import Scanner, ScanPath
683 Scanner(mimetypes = ["application/x-debian-package"],
686 ScanPath(path = "ipk", with_subdirs = True),
687 ScanPath(path = "", with_subdirs = False),
690 description = "Install software updates...",
691 openfnc = filescan_open, )
693 def UpgradeMain(session, **kwargs):
694 session.open(UpdatePluginMenu)
696 def startSetup(menuid):
697 if menuid != "setup":
699 return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
701 def Plugins(path, **kwargs):
705 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
706 #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
707 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)