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()])
451 cmd = "ipkg list_installed"
452 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
454 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
456 self.installed_packetlist = {}
457 for x in result.splitlines():
458 split = x.split(' - ')
459 self.installed_packetlist[split[0].strip()] = split[1].strip()
460 self.buildPacketList()
462 def PacketEntryComponent(self,entry):
464 res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
465 res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
466 res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
467 res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
472 def buildPacketList(self):
475 installedpng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
476 upgradeablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
477 installablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
478 divpng = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
480 if self.cache_ttl > 0 and self.vc != 0:
481 print 'Loading packagelist cache from ',self.cache_file
483 self.cachelist = load_cache(self.cache_file)
484 if len(self.cachelist) > 0:
485 for x in self.cachelist:
486 if x[3] == 'installed':
487 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installedpng,divpng]))
488 elif x[3] == 'upgradeable':
489 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],upgradeablepng,divpng]))
491 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installablepng,divpng]))
492 self['list'].l.setList(self.list)
493 self["list"].instance.show()
498 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
499 print 'rebuilding fresh package list'
500 for x in self.packetlist:
502 if self.installed_packetlist.has_key(x[0].strip()):
503 if self.installed_packetlist[x[0].strip()] == x[1].strip():
505 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installedpng,divpng]))
507 status = "upgradeable"
508 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,upgradeablepng,divpng]))
510 status = "installable"
511 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installablepng,divpng]))
512 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
513 write_cache(self.cache_file, self.cachelist)
514 self['list'].l.setList(self.list)
515 self["list"].instance.show()
519 class UpdatePlugin(Screen):
521 <screen position="100,100" size="550,200" title="Software Update..." >
522 <widget name="activityslider" position="0,0" size="550,5" />
523 <widget name="slider" position="0,100" size="550,30" />
524 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
525 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
528 def __init__(self, session, args = None):
529 self.skin = UpdatePlugin.skin
530 Screen.__init__(self, session)
532 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
534 self.slider = Slider(0, 4)
535 self["slider"] = self.slider
536 self.activityslider = Slider(0, 100)
537 self["activityslider"] = self.activityslider
538 self.status = Label(_("Upgrading Dreambox... Please wait"))
539 self["status"] = self.status
540 self.package = Label()
541 self["package"] = self.package
547 self.activityTimer = eTimer()
548 self.activityTimer.callback.append(self.doActivityTimer)
549 self.activityTimer.start(100, False)
551 self.ipkg = IpkgComponent()
552 self.ipkg.addCallback(self.ipkgCallback)
555 self.package.setText(_("Package list update"))
556 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
558 self["actions"] = ActionMap(["WizardActions"],
564 def doActivityTimer(self):
566 if self.activity == 100:
568 self.activityslider.setValue(self.activity)
570 def ipkgCallback(self, event, param):
571 if event == IpkgComponent.EVENT_DOWNLOAD:
572 self.status.setText(_("Downloading"))
573 elif event == IpkgComponent.EVENT_UPGRADE:
574 if self.sliderPackages.has_key(param):
575 self.slider.setValue(self.sliderPackages[param])
576 self.package.setText(param)
577 self.status.setText(_("Upgrading"))
579 elif event == IpkgComponent.EVENT_INSTALL:
580 self.package.setText(param)
581 self.status.setText(_("Installing"))
583 elif event == IpkgComponent.EVENT_CONFIGURING:
584 self.package.setText(param)
585 self.status.setText(_("Configuring"))
586 elif event == IpkgComponent.EVENT_MODIFIED:
587 self.session.openWithCallback(
588 self.modificationCallback,
590 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
592 elif event == IpkgComponent.EVENT_ERROR:
594 elif event == IpkgComponent.EVENT_DONE:
596 self.updating = False
597 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
598 elif self.error == 0:
599 self.slider.setValue(4)
601 self.activityTimer.stop()
602 self.activityslider.setValue(0)
604 self.package.setText("")
605 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
607 self.activityTimer.stop()
608 self.activityslider.setValue(0)
609 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
610 if self.packages == 0:
611 error = _("No packages were upgraded yet. So you can check your network and try again.")
613 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
614 self.status.setText(_("Error") + " - " + error)
615 #print event, "-", param
618 def modificationCallback(self, res):
619 self.ipkg.write(res and "N" or "Y")
622 if not self.ipkg.isRunning():
623 if self.packages != 0 and self.error == 0:
624 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
628 def exitAnswer(self, result):
629 if result is not None and result:
635 class IpkgInstaller(Screen):
637 <screen position="100,100" size="550,400" title="..." >
638 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
639 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
640 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
641 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
642 <widget name="list" position="0,60" size="550,360" />
646 def __init__(self, session, list):
647 self.skin = IpkgInstaller.skin
648 Screen.__init__(self, session)
650 self.list = SelectionList()
651 self["list"] = self.list
652 for listindex in range(len(list)):
653 self.list.addSelection(list[listindex], list[listindex], listindex, True)
655 self["red"] = Label()
656 self["green"] = Label()
657 self["yellow"] = Label()
658 self["blue"] = Label()
660 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
662 "ok": self.list.toggleSelection,
663 "cancel": self.close,
664 "green": self.install
668 list = self.list.getSelectionsList()
671 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
672 self.session.open(Ipkg, cmdList = cmdList)
674 def filescan_open(list, session, **kwargs):
675 filelist = [x.path for x in list]
676 session.open(IpkgInstaller, filelist) # list
678 def filescan(**kwargs):
679 from Components.Scanner import Scanner, ScanPath
681 Scanner(mimetypes = ["application/x-debian-package"],
684 ScanPath(path = "ipk", with_subdirs = True),
685 ScanPath(path = "", with_subdirs = False),
688 description = "Install software updates...",
689 openfnc = filescan_open, )
691 def UpgradeMain(session, **kwargs):
692 session.open(UpdatePluginMenu)
694 def startSetup(menuid):
695 if menuid != "setup":
697 return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
699 def Plugins(path, **kwargs):
703 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
704 #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
705 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)