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()
143 if (current == "software-restore"):
144 self.session.open(ImageWizard)
145 elif (current == "software-update"):
146 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
147 elif (current == "advanced"):
148 self.session.open(UpdatePluginMenu, 1)
149 elif (current == "system-backup"):
150 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
151 elif (current == "system-restore"):
152 if os_path.exists(self.fullbackupfilename):
153 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
155 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO)
157 if (current == "ipkg-manager"):
158 self.session.open(PacketManager, self.skin_path)
159 elif (current == "ipkg-source"):
160 self.session.open(IPKGSource)
161 elif (current == "ipkg-install"):
163 from Plugins.Extensions.MediaScanner.plugin import main
166 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO)
167 elif (current == "backuplocation"):
168 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
170 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
173 if x[1].startswith('/autofs/'):
176 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
177 elif (current == "backupfiles"):
178 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
179 elif (current == "advancedrestore"):
180 self.session.open(RestoreMenu, self.skin_path)
182 def backupfiles_choosen(self, ret):
183 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
185 def backuplocation_choosen(self, option):
186 if option is not None:
187 config.plugins.configurationbackup.backuplocation.value = str(option[1])
188 config.plugins.configurationbackup.backuplocation.save()
189 config.plugins.configurationbackup.save()
191 self.createBackupfolders()
193 def runUpgrade(self, result):
195 self.session.open(UpdatePlugin, self.skin_path)
197 """def runFinished(self):
198 self.session.openWithCallback(self.reboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
200 def reboot(self, result):
206 def createBackupfolders(self):
207 print "Creating backup folder if not already there..."
208 self.backuppath = getBackupPath()
210 if (os_path.exists(self.backuppath) == False):
211 makedirs(self.backuppath)
213 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO)
215 def backupDone(self,retval = None):
217 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO)
219 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO)
221 def startRestore(self, ret = False):
224 self.session.open(RestoreScreen, runRestore = True)
227 class IPKGSource(Screen):
229 <screen position="100,100" size="550,60" title="IPKG source" >
230 <widget name="text" position="0,0" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
233 def __init__(self, session, args = None):
234 Screen.__init__(self, session)
235 self.session = session
237 #FIXMEEEE add handling for more than one feed conf file!
240 fp = file('/etc/ipkg/official-feed.conf', 'r')
241 sources = fp.readlines()
248 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
250 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions"],
254 "left": self.keyLeft,
255 "right": self.keyRight,
256 "home": self.keyHome,
258 "deleteForward": self.keyDeleteForward,
259 "deleteBackward": self.keyDeleteBackward,
260 "1": self.keyNumberGlobal,
261 "2": self.keyNumberGlobal,
262 "3": self.keyNumberGlobal,
263 "4": self.keyNumberGlobal,
264 "5": self.keyNumberGlobal,
265 "6": self.keyNumberGlobal,
266 "7": self.keyNumberGlobal,
267 "8": self.keyNumberGlobal,
268 "9": self.keyNumberGlobal,
269 "0": self.keyNumberGlobal
273 text = self["text"].getText()
275 fp = file('/etc/ipkg/official-feed.conf', 'w')
292 def keyDeleteForward(self):
293 self["text"].delete()
295 def keyDeleteBackward(self):
296 self["text"].deleteBackward()
298 def keyNumberGlobal(self, number):
299 print "pressed", number
300 self["text"].number(number)
302 class PacketList(MenuList):
303 def __init__(self, list, enableWrapAround=True):
304 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
305 self.l.setFont(0, gFont("Regular", 22))
306 self.l.setFont(1, gFont("Regular", 14))
307 self.l.setItemHeight(52)
309 class PacketManager(Screen):
311 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
312 <widget name="list" position="5,10" size="520,365" zPosition="1" scrollbarMode="showOnDemand" />
313 <widget name="status" position="30,160" size="530,40" zPosition="4" font="Regular;22" halign="left" transparent="1" />
314 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
315 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
316 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
317 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
320 def __init__(self, session, plugin_path, args = None):
321 Screen.__init__(self, session)
322 self.session = session
323 self.skin_path = plugin_path
325 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
330 "green": self.reload,
334 self["list"] = PacketList(self.list)
335 self.status = Label()
336 self["closetext"] = Label(_("Close"))
337 self["reloadtext"] = Label(_("Reload"))
338 self["status"] = self.status
340 self.list_updating = True
342 self.installed_packetlist = {}
343 self.Console = Console()
346 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
347 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
348 self.oktext = _("\nAfter pressing OK, please wait!")
350 self.ipkg = IpkgComponent()
351 self.ipkg.addCallback(self.ipkgCallback)
352 self.onShown.append(self.setWindowTitle)
353 self.onLayoutFinish.append(self.rebuildList)
354 self.onClose.append(self.cleanup)
358 if self.Console is not None:
362 if (os_path.exists(self.cache_file) == True):
363 remove(self.cache_file)
364 self.list_updating = True
367 def setWindowTitle(self):
368 self.setTitle(_("Packet manager"))
370 def rebuildList(self):
371 self["list"].instance.hide()
372 self.status.setText(_("Package list update"))
375 self.vc = valid_cache(self.cache_file, self.cache_ttl)
376 if self.cache_ttl > 0 and self.vc != 0:
378 self.buildPacketList()
381 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
383 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
385 def go(self, returnValue = None):
386 cur = self['list'].l.getCurrentSelection()
390 if returnValue[3] == 'installed':
391 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": returnValue[0] }))
392 if len(self.cmdList):
393 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n" + returnValue[0] + "\n" + self.oktext))
394 elif returnValue[3] == 'upgradeable':
395 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
396 if len(self.cmdList):
397 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n" + returnValue[0] + "\n" + self.oktext))
399 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
400 if len(self.cmdList):
401 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n" + returnValue[0] + "\n" + self.oktext))
403 def runRemove(self, result):
405 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
407 def runRemoveFinished(self):
408 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
410 def RemoveReboot(self, result):
414 cur = self['list'].l.getCurrentSelection()
417 item = self['list'].l.getCurrentSelectionIndex()
418 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installable'])
419 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installable']
420 self['list'].l.setList(self.list)
421 write_cache(self.cache_file, self.cachelist)
425 def runUpgrade(self, result):
427 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
429 def runUpgradeFinished(self):
430 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
432 def UpgradeReboot(self, result):
436 cur = self['list'].l.getCurrentSelection()
439 item = self['list'].l.getCurrentSelectionIndex()
440 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installed'])
441 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installed']
442 self['list'].l.setList(self.list)
443 write_cache(self.cache_file, self.cachelist)
447 def ipkgCallback(self, event, param):
448 if event == IpkgComponent.EVENT_ERROR:
449 self.list_updating = False
450 self.status.setText(_("An error occured!"))
451 elif event == IpkgComponent.EVENT_DONE:
452 if self.list_updating:
453 self.list_updating = False
455 self.Console = Console()
457 self.Console.ePopen(cmd, self.IpkgList_Finished)
458 #print event, "-", param
461 def IpkgList_Finished(self, result, retval, extra_args = None):
464 for x in result.splitlines():
465 split = x.split(' - ')
466 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
468 self.Console = Console()
469 cmd = "ipkg list_installed"
470 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
472 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
474 self.installed_packetlist = {}
475 for x in result.splitlines():
476 split = x.split(' - ')
477 self.installed_packetlist[split[0].strip()] = split[1].strip()
478 self.buildPacketList()
480 def PacketEntryComponent(self,entry):
482 res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
483 res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
484 res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
485 res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
490 def buildPacketList(self):
493 installedpng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
494 upgradeablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
495 installablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
496 divpng = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
498 if self.cache_ttl > 0 and self.vc != 0:
499 print 'Loading packagelist cache from ',self.cache_file
501 self.cachelist = load_cache(self.cache_file)
502 if len(self.cachelist) > 0:
503 for x in self.cachelist:
504 if x[3] == 'installed':
505 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installedpng,divpng]))
506 elif x[3] == 'upgradeable':
507 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],upgradeablepng,divpng]))
509 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installablepng,divpng]))
510 self['list'].l.setList(self.list)
511 self["list"].instance.show()
516 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
517 print 'rebuilding fresh package list'
518 for x in self.packetlist:
520 if self.installed_packetlist.has_key(x[0].strip()):
521 if self.installed_packetlist[x[0].strip()] == x[1].strip():
523 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installedpng,divpng]))
525 status = "upgradeable"
526 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,upgradeablepng,divpng]))
528 status = "installable"
529 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installablepng,divpng]))
530 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
531 write_cache(self.cache_file, self.cachelist)
532 self['list'].l.setList(self.list)
533 self["list"].instance.show()
537 class UpdatePlugin(Screen):
539 <screen position="100,100" size="550,200" title="Software Update..." >
540 <widget name="activityslider" position="0,0" size="550,5" />
541 <widget name="slider" position="0,100" size="550,30" />
542 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
543 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
546 def __init__(self, session, args = None):
547 self.skin = UpdatePlugin.skin
548 Screen.__init__(self, session)
550 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
552 self.slider = Slider(0, 4)
553 self["slider"] = self.slider
554 self.activityslider = Slider(0, 100)
555 self["activityslider"] = self.activityslider
556 self.status = Label(_("Upgrading Dreambox... Please wait"))
557 self["status"] = self.status
558 self.package = Label()
559 self["package"] = self.package
565 self.activityTimer = eTimer()
566 self.activityTimer.callback.append(self.doActivityTimer)
567 self.activityTimer.start(100, False)
569 self.ipkg = IpkgComponent()
570 self.ipkg.addCallback(self.ipkgCallback)
573 self.package.setText(_("Package list update"))
574 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
576 self["actions"] = ActionMap(["WizardActions"],
582 def doActivityTimer(self):
584 if self.activity == 100:
586 self.activityslider.setValue(self.activity)
588 def ipkgCallback(self, event, param):
589 if event == IpkgComponent.EVENT_DOWNLOAD:
590 self.status.setText(_("Downloading"))
591 elif event == IpkgComponent.EVENT_UPGRADE:
592 if self.sliderPackages.has_key(param):
593 self.slider.setValue(self.sliderPackages[param])
594 self.package.setText(param)
595 self.status.setText(_("Upgrading"))
597 elif event == IpkgComponent.EVENT_INSTALL:
598 self.package.setText(param)
599 self.status.setText(_("Installing"))
601 elif event == IpkgComponent.EVENT_CONFIGURING:
602 self.package.setText(param)
603 self.status.setText(_("Configuring"))
604 elif event == IpkgComponent.EVENT_MODIFIED:
605 self.session.openWithCallback(
606 self.modificationCallback,
608 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
610 elif event == IpkgComponent.EVENT_ERROR:
612 elif event == IpkgComponent.EVENT_DONE:
614 self.updating = False
615 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
616 elif self.error == 0:
617 self.slider.setValue(4)
619 self.activityTimer.stop()
620 self.activityslider.setValue(0)
622 self.package.setText("")
623 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
625 self.activityTimer.stop()
626 self.activityslider.setValue(0)
627 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
628 if self.packages == 0:
629 error = _("No packages were upgraded yet. So you can check your network and try again.")
631 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
632 self.status.setText(_("Error") + " - " + error)
633 #print event, "-", param
636 def modificationCallback(self, res):
637 self.ipkg.write(res and "N" or "Y")
640 if not self.ipkg.isRunning():
641 if self.packages != 0 and self.error == 0:
642 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
646 def exitAnswer(self, result):
647 if result is not None and result:
653 class IpkgInstaller(Screen):
655 <screen position="100,100" size="550,400" title="..." >
656 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
657 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
658 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
659 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
660 <widget name="list" position="0,60" size="550,360" />
664 def __init__(self, session, list):
665 self.skin = IpkgInstaller.skin
666 Screen.__init__(self, session)
668 self.list = SelectionList()
669 self["list"] = self.list
670 for listindex in range(len(list)):
671 self.list.addSelection(list[listindex], list[listindex], listindex, True)
673 self["red"] = Label()
674 self["green"] = Label()
675 self["yellow"] = Label()
676 self["blue"] = Label()
678 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
680 "ok": self.list.toggleSelection,
681 "cancel": self.close,
682 "green": self.install
686 list = self.list.getSelectionsList()
689 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
690 self.session.open(Ipkg, cmdList = cmdList)
692 def filescan_open(list, session, **kwargs):
693 filelist = [x.path for x in list]
694 session.open(IpkgInstaller, filelist) # list
696 def filescan(**kwargs):
697 from Components.Scanner import Scanner, ScanPath
699 Scanner(mimetypes = ["application/x-debian-package"],
702 ScanPath(path = "ipk", with_subdirs = True),
703 ScanPath(path = "", with_subdirs = False),
706 description = "Install software updates...",
707 openfnc = filescan_open, )
709 def UpgradeMain(session, **kwargs):
710 session.open(UpdatePluginMenu)
712 def startSetup(menuid):
713 if menuid != "setup":
715 return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
717 def Plugins(path, **kwargs):
721 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
722 #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
723 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)