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 Components.PluginComponent import plugins
20 from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
21 from Tools.LoadPixmap import LoadPixmap
22 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont
23 from cPickle import dump, load
25 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
26 from time import time, gmtime, strftime, localtime
27 from stat import ST_MTIME
28 from datetime import date
30 from ImageWizard import ImageWizard
31 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
33 config.plugins.configurationbackup = ConfigSubsection()
34 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
35 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:
359 if len(self.Console.appContainers):
360 for name in self.Console.appContainers.keys():
361 self.Console.kill(name)
366 if self.Console is not None:
370 if (os_path.exists(self.cache_file) == True):
371 remove(self.cache_file)
372 self.list_updating = True
375 def setWindowTitle(self):
376 self.setTitle(_("Packet manager"))
378 def rebuildList(self):
379 self["list"].instance.hide()
380 self.status.setText(_("Package list update"))
383 self.vc = valid_cache(self.cache_file, self.cache_ttl)
384 if self.cache_ttl > 0 and self.vc != 0:
386 self.buildPacketList()
389 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
391 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
393 def go(self, returnValue = None):
394 cur = self['list'].l.getCurrentSelection()
398 if returnValue[3] == 'installed':
399 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": returnValue[0] }))
400 if len(self.cmdList):
401 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n" + returnValue[0] + "\n" + self.oktext))
402 elif returnValue[3] == 'upgradeable':
403 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
404 if len(self.cmdList):
405 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n" + returnValue[0] + "\n" + self.oktext))
407 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": returnValue[0] }))
408 if len(self.cmdList):
409 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n" + returnValue[0] + "\n" + self.oktext))
411 def runRemove(self, result):
413 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
415 def runRemoveFinished(self):
416 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
418 def RemoveReboot(self, result):
422 cur = self['list'].l.getCurrentSelection()
425 item = self['list'].l.getCurrentSelectionIndex()
426 self.list[item] = self.buildEntryComponent(entry[0], entry[1], entry[2], 'installable')
427 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installable']
428 self['list'].l.setList(self.list)
429 write_cache(self.cache_file, self.cachelist)
430 self.reloadPluginlist()
434 def runUpgrade(self, result):
436 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
438 def runUpgradeFinished(self):
439 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
441 def UpgradeReboot(self, result):
445 cur = self['list'].l.getCurrentSelection()
448 item = self['list'].l.getCurrentSelectionIndex()
449 self.list[item] = self.buildEntryComponent(entry[0], entry[1], entry[2], 'installed')
450 self.cachelist[item] = [entry[0], entry[1], entry[2], 'installed']
451 self['list'].l.setList(self.list)
452 write_cache(self.cache_file, self.cachelist)
453 self.reloadPluginlist()
457 def ipkgCallback(self, event, param):
458 if event == IpkgComponent.EVENT_ERROR:
459 self.list_updating = False
460 self.status.setText(_("An error occured!"))
461 elif event == IpkgComponent.EVENT_DONE:
462 if self.list_updating:
463 self.list_updating = False
465 self.Console = Console()
467 self.Console.ePopen(cmd, self.IpkgList_Finished)
468 #print event, "-", param
471 def IpkgList_Finished(self, result, retval, extra_args = None):
474 for x in result.splitlines():
475 split = x.split(' - ')
476 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
478 self.Console = Console()
479 cmd = "ipkg list_installed"
480 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
482 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
484 self.installed_packetlist = {}
485 for x in result.splitlines():
486 split = x.split(' - ')
487 self.installed_packetlist[split[0].strip()] = split[1].strip()
488 self.buildPacketList()
490 def PacketEntryComponent(self,entry):
492 res.append(MultiContentEntryText(pos=(5, 1), size=(440, 28), font=0, text= entry[0]))
493 res.append(MultiContentEntryText(pos=(5, 26), size=(440, 20), font=1, text=entry[2]))
494 res.append(MultiContentEntryPixmapAlphaTest(pos=(445, 2), size=(48, 48), png = entry[4]))
495 res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 50), size=(510, 2), png = entry[5]))
498 def buildEntryComponent(self, name, version, description, state):
499 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
500 if state == 'installed':
501 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
502 return(self.PacketEntryComponent([name, version, description, state, installedpng, divpng]))
503 elif state == 'upgradeable':
504 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
505 return(self.PacketEntryComponent([name, version, description, state, upgradeablepng, divpng]))
507 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
508 return(self.PacketEntryComponent([name, version, description, state, installablepng, divpng]))
510 def buildPacketList(self):
514 if self.cache_ttl > 0 and self.vc != 0:
515 print 'Loading packagelist cache from ',self.cache_file
517 self.cachelist = load_cache(self.cache_file)
518 if len(self.cachelist) > 0:
519 for x in self.cachelist:
520 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
521 self['list'].l.setList(self.list)
522 self["list"].instance.show()
527 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
528 print 'rebuilding fresh package list'
529 for x in self.packetlist:
531 if self.installed_packetlist.has_key(x[0].strip()):
532 if self.installed_packetlist[x[0].strip()] == x[1].strip():
534 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
536 status = "upgradeable"
537 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
539 status = "installable"
540 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
541 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
542 write_cache(self.cache_file, self.cachelist)
543 self['list'].l.setList(self.list)
544 self["list"].instance.show()
547 def reloadPluginlist(self):
548 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
550 class UpdatePlugin(Screen):
552 <screen position="100,100" size="550,200" title="Software Update..." >
553 <widget name="activityslider" position="0,0" size="550,5" />
554 <widget name="slider" position="0,100" size="550,30" />
555 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
556 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
559 def __init__(self, session, args = None):
560 self.skin = UpdatePlugin.skin
561 Screen.__init__(self, session)
563 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
565 self.slider = Slider(0, 4)
566 self["slider"] = self.slider
567 self.activityslider = Slider(0, 100)
568 self["activityslider"] = self.activityslider
569 self.status = Label(_("Upgrading Dreambox... Please wait"))
570 self["status"] = self.status
571 self.package = Label()
572 self["package"] = self.package
578 self.activityTimer = eTimer()
579 self.activityTimer.callback.append(self.doActivityTimer)
580 self.activityTimer.start(100, False)
582 self.ipkg = IpkgComponent()
583 self.ipkg.addCallback(self.ipkgCallback)
586 self.package.setText(_("Package list update"))
587 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
589 self["actions"] = ActionMap(["WizardActions"],
595 def doActivityTimer(self):
597 if self.activity == 100:
599 self.activityslider.setValue(self.activity)
601 def ipkgCallback(self, event, param):
602 if event == IpkgComponent.EVENT_DOWNLOAD:
603 self.status.setText(_("Downloading"))
604 elif event == IpkgComponent.EVENT_UPGRADE:
605 if self.sliderPackages.has_key(param):
606 self.slider.setValue(self.sliderPackages[param])
607 self.package.setText(param)
608 self.status.setText(_("Upgrading"))
610 elif event == IpkgComponent.EVENT_INSTALL:
611 self.package.setText(param)
612 self.status.setText(_("Installing"))
614 elif event == IpkgComponent.EVENT_CONFIGURING:
615 self.package.setText(param)
616 self.status.setText(_("Configuring"))
617 elif event == IpkgComponent.EVENT_MODIFIED:
618 self.session.openWithCallback(
619 self.modificationCallback,
621 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
623 elif event == IpkgComponent.EVENT_ERROR:
625 elif event == IpkgComponent.EVENT_DONE:
627 self.updating = False
628 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
629 elif self.error == 0:
630 self.slider.setValue(4)
632 self.activityTimer.stop()
633 self.activityslider.setValue(0)
635 self.package.setText("")
636 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
638 self.activityTimer.stop()
639 self.activityslider.setValue(0)
640 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
641 if self.packages == 0:
642 error = _("No packages were upgraded yet. So you can check your network and try again.")
644 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
645 self.status.setText(_("Error") + " - " + error)
646 #print event, "-", param
649 def modificationCallback(self, res):
650 self.ipkg.write(res and "N" or "Y")
653 if not self.ipkg.isRunning():
654 if self.packages != 0 and self.error == 0:
655 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
659 def exitAnswer(self, result):
660 if result is not None and result:
666 class IpkgInstaller(Screen):
668 <screen position="100,100" size="550,400" title="..." >
669 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
670 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
671 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
672 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
673 <widget name="list" position="0,60" size="550,360" />
677 def __init__(self, session, list):
678 self.skin = IpkgInstaller.skin
679 Screen.__init__(self, session)
681 self.list = SelectionList()
682 self["list"] = self.list
683 for listindex in range(len(list)):
684 self.list.addSelection(list[listindex], list[listindex], listindex, True)
686 self["red"] = Label()
687 self["green"] = Label()
688 self["yellow"] = Label()
689 self["blue"] = Label()
691 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
693 "ok": self.list.toggleSelection,
694 "cancel": self.close,
695 "green": self.install
699 list = self.list.getSelectionsList()
702 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
703 self.session.open(Ipkg, cmdList = cmdList)
705 def filescan_open(list, session, **kwargs):
706 filelist = [x.path for x in list]
707 session.open(IpkgInstaller, filelist) # list
709 def filescan(**kwargs):
710 from Components.Scanner import Scanner, ScanPath
712 Scanner(mimetypes = ["application/x-debian-package"],
715 ScanPath(path = "ipk", with_subdirs = True),
716 ScanPath(path = "", with_subdirs = False),
719 description = "Install software updates...",
720 openfnc = filescan_open, )
722 def UpgradeMain(session, **kwargs):
723 session.open(UpdatePluginMenu)
725 def startSetup(menuid):
726 if menuid != "setup":
728 return [(_("Software manager") + "...", UpgradeMain, "software_manager", 50)]
730 def Plugins(path, **kwargs):
734 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
735 #PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain),
736 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)