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.Sources.StaticText import StaticText
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_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, 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="center,center" size="560,400" title="Software manager" >
78 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
79 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
80 <ePixmap pixmap="skin_default/border_menu_300.png" position="5,50" zPosition="1" size="300,300" transparent="1" alphatest="on" />
81 <widget source="menu" render="Listbox" position="10,60" size="290,260" scrollbarMode="showOnDemand">
82 <convert type="TemplatedMultiContent">
84 MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
86 "fonts": [gFont("Regular", 20)],
91 <widget source="menu" render="Listbox" position="310,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
92 <convert type="TemplatedMultiContent">
94 MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
96 "fonts": [gFont("Regular", 20)],
103 def __init__(self, session, args = 0):
104 Screen.__init__(self, session)
105 self.skin_path = plugin_path
108 self.oktext = _("\nPress OK on your remote control to continue.")
109 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
111 self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None))
112 #self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext, None))
113 self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None))
114 self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None))
115 self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None))
116 self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local packages and install them." ) + self.oktext, None))
117 for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
118 if p.__call__.has_key("SoftwareSupported"):
119 callFnc = p.__call__["SoftwareSupported"](None)
120 if callFnc is not None:
121 if p.__call__.has_key("menuEntryName"):
122 menuEntryName = p.__call__["menuEntryName"](None)
124 menuEntryName = _('Extended Software')
125 if p.__call__.has_key("menuEntryDescription"):
126 menuEntryDescription = p.__call__["menuEntryDescription"](None)
128 menuEntryDescription = _('Extended Software Plugin')
129 self.list.append(('default-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
130 if config.usage.setup_level.index >= 2: # expert+
131 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext, None))
133 self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None))
134 self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None))
135 self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None))
136 if config.usage.setup_level.index >= 2: # expert+
137 self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None))
138 self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None))
139 for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
140 if p.__call__.has_key("AdvancedSoftwareSupported"):
141 callFnc = p.__call__["AdvancedSoftwareSupported"](None)
142 if callFnc is not None:
143 if p.__call__.has_key("menuEntryName"):
144 menuEntryName = p.__call__["menuEntryName"](None)
146 menuEntryName = _('Advanced Software')
147 if p.__call__.has_key("menuEntryDescription"):
148 menuEntryDescription = p.__call__["menuEntryDescription"](None)
150 menuEntryDescription = _('Advanced Software Plugin')
151 self.list.append(('advanced-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
153 self["menu"] = List(self.list)
154 self["key_red"] = StaticText(_("Close"))
156 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
163 self.onLayoutFinish.append(self.layoutFinished)
164 self.backuppath = getBackupPath()
165 self.backupfile = getBackupFilename()
166 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
167 self.onShown.append(self.setWindowTitle)
169 def layoutFinished(self):
171 self["menu"].index = idx
173 def setWindowTitle(self):
174 self.setTitle(_("Software manager"))
177 current = self["menu"].getCurrent()
179 currentEntry = current[0]
181 if (currentEntry == "software-update"):
182 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
183 elif (currentEntry == "software-restore"):
184 self.session.open(ImageWizard)
185 elif (currentEntry == "install-plugins"):
186 self.session.open(PluginManager, self.skin_path)
187 elif (currentEntry == "system-backup"):
188 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
189 elif (currentEntry == "system-restore"):
190 if os_path.exists(self.fullbackupfilename):
191 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
193 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO, timeout = 10)
194 elif (currentEntry == "ipkg-install"):
196 from Plugins.Extensions.MediaScanner.plugin import main
199 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO, timeout = 10)
200 elif (currentEntry == "default-plugin"):
201 self.extended = current[3]
202 self.extended(self.session, None)
203 elif (currentEntry == "advanced"):
204 self.session.open(UpdatePluginMenu, 1)
206 if (currentEntry == "ipkg-manager"):
207 self.session.open(PacketManager, self.skin_path)
208 elif (currentEntry == "backuplocation"):
209 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
211 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
214 if x[1].startswith('/autofs/'):
217 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
218 elif (currentEntry == "backupfiles"):
219 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
220 elif (currentEntry == "advancedrestore"):
221 self.session.open(RestoreMenu, self.skin_path)
222 elif (currentEntry == "ipkg-source"):
223 self.session.open(IPKGMenu, self.skin_path)
224 elif (currentEntry == "advanced-plugin"):
225 self.extended = current[3]
226 self.extended(self.session, None)
228 def backupfiles_choosen(self, ret):
229 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
231 def backuplocation_choosen(self, option):
232 if option is not None:
233 config.plugins.configurationbackup.backuplocation.value = str(option[1])
234 config.plugins.configurationbackup.backuplocation.save()
235 config.plugins.configurationbackup.save()
237 self.createBackupfolders()
239 def runUpgrade(self, result):
241 self.session.open(UpdatePlugin, self.skin_path)
243 def createBackupfolders(self):
244 print "Creating backup folder if not already there..."
245 self.backuppath = getBackupPath()
247 if (os_path.exists(self.backuppath) == False):
248 makedirs(self.backuppath)
250 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO, timeout = 10)
252 def backupDone(self,retval = None):
254 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO, timeout = 10)
256 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO, timeout = 10)
258 def startRestore(self, ret = False):
261 self.session.open(RestoreScreen, runRestore = True)
263 class IPKGMenu(Screen):
265 <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." >
266 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
267 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
268 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
269 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
270 <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" />
273 def __init__(self, session, plugin_path):
274 Screen.__init__(self, session)
275 self.skin_path = plugin_path
277 self["key_red"] = StaticText(_("Close"))
278 self["key_green"] = StaticText(_("Edit"))
287 self["actions"] = NumberActionMap(["SetupActions"],
290 "cancel": self.keyCancel
293 self["shortcuts"] = ActionMap(["ShortcutActions"],
295 "red": self.keyCancel,
299 self["filelist"] = MenuList(self.flist)
301 self.onLayoutFinish.append(self.layoutFinished)
303 def layoutFinished(self):
304 self.setWindowTitle()
306 def setWindowTitle(self):
307 self.setTitle(_("Select upgrade source to edit."))
311 self.path = '/etc/ipkg/'
312 if (os_path.exists(self.path) == False):
315 for file in listdir(self.path):
316 if (file.endswith(".conf")):
317 if file != 'arch.conf':
318 self.flist.append((file))
320 self["filelist"].l.setList(self.flist)
323 if (self.exe == False) and (self.entry == True):
324 self.sel = self["filelist"].getCurrent()
325 self.val = self.path + self.sel
326 self.session.open(IPKGSource, self.val)
335 class IPKGSource(Screen):
337 <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." >
338 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
339 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
340 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
341 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
342 <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
345 def __init__(self, session, configfile = None):
346 Screen.__init__(self, session)
347 self.session = session
348 self.configfile = configfile
352 fp = file(configfile, 'r')
353 sources = fp.readlines()
361 x= int(desk.size().width())
362 y= int(desk.size().height())
364 self["key_red"] = StaticText(_("Cancel"))
365 self["key_green"] = StaticText(_("Save"))
368 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
370 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
372 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
378 "left": self.keyLeft,
379 "right": self.keyRight,
380 "home": self.keyHome,
382 "deleteForward": self.keyDeleteForward,
383 "deleteBackward": self.keyDeleteBackward,
384 "1": self.keyNumberGlobal,
385 "2": self.keyNumberGlobal,
386 "3": self.keyNumberGlobal,
387 "4": self.keyNumberGlobal,
388 "5": self.keyNumberGlobal,
389 "6": self.keyNumberGlobal,
390 "7": self.keyNumberGlobal,
391 "8": self.keyNumberGlobal,
392 "9": self.keyNumberGlobal,
393 "0": self.keyNumberGlobal
396 self.onLayoutFinish.append(self.layoutFinished)
398 def layoutFinished(self):
399 self.setWindowTitle()
402 def setWindowTitle(self):
403 self.setTitle(_("Edit upgrade source url."))
406 text = self["text"].getText()
408 fp = file(self.configfile, 'w')
426 def keyDeleteForward(self):
427 self["text"].delete()
429 def keyDeleteBackward(self):
430 self["text"].deleteBackward()
432 def keyNumberGlobal(self, number):
433 self["text"].number(number)
436 class PacketManager(Screen):
438 <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
439 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
440 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
441 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
442 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
443 <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand">
444 <convert type="TemplatedMultiContent">
446 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
447 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
448 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
449 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
451 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
458 def __init__(self, session, plugin_path, args = None):
459 Screen.__init__(self, session)
460 self.session = session
461 self.skin_path = plugin_path
463 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
468 "green": self.reload,
473 self["list"] = List(self.list)
474 self["key_red"] = StaticText(_("Close"))
475 self["key_green"] = StaticText(_("Reload"))
477 self.list_updating = True
479 self.installed_packetlist = {}
480 self.Console = Console()
483 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
484 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
485 self.oktext = _("\nAfter pressing OK, please wait!")
486 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
488 self.ipkg = IpkgComponent()
489 self.ipkg.addCallback(self.ipkgCallback)
490 self.onShown.append(self.setWindowTitle)
491 self.onLayoutFinish.append(self.rebuildList)
495 if self.Console is not None:
496 if len(self.Console.appContainers):
497 for name in self.Console.appContainers.keys():
498 self.Console.kill(name)
502 if (os_path.exists(self.cache_file) == True):
503 remove(self.cache_file)
504 self.list_updating = True
507 def setWindowTitle(self):
508 self.setTitle(_("Packet manager"))
510 def setStatus(self,status = None):
513 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
514 if status == 'update':
515 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
516 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
517 self['list'].setList(self.statuslist)
518 elif status == 'error':
519 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
520 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
521 self['list'].setList(self.statuslist)
523 def rebuildList(self):
524 self.setStatus('update')
526 self.vc = valid_cache(self.cache_file, self.cache_ttl)
527 if self.cache_ttl > 0 and self.vc != 0:
529 self.buildPacketList()
532 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
534 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
536 def go(self, returnValue = None):
537 cur = self["list"].getCurrent()
542 if status == 'installed':
543 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
544 if len(self.cmdList):
545 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
546 elif status == 'upgradeable':
547 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
548 if len(self.cmdList):
549 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
550 elif status == "installable":
551 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
552 if len(self.cmdList):
553 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
555 def runRemove(self, result):
557 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
559 def runRemoveFinished(self):
560 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
562 def RemoveReboot(self, result):
566 cur = self["list"].getCurrent()
568 item = self['list'].getIndex()
569 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
570 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
571 self['list'].setList(self.list)
572 write_cache(self.cache_file, self.cachelist)
573 self.reloadPluginlist()
577 def runUpgrade(self, result):
579 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
581 def runUpgradeFinished(self):
582 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
584 def UpgradeReboot(self, result):
588 cur = self["list"].getCurrent()
590 item = self['list'].getIndex()
591 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
592 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
593 self['list'].setList(self.list)
594 write_cache(self.cache_file, self.cachelist)
595 self.reloadPluginlist()
599 def ipkgCallback(self, event, param):
600 if event == IpkgComponent.EVENT_ERROR:
601 self.list_updating = False
602 self.setStatus('error')
603 elif event == IpkgComponent.EVENT_DONE:
604 if self.list_updating:
605 self.list_updating = False
607 self.Console = Console()
609 self.Console.ePopen(cmd, self.IpkgList_Finished)
610 #print event, "-", param
613 def IpkgList_Finished(self, result, retval, extra_args = None):
616 for x in result.splitlines():
617 split = x.split(' - ') #self.blacklisted_packages
618 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
619 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
621 self.Console = Console()
622 cmd = "ipkg list_installed"
623 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
625 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
627 self.installed_packetlist = {}
628 for x in result.splitlines():
629 split = x.split(' - ')
630 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
631 self.installed_packetlist[split[0].strip()] = split[1].strip()
632 self.buildPacketList()
634 def buildEntryComponent(self, name, version, description, state):
635 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
636 if state == 'installed':
637 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
638 return((name, version, description, state, installedpng, divpng))
639 elif state == 'upgradeable':
640 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png"))
641 return((name, version, description, state, upgradeablepng, divpng))
643 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
644 return((name, version, description, state, installablepng, divpng))
646 def buildPacketList(self):
650 if self.cache_ttl > 0 and self.vc != 0:
651 print 'Loading packagelist cache from ',self.cache_file
653 self.cachelist = load_cache(self.cache_file)
654 if len(self.cachelist) > 0:
655 for x in self.cachelist:
656 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
657 self['list'].setList(self.list)
661 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
662 print 'rebuilding fresh package list'
663 for x in self.packetlist:
665 if self.installed_packetlist.has_key(x[0].strip()):
666 if self.installed_packetlist[x[0].strip()] == x[1].strip():
668 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
670 status = "upgradeable"
671 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
673 status = "installable"
674 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
675 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
676 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
677 write_cache(self.cache_file, self.cachelist)
678 self['list'].setList(self.list)
680 def reloadPluginlist(self):
681 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
684 class PluginManager(Screen, DreamInfoHandler):
686 lastDownloadDate = None
689 <screen name="PluginManager" position="center,center" size="560,440" title="Plugin manager" >
690 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
691 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
692 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
693 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
694 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
695 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
696 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
697 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
698 <widget source="list" render="Listbox" position="5,50" size="550,360" scrollbarMode="showOnDemand">
699 <convert type="TemplatedMultiContent">
702 MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
703 MultiContentEntryText(pos = (30, 25), size = (470, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
704 MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap
705 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap
708 MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
709 MultiContentEntryText(pos = (30, 22), size = (500, 16), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description
710 MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap
713 "fonts": [gFont("Regular", 22),gFont("Regular", 16)],
718 <widget source="status" render="Label" position="5,410" zPosition="10" size="540,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
721 def __init__(self, session, plugin_path, args = None):
722 Screen.__init__(self, session)
723 self.session = session
724 self.skin_path = plugin_path
725 aboutInfo = about.getImageVersionString()
726 if aboutInfo.startswith("dev-"):
727 self.ImageVersion = 'Experimental'
729 self.ImageVersion = 'Stable'
730 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
732 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
733 self.directory = resolveFilename(SCOPE_METADIR)
735 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ],
737 "ok": self.handleCurrent,
740 "green": self.handleCurrent,
741 "yellow": self.handleSelected,
742 "showEventInfo": self.handleSelected,
743 "displayHelp": self.handleHelp,
748 self.selectedFiles = []
749 self.categoryList = []
750 self["list"] = List(self.list)
751 self["key_red"] = StaticText(_("Close"))
752 self["key_green"] = StaticText("")
753 self["key_yellow"] = StaticText("")
754 self["key_blue"] = StaticText("")
755 self["status"] = StaticText("")
757 self.list_updating = True
759 self.installed_packetlist = {}
760 self.available_packetlist = []
761 self.available_updates = 0
762 self.Console = Console()
764 self.oktext = _("\nAfter pressing OK, please wait!")
765 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
767 self.ipkg = IpkgComponent()
768 self.ipkg.addCallback(self.ipkgCallback)
769 if not self.selectionChanged in self["list"].onSelectionChanged:
770 self["list"].onSelectionChanged.append(self.selectionChanged)
773 self.currentSelectedTag = None
774 self.currentSelectedIndex = None
776 self.onShown.append(self.setWindowTitle)
777 self.onLayoutFinish.append(self.rebuildList)
779 def setWindowTitle(self):
780 self.setTitle(_("Plugin manager"))
783 if self.currList == "packages":
784 self.currList = "category"
785 self.currentSelectedTag = None
786 self["list"].style = "category"
787 self['list'].setList(self.categoryList)
788 self["list"].setIndex(self.currentSelectedIndex)
789 self["list"].updateList(self.categoryList)
790 self.selectionChanged()
793 if self.Console is not None:
794 if len(self.Console.appContainers):
795 for name in self.Console.appContainers.keys():
796 self.Console.kill(name)
797 self.prepareInstall()
798 if len(self.cmdList):
799 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
803 def handleHelp(self):
804 if self.currList != "status":
805 self.session.open(PluginManagerHelp, self.skin_path)
807 def setState(self,status = None):
809 self.currList = "status"
811 self["key_green"].setText("")
812 self["key_blue"].setText("")
813 self["key_yellow"].setText("")
814 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
815 if status == 'update':
816 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
817 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' ))
818 self["list"].style = "default"
819 self['list'].setList(self.statuslist)
820 elif status == 'sync':
821 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
822 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
823 self["list"].style = "default"
824 self['list'].setList(self.statuslist)
825 elif status == 'error':
826 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
827 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
828 self["list"].style = "default"
829 self['list'].setList(self.statuslist)
831 def statusCallback(self, status, progress):
834 def selectionChanged(self):
835 current = self["list"].getCurrent()
836 self["status"].setText("")
838 if self.currList == "packages":
839 self["key_red"].setText(_("Back"))
840 if current[4] == 'installed':
841 self["key_green"].setText(_("Remove"))
842 elif current[4] == 'installable':
843 self["key_green"].setText(_("Install"))
844 elif current[4] == 'remove':
845 self["key_green"].setText(_("Undo\nRemove"))
846 elif current[4] == 'install':
847 self["key_green"].setText(_("Undo\nInstall"))
848 self["key_yellow"].setText(_("View details"))
849 self["key_blue"].setText("")
850 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
851 self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
852 elif len(self.selectedFiles) is not 0:
853 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
855 self["status"].setText(_("There is nothing to be done."))
856 elif self.currList == "category":
857 self["key_red"].setText(_("Close"))
858 self["key_green"].setText("")
859 self["key_yellow"].setText("")
860 self["key_blue"].setText("")
861 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
862 self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
863 self["key_yellow"].setText(_("Update"))
864 elif len(self.selectedFiles) is not 0:
865 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
866 self["key_yellow"].setText(_("Process"))
868 self["status"].setText(_("There is nothing to be done."))
870 def getSelectionState(self, detailsFile):
871 for entry in self.selectedFiles:
872 if entry[0] == detailsFile:
876 def rebuildList(self):
877 self.setState('update')
878 if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600:
879 # Only update from internet once per hour
880 PluginManager.lastDownloadDate = time()
881 print "last update time > 1h"
882 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
884 print "last update time < 1h"
887 def ipkgCallback(self, event, param):
888 if event == IpkgComponent.EVENT_ERROR:
889 self.list_updating = False
890 self.setState('error')
891 elif event == IpkgComponent.EVENT_DONE:
895 def startIpkgList(self):
896 if self.list_updating:
898 self.Console = Console()
900 self.Console.ePopen(cmd, self.IpkgList_Finished)
902 def IpkgList_Finished(self, result, retval, extra_args = None):
904 self.available_packetlist = []
905 for x in result.splitlines():
906 split = x.split(' - ')
907 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
908 self.available_packetlist.append([split[0].strip(), split[1].strip(), split[2].strip()])
909 self.startInstallMetaPackage()
911 def startInstallMetaPackage(self):
912 if self.list_updating:
913 self.list_updating = False
915 self.Console = Console()
916 cmd = "ipkg install enigma2-meta" #dummy,will change probably"
917 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
919 def InstallMetaPackage_Finished(self, result, retval, extra_args = None):
921 self.fillPackagesIndexList()
923 self.Console = Console()
924 self.setState('sync')
925 cmd = "ipkg list_installed"
926 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
928 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
930 self.installed_packetlist = {}
931 for x in result.splitlines():
932 split = x.split(' - ')
933 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
934 self.installed_packetlist[split[0].strip()] = split[1].strip()
936 if self.currentSelectedTag is None:
937 self.buildCategoryList()
939 self.buildPacketList(self.currentSelectedTag)
941 def countUpdates(self):
942 self.available_updates = 0
943 for package in self.packagesIndexlist[:]:
944 attributes = package[0]["attributes"]
945 packagename = attributes["packagename"]
946 for x in self.available_packetlist:
947 if x[0].strip() == packagename:
948 if self.installed_packetlist.has_key(packagename):
949 if self.installed_packetlist[packagename] != x[1].strip():
950 self.available_updates +=1
952 def handleCurrent(self):
953 current = self["list"].getCurrent()
955 if self.currList == "category":
956 self.currentSelectedIndex = self["list"].index
957 selectedTag = current[2]
958 self.buildPacketList(selectedTag)
959 elif self.currList == "packages":
960 if current[7] is not '':
961 idx = self["list"].getIndex()
962 detailsFile = self.list[idx][1]
963 if self.list[idx][7] == True:
964 for entry in self.selectedFiles:
965 if entry[0] == detailsFile:
966 self.selectedFiles.remove(entry)
968 alreadyinList = False
969 for entry in self.selectedFiles:
970 if entry[0] == detailsFile:
972 if not alreadyinList:
973 self.selectedFiles.append((detailsFile,current[4],current[3]))
974 if current[4] == 'installed':
975 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True)
976 elif current[4] == 'installable':
977 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
978 elif current[4] == 'remove':
979 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False)
980 elif current[4] == 'install':
981 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
982 self["list"].setList(self.list)
983 self["list"].setIndex(idx)
984 self["list"].updateList(self.list)
985 self.selectionChanged()
987 def handleSelected(self):
988 current = self["list"].getCurrent()
990 if self.currList == "packages":
991 if current[7] is not '':
992 detailsfile = self.directory[0] + "/" + current[1]
993 if (os_path.exists(detailsfile) == True):
994 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
996 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10)
997 elif self.currList == "category":
998 self.prepareInstall()
999 if len(self.cmdList):
1000 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
1002 def detailsClosed(self, result):
1004 if not self.Console:
1005 self.Console = Console()
1006 self.setState('sync')
1007 PluginManager.lastDownloadDate = time()
1008 self.selectedFiles = []
1010 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
1012 def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
1013 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1014 if state == 'installed':
1015 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1016 return((name, details, description, packagename, state, installedpng, divpng, selected))
1017 elif state == 'installable':
1018 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1019 return((name, details, description, packagename, state, installablepng, divpng, selected))
1020 elif state == 'remove':
1021 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1022 return((name, details, description, packagename, state, removepng, divpng, selected))
1023 elif state == 'install':
1024 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1025 return((name, details, description, packagename, state, installpng, divpng, selected))
1027 def buildPacketList(self, categorytag = None):
1028 if categorytag is not None:
1029 self.currList = "packages"
1030 self.currentSelectedTag = categorytag
1031 self.packetlist = []
1032 for package in self.packagesIndexlist[:]:
1033 prerequisites = package[0]["prerequisites"]
1034 if prerequisites.has_key("tag"):
1035 for foundtag in prerequisites["tag"]:
1036 if categorytag == foundtag:
1037 attributes = package[0]["attributes"]
1038 if attributes.has_key("packagetype"):
1039 if attributes["packagetype"] == "internal":
1041 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1043 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1045 for x in self.packetlist:
1047 selectState = self.getSelectionState(x[1].strip())
1048 if self.installed_packetlist.has_key(x[3].strip()):
1049 if selectState == True:
1052 status = "installed"
1053 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1055 if selectState == True:
1058 status = "installable"
1059 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1061 self.list.sort(key=lambda x: x[0])
1062 self["list"].style = "default"
1063 self['list'].setList(self.list)
1064 self["list"].updateList(self.list)
1065 self.selectionChanged()
1067 def buildCategoryList(self):
1068 self.currList = "category"
1069 self.categories = []
1070 self.categoryList = []
1071 for package in self.packagesIndexlist[:]:
1072 prerequisites = package[0]["prerequisites"]
1073 if prerequisites.has_key("tag"):
1074 for foundtag in prerequisites["tag"]:
1075 attributes = package[0]["attributes"]
1076 if foundtag not in self.categories:
1077 self.categories.append(foundtag)
1078 self.categoryList.append(self.buildCategoryComponent(foundtag))
1079 self.categoryList.sort(key=lambda x: x[0])
1080 self["list"].style = "category"
1081 self['list'].setList(self.categoryList)
1082 self["list"].updateList(self.categoryList)
1083 self.selectionChanged()
1085 def buildCategoryComponent(self, tag = None):
1086 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1089 return(( _("System"), _("View list of available system extensions" ), tag, divpng ))
1091 return(( _("Skins"), _("View list of available skins" ), tag, divpng ))
1092 elif tag == 'Recording':
1093 return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng ))
1094 elif tag == 'Network':
1095 return(( _("Network"), _("View list of available networking extensions" ), tag, divpng ))
1097 return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng ))
1098 elif tag == 'Default':
1099 return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng ))
1101 return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng ))
1102 elif tag == 'Software':
1103 return(( _("Software"), _("View list of available software extensions" ), tag, divpng ))
1104 elif tag == 'Multimedia':
1105 return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng ))
1106 elif tag == 'Display':
1107 return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng ))
1109 return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng ))
1110 elif tag == 'Communication':
1111 return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng ))
1112 else: # dynamically generate non existent tags
1113 return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng ))
1115 def prepareInstall(self):
1117 if self.available_updates > 0:
1118 self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False }))
1119 if self.selectedFiles and len(self.selectedFiles):
1120 for plugin in self.selectedFiles:
1121 detailsfile = self.directory[0] + "/" + plugin[0]
1122 if (os_path.exists(detailsfile) == True):
1123 self.fillPackageDetails(plugin[0])
1124 self.package = self.packageDetails[0]
1125 if self.package[0].has_key("attributes"):
1126 self.attributes = self.package[0]["attributes"]
1127 if self.attributes.has_key("package"):
1128 self.packagefiles = self.attributes["package"]
1129 if plugin[1] == 'installed':
1130 if self.packagefiles:
1131 for package in self.packagefiles[:]:
1132 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1134 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1136 if self.packagefiles:
1137 for package in self.packagefiles[:]:
1138 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1140 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1142 if plugin[1] == 'installed':
1143 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1145 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1147 def runExecute(self, result):
1149 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
1153 def runExecuteFinished(self):
1154 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1156 def ExecuteReboot(self, result):
1160 self.reloadPluginlist()
1161 self.detailsClosed(True)
1165 def reloadPluginlist(self):
1166 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1169 class PluginManagerInfo(Screen):
1171 <screen name="PluginManagerInfo" position="center,center" size="560,440" title="Plugin manager activity information" >
1172 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1173 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1174 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1175 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1176 <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
1177 <convert type="TemplatedMultiContent">
1179 MultiContentEntryText(pos = (50, 1), size = (150, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1180 MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1181 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1182 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1184 "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1189 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1190 <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1193 def __init__(self, session, plugin_path, cmdlist = None):
1194 Screen.__init__(self, session)
1195 self.session = session
1196 self.skin_path = plugin_path
1197 self.cmdlist = cmdlist
1199 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1204 "green": self.process,
1208 self["list"] = List(self.list)
1209 self["key_red"] = StaticText(_("Cancel"))
1210 self["key_green"] = StaticText(_("Continue"))
1211 self["status"] = StaticText(_("Following tasks will be done after you press continue!"))
1213 self.onShown.append(self.setWindowTitle)
1214 self.onLayoutFinish.append(self.rebuildList)
1216 def setWindowTitle(self):
1217 self.setTitle(_("Plugin manager activity information"))
1219 def rebuildList(self):
1221 if self.cmdlist is not None:
1222 for entry in self.cmdlist:
1234 info = args['package']
1236 info = args['package']
1238 info = _("Dreambox software because updates are available.")
1240 self.list.append(self.buildEntryComponent(action,info))
1241 self['list'].setList(self.list)
1242 self['list'].updateList(self.list)
1244 def buildEntryComponent(self, action,info):
1245 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1246 upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
1247 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1248 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1249 if action == 'install':
1250 return(( _('Installing'), info, installpng, divpng))
1251 elif action == 'remove':
1252 return(( _('Removing'), info, removepng, divpng))
1254 return(( _('Upgrading'), info, upgradepng, divpng))
1263 class PluginManagerHelp(Screen):
1265 <screen name="PluginManagerHelp" position="center,center" size="560,440" title="Plugin manager help" >
1266 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1267 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1268 <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
1269 <convert type="TemplatedMultiContent">
1271 MultiContentEntryText(pos = (50, 1), size = (540, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1272 MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1273 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1274 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1276 "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1281 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="550,2" transparent="1" alphatest="on" />
1282 <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1285 def __init__(self, session, plugin_path):
1286 Screen.__init__(self, session)
1287 self.session = session
1288 self.skin_path = plugin_path
1290 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1297 self["list"] = List(self.list)
1298 self["key_red"] = StaticText(_("Close"))
1299 self["status"] = StaticText(_("A small overview of the available icon states and actions."))
1301 self.onShown.append(self.setWindowTitle)
1302 self.onLayoutFinish.append(self.rebuildList)
1304 def setWindowTitle(self):
1305 self.setTitle(_("Plugin manager help"))
1307 def rebuildList(self):
1309 self.list.append(self.buildEntryComponent('install'))
1310 self.list.append(self.buildEntryComponent('installable'))
1311 self.list.append(self.buildEntryComponent('installed'))
1312 self.list.append(self.buildEntryComponent('remove'))
1313 self['list'].setList(self.list)
1314 self['list'].updateList(self.list)
1316 def buildEntryComponent(self, state):
1317 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1318 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1319 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1320 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1321 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1323 if state == 'installed':
1324 return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng))
1325 elif state == 'installable':
1326 return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng))
1327 elif state == 'install':
1328 return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng))
1329 elif state == 'remove':
1330 return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng))
1336 class PluginDetails(Screen, DreamInfoHandler):
1338 <screen name="PluginDetails" position="center,center" size="600,440" title="Plugin details" >
1339 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1340 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1341 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1342 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1343 <widget source="author" render="Label" position="10,50" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
1344 <widget name="statuspic" position="550,40" size="48,48" alphatest="on"/>
1345 <widget name="divpic" position="0,80" size="600,2" alphatest="on"/>
1346 <widget name="detailtext" position="10,90" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1347 <widget name="screenshot" position="290,90" size="300,330" alphatest="on"/>
1349 def __init__(self, session, plugin_path, packagedata = None):
1350 Screen.__init__(self, session)
1351 self.skin_path = plugin_path
1352 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
1353 self.attributes = None
1354 self.translatedAttributes = None
1355 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
1356 self.directory = resolveFilename(SCOPE_METADIR)
1358 self.pluginname = packagedata[0]
1359 self.details = packagedata[1]
1360 self.pluginstate = packagedata[4]
1361 self.statuspicinstance = packagedata[5]
1362 self.divpicinstance = packagedata[6]
1363 self.fillPackageDetails(self.details)
1367 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1373 "down": self.pageDown,
1374 "left": self.pageUp,
1375 "right": self.pageDown,
1378 self["key_red"] = StaticText(_("Close"))
1379 self["key_green"] = StaticText("")
1380 self["author"] = StaticText()
1381 self["statuspic"] = Pixmap()
1382 self["divpic"] = Pixmap()
1383 self["screenshot"] = Pixmap()
1384 self["detailtext"] = ScrollLabel()
1386 self["statuspic"].hide()
1387 self["screenshot"].hide()
1388 self["divpic"].hide()
1390 self.package = self.packageDetails[0]
1391 if self.package[0].has_key("attributes"):
1392 self.attributes = self.package[0]["attributes"]
1393 if self.package[0].has_key("translation"):
1394 self.translatedAttributes = self.package[0]["translation"]
1397 self.oktext = _("\nAfter pressing OK, please wait!")
1398 self.picload = ePicLoad()
1399 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
1400 self.onShown.append(self.setWindowTitle)
1401 self.onLayoutFinish.append(self.setInfos)
1403 def setWindowTitle(self):
1404 self.setTitle(_("Package details for: " + self.pluginname))
1410 self["detailtext"].pageUp()
1413 self["detailtext"].pageDown()
1415 def statusCallback(self, status, progress):
1419 if self.translatedAttributes.has_key("name"):
1420 self.pluginname = self.translatedAttributes["name"]
1421 elif self.attributes.has_key("name"):
1422 self.pluginname = self.attributes["name"]
1424 self.pluginname = _("unknown")
1426 if self.translatedAttributes.has_key("author"):
1427 self.author = self.translatedAttributes["author"]
1428 elif self.attributes.has_key("author"):
1429 self.author = self.attributes["author"]
1431 self.author = _("unknown")
1433 if self.translatedAttributes.has_key("description"):
1434 self.description = self.translatedAttributes["description"]
1435 elif self.attributes.has_key("description"):
1436 self.description = self.attributes["description"]
1438 self.description = _("No description available.")
1440 if self.translatedAttributes.has_key("screenshot"):
1441 self.loadThumbnail(self.translatedAttributes)
1443 self.loadThumbnail(self.attributes)
1445 self["author"].setText(_("Author: ") + self.author)
1446 self["detailtext"].setText(self.description.strip())
1447 if self.pluginstate == 'installable':
1448 self["key_green"].setText(_("Install"))
1450 self["key_green"].setText(_("Remove"))
1452 def loadThumbnail(self, entry):
1454 if entry.has_key("screenshot"):
1455 thumbnailUrl = entry["screenshot"]
1456 if thumbnailUrl is not None:
1457 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1458 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1459 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1461 self.setThumbnail(noScreenshot = True)
1463 def setThumbnail(self, noScreenshot = False):
1464 if not noScreenshot:
1465 filename = self.thumbnail
1467 filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png")
1469 sc = AVSwitch().getFramebufferScale()
1470 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1471 self.picload.startDecode(filename)
1473 if self.statuspicinstance != None:
1474 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1475 self["statuspic"].show()
1476 if self.divpicinstance != None:
1477 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1478 self["divpic"].show()
1480 def paintScreenshotPixmapCB(self, picInfo=None):
1481 ptr = self.picload.getData()
1483 self["screenshot"].instance.setPixmap(ptr.__deref__())
1484 self["screenshot"].show()
1486 self.setThumbnail(noScreenshot = True)
1489 if self.attributes.has_key("package"):
1490 self.packagefiles = self.attributes["package"]
1492 if self.pluginstate == 'installed':
1493 if self.packagefiles:
1494 for package in self.packagefiles[:]:
1495 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1496 if len(self.cmdList):
1497 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1499 if self.packagefiles:
1500 for package in self.packagefiles[:]:
1501 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1502 if len(self.cmdList):
1503 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1505 def runUpgrade(self, result):
1507 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1509 def runUpgradeFinished(self):
1510 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1512 def UpgradeReboot(self, result):
1520 def runRemove(self, result):
1522 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1524 def runRemoveFinished(self):
1525 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1527 def RemoveReboot(self, result):
1535 def reloadPluginlist(self):
1536 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1538 def fetchFailed(self,string):
1539 self.setThumbnail(noScreenshot = True)
1540 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1543 class UpdatePlugin(Screen):
1545 <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
1546 <widget name="activityslider" position="0,0" size="550,5" />
1547 <widget name="slider" position="0,150" size="550,30" />
1548 <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1549 <widget source="status" render="Label" position="10,60" size="540,45" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1552 def __init__(self, session, args = None):
1553 Screen.__init__(self, session)
1555 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1557 self.slider = Slider(0, 4)
1558 self["slider"] = self.slider
1559 self.activityslider = Slider(0, 100)
1560 self["activityslider"] = self.activityslider
1561 self.status = StaticText(_("Upgrading Dreambox... Please wait"))
1562 self["status"] = self.status
1563 self.package = StaticText()
1564 self["package"] = self.package
1570 self.activityTimer = eTimer()
1571 self.activityTimer.callback.append(self.doActivityTimer)
1572 self.activityTimer.start(100, False)
1574 self.ipkg = IpkgComponent()
1575 self.ipkg.addCallback(self.ipkgCallback)
1577 self.updating = True
1578 self.package.setText(_("Package list update"))
1579 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1581 self["actions"] = ActionMap(["WizardActions"],
1587 def doActivityTimer(self):
1589 if self.activity == 100:
1591 self.activityslider.setValue(self.activity)
1593 def ipkgCallback(self, event, param):
1594 if event == IpkgComponent.EVENT_DOWNLOAD:
1595 self.status.setText(_("Downloading"))
1596 elif event == IpkgComponent.EVENT_UPGRADE:
1597 if self.sliderPackages.has_key(param):
1598 self.slider.setValue(self.sliderPackages[param])
1599 self.package.setText(param)
1600 self.status.setText(_("Upgrading"))
1602 elif event == IpkgComponent.EVENT_INSTALL:
1603 self.package.setText(param)
1604 self.status.setText(_("Installing"))
1606 elif event == IpkgComponent.EVENT_CONFIGURING:
1607 self.package.setText(param)
1608 self.status.setText(_("Configuring"))
1609 elif event == IpkgComponent.EVENT_MODIFIED:
1610 self.session.openWithCallback(
1611 self.modificationCallback,
1613 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1615 elif event == IpkgComponent.EVENT_ERROR:
1617 elif event == IpkgComponent.EVENT_DONE:
1619 self.updating = False
1620 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1621 elif self.error == 0:
1622 self.slider.setValue(4)
1624 self.activityTimer.stop()
1625 self.activityslider.setValue(0)
1627 self.package.setText("")
1628 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1630 self.activityTimer.stop()
1631 self.activityslider.setValue(0)
1632 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1633 if self.packages == 0:
1634 error = _("No packages were upgraded yet. So you can check your network and try again.")
1636 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1637 self.status.setText(_("Error") + " - " + error)
1638 #print event, "-", param
1641 def modificationCallback(self, res):
1642 self.ipkg.write(res and "N" or "Y")
1645 if not self.ipkg.isRunning():
1646 if self.packages != 0 and self.error == 0:
1647 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1651 def exitAnswer(self, result):
1652 if result is not None and result:
1657 class IpkgInstaller(Screen):
1659 <screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" >
1660 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1661 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1662 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1663 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1664 <widget name="list" position="5,50" size="540,360" />
1665 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1666 <widget source="introduction" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1669 def __init__(self, session, list):
1670 Screen.__init__(self, session)
1672 self.list = SelectionList()
1673 self["list"] = self.list
1674 for listindex in range(len(list)):
1675 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1677 self["key_red"] = StaticText(_("Close"))
1678 self["key_green"] = StaticText(_("Install"))
1679 self["introduction"] = StaticText(_("Press OK to toggle the selection."))
1681 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1683 "ok": self.list.toggleSelection,
1684 "cancel": self.close,
1686 "green": self.install
1690 list = self.list.getSelectionsList()
1693 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1694 self.session.open(Ipkg, cmdList = cmdList)
1697 def filescan_open(list, session, **kwargs):
1698 filelist = [x.path for x in list]
1699 session.open(IpkgInstaller, filelist) # list
1701 def filescan(**kwargs):
1702 from Components.Scanner import Scanner, ScanPath
1704 Scanner(mimetypes = ["application/x-debian-package"],
1707 ScanPath(path = "ipk", with_subdirs = True),
1708 ScanPath(path = "", with_subdirs = False),
1711 description = _("Install extensions."),
1712 openfnc = filescan_open, )
1716 def UpgradeMain(session, **kwargs):
1717 session.open(UpdatePluginMenu)
1719 def startSetup(menuid):
1720 if menuid != "setup":
1722 return [(_("Software manager"), UpgradeMain, "software_manager", 50)]
1724 def Plugins(path, **kwargs):
1728 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1729 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1731 if config.usage.setup_level.index >= 2: # expert+
1732 list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))