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())
330 self["closetext"] = Label(_("Cancel"))
331 self["edittext"] = Label(_("Save"))
334 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
336 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
338 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
344 "left": self.keyLeft,
345 "right": self.keyRight,
346 "home": self.keyHome,
348 "deleteForward": self.keyDeleteForward,
349 "deleteBackward": self.keyDeleteBackward,
350 "1": self.keyNumberGlobal,
351 "2": self.keyNumberGlobal,
352 "3": self.keyNumberGlobal,
353 "4": self.keyNumberGlobal,
354 "5": self.keyNumberGlobal,
355 "6": self.keyNumberGlobal,
356 "7": self.keyNumberGlobal,
357 "8": self.keyNumberGlobal,
358 "9": self.keyNumberGlobal,
359 "0": self.keyNumberGlobal
362 self.onLayoutFinish.append(self.layoutFinished)
364 def layoutFinished(self):
365 self.setWindowTitle()
368 def setWindowTitle(self):
369 self.setTitle(_("Edit IPKG source URL..."))
372 text = self["text"].getText()
374 fp = file(self.configfile, 'w')
392 def keyDeleteForward(self):
393 self["text"].delete()
395 def keyDeleteBackward(self):
396 self["text"].deleteBackward()
398 def keyNumberGlobal(self, number):
399 self["text"].number(number)
402 class PacketManager(Screen):
404 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
405 <widget source="list" render="Listbox" position="5,10" size="520,365" scrollbarMode="showOnDemand">
406 <convert type="TemplatedMultiContent">
408 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
409 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
410 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
411 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
413 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
418 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
419 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
420 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
421 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
424 def __init__(self, session, plugin_path, args = None):
425 Screen.__init__(self, session)
426 self.session = session
427 self.skin_path = plugin_path
429 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
434 "green": self.reload,
439 self["list"] = List(self.list)
440 self["closetext"] = Label(_("Close"))
441 self["reloadtext"] = Label(_("Reload"))
443 self.list_updating = True
445 self.installed_packetlist = {}
446 self.Console = Console()
449 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
450 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
451 self.oktext = _("\nAfter pressing OK, please wait!")
452 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
454 self.ipkg = IpkgComponent()
455 self.ipkg.addCallback(self.ipkgCallback)
456 self.onShown.append(self.setWindowTitle)
457 self.onLayoutFinish.append(self.rebuildList)
461 if self.Console is not None:
462 if len(self.Console.appContainers):
463 for name in self.Console.appContainers.keys():
464 self.Console.kill(name)
468 if (os_path.exists(self.cache_file) == True):
469 remove(self.cache_file)
470 self.list_updating = True
473 def setWindowTitle(self):
474 self.setTitle(_("Packet manager"))
476 def setStatus(self,status = None):
479 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
480 if status == 'update':
481 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgrade.png"))
482 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
483 self['list'].setList(self.statuslist)
484 elif status == 'error':
485 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/remove.png"))
486 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
487 self['list'].setList(self.statuslist)
489 def rebuildList(self):
490 self.setStatus('update')
492 self.vc = valid_cache(self.cache_file, self.cache_ttl)
493 if self.cache_ttl > 0 and self.vc != 0:
495 self.buildPacketList()
498 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
500 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
502 def go(self, returnValue = None):
503 cur = self["list"].getCurrent()
508 if status == 'installed':
509 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
510 if len(self.cmdList):
511 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
512 elif status == 'upgradeable':
513 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
514 if len(self.cmdList):
515 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
516 elif status == "installable":
517 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
518 if len(self.cmdList):
519 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
521 def runRemove(self, result):
523 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
525 def runRemoveFinished(self):
526 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
528 def RemoveReboot(self, result):
532 cur = self["list"].getCurrent()
534 item = self['list'].getIndex()
535 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
536 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
537 self['list'].setList(self.list)
538 write_cache(self.cache_file, self.cachelist)
539 self.reloadPluginlist()
543 def runUpgrade(self, result):
545 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
547 def runUpgradeFinished(self):
548 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
550 def UpgradeReboot(self, result):
554 cur = self["list"].getCurrent()
556 item = self['list'].getIndex()
557 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
558 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
559 self['list'].setList(self.list)
560 write_cache(self.cache_file, self.cachelist)
561 self.reloadPluginlist()
565 def ipkgCallback(self, event, param):
566 if event == IpkgComponent.EVENT_ERROR:
567 self.list_updating = False
568 self.setStatus('error')
569 elif event == IpkgComponent.EVENT_DONE:
570 if self.list_updating:
571 self.list_updating = False
573 self.Console = Console()
575 self.Console.ePopen(cmd, self.IpkgList_Finished)
576 #print event, "-", param
579 def IpkgList_Finished(self, result, retval, extra_args = None):
582 for x in result.splitlines():
583 split = x.split(' - ') #self.blacklisted_packages
584 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
585 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
587 self.Console = Console()
588 cmd = "ipkg list_installed"
589 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
591 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
593 self.installed_packetlist = {}
594 for x in result.splitlines():
595 split = x.split(' - ')
596 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
597 self.installed_packetlist[split[0].strip()] = split[1].strip()
598 self.buildPacketList()
600 def buildEntryComponent(self, name, version, description, state):
601 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
602 if state == 'installed':
603 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
604 return((name, version, description, state, installedpng, divpng))
605 elif state == 'upgradeable':
606 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
607 return((name, version, description, state, upgradeablepng, divpng))
609 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
610 return((name, version, description, state, installablepng, divpng))
612 def buildPacketList(self):
616 if self.cache_ttl > 0 and self.vc != 0:
617 print 'Loading packagelist cache from ',self.cache_file
619 self.cachelist = load_cache(self.cache_file)
620 if len(self.cachelist) > 0:
621 for x in self.cachelist:
622 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
623 self['list'].setList(self.list)
627 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
628 print 'rebuilding fresh package list'
629 for x in self.packetlist:
631 if self.installed_packetlist.has_key(x[0].strip()):
632 if self.installed_packetlist[x[0].strip()] == x[1].strip():
634 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
636 status = "upgradeable"
637 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
639 status = "installable"
640 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
641 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
642 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
643 write_cache(self.cache_file, self.cachelist)
644 self['list'].setList(self.list)
646 def reloadPluginlist(self):
647 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
650 class PluginManager(Screen, DreamInfoHandler):
652 lastDownloadDate = None
655 <screen position="80,80" size="560,440" title="Plugin manager..." >
656 <widget source="list" render="Listbox" position="5,5" size="550,360" scrollbarMode="showOnDemand">
657 <convert type="TemplatedMultiContent">
660 MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
661 MultiContentEntryText(pos = (30, 25), size = (470, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
662 MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap
663 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap
666 MultiContentEntryText(pos = (30, 0), size = (500, 23), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
667 MultiContentEntryText(pos = (30, 24), size = (500, 14), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description
668 MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap
671 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
676 <ePixmap pixmap="skin_default/buttons/red.png" position="0,370" zPosition="2" size="140,40" transparent="1" alphatest="on" />
677 <widget name="closetext" position="0,370" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
678 <ePixmap pixmap="skin_default/buttons/green.png" position="140,370" zPosition="2" size="140,40" transparent="1" alphatest="on" />
679 <widget name="installtext" position="140,370" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
680 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,370" zPosition="2" size="140,40" transparent="1" alphatest="on" />
681 <widget name="viewtext" position="280,370" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
682 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,370" zPosition="2" size="140,40" transparent="1" alphatest="on" />
683 <widget name="bluetext" position="420,370" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
684 <widget name="status" position="10,410" zPosition="10" size="540,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
687 def __init__(self, session, plugin_path, args = None):
688 Screen.__init__(self, session)
689 self.session = session
690 self.skin_path = plugin_path
691 aboutInfo = about.getImageVersionString()
692 if aboutInfo.startswith("dev-"):
693 self.ImageVersion = 'Experimental'
695 self.ImageVersion = 'Stable'
696 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
698 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
699 self.directory = resolveFilename(SCOPE_METADIR)
701 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ],
703 "ok": self.handleCurrent,
706 "green": self.handleCurrent,
707 "yellow": self.handleSelected,
708 "showEventInfo": self.handleSelected,
709 "displayHelp": self.handleHelp,
714 self.selectedFiles = []
715 self.categoryList = []
716 self["list"] = List(self.list)
717 self["closetext"] = Label(_("Close"))
718 self["installtext"] = Label()
719 self["viewtext"] = Label()
720 self["bluetext"] = Label()
721 self["status"] = Label()
723 self.list_updating = True
725 self.installed_packetlist = {}
726 self.available_packetlist = []
727 self.available_updates = 0
728 self.Console = Console()
730 self.oktext = _("\nAfter pressing OK, please wait!")
731 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
733 self.ipkg = IpkgComponent()
734 self.ipkg.addCallback(self.ipkgCallback)
735 if not self.selectionChanged in self["list"].onSelectionChanged:
736 self["list"].onSelectionChanged.append(self.selectionChanged)
738 self["installtext"].hide()
739 self["bluetext"].hide()
740 self["viewtext"].hide()
741 self["status"].hide()
743 self.currentSelectedTag = None
744 self.currentSelectedIndex = None
746 self.onShown.append(self.setWindowTitle)
747 self.onLayoutFinish.append(self.rebuildList)
749 def setWindowTitle(self):
750 self.setTitle(_("Plugin manager"))
753 if self.currList == "packages":
754 self.currList = "category"
755 self.currentSelectedTag = None
756 self["list"].style = "category"
757 self['list'].setList(self.categoryList)
758 self["list"].setIndex(self.currentSelectedIndex)
759 self["list"].updateList(self.categoryList)
760 self.selectionChanged()
763 if self.Console is not None:
764 if len(self.Console.appContainers):
765 for name in self.Console.appContainers.keys():
766 self.Console.kill(name)
767 if len(self.cmdList) and len(self.selectedFiles):
768 self.session.openWithCallback(self.runInstall, PluginManagerInfo, self.skin_path, self.cmdList)
769 elif not len(self.cmdList) and self.available_updates > 0:
771 self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False }))
772 self.session.openWithCallback(self.runInstall, PluginManagerInfo, self.skin_path, self.cmdList)
776 def handleHelp(self):
777 if self.currList != "status":
778 self.session.open(PluginManagerHelp, self.skin_path)
780 def runInstall(self, result):
782 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
786 def setState(self,status = None):
788 self.currList = "status"
790 self["installtext"].hide()
791 self["bluetext"].hide()
792 self["viewtext"].hide()
793 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
794 if status == 'update':
795 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgrade.png"))
796 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' ))
797 self["list"].style = "default"
798 self['list'].setList(self.statuslist)
799 elif status == 'sync':
800 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgrade.png"))
801 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
802 self["list"].style = "default"
803 self['list'].setList(self.statuslist)
804 elif status == 'error':
805 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/remove.png"))
806 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
807 self["list"].style = "default"
808 self['list'].setList(self.statuslist)
810 def statusCallback(self, status, progress):
813 def selectionChanged(self):
814 current = self["list"].getCurrent()
815 self["status"].hide()
817 if self.currList == "packages":
818 self["closetext"].setText(_("Back"))
819 if current[4] == 'installed':
820 self["installtext"].setText(_("Remove"))
821 elif current[4] == 'installable':
822 self["installtext"].setText(_("Install"))
823 elif current[4] == 'remove':
824 self["installtext"].setText(_("Undo\nRemove"))
825 elif current[4] == 'install':
826 self["installtext"].setText(_("Undo\nInstall"))
827 self["installtext"].show()
828 self["viewtext"].setText(_("View details"))
829 self["viewtext"].show()
830 self["bluetext"].hide()
831 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
832 self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
833 self["status"].show()
834 elif len(self.selectedFiles) is not 0:
835 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
836 self["status"].show()
837 elif self.currList == "category":
838 self["closetext"].setText(_("Close"))
839 self["installtext"].hide()
840 self["bluetext"].hide()
841 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
842 self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
843 self["status"].show()
844 self["viewtext"].setText(_("Update"))
845 self["viewtext"].show()
846 elif len(self.selectedFiles) is not 0:
847 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
848 self["status"].show()
849 self["viewtext"].setText(_("Process"))
850 self["viewtext"].show()
851 self["closetext"].show()
853 def getSelectionState(self, detailsFile):
854 for entry in self.selectedFiles:
855 if entry[0] == detailsFile:
859 def rebuildList(self):
860 self.setState('update')
861 if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600:
862 # Only update from internet once per hour
863 PluginManager.lastDownloadDate = time()
864 print "last update time > 1h"
865 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
867 print "last update time < 1h"
870 def ipkgCallback(self, event, param):
871 if event == IpkgComponent.EVENT_ERROR:
872 self.list_updating = False
873 self.setState('error')
874 elif event == IpkgComponent.EVENT_DONE:
878 def startIpkgList(self):
879 if self.list_updating:
881 self.Console = Console()
883 self.Console.ePopen(cmd, self.IpkgList_Finished)
885 def IpkgList_Finished(self, result, retval, extra_args = None):
887 self.available_packetlist = []
888 for x in result.splitlines():
889 split = x.split(' - ')
890 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
891 self.available_packetlist.append([split[0].strip(), split[1].strip(), split[2].strip()])
892 self.startInstallMetaPackage()
894 def startInstallMetaPackage(self):
895 if self.list_updating:
896 self.list_updating = False
898 self.Console = Console()
899 cmd = "ipkg install enigma2-meta" #dummy,will change probably"
900 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
902 def InstallMetaPackage_Finished(self, result, retval, extra_args = None):
904 self.fillPackagesIndexList()
906 self.Console = Console()
907 self.setState('sync')
908 cmd = "ipkg list_installed"
909 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
911 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
913 self.installed_packetlist = {}
914 for x in result.splitlines():
915 split = x.split(' - ')
916 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
917 self.installed_packetlist[split[0].strip()] = split[1].strip()
919 if self.currentSelectedTag is None:
920 self.buildCategoryList()
922 self.buildPacketList(self.currentSelectedTag)
924 def countUpdates(self):
925 self.available_updates = 0
926 for package in self.packagesIndexlist[:]:
927 attributes = package[0]["attributes"]
928 packagename = attributes["packagename"]
929 for x in self.available_packetlist:
930 if x[0].strip() == packagename:
931 if self.installed_packetlist.has_key(packagename):
932 if self.installed_packetlist[packagename] != x[1].strip():
933 self.available_updates +=1
935 def handleCurrent(self):
936 current = self["list"].getCurrent()
938 if self.currList == "category":
939 self.currentSelectedIndex = self["list"].index
940 selectedTag = current[2]
941 self.buildPacketList(selectedTag)
942 elif self.currList == "packages":
943 if current[7] is not '':
944 idx = self["list"].getIndex()
945 detailsFile = self.list[idx][1]
946 if self.list[idx][7] == True:
947 for entry in self.selectedFiles:
948 if entry[0] == detailsFile:
949 self.selectedFiles.remove(entry)
951 alreadyinList = False
952 for entry in self.selectedFiles:
953 if entry[0] == detailsFile:
955 if not alreadyinList:
956 self.selectedFiles.append((detailsFile,current[4],current[3]))
957 if current[4] == 'installed':
958 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True)
959 elif current[4] == 'installable':
960 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
961 elif current[4] == 'remove':
962 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False)
963 elif current[4] == 'install':
964 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
965 self["list"].setList(self.list)
966 self["list"].setIndex(idx)
967 self["list"].updateList(self.list)
968 self.selectionChanged()
970 def handleSelected(self):
971 current = self["list"].getCurrent()
973 if self.currList == "packages":
974 if current[7] is not '':
975 detailsfile = self.directory[0] + "/" + current[1]
976 if (os_path.exists(detailsfile) == True):
977 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
979 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO)
980 elif self.currList == "category":
981 self.installPlugins()
983 def detailsClosed(self, result):
986 self.Console = Console()
987 self.setState('sync')
988 PluginManager.lastDownloadDate = time()
989 self.selectedFiles = []
991 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
993 def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
994 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
995 if state == 'installed':
996 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
997 return((name, details, description, packagename, state, installedpng, divpng, selected))
998 elif state == 'installable':
999 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
1000 return((name, details, description, packagename, state, installablepng, divpng, selected))
1001 elif state == 'remove':
1002 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/remove.png"))
1003 return((name, details, description, packagename, state, removepng, divpng, selected))
1004 elif state == 'install':
1005 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/install.png"))
1006 return((name, details, description, packagename, state, installpng, divpng, selected))
1008 def buildPacketList(self, categorytag = None):
1009 if categorytag is not None:
1010 self.currList = "packages"
1011 self.currentSelectedTag = categorytag
1012 self.packetlist = []
1013 for package in self.packagesIndexlist[:]:
1014 prerequisites = package[0]["prerequisites"]
1015 if prerequisites.has_key("tag"):
1016 for foundtag in prerequisites["tag"]:
1017 if categorytag == foundtag:
1018 attributes = package[0]["attributes"]
1019 if attributes.has_key("packagetype"):
1020 if attributes["packagetype"] == "internal":
1022 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1024 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1026 for x in self.packetlist:
1028 selectState = self.getSelectionState(x[1].strip())
1029 if self.installed_packetlist.has_key(x[3].strip()):
1030 if selectState == True:
1033 status = "installed"
1034 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1036 if selectState == True:
1039 status = "installable"
1040 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1042 self.list.sort(key=lambda x: x[0])
1043 self["list"].style = "default"
1044 self['list'].setList(self.list)
1045 self["list"].updateList(self.list)
1046 self.selectionChanged()
1048 def buildCategoryList(self):
1049 self.currList = "category"
1050 self.categories = []
1051 self.categoryList = []
1052 for package in self.packagesIndexlist[:]:
1053 prerequisites = package[0]["prerequisites"]
1054 if prerequisites.has_key("tag"):
1055 for foundtag in prerequisites["tag"]:
1056 attributes = package[0]["attributes"]
1057 if foundtag not in self.categories:
1058 self.categories.append(foundtag)
1059 self.categoryList.append(self.buildCategoryComponent(foundtag))
1060 self.categoryList.sort(key=lambda x: x[0])
1061 self["list"].style = "category"
1062 self['list'].setList(self.categoryList)
1063 self["list"].updateList(self.categoryList)
1064 self.selectionChanged()
1066 def buildCategoryComponent(self, tag = None):
1067 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
1070 return(( _("System"), _("View list of available system extensions" ), tag, divpng ))
1072 return(( _("Skins"), _("View list of available skins" ), tag, divpng ))
1073 elif tag == 'Recording':
1074 return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng ))
1075 elif tag == 'Network':
1076 return(( _("Network"), _("View list of available networking extensions" ), tag, divpng ))
1078 return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng ))
1079 elif tag == 'Default':
1080 return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng ))
1082 return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng ))
1083 elif tag == 'Software':
1084 return(( _("Software"), _("View list of available software extensions" ), tag, divpng ))
1085 elif tag == 'Multimedia':
1086 return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng ))
1087 elif tag == 'Display':
1088 return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng ))
1090 return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng ))
1091 elif tag == 'Communication':
1092 return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng ))
1093 else: # dynamically generate non existent tags
1094 return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng ))
1096 def installPlugins(self):
1098 if self.available_updates > 0:
1099 self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False }))
1100 if self.selectedFiles and len(self.selectedFiles):
1101 for plugin in self.selectedFiles:
1102 detailsfile = self.directory[0] + "/" + plugin[0]
1103 if (os_path.exists(detailsfile) == True):
1104 self.fillPackageDetails(plugin[0])
1105 self.package = self.packageDetails[0]
1106 if self.package[0].has_key("attributes"):
1107 self.attributes = self.package[0]["attributes"]
1108 if self.attributes.has_key("package"):
1109 self.packagefiles = self.attributes["package"]
1110 if plugin[1] == 'installed':
1111 if self.packagefiles:
1112 for package in self.packagefiles[:]:
1113 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1115 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1117 if self.packagefiles:
1118 for package in self.packagefiles[:]:
1119 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1121 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1123 if plugin[1] == 'installed':
1124 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1126 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1127 if len(self.cmdList):
1128 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
1130 def runExecute(self, result):
1132 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
1134 def runExecuteFinished(self):
1135 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1137 def ExecuteReboot(self, result):
1141 self.reloadPluginlist()
1142 self.detailsClosed(True)
1146 def reloadPluginlist(self):
1147 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1150 class PluginManagerInfo(Screen):
1152 <screen position="80,80" size="560,450" title="Plugin manager job information..." >
1153 <widget name="status" position="5,5" zPosition="10" size="540,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1154 <ePixmap pixmap="skin_default/div-h.png" position="0,35" zPosition="10" size="550,2" transparent="1" alphatest="on" />
1155 <widget source="list" render="Listbox" position="5,45" size="550,360" scrollbarMode="showOnDemand" selectionDisabled="1">
1156 <convert type="TemplatedMultiContent">
1158 MultiContentEntryText(pos = (50, 1), size = (150, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1159 MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1160 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1161 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1163 "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1168 <ePixmap pixmap="skin_default/buttons/red.png" position="0,410" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1169 <widget name="closetext" position="0,410" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1170 <ePixmap pixmap="skin_default/buttons/green.png" position="140,410" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1171 <widget name="continuetext" position="140,410" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1174 def __init__(self, session, plugin_path, cmdlist = None):
1175 Screen.__init__(self, session)
1176 self.session = session
1177 self.skin_path = plugin_path
1178 self.cmdlist = cmdlist
1180 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1185 "green": self.process,
1189 self["list"] = List(self.list)
1190 self["closetext"] = Label(_("Cancel"))
1191 self["continuetext"] = Label(_("Continue"))
1192 self["status"] = Label(_("Following tasks will be done after you press continue."))
1194 self.onShown.append(self.setWindowTitle)
1195 self.onLayoutFinish.append(self.rebuildList)
1197 def setWindowTitle(self):
1198 self.setTitle(_("Plugin manager process information..."))
1200 def rebuildList(self):
1202 if self.cmdlist is not None:
1203 for entry in self.cmdlist:
1214 info = args['package']
1216 info = args['package']
1218 info = _("Dreambox software because updates are available.")
1220 self.list.append(self.buildEntryComponent(action,info))
1221 self['list'].setList(self.list)
1222 self['list'].updateList(self.list)
1224 def buildEntryComponent(self, action,info):
1225 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
1226 upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgrade.png"))
1227 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/install.png"))
1228 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/remove.png"))
1229 if action == 'install':
1230 return(( _('Installing'), info, installpng, divpng))
1231 elif action == 'remove':
1232 return(( _('Remove'), info, removepng, divpng))
1234 return(( _('Upgrade'), info, upgradepng, divpng))
1243 class PluginManagerHelp(Screen):
1245 <screen position="80,80" size="560,450" title="Plugin manager help..." >
1246 <widget name="status" position="5,5" zPosition="10" size="540,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1247 <ePixmap pixmap="skin_default/div-h.png" position="0,35" zPosition="10" size="550,2" transparent="1" alphatest="on" />
1248 <widget source="list" render="Listbox" position="5,45" size="550,360" scrollbarMode="showOnDemand" selectionDisabled="1">
1249 <convert type="TemplatedMultiContent">
1251 MultiContentEntryText(pos = (50, 1), size = (540, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1252 MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1253 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1254 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1256 "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1261 <ePixmap pixmap="skin_default/buttons/red.png" position="0,410" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1262 <widget name="closetext" position="0,410" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1265 def __init__(self, session, plugin_path):
1266 Screen.__init__(self, session)
1267 self.session = session
1268 self.skin_path = plugin_path
1270 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1277 self["list"] = List(self.list)
1278 self["closetext"] = Label(_("Close"))
1279 self["status"] = Label(_("Here is a small overview of the available icon states."))
1281 self.onShown.append(self.setWindowTitle)
1282 self.onLayoutFinish.append(self.rebuildList)
1284 def setWindowTitle(self):
1285 self.setTitle(_("Plugin manager help..."))
1287 def rebuildList(self):
1289 self.list.append(self.buildEntryComponent('install'))
1290 self.list.append(self.buildEntryComponent('installable'))
1291 self.list.append(self.buildEntryComponent('installed'))
1292 self.list.append(self.buildEntryComponent('remove'))
1293 self['list'].setList(self.list)
1294 self['list'].updateList(self.list)
1296 def buildEntryComponent(self, state):
1297 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
1298 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
1299 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
1300 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/remove.png"))
1301 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/install.png"))
1303 if state == 'installed':
1304 return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng))
1305 elif state == 'installable':
1306 return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng))
1307 elif state == 'install':
1308 return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng))
1309 elif state == 'remove':
1310 return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng))
1316 class PluginDetails(Screen, DreamInfoHandler):
1318 <screen name="PluginDetails" position="60,90" size="600,420" title="PluginDetails..." >
1319 <widget name="author" position="10,10" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
1320 <widget name="statuspic" position="550,0" size="48,48" alphatest="on"/>
1321 <widget name="divpic" position="0,40" size="600,2" alphatest="on"/>
1322 <widget name="detailtext" position="10,50" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1323 <widget name="screenshot" position="290,50" size="300,330" alphatest="on"/>
1324 <ePixmap pixmap="skin_default/buttons/red.png" position="0,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1325 <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" />
1326 <ePixmap pixmap="skin_default/buttons/green.png" position="140,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1327 <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" />
1329 def __init__(self, session, plugin_path, packagedata = None):
1330 Screen.__init__(self, session)
1331 self.skin_path = plugin_path
1332 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
1333 self.attributes = None
1334 self.translatedAttributes = None
1335 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
1336 self.directory = resolveFilename(SCOPE_METADIR)
1338 self.pluginname = packagedata[0]
1339 self.details = packagedata[1]
1340 self.pluginstate = packagedata[4]
1341 self.statuspicinstance = packagedata[5]
1342 self.divpicinstance = packagedata[6]
1343 self.fillPackageDetails(self.details)
1347 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1353 "down": self.pageDown,
1354 "left": self.pageUp,
1355 "right": self.pageDown,
1358 self["statuspic"] = Pixmap()
1359 self["divpic"] = Pixmap()
1360 self["screenshot"] = Pixmap()
1361 self["closetext"] = Label(_("Close"))
1362 self["statetext"] = Label()
1363 self["detailtext"] = ScrollLabel()
1364 self["author"] = Label()
1365 self["statuspic"].hide()
1366 self["screenshot"].hide()
1367 self["divpic"].hide()
1369 self.package = self.packageDetails[0]
1370 if self.package[0].has_key("attributes"):
1371 self.attributes = self.package[0]["attributes"]
1372 if self.package[0].has_key("translation"):
1373 self.translatedAttributes = self.package[0]["translation"]
1376 self.oktext = _("\nAfter pressing OK, please wait!")
1377 self.picload = ePicLoad()
1378 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
1379 self.onShown.append(self.setWindowTitle)
1380 self.onLayoutFinish.append(self.setInfos)
1382 def setWindowTitle(self):
1383 self.setTitle(_("Package details for: " + self.pluginname))
1389 self["detailtext"].pageUp()
1392 self["detailtext"].pageDown()
1394 def statusCallback(self, status, progress):
1398 if self.translatedAttributes.has_key("name"):
1399 self.pluginname = self.translatedAttributes["name"]
1400 elif self.attributes.has_key("name"):
1401 self.pluginname = self.attributes["name"]
1403 self.pluginname = _("unknown")
1405 if self.translatedAttributes.has_key("author"):
1406 self.author = self.translatedAttributes["author"]
1407 elif self.attributes.has_key("author"):
1408 self.author = self.attributes["author"]
1410 self.author = _("unknown")
1412 if self.translatedAttributes.has_key("description"):
1413 self.description = self.translatedAttributes["description"]
1414 elif self.attributes.has_key("description"):
1415 self.description = self.attributes["description"]
1417 self.description = _("No description available.")
1419 if self.translatedAttributes.has_key("screenshot"):
1420 self.loadThumbnail(self.translatedAttributes)
1422 self.loadThumbnail(self.attributes)
1424 self["author"].setText(_("Author: ") + self.author)
1425 self["detailtext"].setText(self.description.strip())
1426 if self.pluginstate == 'installable':
1427 self["statetext"].setText(_("Install"))
1429 self["statetext"].setText(_("Remove"))
1431 def loadThumbnail(self, entry):
1433 if entry.has_key("screenshot"):
1434 thumbnailUrl = entry["screenshot"]
1435 if thumbnailUrl is not None:
1436 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1437 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1438 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1440 self.setThumbnail(noScreenshot = True)
1442 def setThumbnail(self, noScreenshot = False):
1443 if not noScreenshot:
1444 filename = self.thumbnail
1446 filename = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/noprev.png")
1448 sc = AVSwitch().getFramebufferScale()
1449 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1450 self.picload.startDecode(filename)
1452 if self.statuspicinstance != None:
1453 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1454 self["statuspic"].show()
1455 if self.divpicinstance != None:
1456 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1457 self["divpic"].show()
1459 def paintScreenshotPixmapCB(self, picInfo=None):
1460 ptr = self.picload.getData()
1462 self["screenshot"].instance.setPixmap(ptr.__deref__())
1463 self["screenshot"].show()
1465 self.setThumbnail(noScreenshot = True)
1468 if self.attributes.has_key("package"):
1469 self.packagefiles = self.attributes["package"]
1471 if self.pluginstate == 'installed':
1472 if self.packagefiles:
1473 for package in self.packagefiles[:]:
1474 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1475 if len(self.cmdList):
1476 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1478 if self.packagefiles:
1479 for package in self.packagefiles[:]:
1480 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1481 if len(self.cmdList):
1482 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1484 def runUpgrade(self, result):
1486 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1488 def runUpgradeFinished(self):
1489 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1491 def UpgradeReboot(self, result):
1499 def runRemove(self, result):
1501 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1503 def runRemoveFinished(self):
1504 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1506 def RemoveReboot(self, result):
1514 def reloadPluginlist(self):
1515 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1517 def fetchFailed(self,string):
1518 self.setThumbnail(noScreenshot = True)
1519 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1522 class UpdatePlugin(Screen):
1524 <screen position="100,100" size="550,200" title="Software Update..." >
1525 <widget name="activityslider" position="0,0" size="550,5" />
1526 <widget name="slider" position="0,100" size="550,30" />
1527 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
1528 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
1531 def __init__(self, session, args = None):
1532 self.skin = UpdatePlugin.skin
1533 Screen.__init__(self, session)
1535 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1537 self.slider = Slider(0, 4)
1538 self["slider"] = self.slider
1539 self.activityslider = Slider(0, 100)
1540 self["activityslider"] = self.activityslider
1541 self.status = Label(_("Upgrading Dreambox... Please wait"))
1542 self["status"] = self.status
1543 self.package = Label()
1544 self["package"] = self.package
1550 self.activityTimer = eTimer()
1551 self.activityTimer.callback.append(self.doActivityTimer)
1552 self.activityTimer.start(100, False)
1554 self.ipkg = IpkgComponent()
1555 self.ipkg.addCallback(self.ipkgCallback)
1557 self.updating = True
1558 self.package.setText(_("Package list update"))
1559 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1561 self["actions"] = ActionMap(["WizardActions"],
1567 def doActivityTimer(self):
1569 if self.activity == 100:
1571 self.activityslider.setValue(self.activity)
1573 def ipkgCallback(self, event, param):
1574 if event == IpkgComponent.EVENT_DOWNLOAD:
1575 self.status.setText(_("Downloading"))
1576 elif event == IpkgComponent.EVENT_UPGRADE:
1577 if self.sliderPackages.has_key(param):
1578 self.slider.setValue(self.sliderPackages[param])
1579 self.package.setText(param)
1580 self.status.setText(_("Upgrading"))
1582 elif event == IpkgComponent.EVENT_INSTALL:
1583 self.package.setText(param)
1584 self.status.setText(_("Installing"))
1586 elif event == IpkgComponent.EVENT_CONFIGURING:
1587 self.package.setText(param)
1588 self.status.setText(_("Configuring"))
1589 elif event == IpkgComponent.EVENT_MODIFIED:
1590 self.session.openWithCallback(
1591 self.modificationCallback,
1593 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1595 elif event == IpkgComponent.EVENT_ERROR:
1597 elif event == IpkgComponent.EVENT_DONE:
1599 self.updating = False
1600 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1601 elif self.error == 0:
1602 self.slider.setValue(4)
1604 self.activityTimer.stop()
1605 self.activityslider.setValue(0)
1607 self.package.setText("")
1608 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1610 self.activityTimer.stop()
1611 self.activityslider.setValue(0)
1612 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1613 if self.packages == 0:
1614 error = _("No packages were upgraded yet. So you can check your network and try again.")
1616 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1617 self.status.setText(_("Error") + " - " + error)
1618 #print event, "-", param
1621 def modificationCallback(self, res):
1622 self.ipkg.write(res and "N" or "Y")
1625 if not self.ipkg.isRunning():
1626 if self.packages != 0 and self.error == 0:
1627 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1631 def exitAnswer(self, result):
1632 if result is not None and result:
1637 class IpkgInstaller(Screen):
1639 <screen position="100,100" size="550,400" title="..." >
1640 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
1641 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
1642 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
1643 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
1644 <widget name="list" position="0,60" size="550,360" />
1648 def __init__(self, session, list):
1649 self.skin = IpkgInstaller.skin
1650 Screen.__init__(self, session)
1652 self.list = SelectionList()
1653 self["list"] = self.list
1654 for listindex in range(len(list)):
1655 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1657 self["red"] = Label()
1658 self["green"] = Label()
1659 self["yellow"] = Label()
1660 self["blue"] = Label()
1662 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1664 "ok": self.list.toggleSelection,
1665 "cancel": self.close,
1666 "green": self.install
1670 list = self.list.getSelectionsList()
1673 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1674 self.session.open(Ipkg, cmdList = cmdList)
1676 def filescan_open(list, session, **kwargs):
1677 filelist = [x.path for x in list]
1678 session.open(IpkgInstaller, filelist) # list
1680 def filescan(**kwargs):
1681 from Components.Scanner import Scanner, ScanPath
1683 Scanner(mimetypes = ["application/x-debian-package"],
1686 ScanPath(path = "ipk", with_subdirs = True),
1687 ScanPath(path = "", with_subdirs = False),
1690 description = _("Install software updates..."),
1691 openfnc = filescan_open, )
1695 def UpgradeMain(session, **kwargs):
1696 session.open(UpdatePluginMenu)
1698 def startSetup(menuid):
1699 if menuid != "setup":
1701 return [(_("Software manager"), UpgradeMain, "software_manager", 50)]
1703 def Plugins(path, **kwargs):
1707 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1708 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1710 if config.usage.setup_level.index >= 2: # expert+
1711 list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))