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.ScrollLabel import ScrollLabel
12 from Components.Pixmap import Pixmap
13 from Components.MenuList import MenuList
14 from Components.Sources.List import List
15 from Components.Slider import Slider
16 from Components.Harddisk import harddiskmanager
17 from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
18 from Components.Console import Console
19 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
20 from Components.SelectionList import SelectionList
21 from Components.PluginComponent import plugins
22 from Components.About import about
23 from Components.DreamInfoHandler import DreamInfoHandler
24 from Components.Language import language
25 from Components.AVSwitch import AVSwitch
26 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_METADIR
27 from Tools.LoadPixmap import LoadPixmap
28 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
29 from cPickle import dump, load
30 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
31 from time import time, gmtime, strftime, localtime
32 from stat import ST_MTIME
33 from datetime import date
34 from twisted.web import client
35 from twisted.internet import reactor
37 from ImageWizard import ImageWizard
38 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
40 config.plugins.configurationbackup = ConfigSubsection()
41 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
42 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
44 def write_cache(cache_file, cache_data):
46 if not os_path.isdir( os_path.dirname(cache_file) ):
48 mkdir( os_path.dirname(cache_file) )
50 print os_path.dirname(cache_file), 'is a file'
51 fd = open(cache_file, 'w')
52 dump(cache_data, fd, -1)
55 def valid_cache(cache_file, cache_ttl):
56 #See if the cache file exists and is still living
58 mtime = stat(cache_file)[ST_MTIME]
62 if (curr_time - mtime) > cache_ttl:
67 def load_cache(cache_file):
75 class UpdatePluginMenu(Screen):
77 <screen name="UpdatePluginMenu" position="80,130" size="560,330" title="Softwaremanager..." >
78 <ePixmap pixmap="skin_default/border_menu_300.png" position="5,10" zPosition="1" size="300,300" transparent="1" alphatest="on" />
79 <widget source="menu" render="Listbox" position="10,20" size="290,260" scrollbarMode="showOnDemand">
80 <convert type="TemplatedMultiContent">
82 MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
84 "fonts": [gFont("Regular", 20)],
89 <widget source="menu" render="Listbox" position="310,10" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
90 <convert type="TemplatedMultiContent">
92 MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
94 "fonts": [gFont("Regular", 20)],
101 def __init__(self, session, args = 0):
102 Screen.__init__(self, session)
103 self.skin_path = plugin_path
106 self.oktext = _("\nPress OK on your remote control to continue.")
107 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
109 self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext) )
110 #self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext) )
111 self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext))
112 self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext))
113 self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext))
114 self.list.append(("ipkg-install", _("Install local IPKG"), _("\nScan for local packages and install them." ) + self.oktext))
115 if config.usage.setup_level.index >= 2: # expert+
116 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext))
118 self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext))
119 self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext ))
120 self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext))
121 if config.usage.setup_level.index >= 2: # expert+
122 self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext))
123 self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext))
125 self["menu"] = List(self.list)
127 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
134 self.onLayoutFinish.append(self.layoutFinished)
135 self.backuppath = getBackupPath()
136 self.backupfile = getBackupFilename()
137 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
138 self.onShown.append(self.setWindowTitle)
140 def layoutFinished(self):
142 self["menu"].index = idx
144 def setWindowTitle(self):
145 self.setTitle(_("Software manager..."))
148 current = self["menu"].getCurrent()
152 if (current == "software-update"):
153 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
154 elif (current == "software-restore"):
155 self.session.open(ImageWizard)
156 elif (current == "install-plugins"):
157 self.session.open(PluginManager, self.skin_path)
158 elif (current == "system-backup"):
159 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
160 elif (current == "system-restore"):
161 if os_path.exists(self.fullbackupfilename):
162 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
164 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO)
165 elif (current == "ipkg-install"):
167 from Plugins.Extensions.MediaScanner.plugin import main
170 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO)
171 elif (current == "advanced"):
172 self.session.open(UpdatePluginMenu, 1)
174 if (current == "ipkg-manager"):
175 self.session.open(PacketManager, self.skin_path)
176 elif (current == "backuplocation"):
177 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
179 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
182 if x[1].startswith('/autofs/'):
185 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
186 elif (current == "backupfiles"):
187 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
188 elif (current == "advancedrestore"):
189 self.session.open(RestoreMenu, self.skin_path)
190 elif (current == "ipkg-source"):
191 self.session.open(IPKGMenu, self.skin_path)
193 def backupfiles_choosen(self, ret):
194 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
196 def backuplocation_choosen(self, option):
197 if option is not None:
198 config.plugins.configurationbackup.backuplocation.value = str(option[1])
199 config.plugins.configurationbackup.backuplocation.save()
200 config.plugins.configurationbackup.save()
202 self.createBackupfolders()
204 def runUpgrade(self, result):
206 self.session.open(UpdatePlugin, self.skin_path)
208 def createBackupfolders(self):
209 print "Creating backup folder if not already there..."
210 self.backuppath = getBackupPath()
212 if (os_path.exists(self.backuppath) == False):
213 makedirs(self.backuppath)
215 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO)
217 def backupDone(self,retval = None):
219 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO)
221 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO)
223 def startRestore(self, ret = False):
226 self.session.open(RestoreScreen, runRestore = True)
228 class IPKGMenu(Screen):
230 <screen name="IPKGMenu" position="135,144" size="450,320" title="Select IPKG source......" >
231 <widget name="filelist" position="10,10" size="430,240" scrollbarMode="showOnDemand" />
232 <ePixmap pixmap="skin_default/buttons/red.png" position="10,280" zPosition="2" size="140,40" transparent="1" alphatest="on" />
233 <widget name="closetext" position="20,290" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
234 <ePixmap pixmap="skin_default/buttons/green.png" position="160,280" zPosition="2" size="140,40" transparent="1" alphatest="on" />
235 <widget name="edittext" position="170,290" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
238 def __init__(self, session, plugin_path):
239 Screen.__init__(self, session)
240 self.skin_path = plugin_path
242 self["closetext"] = Label(_("Close"))
243 self["edittext"] = Label(_("Edit"))
252 self["actions"] = NumberActionMap(["SetupActions"],
255 "cancel": self.keyCancel
258 self["shortcuts"] = ActionMap(["ShortcutActions"],
260 "red": self.keyCancel,
264 self["filelist"] = MenuList(self.flist)
266 self.onLayoutFinish.append(self.layoutFinished)
268 def layoutFinished(self):
269 self.setWindowTitle()
271 def setWindowTitle(self):
272 self.setTitle(_("Select IPKG source to edit..."))
277 self.path = '/etc/ipkg/'
278 if (os_path.exists(self.path) == False):
281 for file in listdir(self.path):
282 if (file.endswith(".conf")):
283 if file != 'arch.conf':
284 self.flist.append((file))
286 self["filelist"].l.setList(self.flist)
289 if (self.exe == False) and (self.entry == True):
290 self.sel = self["filelist"].getCurrent()
291 self.val = self.path + self.sel
292 self.session.open(IPKGSource, self.val)
301 class IPKGSource(Screen):
303 <screen name="IPKGSource" position="100,100" size="550,80" title="IPKG source" >
304 <widget name="text" position="10,10" size="530,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
305 <ePixmap pixmap="skin_default/buttons/red.png" position="10,40" zPosition="2" size="140,40" transparent="1" alphatest="on" />
306 <widget name="closetext" position="20,50" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
307 <ePixmap pixmap="skin_default/buttons/green.png" position="160,40" zPosition="2" size="140,40" transparent="1" alphatest="on" />
308 <widget name="edittext" position="170,50" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
311 def __init__(self, session, configfile = None):
312 Screen.__init__(self, session)
313 self.session = session
314 self.configfile = configfile
318 fp = file(configfile, 'r')
319 sources = fp.readlines()
327 x= int(desk.size().width())
328 y= int(desk.size().height())
329 #print "[IPKGSource] mainscreen: current desktop size: %dx%d" % (x,y)
331 self["closetext"] = Label(_("Cancel"))
332 self["edittext"] = Label(_("Save"))
335 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
337 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
339 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
345 "left": self.keyLeft,
346 "right": self.keyRight,
347 "home": self.keyHome,
349 "deleteForward": self.keyDeleteForward,
350 "deleteBackward": self.keyDeleteBackward,
351 "1": self.keyNumberGlobal,
352 "2": self.keyNumberGlobal,
353 "3": self.keyNumberGlobal,
354 "4": self.keyNumberGlobal,
355 "5": self.keyNumberGlobal,
356 "6": self.keyNumberGlobal,
357 "7": self.keyNumberGlobal,
358 "8": self.keyNumberGlobal,
359 "9": self.keyNumberGlobal,
360 "0": self.keyNumberGlobal
363 self.onLayoutFinish.append(self.layoutFinished)
365 def layoutFinished(self):
366 self.setWindowTitle()
369 def setWindowTitle(self):
370 self.setTitle(_("Edit IPKG source URL..."))
373 text = self["text"].getText()
375 fp = file(self.configfile, 'w')
393 def keyDeleteForward(self):
394 self["text"].delete()
396 def keyDeleteBackward(self):
397 self["text"].deleteBackward()
399 def keyNumberGlobal(self, number):
400 print "pressed", number
401 self["text"].number(number)
404 class PacketManager(Screen):
406 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
407 <widget source="list" render="Listbox" position="5,10" size="520,365" scrollbarMode="showOnDemand">
408 <convert type="TemplatedMultiContent">
410 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
411 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
412 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
413 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
415 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
420 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
421 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
422 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
423 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
426 def __init__(self, session, plugin_path, args = None):
427 Screen.__init__(self, session)
428 self.session = session
429 self.skin_path = plugin_path
431 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
436 "green": self.reload,
441 self["list"] = List(self.list)
442 self["closetext"] = Label(_("Close"))
443 self["reloadtext"] = Label(_("Reload"))
445 self.list_updating = True
447 self.installed_packetlist = {}
448 self.Console = Console()
451 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
452 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
453 self.oktext = _("\nAfter pressing OK, please wait!")
454 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
456 self.ipkg = IpkgComponent()
457 self.ipkg.addCallback(self.ipkgCallback)
458 self.onShown.append(self.setWindowTitle)
459 self.onLayoutFinish.append(self.rebuildList)
463 if self.Console is not None:
464 if len(self.Console.appContainers):
465 for name in self.Console.appContainers.keys():
466 self.Console.kill(name)
470 if (os_path.exists(self.cache_file) == True):
471 remove(self.cache_file)
472 self.list_updating = True
475 def setWindowTitle(self):
476 self.setTitle(_("Packet manager"))
478 def setStatus(self,status = None):
481 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
482 if status == 'update':
483 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
484 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
485 self['list'].setList(self.statuslist)
486 elif status == 'error':
487 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
488 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
489 self['list'].setList(self.statuslist)
491 def rebuildList(self):
492 self.setStatus('update')
494 self.vc = valid_cache(self.cache_file, self.cache_ttl)
495 if self.cache_ttl > 0 and self.vc != 0:
497 self.buildPacketList()
500 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
502 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
504 def go(self, returnValue = None):
505 cur = self["list"].getCurrent()
510 if status == 'installed':
511 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
512 if len(self.cmdList):
513 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
514 elif status == 'upgradeable':
515 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
516 if len(self.cmdList):
517 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
518 elif status == "installable":
519 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
520 if len(self.cmdList):
521 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
523 def runRemove(self, result):
525 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
527 def runRemoveFinished(self):
528 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
530 def RemoveReboot(self, result):
534 cur = self["list"].getCurrent()
536 item = self['list'].getIndex()
537 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
538 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
539 self['list'].setList(self.list)
540 write_cache(self.cache_file, self.cachelist)
541 self.reloadPluginlist()
545 def runUpgrade(self, result):
547 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
549 def runUpgradeFinished(self):
550 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
552 def UpgradeReboot(self, result):
556 cur = self["list"].getCurrent()
558 item = self['list'].getIndex()
559 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
560 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
561 self['list'].setList(self.list)
562 write_cache(self.cache_file, self.cachelist)
563 self.reloadPluginlist()
567 def ipkgCallback(self, event, param):
568 if event == IpkgComponent.EVENT_ERROR:
569 self.list_updating = False
570 self.setStatus('error')
571 elif event == IpkgComponent.EVENT_DONE:
572 if self.list_updating:
573 self.list_updating = False
575 self.Console = Console()
577 self.Console.ePopen(cmd, self.IpkgList_Finished)
578 #print event, "-", param
581 def IpkgList_Finished(self, result, retval, extra_args = None):
584 for x in result.splitlines():
585 split = x.split(' - ') #self.blacklisted_packages
586 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
587 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
589 self.Console = Console()
590 cmd = "ipkg list_installed"
591 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
593 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
595 self.installed_packetlist = {}
596 for x in result.splitlines():
597 split = x.split(' - ')
598 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
599 self.installed_packetlist[split[0].strip()] = split[1].strip()
600 self.buildPacketList()
602 def buildEntryComponent(self, name, version, description, state):
603 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
604 if state == 'installed':
605 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
606 return((name, version, description, state, installedpng, divpng))
607 elif state == 'upgradeable':
608 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
609 return((name, version, description, state, upgradeablepng, divpng))
611 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
612 return((name, version, description, state, installablepng, divpng))
614 def buildPacketList(self):
618 if self.cache_ttl > 0 and self.vc != 0:
619 print 'Loading packagelist cache from ',self.cache_file
621 self.cachelist = load_cache(self.cache_file)
622 if len(self.cachelist) > 0:
623 for x in self.cachelist:
624 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
625 self['list'].setList(self.list)
629 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
630 print 'rebuilding fresh package list'
631 for x in self.packetlist:
633 if self.installed_packetlist.has_key(x[0].strip()):
634 if self.installed_packetlist[x[0].strip()] == x[1].strip():
636 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
638 status = "upgradeable"
639 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
641 status = "installable"
642 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
643 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
644 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
645 write_cache(self.cache_file, self.cachelist)
646 self['list'].setList(self.list)
648 def reloadPluginlist(self):
649 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
652 class PluginManager(Screen, DreamInfoHandler):
654 <screen position="80,90" size="560,420" title="Plugin manager..." >
655 <widget source="list" render="Listbox" position="5,10" size="550,365" scrollbarMode="showOnDemand">
656 <convert type="TemplatedMultiContent">
659 MultiContentEntryText(pos = (30, 1), size = (500, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
660 MultiContentEntryText(pos = (30, 26), size = (500, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
661 MultiContentEntryPixmapAlphaTest(pos = (500, 2), size = (48, 48), png = 5), # index 5 is the status pixmap
662 MultiContentEntryPixmapAlphaTest(pos = (0, 50), size = (550, 2), png = 6), # index 6 is the div pixmap
663 MultiContentEntryPixmapAlphaTest(pos = (0, 10), size = (25, 25), png = 7), # index 7 is the selected pixmap
666 MultiContentEntryText(pos = (30, 1), size = (500, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
667 MultiContentEntryText(pos = (30, 26), size = (500, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
668 MultiContentEntryPixmapAlphaTest(pos = (500, 2), size = (48, 48), png = 5), # index 5 is the status pixmap
669 MultiContentEntryPixmapAlphaTest(pos = (0, 50), size = (550, 2), png = 6), # index 6 is the div pixmap
670 MultiContentEntryPixmapAlphaTest(pos = (0, 10), size = (25, 25), png = 7), # index 7 is the selected pixmap
673 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
679 <ePixmap pixmap="skin_default/buttons/red.png" position="0,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
680 <widget name="closetext" position="0,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
681 <ePixmap pixmap="skin_default/buttons/green.png" position="140,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
682 <widget name="installtext" position="140,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
683 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
684 <widget name="selecttext" position="280,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
685 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
686 <widget name="viewtext" position="420,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
690 def __init__(self, session, plugin_path, args = None):
691 Screen.__init__(self, session)
692 self.session = session
693 self.skin_path = plugin_path
694 aboutInfo = about.getImageVersionString()
695 if aboutInfo.startswith("dev-"):
696 self.ImageVersion = 'Experimental'
698 self.ImageVersion = 'Stable'
699 lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
704 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
705 self.directory = resolveFilename(SCOPE_METADIR)
707 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
712 "green": self.installPlugins,
713 "yellow": self.changeSelectionState,
719 self.selectedFiles = []
720 self.categoryList = []
721 self["list"] = List(self.list)
722 self["closetext"] = Label(_("Close"))
723 self["installtext"] = Label()
724 self["selecttext"] = Label()
725 self["viewtext"] = Label()
727 self.list_updating = True
729 self.installed_packetlist = {}
730 self.Console = Console()
732 self.oktext = _("\nAfter pressing OK, please wait!")
733 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
735 self.ipkg = IpkgComponent()
736 self.ipkg.addCallback(self.ipkgCallback)
737 if not self.selectionChanged in self["list"].onSelectionChanged:
738 self["list"].onSelectionChanged.append(self.selectionChanged)
740 self["installtext"].hide()
741 self["selecttext"].hide()
742 self["viewtext"].hide()
745 self.onShown.append(self.setWindowTitle)
746 self.onLayoutFinish.append(self.rebuildList)
748 def setWindowTitle(self):
749 self.setTitle(_("Plugin manager"))
752 if self.currList == "packages":
753 self.currList = "category"
754 self['list'].setList(self.categoryList)
757 if self.Console is not None:
758 if len(self.Console.appContainers):
759 for name in self.Console.appContainers.keys():
760 self.Console.kill(name)
764 if (os_path.exists(self.cache_file) == True):
765 remove(self.cache_file)
766 self.list_updating = True
769 def setState(self,status = None):
771 self.currList = "status"
773 self["installtext"].hide()
774 self["selecttext"].hide()
775 self["viewtext"].hide()
776 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
777 if status == 'update':
778 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
779 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' ))
780 self["list"].style = "default"
781 self['list'].setList(self.statuslist)
782 elif status == 'sync':
783 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
784 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
785 self["list"].style = "default"
786 self['list'].setList(self.statuslist)
787 elif status == 'error':
788 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
789 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
790 self["list"].style = "default"
791 self['list'].setList(self.statuslist)
793 def statusCallback(self, status, progress):
796 def selectionChanged(self):
797 current = self["list"].getCurrent()
799 if self.currList == "packages":
800 self["closetext"].setText(_("Back"))
801 self["closetext"].show()
802 self["installtext"].setText(_("Install/\nRemove"))
803 self["installtext"].show()
804 self["viewtext"].setText(_("Details"))
805 self["viewtext"].show()
806 if current[8] == False:
807 self["selecttext"].setText(_("Select"))
809 self["selecttext"].setText(_("Deselect"))
810 self["selecttext"].show()
811 elif self.currList == "category":
812 self["closetext"].setText(_("Close"))
813 self["closetext"].show()
814 self["installtext"].hide()
815 self["selecttext"].hide()
816 self["viewtext"].setText(_("View"))
817 self["viewtext"].show()
820 def changeSelectionState(self):
821 current = self["list"].getCurrent()
823 if current[8] is not '':
824 idx = self["list"].getIndex()
832 for entry in self.selectedFiles:
833 if entry[0] == detailsFile:
834 self.selectedFiles.remove(entry)
837 alreadyinList = False
838 for entry in self.selectedFiles:
839 if entry[0] == detailsFile:
841 if not alreadyinList:
842 self.selectedFiles.append((detailsFile,x[4],x[3]))
843 newList.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), x[4].strip(), selected = SelectState))
849 self['list'].updateList(self.list)
850 self.selectionChanged()
852 def rebuildList(self):
853 self.setState('update')
854 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
856 def ipkgCallback(self, event, param):
857 if event == IpkgComponent.EVENT_ERROR:
858 self.list_updating = False
859 self.setState('error')
860 elif event == IpkgComponent.EVENT_DONE:
861 if self.list_updating:
862 self.list_updating = False
864 self.Console = Console()
865 cmd = "ipkg list" ### ipkg install enigma2-plugins-meta
866 self.Console.ePopen(cmd, self.IpkgList_Finished)
869 def IpkgList_Finished(self, result, retval, extra_args = None):
871 self.fillPackagesIndexList()
873 self.Console = Console()
874 self.setState('sync')
875 cmd = "ipkg list_installed"
876 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
878 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
880 self.installed_packetlist = {}
881 for x in result.splitlines():
882 split = x.split(' - ')
883 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
884 self.installed_packetlist[split[0].strip()] = split[1].strip()
885 self.buildCategoryList()
887 def go(self, returnValue = None):
888 current = self["list"].getCurrent()
890 if self.currList == "category":
891 selectedTag = current[4]
892 self.buildPacketList(selectedTag)
893 elif self.currList == "packages":
894 if current[8] is not '':
895 detailsfile = self.directory[0] + "/" + current[1]
896 if (os_path.exists(detailsfile) == True):
897 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
899 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO)
900 def detailsClosed(self, result):
903 self.Console = Console()
904 self.setState('sync')
905 cmd = "ipkg list_installed"
906 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
908 def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
909 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
910 if selected is False:
911 selectedicon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_off.png"))
913 selectedicon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png"))
915 if state == 'installed':
916 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
917 return((name, details, description, packagename, state, installedpng, divpng, selectedicon, selected))
919 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
920 return((name, details, description, packagename, state, installablepng, divpng, selectedicon, selected))
922 def buildPacketList(self, categorytag = None):
923 if categorytag is not None:
924 self.currList = "packages"
925 #print self.packagesIndexlist
927 for package in self.packagesIndexlist[:]:
928 #print "package--->",package
929 prerequisites = package[0]["prerequisites"]
930 #print "prerequisite",prerequisites
931 if prerequisites.has_key("tag"):
932 for foundtag in prerequisites["tag"]:
933 if categorytag == foundtag:
934 attributes = package[0]["attributes"]
935 #print "attributes---->",attributes
936 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
939 for x in self.packetlist:
942 if self.installed_packetlist.has_key(x[3].strip()):
944 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = False))
946 status = "installable"
947 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = False))
950 self.list.sort(key=lambda x: x[0])
951 self["list"].style = "default"
952 self['list'].setList(self.list)
953 self.selectionChanged()
956 def buildCategoryList(self):
957 self.currList = "category"
958 #print self.packagesIndexlist
960 self.categoryList = []
961 for package in self.packagesIndexlist[:]:
962 #print "package--->",package
963 prerequisites = package[0]["prerequisites"]
964 #print "prerequisite",prerequisites
965 if prerequisites.has_key("tag"):
966 for foundtag in prerequisites["tag"]:
967 #print "found tag----",foundtag
968 if foundtag not in self.categories:
969 self.categories.append(foundtag)
970 self.categoryList.append(self.buildCategoryComponent(foundtag))
971 self.categoryList.sort(key=lambda x: x[0])
972 self["list"].style = "category"
973 self['list'].setList(self.categoryList)
974 self.selectionChanged()
976 def buildCategoryComponent(self, tag = None):
977 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
980 return(( _("System"), '', _("View list of available system extensions" ),'', tag, None, divpng, None, '' ))
982 return(( _("Skins"), '', _("View list of available skins" ),'', tag, None, divpng, None, '' ))
983 elif tag == 'Recording':
984 return(( _("Recordings"), '', _("View list of available recording extensions" ),'', tag, None, divpng, None, '' ))
985 elif tag == 'Network':
986 return(( _("Network"), '', _("View list of available networking extensions" ),'', tag, None, divpng, None, '' ))
988 return(( _("CommonInterface"), '', _("View list of available CommonInterface extensions" ),'', tag, None, divpng, None, '' ))
989 elif tag == 'Default':
990 return(( _("Default Settings"), '', _("View list of available default settings" ),'', tag, None, divpng, None, '' ))
992 return(( _("Satteliteequipment"), '', _("View list of available Satteliteequipment extensions." ),'', tag, None, divpng, None, '' ))
993 elif tag == 'Software':
994 return(( _("Software"), '', _("View list of available software extensions" ),'', tag, None, divpng, None, '' ))
995 elif tag == 'Multimedia':
996 return(( _("Multimedia"), '', _("View list of available multimedia extensions." ),'', tag, None, divpng, None, '' ))
997 elif tag == 'Display':
998 return(( _("Display and Userinterface"), '', _("View list of available Display and Userinterface extensions." ),'', tag, None, divpng, None, '' ))
1000 return(( _("Electronic Program Guide"), '', _("View list of available EPG extensions." ),'', tag, None, divpng, None, '' ))
1001 elif tag == 'Communication':
1002 return(( _("Communication"), '', _("View list of available communication extensions." ),'', tag, None, divpng, None, '' ))
1005 def installPlugins(self):
1007 if self.selectedFiles and len(self.selectedFiles):
1008 for plugin in self.selectedFiles:
1009 #print "processing Plugin-->",plugin
1010 detailsfile = self.directory[0] + "/" + plugin[0]
1011 if (os_path.exists(detailsfile) == True):
1012 self.fillPackageDetails(plugin[0])
1013 self.package = self.packageDetails[0]
1014 if self.package[0].has_key("attributes"):
1015 self.attributes = self.package[0]["attributes"]
1016 if self.attributes.has_key("package"):
1017 self.packagefiles = self.attributes["package"]
1018 if plugin[1] == 'installed':
1019 if self.packagefiles:
1020 for package in self.packagefiles[:]:
1021 #print "removing package: ",package["name"]
1022 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1024 if self.packagefiles:
1025 for package in self.packagefiles[:]:
1026 #print "adding package: ",package["name"]
1027 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1029 if plugin[1] == 'installed':
1030 #print "removing package: ",plugin[2]
1031 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1033 #print "adding package: ",plugin[2]
1034 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1036 current = self["list"].getCurrent()
1038 if current[8] is not '':
1039 detailsfile = self.directory[0] + "/" + current[1]
1040 if (os_path.exists(detailsfile) == True):
1041 self.fillPackageDetails(current[1])
1042 self.package = self.packageDetails[0]
1043 if self.package[0].has_key("attributes"):
1044 self.attributes = self.package[0]["attributes"]
1045 if self.attributes.has_key("package"):
1046 self.packagefiles = self.attributes["package"]
1047 if current[4] == 'installed':
1048 if self.packagefiles:
1049 for package in self.packagefiles[:]:
1050 #print "removing package: ",package["name"]
1051 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1053 if self.packagefiles:
1054 for package in self.packagefiles[:]:
1055 #print "adding package: ",package["name"]
1056 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1058 if current[4] == 'installed':
1059 #print "removing package: ",current[0]
1060 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": current[3] }))
1062 #print "adding package: ",current[0]
1063 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": current[3] }))
1065 if len(self.cmdList):
1067 self.session.openWithCallback(self.runExecute, MessageBox, _("Do you want to continue installing or removing selected plugins?\n") + self.oktext)
1069 def runExecute(self, result):
1071 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
1073 def runExecuteFinished(self):
1074 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1076 def ExecuteReboot(self, result):
1080 self.reloadPluginlist()
1081 self.detailsClosed(True)
1085 def reloadPluginlist(self):
1086 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1089 class PluginDetails(Screen, DreamInfoHandler):
1091 <screen name="PluginDetails" position="60,90" size="600,420" title="PluginDetails..." >
1092 <widget name="author" position="10,10" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
1093 <widget name="statuspic" position="550,0" size="48,48" alphatest="on"/>
1094 <widget name="divpic" position="0,40" size="600,2" alphatest="on"/>
1095 <widget name="detailtext" position="10,50" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1096 <widget name="screenshot" position="290,50" size="300,330" alphatest="on"/>
1097 <ePixmap pixmap="skin_default/buttons/red.png" position="0,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1098 <widget name="closetext" position="0,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1099 <ePixmap pixmap="skin_default/buttons/green.png" position="140,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1100 <widget name="statetext" position="140,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1102 def __init__(self, session, plugin_path, packagedata = None):
1103 Screen.__init__(self, session)
1104 self.skin_path = plugin_path
1105 lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
1107 self.language = None
1109 self.language = lang
1110 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
1111 self.directory = resolveFilename(SCOPE_METADIR)
1113 self.pluginname = packagedata[0]
1114 self.details = packagedata[1]
1115 self.pluginstate = packagedata[4]
1116 self.statuspicinstance = packagedata[5]
1117 self.divpicinstance = packagedata[6]
1118 self.fillPackageDetails(self.details)
1122 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1128 "down": self.pageDown,
1129 "left": self.pageUp,
1130 "right": self.pageDown,
1133 self["statuspic"] = Pixmap()
1134 self["divpic"] = Pixmap()
1135 self["screenshot"] = Pixmap()
1136 self["closetext"] = Label(_("Close"))
1137 self["statetext"] = Label()
1138 self["detailtext"] = ScrollLabel()
1139 self["author"] = Label()
1140 self["statuspic"].hide()
1141 self["screenshot"].hide()
1142 self["divpic"].hide()
1144 self.package = self.packageDetails[0]
1145 #print "PACKAGE-------im DETAILS",self.package
1146 if self.package[0].has_key("attributes"):
1147 self.attributes = self.package[0]["attributes"]
1150 self.oktext = _("\nAfter pressing OK, please wait!")
1151 self.picload = ePicLoad()
1152 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
1153 self.onShown.append(self.setWindowTitle)
1154 self.onLayoutFinish.append(self.setInfos)
1156 def setWindowTitle(self):
1157 self.setTitle(_("Package details for: " + self.pluginname))
1163 self["detailtext"].pageUp()
1166 self["detailtext"].pageDown()
1168 def statusCallback(self, status, progress):
1172 if self.attributes.has_key("name"):
1173 self.pluginname = self.attributes["name"]
1175 self.pluginname = _("unknown")
1176 if self.attributes.has_key("author"):
1177 self.author = self.attributes["author"]
1179 self.author = _("unknown")
1180 if self.attributes.has_key("description"):
1181 self.description = self.attributes["description"]
1183 self.author = _("No description available.")
1184 self.loadThumbnail(self.attributes)
1185 self["author"].setText(_("Author: ") + self.author)
1186 self["detailtext"].setText(self.description.strip())
1187 if self.pluginstate == 'installable':
1188 self["statetext"].setText(_("Install"))
1190 self["statetext"].setText(_("Remove"))
1192 def loadThumbnail(self, entry):
1194 if entry.has_key("screenshot"):
1195 thumbnailUrl = entry["screenshot"]
1196 if thumbnailUrl is not None:
1197 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1198 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1199 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1201 self.setThumbnail(noScreenshot = True)
1203 def setThumbnail(self, noScreenshot = False):
1204 if not noScreenshot:
1205 filename = self.thumbnail
1207 filename = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/noprev.png")
1209 sc = AVSwitch().getFramebufferScale()
1210 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1211 self.picload.startDecode(filename)
1213 if self.statuspicinstance != None:
1214 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1215 self["statuspic"].show()
1216 if self.divpicinstance != None:
1217 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1218 self["divpic"].show()
1220 def paintScreenshotPixmapCB(self, picInfo=None):
1221 ptr = self.picload.getData()
1223 self["screenshot"].instance.setPixmap(ptr.__deref__())
1224 self["screenshot"].show()
1226 self.setThumbnail(noScreenshot = True)
1229 if self.attributes.has_key("package"):
1230 self.packagefiles = self.attributes["package"]
1232 if self.pluginstate == 'installed':
1233 if self.packagefiles:
1234 for package in self.packagefiles[:]:
1235 #print "removing packagefile: ",package["name"]
1236 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1237 if len(self.cmdList):
1238 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1240 if self.packagefiles:
1241 for package in self.packagefiles[:]:
1242 #print "adding packagefile: ",package["name"]
1243 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1244 if len(self.cmdList):
1245 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1247 def runUpgrade(self, result):
1249 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1251 def runUpgradeFinished(self):
1252 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1254 def UpgradeReboot(self, result):
1262 def runRemove(self, result):
1264 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1266 def runRemoveFinished(self):
1267 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1269 def RemoveReboot(self, result):
1277 def reloadPluginlist(self):
1278 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1280 def fetchFailed(self,string):
1281 self.setThumbnail(noScreenshot = True)
1282 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1285 class UpdatePlugin(Screen):
1287 <screen position="100,100" size="550,200" title="Software Update..." >
1288 <widget name="activityslider" position="0,0" size="550,5" />
1289 <widget name="slider" position="0,100" size="550,30" />
1290 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
1291 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
1294 def __init__(self, session, args = None):
1295 self.skin = UpdatePlugin.skin
1296 Screen.__init__(self, session)
1298 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1300 self.slider = Slider(0, 4)
1301 self["slider"] = self.slider
1302 self.activityslider = Slider(0, 100)
1303 self["activityslider"] = self.activityslider
1304 self.status = Label(_("Upgrading Dreambox... Please wait"))
1305 self["status"] = self.status
1306 self.package = Label()
1307 self["package"] = self.package
1313 self.activityTimer = eTimer()
1314 self.activityTimer.callback.append(self.doActivityTimer)
1315 self.activityTimer.start(100, False)
1317 self.ipkg = IpkgComponent()
1318 self.ipkg.addCallback(self.ipkgCallback)
1320 self.updating = True
1321 self.package.setText(_("Package list update"))
1322 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1324 self["actions"] = ActionMap(["WizardActions"],
1330 def doActivityTimer(self):
1332 if self.activity == 100:
1334 self.activityslider.setValue(self.activity)
1336 def ipkgCallback(self, event, param):
1337 if event == IpkgComponent.EVENT_DOWNLOAD:
1338 self.status.setText(_("Downloading"))
1339 elif event == IpkgComponent.EVENT_UPGRADE:
1340 if self.sliderPackages.has_key(param):
1341 self.slider.setValue(self.sliderPackages[param])
1342 self.package.setText(param)
1343 self.status.setText(_("Upgrading"))
1345 elif event == IpkgComponent.EVENT_INSTALL:
1346 self.package.setText(param)
1347 self.status.setText(_("Installing"))
1349 elif event == IpkgComponent.EVENT_CONFIGURING:
1350 self.package.setText(param)
1351 self.status.setText(_("Configuring"))
1352 elif event == IpkgComponent.EVENT_MODIFIED:
1353 self.session.openWithCallback(
1354 self.modificationCallback,
1356 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1358 elif event == IpkgComponent.EVENT_ERROR:
1360 elif event == IpkgComponent.EVENT_DONE:
1362 self.updating = False
1363 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1364 elif self.error == 0:
1365 self.slider.setValue(4)
1367 self.activityTimer.stop()
1368 self.activityslider.setValue(0)
1370 self.package.setText("")
1371 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1373 self.activityTimer.stop()
1374 self.activityslider.setValue(0)
1375 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1376 if self.packages == 0:
1377 error = _("No packages were upgraded yet. So you can check your network and try again.")
1379 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1380 self.status.setText(_("Error") + " - " + error)
1381 #print event, "-", param
1384 def modificationCallback(self, res):
1385 self.ipkg.write(res and "N" or "Y")
1388 if not self.ipkg.isRunning():
1389 if self.packages != 0 and self.error == 0:
1390 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1394 def exitAnswer(self, result):
1395 if result is not None and result:
1400 class IpkgInstaller(Screen):
1402 <screen position="100,100" size="550,400" title="..." >
1403 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
1404 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
1405 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
1406 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
1407 <widget name="list" position="0,60" size="550,360" />
1411 def __init__(self, session, list):
1412 self.skin = IpkgInstaller.skin
1413 Screen.__init__(self, session)
1415 self.list = SelectionList()
1416 self["list"] = self.list
1417 for listindex in range(len(list)):
1418 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1420 self["red"] = Label()
1421 self["green"] = Label()
1422 self["yellow"] = Label()
1423 self["blue"] = Label()
1425 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1427 "ok": self.list.toggleSelection,
1428 "cancel": self.close,
1429 "green": self.install
1433 list = self.list.getSelectionsList()
1436 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1437 self.session.open(Ipkg, cmdList = cmdList)
1439 def filescan_open(list, session, **kwargs):
1440 filelist = [x.path for x in list]
1441 session.open(IpkgInstaller, filelist) # list
1443 def filescan(**kwargs):
1444 from Components.Scanner import Scanner, ScanPath
1446 Scanner(mimetypes = ["application/x-debian-package"],
1449 ScanPath(path = "ipk", with_subdirs = True),
1450 ScanPath(path = "", with_subdirs = False),
1453 description = _("Install software updates..."),
1454 openfnc = filescan_open, )
1458 def UpgradeMain(session, **kwargs):
1459 session.open(UpdatePluginMenu)
1461 def startSetup(menuid):
1462 if menuid != "setup":
1464 return [(_("Software manager"), UpgradeMain, "software_manager", 50)]
1466 def Plugins(path, **kwargs):
1470 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1471 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1473 if config.usage.setup_level.index >= 2: # expert+
1474 list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))