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 #FIXMEEEE add handling for more than one feed conf file!
238 fp = file('/etc/ipkg/official-feed.conf', 'r')
239 sources = fp.readlines()
246 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
248 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions"],
252 "left": self.keyLeft,
253 "right": self.keyRight,
254 "home": self.keyHome,
256 "deleteForward": self.keyDeleteForward,
257 "deleteBackward": self.keyDeleteBackward,
258 "1": self.keyNumberGlobal,
259 "2": self.keyNumberGlobal,
260 "3": self.keyNumberGlobal,
261 "4": self.keyNumberGlobal,
262 "5": self.keyNumberGlobal,
263 "6": self.keyNumberGlobal,
264 "7": self.keyNumberGlobal,
265 "8": self.keyNumberGlobal,
266 "9": self.keyNumberGlobal,
267 "0": self.keyNumberGlobal
271 text = self["text"].getText()
273 fp = file('/etc/ipkg/official-feed.conf', 'w')
290 def keyDeleteForward(self):
291 self["text"].delete()
293 def keyDeleteBackward(self):
294 self["text"].deleteBackward()
296 def keyNumberGlobal(self, number):
297 print "pressed", number
298 self["text"].number(number)
300 class PacketList(MenuList):
301 def __init__(self, list, enableWrapAround=True):
302 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
303 self.l.setFont(0, gFont("Regular", 22))
304 self.l.setFont(1, gFont("Regular", 14))
305 self.l.setItemHeight(52)
307 class PacketManager(Screen):
309 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
310 <widget name="list" position="5,10" size="520,365" zPosition="1" scrollbarMode="showOnDemand" />
311 <widget name="status" position="30,160" size="530,40" zPosition="4" font="Regular;22" halign="left" transparent="1" />
312 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
313 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
314 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
315 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
318 def __init__(self, session, plugin_path, args = None):
319 Screen.__init__(self, session)
320 self.session = session
321 self.skin_path = plugin_path
323 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
328 "green": self.reload,
332 self["list"] = PacketList(self.list)
333 self.status = Label()
334 self["closetext"] = Label(_("Close"))
335 self["reloadtext"] = Label(_("Reload"))
336 self["status"] = self.status
338 self.list_updating = True
340 self.installed_packetlist = {}
341 self.Console = Console()
344 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
345 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
346 self.oktext = _("\nAfter pressing OK, please wait!")
348 self.ipkg = IpkgComponent()
349 self.ipkg.addCallback(self.ipkgCallback)
350 self.onShown.append(self.setWindowTitle)
351 self.onLayoutFinish.append(self.rebuildList)
352 self.onClose.append(self.cleanup)
356 if self.Console is not None:
360 if (os_path.exists(self.cache_file) == True):
361 remove(self.cache_file)
362 self.list_updating = True
365 def setWindowTitle(self):
366 self.setTitle(_("Packet manager"))
368 def rebuildList(self):
369 self["list"].instance.hide()
370 self.status.setText(_("Package list update"))
373 self.vc = valid_cache(self.cache_file, self.cache_ttl)
374 if self.cache_ttl > 0 and self.vc != 0:
376 self.buildPacketList()
379 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
381 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
383 def go(self, returnValue = None):
384 returnValue = self['list'].l.getCurrentSelection()[0]
386 if returnValue[3] == 'installed':
387 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": returnValue[0] }))
388 if len(self.cmdList):
389 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n" + returnValue[0] + "\n" + self.oktext))
390 elif returnValue[3] == 'upgradeable':
391 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
392 if len(self.cmdList):
393 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n" + returnValue[0] + "\n" + self.oktext))
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 install the package:\n" + returnValue[0] + "\n" + self.oktext))
399 def runRemove(self, result):
401 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
403 def runRemoveFinished(self):
404 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
406 def RemoveReboot(self, result):
410 entry = self['list'].l.getCurrentSelection()[0]
411 item = self['list'].l.getCurrentSelectionIndex()
412 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installable'])
413 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installable']
414 self['list'].l.setList(self.list)
415 write_cache(self.cache_file, self.cachelist)
419 def runUpgrade(self, result):
421 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
423 def runUpgradeFinished(self):
424 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
426 def UpgradeReboot(self, result):
430 entry = self['list'].l.getCurrentSelection()[0]
431 item = self['list'].l.getCurrentSelectionIndex()
432 self.list[item] = PacketEntryComponent([entry[0], entry[1], entry[2], 'installed'])
433 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installed']
434 self['list'].l.setList(self.list)
435 write_cache(self.cache_file, self.cachelist)
439 def ipkgCallback(self, event, param):
440 if event == IpkgComponent.EVENT_ERROR:
441 self.list_updating = False
442 self.status.setText(_("An error occured!"))
443 elif event == IpkgComponent.EVENT_DONE:
444 if self.list_updating:
445 self.list_updating = False
447 self.Console = Console()
449 self.Console.ePopen(cmd, self.IpkgList_Finished)
450 #print event, "-", param
453 def IpkgList_Finished(self, result, retval, extra_args = None):
456 for x in result.splitlines():
457 split = x.split(' - ')
458 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
460 self.Console = Console()
461 cmd = "ipkg list_installed"
462 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
464 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
466 self.installed_packetlist = {}
467 for x in result.splitlines():
468 split = x.split(' - ')
469 self.installed_packetlist[split[0].strip()] = split[1].strip()
470 self.buildPacketList()
472 def PacketEntryComponent(self,entry):
474 res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
475 res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
476 res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
477 res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
482 def buildPacketList(self):
485 installedpng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
486 upgradeablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
487 installablepng = loadPNG(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
488 divpng = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
490 if self.cache_ttl > 0 and self.vc != 0:
491 print 'Loading packagelist cache from ',self.cache_file
493 self.cachelist = load_cache(self.cache_file)
494 if len(self.cachelist) > 0:
495 for x in self.cachelist:
496 if x[3] == 'installed':
497 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installedpng,divpng]))
498 elif x[3] == 'upgradeable':
499 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],upgradeablepng,divpng]))
501 self.list.append(self.PacketEntryComponent([x[0], x[1], x[2], x[3],installablepng,divpng]))
502 self['list'].l.setList(self.list)
503 self["list"].instance.show()
508 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
509 print 'rebuilding fresh package list'
510 for x in self.packetlist:
512 if self.installed_packetlist.has_key(x[0].strip()):
513 if self.installed_packetlist[x[0].strip()] == x[1].strip():
515 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installedpng,divpng]))
517 status = "upgradeable"
518 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,upgradeablepng,divpng]))
520 status = "installable"
521 self.list.append(self.PacketEntryComponent([x[0].strip(), x[1].strip(), x[2].strip(), status,installablepng,divpng]))
522 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
523 write_cache(self.cache_file, self.cachelist)
524 self['list'].l.setList(self.list)
525 self["list"].instance.show()
529 class UpdatePlugin(Screen):
531 <screen position="100,100" size="550,200" title="Software Update..." >
532 <widget name="activityslider" position="0,0" size="550,5" />
533 <widget name="slider" position="0,100" size="550,30" />
534 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
535 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
538 def __init__(self, session, args = None):
539 self.skin = UpdatePlugin.skin
540 Screen.__init__(self, session)
542 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
544 self.slider = Slider(0, 4)
545 self["slider"] = self.slider
546 self.activityslider = Slider(0, 100)
547 self["activityslider"] = self.activityslider
548 self.status = Label(_("Upgrading Dreambox... Please wait"))
549 self["status"] = self.status
550 self.package = Label()
551 self["package"] = self.package
557 self.activityTimer = eTimer()
558 self.activityTimer.callback.append(self.doActivityTimer)
559 self.activityTimer.start(100, False)
561 self.ipkg = IpkgComponent()
562 self.ipkg.addCallback(self.ipkgCallback)
565 self.package.setText(_("Package list update"))
566 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
568 self["actions"] = ActionMap(["WizardActions"],
574 def doActivityTimer(self):
576 if self.activity == 100:
578 self.activityslider.setValue(self.activity)
580 def ipkgCallback(self, event, param):
581 if event == IpkgComponent.EVENT_DOWNLOAD:
582 self.status.setText(_("Downloading"))
583 elif event == IpkgComponent.EVENT_UPGRADE:
584 if self.sliderPackages.has_key(param):
585 self.slider.setValue(self.sliderPackages[param])
586 self.package.setText(param)
587 self.status.setText(_("Upgrading"))
589 elif event == IpkgComponent.EVENT_INSTALL:
590 self.package.setText(param)
591 self.status.setText(_("Installing"))
593 elif event == IpkgComponent.EVENT_CONFIGURING:
594 self.package.setText(param)
595 self.status.setText(_("Configuring"))
596 elif event == IpkgComponent.EVENT_MODIFIED:
597 self.session.openWithCallback(
598 self.modificationCallback,
600 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
602 elif event == IpkgComponent.EVENT_ERROR:
604 elif event == IpkgComponent.EVENT_DONE:
606 self.updating = False
607 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
608 elif self.error == 0:
609 self.slider.setValue(4)
611 self.activityTimer.stop()
612 self.activityslider.setValue(0)
614 self.package.setText("")
615 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
617 self.activityTimer.stop()
618 self.activityslider.setValue(0)
619 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
620 if self.packages == 0:
621 error = _("No packages were upgraded yet. So you can check your network and try again.")
623 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
624 self.status.setText(_("Error") + " - " + error)
625 #print event, "-", param
628 def modificationCallback(self, res):
629 self.ipkg.write(res and "N" or "Y")
632 if not self.ipkg.isRunning():
633 if self.packages != 0 and self.error == 0:
634 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
638 def exitAnswer(self, result):
639 if result is not None and result:
645 class IpkgInstaller(Screen):
647 <screen position="100,100" size="550,400" title="..." >
648 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
649 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
650 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
651 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
652 <widget name="list" position="0,60" size="550,360" />
656 def __init__(self, session, list):
657 self.skin = IpkgInstaller.skin
658 Screen.__init__(self, session)
660 self.list = SelectionList()
661 self["list"] = self.list
662 for listindex in range(len(list)):
663 self.list.addSelection(list[listindex], list[listindex], listindex, True)
665 self["red"] = Label()
666 self["green"] = Label()
667 self["yellow"] = Label()
668 self["blue"] = Label()
670 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
672 "ok": self.list.toggleSelection,
673 "cancel": self.close,
674 "green": self.install
678 list = self.list.getSelectionsList()
681 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
682 self.session.open(Ipkg, cmdList = cmdList)
684 def filescan_open(list, session, **kwargs):
685 filelist = [x.path for x in list]
686 session.open(IpkgInstaller, filelist) # list
688 def filescan(**kwargs):
689 from Components.Scanner import Scanner, ScanPath
691 Scanner(mimetypes = ["application/x-debian-package"],
694 ScanPath(path = "ipk", with_subdirs = True),
695 ScanPath(path = "", with_subdirs = False),
698 description = "Install software updates...",
699 openfnc = filescan_open, )
701 def UpgradeMain(session, **kwargs):
702 session.open(UpdatePluginMenu)
704 def startSetup(menuid):
705 if menuid != "setup":
707 return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
709 def Plugins(path, **kwargs):
713 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
714 #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
715 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)